From 7e7ee24109f5a765ca5f6584c23afcdd6424a77c Mon Sep 17 00:00:00 2001 From: "a.bouhuolia" Date: Thu, 9 Feb 2023 23:38:13 +0200 Subject: [PATCH 1/2] feat(server): bigcapital cli commands --- packages/server/bin/bigcapital.js | 282 ++++++++++++++++++ packages/server/bin/utils.js | 51 ++++ .../server/src/config/{index.ts => index.js} | 4 +- packages/webapp/package-lock.json | 42 +-- 4 files changed, 356 insertions(+), 23 deletions(-) create mode 100644 packages/server/bin/bigcapital.js create mode 100644 packages/server/bin/utils.js rename packages/server/src/config/{index.ts => index.js} (98%) diff --git a/packages/server/bin/bigcapital.js b/packages/server/bin/bigcapital.js new file mode 100644 index 000000000..5224d0dc5 --- /dev/null +++ b/packages/server/bin/bigcapital.js @@ -0,0 +1,282 @@ +#!/usr/bin/env node +const commander = require('commander'); +const color = require('colorette'); +const argv = require('getopts'); +const Knex = require('knex'); +const { knexSnakeCaseMappers } = require('objection'); +const config = require('../src/config'); + +function initSystemKnex() { + return Knex({ + client: config.system.db_client, + connection: { + host: config.system.db_host, + user: config.system.db_user, + password: config.system.db_password, + database: config.system.db_name, + charset: 'utf8', + }, + migrations: { + directory: config.system.migrations_dir, + }, + seeds: { + directory: config.system.seeds_dir, + }, + pool: { min: 0, max: 7 }, + ...knexSnakeCaseMappers({ upperCase: true }), + }); +} + +function initTenantKnex(organizationId) { + return Knex({ + client: config.tenant.db_client, + connection: { + host: config.tenant.db_host, + user: config.tenant.db_user, + password: config.tenant.db_password, + database: `${config.tenant.db_name_prefix}${organizationId}`, + charset: config.tenant.charset, + }, + migrations: { + directory: config.tenant.migrations_dir, + }, + seeds: { + directory: config.tenant.seeds_dir, + }, + pool: { min: 0, max: 5 }, + ...knexSnakeCaseMappers({ upperCase: true }), + }); +} +function exit(text) { + if (text instanceof Error) { + console.error( + color.red(`${text.detail ? `${text.detail}\n` : ''}${text.stack}`) + ); + } else { + console.error(color.red(text)); + } + process.exit(1); +} + +function success(text) { + console.log(text); + process.exit(0); +} +function log(text) { + console.log(text); +} + +function getAllSystemTenants(knex) { + return knex('tenants'); +} + +// module.exports = { +// log, +// success, +// exit, +// initSystemKnex, +// }; + +// - bigcapital system:migrate:latest +// - bigcapital system:migrate:rollback +// - bigcapital tenants:migrate:latest +// - bigcapital tenants:migrate:latest --tenant_id=XXX +// - bigcapital tenants:migrate:rollback +// - bigcapital tenants:migrate:rollback --tenant_id=XXX +// - bigcapital tenants:migrate:make +// - bigcapital system:migrate:make +// - bigcapital tenants:list + +commander + .command('system:migrate:rollback') + .description('Migrate the system database of the application.') + .action(async () => { + try { + const sysKnex = await initSystemKnex(); + const [batchNo, _log] = await sysKnex.migrate.rollback(); + + if (_log.length === 0) { + success(color.cyan('Already at the base migration')); + } + success( + color.green(`Batch ${batchNo} rolled back: ${_log.length} migrations`) + + (argv.verbose ? `\n${color.cyan(_log.join('\n'))}` : '') + ); + } catch (error) { + exit(error); + } + }); + +commander + .command('system:migrate:latest') + .description('Migrate latest mgiration of the system database.') + .action(async () => { + try { + const sysKnex = await initSystemKnex(); + const [batchNo, log] = await sysKnex.migrate.latest(); + + if (log.length === 0) { + success(color.cyan('Already up to date')); + } + success( + color.green(`Batch ${batchNo} run: ${log.length} migrations`) + + (argv.verbose ? `\n${color.cyan(log.join('\n'))}` : '') + ); + } catch (error) { + exit(error); + } + }); + +commander + .command('system:migrate:make ') + .description('Created a named migration file to the system database.') + .action(async (name) => { + const sysKnex = await initSystemKnex(); + + sysKnex.migrate + .make(name) + .then((name) => { + success(color.green(`Created Migration: ${name}`)); + }) + .catch(exit); + }); + +commander + .command('tenants:list') + .description('Retrieve a list of all system tenants databases.') + .action(async (cmd) => { + try { + const sysKnex = await initSystemKnex(); + const tenants = await getAllSystemTenants(sysKnex); + + tenants.forEach((tenant) => { + const dbName = `${config.tenant.db_name_prefix}${tenant.organizationId}`; + console.log( + `ID: ${tenant.id} | Organization ID: ${tenant.organizationId} | DB Name: ${dbName}` + ); + }); + } catch (error) { + exit(error); + } + success('---'); + }); + +commander + .command('tenants:migrate:make ') + .description('Created a named migration file to the tenants database.') + .action(async (name) => { + const sysKnex = await initTenantKnex(); + + sysKnex.migrate + .make(name) + .then((name) => { + success(color.green(`Created Migration: ${name}`)); + }) + .catch(exit); + }); + +commander + .command('tenants:migrate:latest') + .description('Migrate all tenants or the given tenant id.') + .option('-t, --tenant_id [tenant_id]', 'Which tenant id do you migrate.') + .action(async (cmd) => { + try { + const sysKnex = await initSystemKnex(); + const tenants = await getAllSystemTenants(sysKnex); + const tenantsOrgsIds = tenants.map((tenant) => tenant.organizationId); + + if (cmd.tenant_id && tenantsOrgsIds.indexOf(cmd.tenant_id) === -1) { + exit(`The given tenant id ${cmd.tenant_id} is not exists.`); + } + // Validate the tenant id exist first of all. + const migrateOpers = []; + const migrateTenant = async (organizationId) => { + try { + const tenantKnex = await initTenantKnex(organizationId); + const [batchNo, _log] = await tenantKnex.migrate.latest(); + + const tenantDb = `${config.tenant.db_name_prefix}${organizationId}`; + + if (_log.length === 0) { + log(color.cyan('Already up to date')); + } + log( + color.green( + `Tenant ${tenantDb} > Batch ${batchNo} run: ${_log.length} migrations` + ) + (argv.verbose ? `\n${color.cyan(log.join('\n'))}` : '') + ); + log('-------------------'); + } catch (error) { + log(error); + } + }; + if (!cmd.tenant_id) { + tenants.forEach((tenant) => { + const oper = migrateTenant(tenant.organizationId); + migrateOpers.push(oper); + }); + } else { + const oper = migrateTenant(cmd.tenant_id); + migrateOpers.push(oper); + } + + Promise.all(migrateOpers).then(() => { + success('All tenants are migrated.'); + }); + } catch (error) { + exit(error); + } + }); + +commander + .command('tenants:migrate:rollback') + .description('Rollback the last batch of tenants migrations.') + .option('-t, --tenant_id [tenant_id]', 'Which tenant id do you migrate.') + .action(async (cmd) => { + try { + const sysKnex = await initSystemKnex(); + const tenants = await getAllSystemTenants(sysKnex); + const tenantsOrgsIds = tenants.map((tenant) => tenant.organizationId); + + if (cmd.tenant_id && tenantsOrgsIds.indexOf(cmd.tenant_id) === -1) { + exit(`The given tenant id ${cmd.tenant_id} is not exists.`); + } + + const migrateOpers = []; + const migrateTenant = async (organizationId) => { + try { + const tenantKnex = await initTenantKnex(organizationId); + const [batchNo, _log] = await tenantKnex.migrate.rollback(); + const tenantDb = `${config.tenant.db_name_prefix}${organizationId}`; + + if (_log.length === 0) { + log(color.cyan('Already at the base migration')); + } + log( + color.green( + `Tenant: ${tenantDb} > Batch ${batchNo} rolled back: ${_log.length} migrations` + ) + (argv.verbose ? `\n${color.cyan(_log.join('\n'))}` : '') + ); + log('---------------'); + } catch (error) { + exit(error); + } + }; + + if (!cmd.tenant_id) { + tenants.forEach((tenant) => { + const oper = migrateTenant(tenant.organizationId); + migrateOpers.push(oper); + }); + } else { + const oper = migrateTenant(cmd.tenant_id); + migrateOpers.push(oper); + } + Promise.all(migrateOpers).then(() => { + success('All tenants are rollbacked.'); + }); + } catch (error) { + exit(error); + } + }); +commander.parse(); diff --git a/packages/server/bin/utils.js b/packages/server/bin/utils.js new file mode 100644 index 000000000..82c4d8cde --- /dev/null +++ b/packages/server/bin/utils.js @@ -0,0 +1,51 @@ +const Knex = require('knex'); +const { knexSnakeCaseMappers } = require('objection'); +const color = require('colorette'); +const config = require('./config'); + +function initSystemKnex() { + return Knex({ + client: config.system.db_client, + connection: { + host: config.system.db_host, + user: config.system.db_user, + password: config.system.db_password, + database: config.system.db_name, + charset: 'utf8', + }, + migrations: { + directory: config.system.migrations_dir, + }, + seeds: { + directory: config.system.seeds_dir, + }, + pool: { min: 0, max: 7 }, + ...knexSnakeCaseMappers({ upperCase: true }), + }); +} + +function exit(text) { + if (text instanceof Error) { + console.error( + color.red(`${text.detail ? `${text.detail}\n` : ''}${text.stack}`) + ); + } else { + console.error(color.red(text)); + } + process.exit(1); +} + +function success(text) { + console.log(text); + process.exit(0); +} +function log(text) { + console.log(text); +} + +module.exports = { + log, + success, + exit, + initSystemKnex, +}; diff --git a/packages/server/src/config/index.ts b/packages/server/src/config/index.js similarity index 98% rename from packages/server/src/config/index.ts rename to packages/server/src/config/index.js index b9ff6286c..6bc4e0116 100644 --- a/packages/server/src/config/index.ts +++ b/packages/server/src/config/index.js @@ -1,4 +1,4 @@ -import dotenv from 'dotenv'; +const dotenv = require('dotenv'); // Set the NODE_ENV to 'development' by default // process.env.NODE_ENV = process.env.NODE_ENV || 'development'; @@ -9,7 +9,7 @@ if (envFound.error) { throw new Error("⚠️ Couldn't find .env file ⚠️"); } -export default { +module.exports = { /** * Your favorite port */ diff --git a/packages/webapp/package-lock.json b/packages/webapp/package-lock.json index fa96c39ab..1852ca0f5 100644 --- a/packages/webapp/package-lock.json +++ b/packages/webapp/package-lock.json @@ -1144,6 +1144,11 @@ "@babel/plugin-transform-typescript": "^7.9.0" } }, + "@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" + }, "@babel/runtime": { "version": "7.20.13", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.13.tgz", @@ -3516,9 +3521,9 @@ } }, "async-each": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.5.tgz", - "integrity": "sha512-5QzqtU3BlagehwmdoqwaS2FBQF2P5eL6vFqXwNsb5jwoEsmtfAXg1ocFvW7I6/gGLFhBMKwcMwZuy7uv/Bo9jA==" + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.6.tgz", + "integrity": "sha512-c646jH1avxr+aVpndVMeAfYw7wAa6idufrlN3LPA4PmKS0QEGp6PIC9nwz0WQkkvBGAMEki3pFdtxaF39J9vvg==" }, "async-foreach": { "version": "0.1.3", @@ -4681,9 +4686,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001450", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001450.tgz", - "integrity": "sha512-qMBmvmQmFXaSxexkjjfMvD5rnDL0+m+dUMZKoDYsGG8iZN29RuYh9eRoMvKsT6uMAWlyUUGDEQGJJYjzCIO9ew==" + "version": "1.0.30001451", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001451.tgz", + "integrity": "sha512-XY7UbUpGRatZzoRft//5xOa69/1iGJRBlrieH6QYrkKLIFn3m7OVEJ81dSrKoy2BnKsdbX5cLrOispZNYo9v2w==" }, "capture-exit": { "version": "2.0.0", @@ -6015,9 +6020,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "electron-to-chromium": { - "version": "1.4.285", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.285.tgz", - "integrity": "sha512-47o4PPgxfU1KMNejz+Dgaodf7YTcg48uOfV1oM6cs3adrl2+7R+dHkt3Jpxqo0LRCbGJEzTKMUt0RdvByb/leg==" + "version": "1.4.289", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.289.tgz", + "integrity": "sha512-relLdMfPBxqGCxy7Gyfm1HcbRPcFUJdlgnCPVgQ23sr1TvUrRJz0/QPoGP0+x41wOVSTN/Wi3w6YDgHiHJGOzg==" }, "elliptic": { "version": "6.5.4", @@ -10984,9 +10989,9 @@ } }, "node-releases": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.9.tgz", - "integrity": "sha512-2xfmOrRkGogbTK9R6Leda0DGiXeY3p2NJpy4+gNCffdUvV6mdEJnaDEic1i3Ec2djAo8jWYoJMR5PB0MSMpxUA==" + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", + "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==" }, "node-sass": { "version": "4.14.1", @@ -14129,23 +14134,18 @@ "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==" }, "regexpu-core": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.2.2.tgz", - "integrity": "sha512-T0+1Zp2wjF/juXMrMxHxidqGYn8U4R+zleSJhX9tQ1PUsS8a9UtYfbsF9LdiVgNX3kiX8RNaKM42nfSgvFJjmw==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.0.tgz", + "integrity": "sha512-ZdhUQlng0RoscyW7jADnUZ25F5eVtHdMyXSb2PiwafvteRAOJUjFoUPEYZSIfP99fBIs3maLIRfpEddT78wAAQ==", "requires": { + "@babel/regjsgen": "^0.8.0", "regenerate": "^1.4.2", "regenerate-unicode-properties": "^10.1.0", - "regjsgen": "^0.7.1", "regjsparser": "^0.9.1", "unicode-match-property-ecmascript": "^2.0.0", "unicode-match-property-value-ecmascript": "^2.1.0" } }, - "regjsgen": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.7.1.tgz", - "integrity": "sha512-RAt+8H2ZEzHeYWxZ3H2z6tF18zyyOnlcdaafLrm21Bguj7uZy6ULibiAFdXEtKQY4Sy7wDTwDiOazasMLc4KPA==" - }, "regjsparser": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", From 72c1685fa6d469869314fb730a886a5542ffb18d Mon Sep 17 00:00:00 2001 From: "a.bouhuolia" Date: Mon, 13 Feb 2023 20:47:09 +0200 Subject: [PATCH 2/2] feat(server): move all cli commands codebase to be TS based. --- packages/server/bin/utils.js | 51 ------------ packages/server/package.json | 4 +- packages/server/scripts/webpack.cli.js | 11 +++ packages/server/scripts/webpack.common.js | 76 ++++++++++++++++++ packages/server/scripts/webpack.config.js | 77 ++----------------- .../commands/bigcapital.ts} | 14 ++-- packages/server/src/commands/index.ts | 4 + .../server/src/config/{index.js => index.ts} | 2 +- 8 files changed, 109 insertions(+), 130 deletions(-) delete mode 100644 packages/server/bin/utils.js create mode 100644 packages/server/scripts/webpack.cli.js create mode 100644 packages/server/scripts/webpack.common.js rename packages/server/{bin/bigcapital.js => src/commands/bigcapital.ts} (96%) create mode 100644 packages/server/src/commands/index.ts rename packages/server/src/config/{index.js => index.ts} (99%) diff --git a/packages/server/bin/utils.js b/packages/server/bin/utils.js deleted file mode 100644 index 82c4d8cde..000000000 --- a/packages/server/bin/utils.js +++ /dev/null @@ -1,51 +0,0 @@ -const Knex = require('knex'); -const { knexSnakeCaseMappers } = require('objection'); -const color = require('colorette'); -const config = require('./config'); - -function initSystemKnex() { - return Knex({ - client: config.system.db_client, - connection: { - host: config.system.db_host, - user: config.system.db_user, - password: config.system.db_password, - database: config.system.db_name, - charset: 'utf8', - }, - migrations: { - directory: config.system.migrations_dir, - }, - seeds: { - directory: config.system.seeds_dir, - }, - pool: { min: 0, max: 7 }, - ...knexSnakeCaseMappers({ upperCase: true }), - }); -} - -function exit(text) { - if (text instanceof Error) { - console.error( - color.red(`${text.detail ? `${text.detail}\n` : ''}${text.stack}`) - ); - } else { - console.error(color.red(text)); - } - process.exit(1); -} - -function success(text) { - console.log(text); - process.exit(0); -} -function log(text) { - console.log(text); -} - -module.exports = { - log, - success, - exit, - initSystemKnex, -}; diff --git a/packages/server/package.json b/packages/server/package.json index bd7899d2e..7b23f9734 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -8,7 +8,9 @@ "clear": "rimraf build", "dev": "cross-env NODE_ENV=development webpack --config scripts/webpack.config.js", "build:resources": "gulp --gulpfile=scripts/gulpfile.js styles styles-rtl", - "build": "cross-env NODE_ENV=production webpack --config scripts/webpack.config.js", + "build:app": "cross-env NODE_ENV=production webpack --config scripts/webpack.config.js", + "build:commands": "cross-env NODE_ENV=production webpack --config scripts/webpack.cli.js", + "build": "npm-run-all build:*", "lint:fix": "eslint --fix ./**/*.ts" }, "author": "Ahmed Bouhuolia, ", diff --git a/packages/server/scripts/webpack.cli.js b/packages/server/scripts/webpack.cli.js new file mode 100644 index 000000000..b4ca9edc5 --- /dev/null +++ b/packages/server/scripts/webpack.cli.js @@ -0,0 +1,11 @@ +const { getCommonWebpackOptions } = require('./webpack.common'); + +const inputEntry = './src/commands/index.ts'; +const outputDir = '../build'; +const outputFilename = 'commands.js'; + +module.exports = getCommonWebpackOptions({ + inputEntry, + outputDir, + outputFilename, +}); diff --git a/packages/server/scripts/webpack.common.js b/packages/server/scripts/webpack.common.js new file mode 100644 index 000000000..b04d6dc4f --- /dev/null +++ b/packages/server/scripts/webpack.common.js @@ -0,0 +1,76 @@ +const path = require('path'); +const { NormalModuleReplacementPlugin } = require('webpack'); +const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin'); +const { RunScriptWebpackPlugin } = require('run-script-webpack-plugin'); +const nodeExternals = require('webpack-node-externals'); +const ProgressBarPlugin = require('progress-bar-webpack-plugin'); + +const isDev = process.env.NODE_ENV === 'development'; + +exports.getCommonWebpackOptions = ({ + inputEntry, + outputDir, + outputFilename, +}) => { + const webpackOptions = { + entry: ['regenerator-runtime/runtime', inputEntry], + target: 'node', + mode: isDev ? 'development' : 'production', + watch: isDev, + watchOptions: { + aggregateTimeout: 200, + poll: 1000, + }, + output: { + path: path.resolve(__dirname, outputDir), + filename: outputFilename, + }, + resolve: { + extensions: ['.ts', '.tsx', '.js'], + extensionAlias: { + '.ts': ['.js', '.ts'], + '.cts': ['.cjs', '.cts'], + '.mts': ['.mjs', '.mts'], + }, + plugins: [ + new TsconfigPathsPlugin({ + configFile: './tsconfig.json', + extensions: ['.ts', '.tsx', '.js'], + }), + ], + }, + plugins: [ + // Ignore knex dynamic required dialects that we don't use + new NormalModuleReplacementPlugin( + /m[sy]sql2?|oracle(db)?|sqlite3|pg-(native|query)/, + 'noop2' + ), + new ProgressBarPlugin(), + ], + externals: [nodeExternals(), 'aws-sdk', 'prettier'], + module: { + rules: [ + { + test: /\.([cm]?ts|tsx|js)$/, + use: [ + { + loader: 'ts-loader', + options: { + transpileOnly: true, + configFile: 'tsconfig.json', + }, + }, + ], + exclude: /(node_modules)/, + }, + ], + }, + }; + + if (isDev) { + webpackOptions.plugins.push( + new RunScriptWebpackPlugin({ name: outputFilename }) + ); + } + return webpackOptions; +}; diff --git a/packages/server/scripts/webpack.config.js b/packages/server/scripts/webpack.config.js index cdf738bef..5a4cda373 100644 --- a/packages/server/scripts/webpack.config.js +++ b/packages/server/scripts/webpack.config.js @@ -1,74 +1,11 @@ -const path = require('path'); -const { NormalModuleReplacementPlugin } = require('webpack'); -const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin'); -const { RunScriptWebpackPlugin } = require('run-script-webpack-plugin'); -const nodeExternals = require('webpack-node-externals'); -const ProgressBarPlugin = require('progress-bar-webpack-plugin'); +const { getCommonWebpackOptions } = require('./webpack.common'); -const isDev = process.env.NODE_ENV === 'development'; +const inputEntry = './src/server.ts'; const outputDir = '../build'; const outputFilename = 'index.js'; -const inputEntry = './src/server.ts'; -const webpackOptions = { - entry: ['regenerator-runtime/runtime', inputEntry], - target: 'node', - mode: isDev ? 'development' : 'production', - watch: isDev, - watchOptions: { - aggregateTimeout: 200, - poll: 1000, - }, - output: { - path: path.resolve(__dirname, outputDir), - filename: outputFilename, - }, - resolve: { - extensions: ['.ts', '.tsx', '.js'], - extensionAlias: { - '.ts': ['.js', '.ts'], - '.cts': ['.cjs', '.cts'], - '.mts': ['.mjs', '.mts'], - }, - plugins: [ - new TsconfigPathsPlugin({ - configFile: './tsconfig.json', - extensions: ['.ts', '.tsx', '.js'], - }), - ], - }, - plugins: [ - // Ignore knex dynamic required dialects that we don't use - new NormalModuleReplacementPlugin( - /m[sy]sql2?|oracle(db)?|sqlite3|pg-(native|query)/, - 'noop2' - ), - new ProgressBarPlugin(), - ], - externals: [nodeExternals(), 'aws-sdk', 'prettier'], - module: { - rules: [ - { - test: /\.([cm]?ts|tsx|js)$/, - use: [ - { - loader: 'ts-loader', - options: { - transpileOnly: true, - configFile: 'tsconfig.json', - }, - }, - ], - exclude: /(node_modules)/, - }, - ], - }, -}; - -if (isDev) { - webpackOptions.plugins.push( - new RunScriptWebpackPlugin({ name: outputFilename }) - ); -} - -module.exports = webpackOptions; +module.exports = getCommonWebpackOptions({ + inputEntry, + outputDir, + outputFilename, +}); diff --git a/packages/server/bin/bigcapital.js b/packages/server/src/commands/bigcapital.ts similarity index 96% rename from packages/server/bin/bigcapital.js rename to packages/server/src/commands/bigcapital.ts index 5224d0dc5..fa52b5e38 100644 --- a/packages/server/bin/bigcapital.js +++ b/packages/server/src/commands/bigcapital.ts @@ -1,10 +1,10 @@ #!/usr/bin/env node -const commander = require('commander'); -const color = require('colorette'); -const argv = require('getopts'); -const Knex = require('knex'); -const { knexSnakeCaseMappers } = require('objection'); -const config = require('../src/config'); +import commander from 'commander'; +import color from 'colorette'; +import argv from 'getopts'; +import Knex from 'knex'; +import { knexSnakeCaseMappers } from 'objection'; +import config from '../config'; function initSystemKnex() { return Knex({ @@ -279,4 +279,4 @@ commander exit(error); } }); -commander.parse(); + diff --git a/packages/server/src/commands/index.ts b/packages/server/src/commands/index.ts new file mode 100644 index 000000000..627eeb658 --- /dev/null +++ b/packages/server/src/commands/index.ts @@ -0,0 +1,4 @@ +import commander from 'commander'; +import './bigcapital'; + +commander.parse(); diff --git a/packages/server/src/config/index.js b/packages/server/src/config/index.ts similarity index 99% rename from packages/server/src/config/index.js rename to packages/server/src/config/index.ts index 6bc4e0116..9563d914c 100644 --- a/packages/server/src/config/index.js +++ b/packages/server/src/config/index.ts @@ -1,4 +1,4 @@ -const dotenv = require('dotenv'); +import dotenv from 'dotenv'; // Set the NODE_ENV to 'development' by default // process.env.NODE_ENV = process.env.NODE_ENV || 'development';