mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-22 15:50:32 +00:00
Compare commits
1 Commits
v0.17.1
...
dependabot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4b0780bf2a |
23
.env.example
23
.env.example
@@ -75,9 +75,30 @@ PLAID_ENV=sandbox
|
|||||||
# Your Plaid keys, which can be found in the Plaid Dashboard.
|
# Your Plaid keys, which can be found in the Plaid Dashboard.
|
||||||
# https://dashboard.plaid.com/account/keys
|
# https://dashboard.plaid.com/account/keys
|
||||||
PLAID_CLIENT_ID=
|
PLAID_CLIENT_ID=
|
||||||
PLAID_SECRET=
|
PLAID_SECRET_DEVELOPMENT=
|
||||||
|
PLAID_SECRET_SANDBOX=
|
||||||
|
|
||||||
PLAID_LINK_WEBHOOK=
|
PLAID_LINK_WEBHOOK=
|
||||||
|
|
||||||
|
# (Optional) Redirect URI settings section
|
||||||
|
# Only required for OAuth redirect URI testing (not common on desktop):
|
||||||
|
# Sandbox Mode:
|
||||||
|
# Set the PLAID_SANDBOX_REDIRECT_URI below to 'http://localhost:3001/oauth-link'.
|
||||||
|
# The OAuth redirect flow requires an endpoint on the developer's website
|
||||||
|
# that the bank website should redirect to. You will also need to configure
|
||||||
|
# this redirect URI for your client ID through the Plaid developer dashboard
|
||||||
|
# at https://dashboard.plaid.com/team/api.
|
||||||
|
# Development mode:
|
||||||
|
# When running in development mode, you must use an https:// url.
|
||||||
|
# You will need to configure this https:// redirect URI in the Plaid developer dashboard.
|
||||||
|
# Instructions to create a self-signed certificate for localhost can be found at
|
||||||
|
# https://github.com/plaid/pattern/blob/master/README.md#testing-oauth.
|
||||||
|
# If your system is not set up to run localhost with https://, you will be unable to test
|
||||||
|
# the OAuth in development and should leave the PLAID_DEVELOPMENT_REDIRECT_URI blank.
|
||||||
|
|
||||||
|
PLAID_SANDBOX_REDIRECT_URI=
|
||||||
|
PLAID_DEVELOPMENT_REDIRECT_URI=
|
||||||
|
|
||||||
# https://docs.lemonsqueezy.com/guides/developer-guide/getting-started#create-an-api-key
|
# https://docs.lemonsqueezy.com/guides/developer-guide/getting-started#create-an-api-key
|
||||||
LEMONSQUEEZY_API_KEY=
|
LEMONSQUEEZY_API_KEY=
|
||||||
LEMONSQUEEZY_STORE_ID=
|
LEMONSQUEEZY_STORE_ID=
|
||||||
|
|||||||
@@ -22,15 +22,11 @@ services:
|
|||||||
- server
|
- server
|
||||||
- webapp
|
- webapp
|
||||||
restart: on-failure
|
restart: on-failure
|
||||||
networks:
|
|
||||||
- bigcapital_network
|
|
||||||
|
|
||||||
webapp:
|
webapp:
|
||||||
container_name: bigcapital-webapp
|
container_name: bigcapital-webapp
|
||||||
image: bigcapitalhq/webapp:latest
|
image: bigcapitalhq/webapp:latest
|
||||||
restart: on-failure
|
restart: on-failure
|
||||||
networks:
|
|
||||||
- bigcapital_network
|
|
||||||
|
|
||||||
server:
|
server:
|
||||||
container_name: bigcapital-server
|
container_name: bigcapital-server
|
||||||
@@ -93,17 +89,14 @@ services:
|
|||||||
- GOTENBERG_URL=${GOTENBERG_URL}
|
- GOTENBERG_URL=${GOTENBERG_URL}
|
||||||
- GOTENBERG_DOCS_URL=${GOTENBERG_DOCS_URL}
|
- GOTENBERG_DOCS_URL=${GOTENBERG_DOCS_URL}
|
||||||
|
|
||||||
# Exchange Rate
|
|
||||||
- EXCHANGE_RATE_SERVICE=${EXCHANGE_RATE_SERVICE}
|
|
||||||
- OPEN_EXCHANGE_RATE_APP_ID-${OPEN_EXCHANGE_RATE_APP_ID}
|
|
||||||
|
|
||||||
# Bank Sync
|
# Bank Sync
|
||||||
- BANKING_CONNECT=${BANKING_CONNECT}
|
- BANKING_CONNECT=${BANKING_CONNECT}
|
||||||
|
|
||||||
# Plaid
|
# Plaid
|
||||||
- PLAID_ENV=${PLAID_ENV}
|
- PLAID_ENV=${PLAID_ENV}
|
||||||
- PLAID_CLIENT_ID=${PLAID_CLIENT_ID}
|
- PLAID_CLIENT_ID=${PLAID_CLIENT_ID}
|
||||||
- PLAID_SECRET=${PLAID_SECRET}
|
- PLAID_SECRET_DEVELOPMENT=${PLAID_SECRET_DEVELOPMENT}
|
||||||
|
- PLAID_SECRET_SANDBOX=${b8cf42b441e110451e2f69ad7e1e9f}
|
||||||
- PLAID_LINK_WEBHOOK=${PLAID_LINK_WEBHOOK}
|
- PLAID_LINK_WEBHOOK=${PLAID_LINK_WEBHOOK}
|
||||||
|
|
||||||
# Lemon Squeez
|
# Lemon Squeez
|
||||||
@@ -121,15 +114,6 @@ services:
|
|||||||
- NEW_RELIC_LICENSE_KEY=${NEW_RELIC_LICENSE_KEY}
|
- NEW_RELIC_LICENSE_KEY=${NEW_RELIC_LICENSE_KEY}
|
||||||
- NEW_RELIC_APP_NAME=${NEW_RELIC_APP_NAME}
|
- NEW_RELIC_APP_NAME=${NEW_RELIC_APP_NAME}
|
||||||
|
|
||||||
# S3
|
|
||||||
- S3_REGION=${S3_REGION}
|
|
||||||
- S3_ACCESS_KEY_ID=${S3_ACCESS_KEY_ID}
|
|
||||||
- S3_SECRET_ACCESS_KEY=${S3_SECRET_ACCESS_KEY}
|
|
||||||
- S3_ENDPOINT=${S3_ENDPOINT}
|
|
||||||
- S3_BUCKET=${S3_BUCKET}
|
|
||||||
networks:
|
|
||||||
- bigcapital_network
|
|
||||||
|
|
||||||
database_migration:
|
database_migration:
|
||||||
container_name: bigcapital-database-migration
|
container_name: bigcapital-database-migration
|
||||||
build:
|
build:
|
||||||
@@ -146,8 +130,6 @@ services:
|
|||||||
- TENANT_DB_NAME_PERFIX=${TENANT_DB_NAME_PERFIX}
|
- TENANT_DB_NAME_PERFIX=${TENANT_DB_NAME_PERFIX}
|
||||||
depends_on:
|
depends_on:
|
||||||
- mysql
|
- mysql
|
||||||
networks:
|
|
||||||
- bigcapital_network
|
|
||||||
|
|
||||||
mysql:
|
mysql:
|
||||||
container_name: bigcapital-mysql
|
container_name: bigcapital-mysql
|
||||||
@@ -163,8 +145,6 @@ services:
|
|||||||
- mysql:/var/lib/mysql
|
- mysql:/var/lib/mysql
|
||||||
expose:
|
expose:
|
||||||
- '3306'
|
- '3306'
|
||||||
networks:
|
|
||||||
- bigcapital_network
|
|
||||||
|
|
||||||
mongo:
|
mongo:
|
||||||
container_name: bigcapital-mongo
|
container_name: bigcapital-mongo
|
||||||
@@ -174,8 +154,6 @@ services:
|
|||||||
- '27017'
|
- '27017'
|
||||||
volumes:
|
volumes:
|
||||||
- mongo:/var/lib/mongodb
|
- mongo:/var/lib/mongodb
|
||||||
networks:
|
|
||||||
- bigcapital_network
|
|
||||||
|
|
||||||
redis:
|
redis:
|
||||||
container_name: bigcapital-redis
|
container_name: bigcapital-redis
|
||||||
@@ -186,15 +164,11 @@ services:
|
|||||||
- '6379'
|
- '6379'
|
||||||
volumes:
|
volumes:
|
||||||
- redis:/data
|
- redis:/data
|
||||||
networks:
|
|
||||||
- bigcapital_network
|
|
||||||
|
|
||||||
gotenberg:
|
gotenberg:
|
||||||
image: gotenberg/gotenberg:7
|
image: gotenberg/gotenberg:7
|
||||||
expose:
|
expose:
|
||||||
- '9000'
|
- '9000'
|
||||||
networks:
|
|
||||||
- bigcapital_network
|
|
||||||
|
|
||||||
# Volumes
|
# Volumes
|
||||||
volumes:
|
volumes:
|
||||||
@@ -209,8 +183,3 @@ volumes:
|
|||||||
redis:
|
redis:
|
||||||
name: bigcapital_prod_redis
|
name: bigcapital_prod_redis
|
||||||
driver: local
|
driver: local
|
||||||
|
|
||||||
# Networks
|
|
||||||
networks:
|
|
||||||
bigcapital_network:
|
|
||||||
driver: bridge
|
|
||||||
|
|||||||
@@ -86,7 +86,7 @@
|
|||||||
"multer-s3": "^3.0.1",
|
"multer-s3": "^3.0.1",
|
||||||
"mustache": "^3.0.3",
|
"mustache": "^3.0.3",
|
||||||
"mysql": "^2.17.1",
|
"mysql": "^2.17.1",
|
||||||
"mysql2": "^1.6.5",
|
"mysql2": "^3.9.8",
|
||||||
"newrelic": "^11.15.0",
|
"newrelic": "^11.15.0",
|
||||||
"node-cache": "^4.2.1",
|
"node-cache": "^4.2.1",
|
||||||
"nodemailer": "^6.3.0",
|
"nodemailer": "^6.3.0",
|
||||||
|
|||||||
@@ -4,16 +4,12 @@ import { Router, Response, NextFunction, Request } from 'express';
|
|||||||
import { body, param } from 'express-validator';
|
import { body, param } from 'express-validator';
|
||||||
import BaseController from '@/api/controllers/BaseController';
|
import BaseController from '@/api/controllers/BaseController';
|
||||||
import { AttachmentsApplication } from '@/services/Attachments/AttachmentsApplication';
|
import { AttachmentsApplication } from '@/services/Attachments/AttachmentsApplication';
|
||||||
import { AttachmentUploadPipeline } from '@/services/Attachments/S3UploadPipeline';
|
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export class AttachmentsController extends BaseController {
|
export class AttachmentsController extends BaseController {
|
||||||
@Inject()
|
@Inject()
|
||||||
private attachmentsApplication: AttachmentsApplication;
|
private attachmentsApplication: AttachmentsApplication;
|
||||||
|
|
||||||
@Inject()
|
|
||||||
private uploadPipelineService: AttachmentUploadPipeline;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Router constructor.
|
* Router constructor.
|
||||||
*/
|
*/
|
||||||
@@ -22,8 +18,7 @@ export class AttachmentsController extends BaseController {
|
|||||||
|
|
||||||
router.post(
|
router.post(
|
||||||
'/',
|
'/',
|
||||||
this.uploadPipelineService.validateS3Configured,
|
this.attachmentsApplication.uploadPipeline.single('file'),
|
||||||
this.uploadPipelineService.uploadPipeline().single('file'),
|
|
||||||
this.validateUploadedFileExistance,
|
this.validateUploadedFileExistance,
|
||||||
this.uploadAttachment.bind(this)
|
this.uploadAttachment.bind(this)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -71,10 +71,6 @@ function getAllSystemTenants(knex) {
|
|||||||
return knex('tenants');
|
return knex('tenants');
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAllInitializedSystemTenants(knex) {
|
|
||||||
return knex('tenants').whereNotNull('initializedAt');
|
|
||||||
}
|
|
||||||
|
|
||||||
// module.exports = {
|
// module.exports = {
|
||||||
// log,
|
// log,
|
||||||
// success,
|
// success,
|
||||||
@@ -187,7 +183,7 @@ commander
|
|||||||
.action(async (cmd) => {
|
.action(async (cmd) => {
|
||||||
try {
|
try {
|
||||||
const sysKnex = await initSystemKnex();
|
const sysKnex = await initSystemKnex();
|
||||||
const tenants = await getAllInitializedSystemTenants(sysKnex);
|
const tenants = await getAllSystemTenants(sysKnex);
|
||||||
const tenantsOrgsIds = tenants.map((tenant) => tenant.organizationId);
|
const tenantsOrgsIds = tenants.map((tenant) => tenant.organizationId);
|
||||||
|
|
||||||
if (cmd.tenant_id && tenantsOrgsIds.indexOf(cmd.tenant_id) === -1) {
|
if (cmd.tenant_id && tenantsOrgsIds.indexOf(cmd.tenant_id) === -1) {
|
||||||
@@ -224,6 +220,7 @@ commander
|
|||||||
const oper = migrateTenant(cmd.tenant_id);
|
const oper = migrateTenant(cmd.tenant_id);
|
||||||
migrateOpers.push(oper);
|
migrateOpers.push(oper);
|
||||||
}
|
}
|
||||||
|
|
||||||
Promise.all(migrateOpers).then(() => {
|
Promise.all(migrateOpers).then(() => {
|
||||||
success('All tenants are migrated.');
|
success('All tenants are migrated.');
|
||||||
});
|
});
|
||||||
@@ -283,3 +280,4 @@ commander
|
|||||||
exit(error);
|
exit(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -204,7 +204,10 @@ module.exports = {
|
|||||||
plaid: {
|
plaid: {
|
||||||
env: process.env.PLAID_ENV || 'sandbox',
|
env: process.env.PLAID_ENV || 'sandbox',
|
||||||
clientId: process.env.PLAID_CLIENT_ID,
|
clientId: process.env.PLAID_CLIENT_ID,
|
||||||
secret: process.env.PLAID_SECRET,
|
secretDevelopment: process.env.PLAID_SECRET_DEVELOPMENT,
|
||||||
|
secretSandbox: process.env.PLAID_SECRET_SANDBOX,
|
||||||
|
redirectSandBox: process.env.PLAID_SANDBOX_REDIRECT_URI,
|
||||||
|
redirectDevelopment: process.env.PLAID_DEVELOPMENT_REDIRECT_URI,
|
||||||
linkWebhook: process.env.PLAID_LINK_WEBHOOK,
|
linkWebhook: process.env.PLAID_LINK_WEBHOOK,
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -215,7 +218,6 @@ module.exports = {
|
|||||||
key: process.env.LEMONSQUEEZY_API_KEY,
|
key: process.env.LEMONSQUEEZY_API_KEY,
|
||||||
storeId: process.env.LEMONSQUEEZY_STORE_ID,
|
storeId: process.env.LEMONSQUEEZY_STORE_ID,
|
||||||
webhookSecret: process.env.LEMONSQUEEZY_WEBHOOK_SECRET,
|
webhookSecret: process.env.LEMONSQUEEZY_WEBHOOK_SECRET,
|
||||||
redirectTo: `${process.env.BASE_URL}/setup`,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -235,6 +237,6 @@ module.exports = {
|
|||||||
accessKeyId: process.env.S3_ACCESS_KEY_ID,
|
accessKeyId: process.env.S3_ACCESS_KEY_ID,
|
||||||
secretAccessKey: process.env.S3_SECRET_ACCESS_KEY,
|
secretAccessKey: process.env.S3_SECRET_ACCESS_KEY,
|
||||||
endpoint: process.env.S3_ENDPOINT,
|
endpoint: process.env.S3_ENDPOINT,
|
||||||
bucket: process.env.S3_BUCKET || 'bigcapital-documents',
|
bucket: process.env.S3_BUCKET,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
exports.up = function (knex) {
|
|
||||||
return knex.schema.createTable('storage', (table) => {
|
|
||||||
table.increments('id').primary();
|
|
||||||
table.string('key').notNullable();
|
|
||||||
table.string('path').notNullable();
|
|
||||||
table.string('extension').notNullable();
|
|
||||||
table.integer('expire_in');
|
|
||||||
table.timestamps();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.down = function (knex) {
|
|
||||||
return knex.schema.dropTableIfExists('storage');
|
|
||||||
};
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
exports.up = function (knex) {
|
|
||||||
return knex.schema.dropTableIfExists('storage');
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.down = function (knex) {};
|
|
||||||
@@ -70,7 +70,10 @@ export class PlaidClientWrapper {
|
|||||||
baseOptions: {
|
baseOptions: {
|
||||||
headers: {
|
headers: {
|
||||||
'PLAID-CLIENT-ID': config.plaid.clientId,
|
'PLAID-CLIENT-ID': config.plaid.clientId,
|
||||||
'PLAID-SECRET': config.plaid.secret,
|
'PLAID-SECRET':
|
||||||
|
config.plaid.env === 'development'
|
||||||
|
? config.plaid.secretDevelopment
|
||||||
|
: config.plaid.secretSandbox,
|
||||||
'Plaid-Version': '2020-09-14',
|
'Plaid-Version': '2020-09-14',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2,9 +2,11 @@ import { Inject, Service } from 'typedi';
|
|||||||
import { UploadDocument } from './UploadDocument';
|
import { UploadDocument } from './UploadDocument';
|
||||||
import { DeleteAttachment } from './DeleteAttachment';
|
import { DeleteAttachment } from './DeleteAttachment';
|
||||||
import { GetAttachment } from './GetAttachment';
|
import { GetAttachment } from './GetAttachment';
|
||||||
|
import { AttachmentUploadPipeline } from './S3UploadPipeline';
|
||||||
import { LinkAttachment } from './LinkAttachment';
|
import { LinkAttachment } from './LinkAttachment';
|
||||||
import { UnlinkAttachment } from './UnlinkAttachment';
|
import { UnlinkAttachment } from './UnlinkAttachment';
|
||||||
import { getAttachmentPresignedUrl } from './GetAttachmentPresignedUrl';
|
import { getAttachmentPresignedUrl } from './GetAttachmentPresignedUrl';
|
||||||
|
import type { Multer } from 'multer';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export class AttachmentsApplication {
|
export class AttachmentsApplication {
|
||||||
@@ -17,6 +19,9 @@ export class AttachmentsApplication {
|
|||||||
@Inject()
|
@Inject()
|
||||||
private getDocumentService: GetAttachment;
|
private getDocumentService: GetAttachment;
|
||||||
|
|
||||||
|
@Inject()
|
||||||
|
private uploadPipelineService: AttachmentUploadPipeline;
|
||||||
|
|
||||||
@Inject()
|
@Inject()
|
||||||
private linkDocumentService: LinkAttachment;
|
private linkDocumentService: LinkAttachment;
|
||||||
|
|
||||||
@@ -26,6 +31,14 @@ export class AttachmentsApplication {
|
|||||||
@Inject()
|
@Inject()
|
||||||
private getPresignedUrlService: getAttachmentPresignedUrl;
|
private getPresignedUrlService: getAttachmentPresignedUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Express middleware for uploading attachments to an S3 bucket.
|
||||||
|
* @returns {Multer}
|
||||||
|
*/
|
||||||
|
get uploadPipeline(): Multer {
|
||||||
|
return this.uploadPipelineService.uploadPipeline();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves the metadata of uploaded document to S3 on database.
|
* Saves the metadata of uploaded document to S3 on database.
|
||||||
* @param {number} tenantId
|
* @param {number} tenantId
|
||||||
|
|||||||
@@ -1,38 +1,12 @@
|
|||||||
import multer from 'multer';
|
import multer from 'multer';
|
||||||
import type { Multer } from 'multer';
|
import type { Multer } from 'multer'
|
||||||
import multerS3 from 'multer-s3';
|
import multerS3 from 'multer-s3';
|
||||||
import { s3 } from '@/lib/S3/S3';
|
import { s3 } from '@/lib/S3/S3';
|
||||||
import { Service } from 'typedi';
|
import { Service } from 'typedi';
|
||||||
import config from '@/config';
|
import config from '@/config';
|
||||||
import { NextFunction, Request, Response } from 'express';
|
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export class AttachmentUploadPipeline {
|
export class AttachmentUploadPipeline {
|
||||||
/**
|
|
||||||
* Middleware to ensure that S3 configuration is properly set before proceeding.
|
|
||||||
* This function checks if the necessary S3 configuration keys are present and throws an error if any are missing.
|
|
||||||
*
|
|
||||||
* @param req The HTTP request object.
|
|
||||||
* @param res The HTTP response object.
|
|
||||||
* @param next The callback to pass control to the next middleware function.
|
|
||||||
*/
|
|
||||||
public validateS3Configured(req: Request, res: Response, next: NextFunction) {
|
|
||||||
if (
|
|
||||||
!config.s3.region ||
|
|
||||||
!config.s3.accessKeyId ||
|
|
||||||
!config.s3.secretAccessKey
|
|
||||||
) {
|
|
||||||
const missingKeys = [];
|
|
||||||
if (!config.s3.region) missingKeys.push('region');
|
|
||||||
if (!config.s3.accessKeyId) missingKeys.push('accessKeyId');
|
|
||||||
if (!config.s3.secretAccessKey) missingKeys.push('secretAccessKey');
|
|
||||||
const missing = missingKeys.join(', ');
|
|
||||||
|
|
||||||
throw new Error(`S3 configuration error: Missing ${missing}`);
|
|
||||||
}
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Express middleware for uploading attachments to an S3 bucket.
|
* Express middleware for uploading attachments to an S3 bucket.
|
||||||
* It utilizes the multer middleware for handling multipart/form-data, specifically for file uploads.
|
* It utilizes the multer middleware for handling multipart/form-data, specifically for file uploads.
|
||||||
|
|||||||
@@ -42,12 +42,7 @@ export const transformPlaidTrxsToCashflowCreate = R.curry(
|
|||||||
): CreateUncategorizedTransactionDTO => {
|
): CreateUncategorizedTransactionDTO => {
|
||||||
return {
|
return {
|
||||||
date: plaidTranasction.date,
|
date: plaidTranasction.date,
|
||||||
|
amount: plaidTranasction.amount,
|
||||||
// Plaid: Positive values when money moves out of the account; negative values
|
|
||||||
// when money moves in. For example, debit card purchases are positive;
|
|
||||||
// credit card payments, direct deposits, and refunds are negative.
|
|
||||||
amount: -1 * plaidTranasction.amount,
|
|
||||||
|
|
||||||
description: plaidTranasction.name,
|
description: plaidTranasction.name,
|
||||||
payee: plaidTranasction.payment_meta?.payee,
|
payee: plaidTranasction.payment_meta?.payee,
|
||||||
currencyCode: plaidTranasction.iso_currency_code,
|
currencyCode: plaidTranasction.iso_currency_code,
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import { Service } from 'typedi';
|
|||||||
import { createCheckout } from '@lemonsqueezy/lemonsqueezy.js';
|
import { createCheckout } from '@lemonsqueezy/lemonsqueezy.js';
|
||||||
import { SystemUser } from '@/system/models';
|
import { SystemUser } from '@/system/models';
|
||||||
import { configureLemonSqueezy } from './utils';
|
import { configureLemonSqueezy } from './utils';
|
||||||
import config from '@/config';
|
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export class LemonSqueezyService {
|
export class LemonSqueezyService {
|
||||||
@@ -29,7 +28,7 @@ export class LemonSqueezyService {
|
|||||||
},
|
},
|
||||||
productOptions: {
|
productOptions: {
|
||||||
enabledVariants: [variantId],
|
enabledVariants: [variantId],
|
||||||
redirectUrl: config.lemonSqueezy.redirectTo,
|
redirectUrl: `http://localhost:4000/dashboard/billing/`,
|
||||||
receiptButtonText: 'Go to Dashboard',
|
receiptButtonText: 'Go to Dashboard',
|
||||||
receiptThankYouNote: 'Thank you for signing up to Lemon Stand!',
|
receiptThankYouNote: 'Thank you for signing up to Lemon Stand!',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ import InvoiceMailDialog from '@/containers/Sales/Invoices/InvoiceMailDialog/Inv
|
|||||||
import EstimateMailDialog from '@/containers/Sales/Estimates/EstimateMailDialog/EstimateMailDialog';
|
import EstimateMailDialog from '@/containers/Sales/Estimates/EstimateMailDialog/EstimateMailDialog';
|
||||||
import ReceiptMailDialog from '@/containers/Sales/Receipts/ReceiptMailDialog/ReceiptMailDialog';
|
import ReceiptMailDialog from '@/containers/Sales/Receipts/ReceiptMailDialog/ReceiptMailDialog';
|
||||||
import PaymentMailDialog from '@/containers/Sales/PaymentReceives/PaymentMailDialog/PaymentMailDialog';
|
import PaymentMailDialog from '@/containers/Sales/PaymentReceives/PaymentMailDialog/PaymentMailDialog';
|
||||||
|
import { ConnectBankDialog } from '@/containers/CashFlow/ConnectBankDialog';
|
||||||
import { ExportDialog } from '@/containers/Dialogs/ExportDialog';
|
import { ExportDialog } from '@/containers/Dialogs/ExportDialog';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -96,6 +97,7 @@ export default function DialogsContainer() {
|
|||||||
<NotifyPaymentReceiveViaSMSDialog
|
<NotifyPaymentReceiveViaSMSDialog
|
||||||
dialogName={DialogsName.NotifyPaymentViaForm}
|
dialogName={DialogsName.NotifyPaymentViaForm}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<BadDebtDialog dialogName={DialogsName.BadDebtForm} />
|
<BadDebtDialog dialogName={DialogsName.BadDebtForm} />
|
||||||
<SMSMessageDialog dialogName={DialogsName.SMSMessageForm} />
|
<SMSMessageDialog dialogName={DialogsName.SMSMessageForm} />
|
||||||
<RefundCreditNoteDialog dialogName={DialogsName.RefundCreditNote} />
|
<RefundCreditNoteDialog dialogName={DialogsName.RefundCreditNote} />
|
||||||
@@ -146,6 +148,8 @@ export default function DialogsContainer() {
|
|||||||
<EstimateMailDialog dialogName={DialogsName.EstimateMail} />
|
<EstimateMailDialog dialogName={DialogsName.EstimateMail} />
|
||||||
<ReceiptMailDialog dialogName={DialogsName.ReceiptMail} />
|
<ReceiptMailDialog dialogName={DialogsName.ReceiptMail} />
|
||||||
<PaymentMailDialog dialogName={DialogsName.PaymentMail} />
|
<PaymentMailDialog dialogName={DialogsName.PaymentMail} />
|
||||||
|
<ConnectBankDialog dialogName={DialogsName.ConnectBankCreditCard} />
|
||||||
|
|
||||||
<ExportDialog dialogName={DialogsName.Export} />
|
<ExportDialog dialogName={DialogsName.Export} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import {
|
|||||||
FeatureCan,
|
FeatureCan,
|
||||||
} from '@/components';
|
} from '@/components';
|
||||||
import { useRefreshCashflowAccounts } from '@/hooks/query';
|
import { useRefreshCashflowAccounts } from '@/hooks/query';
|
||||||
import { useOpenPlaidConnect } from '@/hooks/utils/useOpenPlaidConnect';
|
|
||||||
import { CashflowAction, AbilitySubject } from '@/constants/abilityOption';
|
import { CashflowAction, AbilitySubject } from '@/constants/abilityOption';
|
||||||
|
|
||||||
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
||||||
@@ -40,9 +39,6 @@ function CashFlowAccountsActionsBar({
|
|||||||
}) {
|
}) {
|
||||||
const { refresh } = useRefreshCashflowAccounts();
|
const { refresh } = useRefreshCashflowAccounts();
|
||||||
|
|
||||||
// Opens the Plaid popup.
|
|
||||||
const { openPlaidAsync, isPlaidLoading } = useOpenPlaidConnect();
|
|
||||||
|
|
||||||
// Handle refresh button click.
|
// Handle refresh button click.
|
||||||
const handleRefreshBtnClick = () => {
|
const handleRefreshBtnClick = () => {
|
||||||
refresh();
|
refresh();
|
||||||
@@ -68,7 +64,7 @@ function CashFlowAccountsActionsBar({
|
|||||||
};
|
};
|
||||||
// Handle connect button click.
|
// Handle connect button click.
|
||||||
const handleConnectToBank = () => {
|
const handleConnectToBank = () => {
|
||||||
openPlaidAsync();
|
openDialog(DialogsName.ConnectBankCreditCard);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -120,7 +116,6 @@ function CashFlowAccountsActionsBar({
|
|||||||
className={Classes.MINIMAL}
|
className={Classes.MINIMAL}
|
||||||
text={'Connect to Bank / Credit Card'}
|
text={'Connect to Bank / Credit Card'}
|
||||||
onClick={handleConnectToBank}
|
onClick={handleConnectToBank}
|
||||||
disabled={isPlaidLoading}
|
|
||||||
/>
|
/>
|
||||||
<NavbarDivider />
|
<NavbarDivider />
|
||||||
</FeatureCan>
|
</FeatureCan>
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
import React from 'react';
|
||||||
|
import { Dialog, DialogSuspense } from '@/components';
|
||||||
|
import withDialogRedux from '@/components/DialogReduxConnect';
|
||||||
|
import { compose } from '@/utils';
|
||||||
|
|
||||||
|
const ConnectBankDialogBody = React.lazy(
|
||||||
|
() => import('./ConnectBankDialogBody'),
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connect bank dialog.
|
||||||
|
*/
|
||||||
|
function ConnectBankDialogRoot({ dialogName, payload = {}, isOpen }) {
|
||||||
|
return (
|
||||||
|
<Dialog
|
||||||
|
name={dialogName}
|
||||||
|
title={'Securly connect your bank or credit card.'}
|
||||||
|
isOpen={isOpen}
|
||||||
|
canEscapeJeyClose={true}
|
||||||
|
autoFocus={true}
|
||||||
|
>
|
||||||
|
<DialogSuspense>
|
||||||
|
<ConnectBankDialogBody dialogName={dialogName} />
|
||||||
|
</DialogSuspense>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ConnectBankDialog = compose(withDialogRedux())(
|
||||||
|
ConnectBankDialogRoot,
|
||||||
|
);
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
import * as R from 'ramda';
|
||||||
|
import { Form, Formik, FormikHelpers } from 'formik';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import { ConnectBankDialogContent } from './ConnectBankDialogContent';
|
||||||
|
import { useGetPlaidLinkToken } from '@/hooks/query';
|
||||||
|
import { useSetBankingPlaidToken } from '@/hooks/state/banking';
|
||||||
|
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
||||||
|
import { CLASSES } from '@/constants';
|
||||||
|
import { AppToaster } from '@/components';
|
||||||
|
import { Intent } from '@blueprintjs/core';
|
||||||
|
import { DialogsName } from '@/constants/dialogs';
|
||||||
|
|
||||||
|
const initialValues: ConnectBankDialogForm = {
|
||||||
|
serviceProvider: 'plaid',
|
||||||
|
};
|
||||||
|
|
||||||
|
interface ConnectBankDialogForm {
|
||||||
|
serviceProvider: 'plaid';
|
||||||
|
}
|
||||||
|
|
||||||
|
function ConnectBankDialogBodyRoot({
|
||||||
|
// #withDialogActions
|
||||||
|
closeDialog,
|
||||||
|
}) {
|
||||||
|
const { mutateAsync: getPlaidLinkToken } = useGetPlaidLinkToken();
|
||||||
|
const setPlaidId = useSetBankingPlaidToken();
|
||||||
|
|
||||||
|
// Handles the form submitting.
|
||||||
|
const handleSubmit = (
|
||||||
|
values: ConnectBankDialogForm,
|
||||||
|
{ setSubmitting }: FormikHelpers<ConnectBankDialogForm>,
|
||||||
|
) => {
|
||||||
|
setSubmitting(true);
|
||||||
|
getPlaidLinkToken()
|
||||||
|
.then((res) => {
|
||||||
|
setSubmitting(false);
|
||||||
|
closeDialog(DialogsName.ConnectBankCreditCard);
|
||||||
|
setPlaidId(res.data.link_token);
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
setSubmitting(false);
|
||||||
|
AppToaster.show({
|
||||||
|
message: 'Something went wrong.',
|
||||||
|
intent: Intent.DANGER,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={classNames(CLASSES.DIALOG_BODY)}>
|
||||||
|
<Formik initialValues={initialValues} onSubmit={handleSubmit}>
|
||||||
|
<Form>
|
||||||
|
<ConnectBankDialogContent />
|
||||||
|
</Form>
|
||||||
|
</Formik>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default R.compose(withDialogActions)(ConnectBankDialogBodyRoot);
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
import styled from 'styled-components';
|
||||||
|
import { Stack } from '@/components';
|
||||||
|
import { TellerIcon } from '../Icons/TellerIcon';
|
||||||
|
import { YodleeIcon } from '../Icons/YodleeIcon';
|
||||||
|
import { PlaidIcon } from '../Icons/PlaidIcon';
|
||||||
|
import { BankServiceCard } from './ConnectBankServiceCard';
|
||||||
|
|
||||||
|
const TopDesc = styled('p')`
|
||||||
|
margin-bottom: 20px;
|
||||||
|
color: #5f6b7c;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export function ConnectBankDialogContent() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<TopDesc>
|
||||||
|
Connect your bank accounts and fetch the bank transactions using
|
||||||
|
one of our supported third-party service providers.
|
||||||
|
</TopDesc>
|
||||||
|
|
||||||
|
<Stack>
|
||||||
|
<BankServiceCard
|
||||||
|
title={'Plaid (US, UK & Canada)'}
|
||||||
|
icon={<PlaidIcon />}
|
||||||
|
>
|
||||||
|
Plaid gives the connection to 12,000 financial institutions across US, UK and Canada.
|
||||||
|
</BankServiceCard>
|
||||||
|
|
||||||
|
<BankServiceCard
|
||||||
|
title={'Teller (US) — Soon'}
|
||||||
|
icon={<TellerIcon />}
|
||||||
|
disabled
|
||||||
|
>
|
||||||
|
Connect instantly with more than 5,000 financial institutions across US.
|
||||||
|
</BankServiceCard>
|
||||||
|
|
||||||
|
<BankServiceCard
|
||||||
|
title={'Yodlee (Global) — Soon'}
|
||||||
|
icon={<YodleeIcon />}
|
||||||
|
disabled
|
||||||
|
>
|
||||||
|
Connect instantly with a global network of financial institutions.
|
||||||
|
</BankServiceCard>
|
||||||
|
</Stack>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
import styled from 'styled-components';
|
||||||
|
import { Group } from '@/components';
|
||||||
|
|
||||||
|
const BankServiceIcon = styled('div')`
|
||||||
|
height: 40px;
|
||||||
|
width: 40px;
|
||||||
|
border: 1px solid #c8cad0;
|
||||||
|
border-radius: 3px;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
const BankServiceContent = styled(`div`)`
|
||||||
|
flex: 1 0;
|
||||||
|
`;
|
||||||
|
const BankServiceCardRoot = styled('button')`
|
||||||
|
border-radius: 3px;
|
||||||
|
border: 1px solid #c8cad0;
|
||||||
|
transition: all 0.1s ease-in-out;
|
||||||
|
background: transparent;
|
||||||
|
text-align: inherit;
|
||||||
|
padding: 14px;
|
||||||
|
|
||||||
|
&:not(:disabled) {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
&:hover:not(:disabled) {
|
||||||
|
border-color: #0153cc;
|
||||||
|
}
|
||||||
|
&:disabled {
|
||||||
|
background: #f9fdff;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
const BankServiceTitle = styled(`h3`)`
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #2d333d;
|
||||||
|
`;
|
||||||
|
const BankServiceDesc = styled('p')`
|
||||||
|
margin-top: 4px;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
font-size: 13px;
|
||||||
|
color: #738091;
|
||||||
|
`;
|
||||||
|
|
||||||
|
interface BankServiceCardProps {
|
||||||
|
title: string;
|
||||||
|
children: React.ReactNode;
|
||||||
|
disabled?: boolean;
|
||||||
|
icon: React.ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function BankServiceCard({
|
||||||
|
title,
|
||||||
|
children,
|
||||||
|
icon,
|
||||||
|
disabled,
|
||||||
|
}: BankServiceCardProps) {
|
||||||
|
return (
|
||||||
|
<BankServiceCardRoot disabled={disabled}>
|
||||||
|
<Group>
|
||||||
|
<BankServiceIcon>{icon}</BankServiceIcon>
|
||||||
|
<BankServiceContent>
|
||||||
|
<BankServiceTitle>{title}</BankServiceTitle>
|
||||||
|
<BankServiceDesc>{children}</BankServiceDesc>
|
||||||
|
</BankServiceContent>
|
||||||
|
</Group>
|
||||||
|
</BankServiceCardRoot>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from './ConnectBankDialog';
|
||||||
@@ -26,7 +26,7 @@ function SubscriptionPricing({
|
|||||||
useGetLemonSqueezyCheckout();
|
useGetLemonSqueezyCheckout();
|
||||||
|
|
||||||
const handleClick = () => {
|
const handleClick = () => {
|
||||||
getLemonCheckout({ variantId: '337977' })
|
getLemonCheckout({ variantId: '338516' })
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
const checkoutUrl = res.data.data.attributes.url;
|
const checkoutUrl = res.data.data.attributes.url;
|
||||||
window.LemonSqueezy.Url.Open(checkoutUrl);
|
window.LemonSqueezy.Url.Open(checkoutUrl);
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
import { useCallback } from 'react';
|
|
||||||
import { useSetBankingPlaidToken } from '../state/banking';
|
|
||||||
import { AppToaster } from '@/components';
|
|
||||||
import { useGetPlaidLinkToken } from '../query';
|
|
||||||
import { Intent } from '@blueprintjs/core';
|
|
||||||
|
|
||||||
export const useOpenPlaidConnect = () => {
|
|
||||||
const { mutateAsync: getPlaidLinkToken, isLoading } = useGetPlaidLinkToken();
|
|
||||||
const setPlaidId = useSetBankingPlaidToken();
|
|
||||||
|
|
||||||
const openPlaidAsync = useCallback(() => {
|
|
||||||
return getPlaidLinkToken()
|
|
||||||
.then((res) => {
|
|
||||||
setPlaidId(res.data.link_token);
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
AppToaster.show({
|
|
||||||
message: 'Something went wrong.',
|
|
||||||
intent: Intent.DANGER,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}, [getPlaidLinkToken, setPlaidId]);
|
|
||||||
|
|
||||||
return { openPlaidAsync, isPlaidLoading: isLoading };
|
|
||||||
};
|
|
||||||
55
pnpm-lock.yaml
generated
55
pnpm-lock.yaml
generated
@@ -58,7 +58,7 @@ importers:
|
|||||||
version: 0.8.8
|
version: 0.8.8
|
||||||
'@types/knex':
|
'@types/knex':
|
||||||
specifier: ^0.16.1
|
specifier: ^0.16.1
|
||||||
version: 0.16.1(mysql2@1.7.0)(mysql@2.18.1)
|
version: 0.16.1(mysql2@3.9.8)(mysql@2.18.1)
|
||||||
'@types/mathjs':
|
'@types/mathjs':
|
||||||
specifier: ^6.0.12
|
specifier: ^6.0.12
|
||||||
version: 6.0.12
|
version: 6.0.12
|
||||||
@@ -181,7 +181,7 @@ importers:
|
|||||||
version: 8.5.1
|
version: 8.5.1
|
||||||
knex:
|
knex:
|
||||||
specifier: ^0.95.15
|
specifier: ^0.95.15
|
||||||
version: 0.95.15(mysql2@1.7.0)(mysql@2.18.1)
|
version: 0.95.15(mysql2@3.9.8)(mysql@2.18.1)
|
||||||
knex-cleaner:
|
knex-cleaner:
|
||||||
specifier: ^1.3.0
|
specifier: ^1.3.0
|
||||||
version: 1.3.1
|
version: 1.3.1
|
||||||
@@ -234,8 +234,8 @@ importers:
|
|||||||
specifier: ^2.17.1
|
specifier: ^2.17.1
|
||||||
version: 2.18.1
|
version: 2.18.1
|
||||||
mysql2:
|
mysql2:
|
||||||
specifier: ^1.6.5
|
specifier: ^3.9.8
|
||||||
version: 1.7.0
|
version: 3.9.8
|
||||||
newrelic:
|
newrelic:
|
||||||
specifier: ^11.15.0
|
specifier: ^11.15.0
|
||||||
version: 11.17.0
|
version: 11.17.0
|
||||||
@@ -6480,11 +6480,11 @@ packages:
|
|||||||
'@types/node': 14.18.63
|
'@types/node': 14.18.63
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@types/knex@0.16.1(mysql2@1.7.0)(mysql@2.18.1):
|
/@types/knex@0.16.1(mysql2@3.9.8)(mysql@2.18.1):
|
||||||
resolution: {integrity: sha512-54gWD1HWwdVx5iLHaJ1qxH3I6KyBsj5fFqzRpXFn7REWiEB2jwspeVCombNsocSrqPd7IRPqKrsIME7/cD+TFQ==}
|
resolution: {integrity: sha512-54gWD1HWwdVx5iLHaJ1qxH3I6KyBsj5fFqzRpXFn7REWiEB2jwspeVCombNsocSrqPd7IRPqKrsIME7/cD+TFQ==}
|
||||||
deprecated: This is a stub types definition. knex provides its own type definitions, so you do not need this installed.
|
deprecated: This is a stub types definition. knex provides its own type definitions, so you do not need this installed.
|
||||||
dependencies:
|
dependencies:
|
||||||
knex: 0.95.15(mysql2@1.7.0)(mysql@2.18.1)
|
knex: 0.95.15(mysql2@3.9.8)(mysql@2.18.1)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- mysql
|
- mysql
|
||||||
- mysql2
|
- mysql2
|
||||||
@@ -10788,6 +10788,11 @@ packages:
|
|||||||
engines: {node: '>=0.10'}
|
engines: {node: '>=0.10'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/denque@2.1.0:
|
||||||
|
resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==}
|
||||||
|
engines: {node: '>=0.10'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/depd@1.1.2:
|
/depd@1.1.2:
|
||||||
resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==}
|
resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==}
|
||||||
engines: {node: '>= 0.6'}
|
engines: {node: '>= 0.6'}
|
||||||
@@ -14214,13 +14219,6 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
safer-buffer: 2.1.2
|
safer-buffer: 2.1.2
|
||||||
|
|
||||||
/iconv-lite@0.5.2:
|
|
||||||
resolution: {integrity: sha512-kERHXvpSaB4aU3eANwidg79K8FlrN77m8G9V+0vOR3HYaRifrlwMEpT7ZBJqLSEIHnEgJTHcWK82wwLwwKwtag==}
|
|
||||||
engines: {node: '>=0.10.0'}
|
|
||||||
dependencies:
|
|
||||||
safer-buffer: 2.1.2
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/iconv-lite@0.6.3:
|
/iconv-lite@0.6.3:
|
||||||
resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
|
resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@@ -16531,7 +16529,7 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
bluebird: 3.7.2
|
bluebird: 3.7.2
|
||||||
glob: 7.2.3
|
glob: 7.2.3
|
||||||
knex: 0.95.15(mysql2@1.7.0)(mysql@2.18.1)
|
knex: 0.95.15(mysql2@3.9.8)(mysql@2.18.1)
|
||||||
lodash: 4.17.21
|
lodash: 4.17.21
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
@@ -16541,7 +16539,7 @@ packages:
|
|||||||
lodash: 4.17.21
|
lodash: 4.17.21
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/knex@0.95.15(mysql2@1.7.0)(mysql@2.18.1):
|
/knex@0.95.15(mysql2@3.9.8)(mysql@2.18.1):
|
||||||
resolution: {integrity: sha512-Loq6WgHaWlmL2bfZGWPsy4l8xw4pOE+tmLGkPG0auBppxpI0UcK+GYCycJcqz9W54f2LiGewkCVLBm3Wq4ur/w==}
|
resolution: {integrity: sha512-Loq6WgHaWlmL2bfZGWPsy4l8xw4pOE+tmLGkPG0auBppxpI0UcK+GYCycJcqz9W54f2LiGewkCVLBm3Wq4ur/w==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
@@ -16575,7 +16573,7 @@ packages:
|
|||||||
interpret: 2.2.0
|
interpret: 2.2.0
|
||||||
lodash: 4.17.21
|
lodash: 4.17.21
|
||||||
mysql: 2.18.1
|
mysql: 2.18.1
|
||||||
mysql2: 1.7.0
|
mysql2: 3.9.8
|
||||||
pg-connection-string: 2.5.0
|
pg-connection-string: 2.5.0
|
||||||
rechoir: 0.7.0
|
rechoir: 0.7.0
|
||||||
resolve-from: 5.0.0
|
resolve-from: 5.0.0
|
||||||
@@ -17089,10 +17087,6 @@ packages:
|
|||||||
'@sinonjs/commons': 1.8.6
|
'@sinonjs/commons': 1.8.6
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/long@4.0.0:
|
|
||||||
resolution: {integrity: sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/long@5.2.3:
|
/long@5.2.3:
|
||||||
resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==}
|
resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==}
|
||||||
dev: false
|
dev: false
|
||||||
@@ -17147,6 +17141,11 @@ packages:
|
|||||||
resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==}
|
resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
|
/lru-cache@8.0.5:
|
||||||
|
resolution: {integrity: sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA==}
|
||||||
|
engines: {node: '>=16.14'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/luxon@1.28.1:
|
/luxon@1.28.1:
|
||||||
resolution: {integrity: sha512-gYHAa180mKrNIUJCbwpmD0aTu9kV0dREDrwNnuyFAsO1Wt0EVYSZelPnJlbj9HplzXX/YWXHFTL45kvZ53M0pw==}
|
resolution: {integrity: sha512-gYHAa180mKrNIUJCbwpmD0aTu9kV0dREDrwNnuyFAsO1Wt0EVYSZelPnJlbj9HplzXX/YWXHFTL45kvZ53M0pw==}
|
||||||
dev: false
|
dev: false
|
||||||
@@ -17382,6 +17381,7 @@ packages:
|
|||||||
|
|
||||||
/memory-pager@1.5.0:
|
/memory-pager@1.5.0:
|
||||||
resolution: {integrity: sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==}
|
resolution: {integrity: sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==}
|
||||||
|
requiresBuild: true
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/memorystream@0.3.1:
|
/memorystream@0.3.1:
|
||||||
@@ -17990,15 +17990,15 @@ packages:
|
|||||||
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
|
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/mysql2@1.7.0:
|
/mysql2@3.9.8:
|
||||||
resolution: {integrity: sha512-xTWWQPjP5rcrceZQ7CSTKR/4XIDeH/cRkNH/uzvVGQ7W5c7EJ0dXeJUusk7OKhIoHj7uFKUxDVSCfLIl+jluog==}
|
resolution: {integrity: sha512-+5JKNjPuks1FNMoy9TYpl77f+5frbTklz7eb3XDwbpsERRLEeXiW2PDEkakYF50UuKU2qwfGnyXpKYvukv8mGA==}
|
||||||
engines: {node: '>= 8.0'}
|
engines: {node: '>= 8.0'}
|
||||||
dependencies:
|
dependencies:
|
||||||
denque: 1.5.1
|
denque: 2.1.0
|
||||||
generate-function: 2.3.1
|
generate-function: 2.3.1
|
||||||
iconv-lite: 0.5.2
|
iconv-lite: 0.6.3
|
||||||
long: 4.0.0
|
long: 5.2.3
|
||||||
lru-cache: 5.1.1
|
lru-cache: 8.0.5
|
||||||
named-placeholders: 1.1.3
|
named-placeholders: 1.1.3
|
||||||
seq-queue: 0.0.5
|
seq-queue: 0.0.5
|
||||||
sqlstring: 2.3.3
|
sqlstring: 2.3.3
|
||||||
@@ -18866,7 +18866,7 @@ packages:
|
|||||||
ajv: 8.13.0
|
ajv: 8.13.0
|
||||||
ajv-formats: 2.1.1(ajv@8.13.0)
|
ajv-formats: 2.1.1(ajv@8.13.0)
|
||||||
db-errors: 0.2.3
|
db-errors: 0.2.3
|
||||||
knex: 0.95.15(mysql2@1.7.0)(mysql@2.18.1)
|
knex: 0.95.15(mysql2@3.9.8)(mysql@2.18.1)
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/oblivious-set@1.0.0:
|
/oblivious-set@1.0.0:
|
||||||
@@ -23472,6 +23472,7 @@ packages:
|
|||||||
|
|
||||||
/sparse-bitfield@3.0.3:
|
/sparse-bitfield@3.0.3:
|
||||||
resolution: {integrity: sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==}
|
resolution: {integrity: sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==}
|
||||||
|
requiresBuild: true
|
||||||
dependencies:
|
dependencies:
|
||||||
memory-pager: 1.5.0
|
memory-pager: 1.5.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|||||||
Reference in New Issue
Block a user