diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 000000000..5e9018d88 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,5 @@ +{ + "recommendations": [ + "biomejs.biome" + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index ce96ff416..ad96e1c71 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,30 +1,28 @@ { - "eslint.validate": [ - { - "language":"vue", - "autoFix":true - }, - { - "language":"html", - "autoFix":true - }, - { - "language":"javascript", - "autoFix":true - }, - { - "language":"typescript", - "autoFix":true - } - ], - "eslint.alwaysShowStatus": true, - "eslint.workingDirectories": [ - "./client", - "./server" - ], "editor.useTabStops": false, "editor.tabSize": 2, "editor.insertSpaces": true, "git.ignoreLimitWarning": true, - "god.tsconfig": "./server/tsconfig.json", -} \ No newline at end of file + "[typescript]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[json]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[typescriptreact]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[javascript]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "editor.defaultFormatter": "biomejs.biome", + "editor.codeActionsOnSave": { + "quickfix.biome": "explicit", + "source.organizeImports.biome": "explicit" + }, + "editor.formatOnPaste": true, + "editor.formatOnSave": true, + "biome.rename": true, + "biome_lsp.trace.server": "messages" + } + \ No newline at end of file diff --git a/biome.json b/biome.json new file mode 100644 index 000000000..d94ddee79 --- /dev/null +++ b/biome.json @@ -0,0 +1,234 @@ +{ + "$schema": "./node_modules/@biomejs/biome/configuration_schema.json", + "vcs": { + "clientKind": "git", + "enabled": true, + "useIgnoreFile": true, + "defaultBranch": "master" + }, + "formatter": { + "enabled": true, + "indentStyle": "space", + "indentWidth": 2, + "lineEnding": "lf", + "ignore": [ + "apps/**/*.min.js", + "apps/**/*.min.css", + "apps/**/*-lock.yaml", + "**/*.lock.json", + "**/build/**" + ] + }, + "organizeImports": { "enabled": true }, + "linter": { + "enabled": true, + "rules": { + "recommended": false, + "complexity": { + "noBannedTypes": "warn", + "noExtraBooleanCast": "error", + "noMultipleSpacesInRegularExpressionLiterals": "error", + "noUselessCatch": "error", + "noUselessConstructor": "error", + "noUselessLabel": "error", + "noUselessLoneBlockStatements": "error", + "noUselessRename": "error", + "noUselessTernary": "error", + "noVoid": "error", + "noWith": "error", + "useLiteralKeys": "error", + "useRegexLiterals": "error" + }, + "correctness": { + "noConstAssign": "error", + "noConstantCondition": "warn", + "noConstructorReturn": "error", + "noEmptyCharacterClassInRegex": "error", + "noEmptyPattern": "error", + "noGlobalObjectCalls": "error", + "noInnerDeclarations": "error", + "noInvalidConstructorSuper": "error", + "noInvalidUseBeforeDeclaration": "error", + "noNewSymbol": "error", + "noNonoctalDecimalEscape": "error", + "noPrecisionLoss": "error", + "noSelfAssign": "error", + "noSetterReturn": "error", + "noSwitchDeclarations": "error", + "noUndeclaredVariables": "error", + "noUnreachable": "error", + "noUnreachableSuper": "error", + "noUnsafeFinally": "error", + "noUnsafeOptionalChaining": "error", + "noUnusedImports": "off", + "noUnusedLabels": "error", + "noUnusedPrivateClassMembers": "off", + "noUnusedVariables": "error", + "useExhaustiveDependencies": "warn", + "useIsNan": "error", + "useValidForDirection": "error", + "useYield": "error" + }, + "security": { "noGlobalEval": "error" }, + "style": { + "noArguments": "error", + "noCommaOperator": "error", + "noDefaultExport": "off", + "noNegationElse": "off", + "noParameterAssign": "error", + "noRestrictedGlobals": { + "level": "error", + "options": { + "deniedGlobals": [ + "isFinite", + "isNaN", + "addEventListener", + "blur", + "close", + "closed", + "confirm", + "defaultStatus", + "defaultstatus", + "event", + "external", + "find", + "focus", + "frameElement", + "frames", + "history", + "innerHeight", + "innerWidth", + "length", + "location", + "locationbar", + "menubar", + "moveBy", + "moveTo", + "name", + "onblur", + "onerror", + "onfocus", + "onload", + "onresize", + "onunload", + "open", + "opener", + "opera", + "outerHeight", + "outerWidth", + "pageXOffset", + "pageYOffset", + "parent", + "print", + "removeEventListener", + "resizeBy", + "resizeTo", + "screen", + "screenLeft", + "screenTop", + "screenX", + "screenY", + "scroll", + "scrollbars", + "scrollBy", + "scrollTo", + "scrollX", + "scrollY", + "self", + "status", + "statusbar", + "stop", + "toolbar", + "top" + ] + } + }, + "noVar": "error", + "useBlockStatements": "error", + "useCollapsedElseIf": "error", + "useConst": "error", + "useDefaultParameterLast": "error", + "useExponentiationOperator": "error", + "useImportType": "off", + "useNumericLiterals": "error", + "useShorthandAssign": "error", + "useSingleVarDeclarator": "error", + "useTemplate": "error" + }, + "suspicious": { + "noAsyncPromiseExecutor": "error", + "noCatchAssign": "error", + "noClassAssign": "error", + "noCompareNegZero": "error", + "noControlCharactersInRegex": "error", + "noDebugger": "error", + "noDoubleEquals": "error", + "noDuplicateCase": "error", + "noDuplicateClassMembers": "error", + "noDuplicateObjectKeys": "error", + "noDuplicateParameters": "error", + "noEmptyBlockStatements": "error", + "noExplicitAny": "warn", + "noFallthroughSwitchClause": "error", + "noFunctionAssign": "error", + "noGlobalAssign": "error", + "noImportAssign": "error", + "noLabelVar": "error", + "noMisleadingCharacterClass": "error", + "noPrototypeBuiltins": "error", + "noRedeclare": "error", + "noSelfCompare": "error", + "noShadowRestrictedNames": "error", + "noUnsafeNegation": "error", + "useAwait": "off", + "useDefaultSwitchClauseLast": "error", + "useGetterReturn": "error", + "useValidTypeof": "error" + } + } + }, + "javascript": { + "formatter": { + "trailingComma": "all", + "semicolons": "always", + "enabled": true, + "lineWidth": 120, + "quoteStyle": "single" + }, + "globals": ["Atomics", "SharedArrayBuffer"] + }, + "json": { + "parser": { "allowComments": true }, + "formatter": { "enabled": true, "lineWidth": 120 } + }, + "overrides": [ + { + "include": ["**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx"], + "linter": { + "rules": { + "correctness": { + "noConstAssign": "off", + "noGlobalObjectCalls": "off", + "noInvalidConstructorSuper": "off", + "noNewSymbol": "off", + "noSetterReturn": "off", + "noUndeclaredVariables": "off", + "noUnreachable": "off", + "noUnreachableSuper": "off" + }, + "suspicious": { + "noDuplicateClassMembers": "off", + "noDuplicateObjectKeys": "off", + "noDuplicateParameters": "off", + "noFunctionAssign": "off", + "noImportAssign": "off", + "noRedeclare": "off", + "noUnsafeNegation": "off", + "useGetterReturn": "off", + "useValidTypeof": "off" + } + } + } + } + ] +} diff --git a/package.json b/package.json index b7b03c44a..d8c8b6dd9 100644 --- a/package.json +++ b/package.json @@ -1,37 +1,43 @@ { "name": "bigcapital-monorepo", "private": true, + "workspaces": [ + "packages/*" + ], "scripts": { - "dev": "lerna run dev", "build": "lerna run build", - "dev:webapp": "lerna run dev --scope \"@bigcapital/webapp\"", - "dev:website": "lerna run dev --scope \"@bigcapital/website\"", + "build:server": "lerna run build --scope \"@bigcapital/server\"", "build:webapp": "lerna run build --scope \"@bigcapital/webapp\"", + "dev": "lerna run dev", "dev:server": "lerna run dev --scope \"@bigcapital/server\"", - "build:server": "lerna run build --scope \"@bigcapital/server\"", + "dev:webapp": "lerna run dev --scope \"@bigcapital/webapp\"", + "dev:website": "lerna run dev --scope \"@bigcapital/website\"", + "format": "lerna run format --scope \"@bigcapital/webapp\" --scope \"@bigcapital/server\" --scope \"@bigcapital/website\"", + "lint": "lerna run lint --scope \"@bigcapital/webapp\" --scope \"@bigcapital/server\" --scope \"@bigcapital/website\"", + "prepare": "husky install", "serve:server": "lerna run serve --scope \"@bigcapital/server\"", - "test:e2e": "playwright test", - "prepare": "husky install" + "test:e2e": "playwright test" + }, + "husky": { + "hooks": { + "commit-msg": "commitlint -E HUSKY_GIT_PARAMS" + } }, - "workspaces": [ - "packages/*" - ], "devDependencies": { + "@biomejs/biome": "^1.7.3", "@commitlint/cli": "^17.4.2", "@commitlint/config-conventional": "^17.4.2", "@commitlint/config-lerna-scopes": "^17.4.2", "@faker-js/faker": "^8.0.2", "@playwright/test": "^1.32.3", "husky": "^8.0.3", - "lerna": "^8.1.2", - "pnpm": "^9.0.5" + "lerna": "^8.1.2" }, "engines": { - "node": "16.x || 17.x || 18.x" + "bun": ">=1", + "node": "please-use-bun", + "pnpm": "please-use-bun", + "yarn": "please-use-bun" }, - "husky": { - "hooks": { - "commit-msg": "commitlint -E HUSKY_GIT_PARAMS" - } - } + "engineStrict": true } diff --git a/packages/server/.eslintrc.js b/packages/server/.eslintrc.js deleted file mode 100644 index 1ad00ade5..000000000 --- a/packages/server/.eslintrc.js +++ /dev/null @@ -1,34 +0,0 @@ -module.exports = { - env: { - browser: true, - es6: true, - }, - extends: ['airbnb-base', 'airbnb-typescript'], - parser: '@typescript-eslint/parser', - parserOptions: { - ecmaVersion: 2018, - sourceType: 'module', - project: 'tsconfig.json', - tsconfigRootDir: './', - }, - globals: { - Atomics: 'readonly', - SharedArrayBuffer: 'readonly', - }, - plugins: ['import'], - rules: { - 'import/no-unresolved': 'error', - 'import/prefer-default-export': 'off', - }, - settings: { - 'import/parsers': { - '@typescript-eslint/parser': ['.ts', '.tsx'], - }, - 'import/resolver': { - typescript: { - alwaysTryTypes: true, - project: 'tsconfig.json', - }, - }, - }, -}; diff --git a/packages/server/biome.json b/packages/server/biome.json new file mode 100644 index 000000000..4eca9fbf5 --- /dev/null +++ b/packages/server/biome.json @@ -0,0 +1,15 @@ +{ + "$schema": "../../node_modules/@biomejs/biome/configuration_schema.json", + "extends": ["../../biome.json"], + "linter": { + "enabled": true, + "rules": { + "style": { + "useImportType": "error" + }, + "correctness": { + "noUnusedImports": "error" + } + } + } +} diff --git a/packages/server/package.json b/packages/server/package.json index 45fea4b88..614dce89d 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -2,7 +2,12 @@ "name": "@bigcapital/server", "version": "0.10.2", "description": "", + "license": "ISC", + "author": "Ahmed Bouhuolia, ", "main": "src/server.ts", + "bin": { + "bigcapital": "./bin/bigcapital.js" + }, "scripts": { "inspect": "cross-env NODE_PATH=./src nodemon src/server.ts", "clear": "rimraf build", @@ -12,12 +17,8 @@ "build:commands": "cross-env NODE_ENV=production webpack --config scripts/webpack.cli.js", "build": "npm-run-all build:*", "serve": "node ./build/index.js", - "lint:fix": "eslint --fix ./**/*.ts" - }, - "author": "Ahmed Bouhuolia, ", - "license": "ISC", - "bin": { - "bigcapital": "./bin/bigcapital.js" + "format": "biome format --write ./", + "lint": "biome check --apply ./" }, "dependencies": { "@casl/ability": "^5.4.3", @@ -82,7 +83,6 @@ "mustache": "^3.0.3", "mysql": "^2.17.1", "mysql2": "^1.6.5", - "newrelic": "^11.15.0", "node-cache": "^4.2.1", "nodemailer": "^6.3.0", "nodemon": "^1.19.1", @@ -112,26 +112,17 @@ "yup": "^0.28.1" }, "devDependencies": { - "@types/lodash": "^4.14.158", + "@types/lodash": "^4.14.191", "@types/ramda": "^0.27.64", - "@typescript-eslint/eslint-plugin": "^5.50.0", - "@typescript-eslint/parser": "^5.50.0", "chai": "^4.2.0", "chai-http": "^4.3.0", "chai-things": "^0.2.0", "colorette": "^1.2.0", "commander": "^5.0.0", "cross-env": "^5.2.0", - "eslint": "^8.33.0", - "eslint-config-airbnb-base": "^15.0.0", - "eslint-config-airbnb-typescript": "^17.0.0", - "eslint-friendly-formatter": "^4.0.1", - "eslint-import-resolver-typescript": "^3.5.3", - "eslint-import-resolver-webpack": "^0.11.1", - "eslint-loader": "^2.2.1", - "eslint-plugin-import": "^2.27.5", "faker": "^4.1.0", "getopts": "^2.2.5", + "globals": "^15.0.0", "gulp-postcss": "^9.0.0", "gulp-rename": "^2.0.0", "knex-factory": "0.0.6", @@ -150,7 +141,7 @@ "ts-loader": "^9.4.2", "ts-node": "^9.0.0", "tsconfig-paths-webpack-plugin": "^4.0.0", - "typescript": "^3.9.7", + "typescript": "^3.9.10", "webpack": "^5.75.0", "webpack-cli": "^4.10.0", "webpack-merge": "^5.8.0", diff --git a/packages/server/project.json b/packages/server/project.json new file mode 100644 index 000000000..fe5fe0e78 --- /dev/null +++ b/packages/server/project.json @@ -0,0 +1,10 @@ +{ + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "name": "server", + "prefix": "server", + "projectType": "application", + "sourceRoot": "packages/server/src", + "tags": [], + "targets": { + } +} diff --git a/packages/server/src/data/ResourceFieldsKeys.ts b/packages/server/src/data/ResourceFieldsKeys.ts index 8504d3fdf..b2693255c 100644 --- a/packages/server/src/data/ResourceFieldsKeys.ts +++ b/packages/server/src/data/ResourceFieldsKeys.ts @@ -1,5 +1,3 @@ -/* eslint-disable quote-props */ - export default { // Expenses. expense: { @@ -17,7 +15,7 @@ export default { column: 'currency_code', }, reference_no: { - column: 'reference_no' + column: 'reference_no', }, description: { column: 'description', @@ -58,11 +56,11 @@ export default { columnType: 'date', }, active: { - column: 'active', + column: 'active', }, balance: { column: 'amount', - columnType: 'number' + columnType: 'number', }, currency: { column: 'currency_code', @@ -70,7 +68,7 @@ export default { normal: { column: 'account_type_id', relation: 'account_types.id', - relationColumn: 'account_types.normal' + relationColumn: 'account_types.normal', }, }, @@ -89,7 +87,7 @@ export default { column: 'purchasable', }, sell_price: { - column: 'sell_price' + column: 'sell_price', }, cost_price: { column: 'cost_price', @@ -132,7 +130,7 @@ export default { }, created_at: { column: 'created_at', - } + }, }, // Item category. @@ -201,5 +199,5 @@ export default { created_at: { column: 'created_at', }, - } + }, }; diff --git a/packages/server/src/database/seeds/core/20210810121909_seed_roles.ts b/packages/server/src/database/seeds/core/20210810121909_seed_roles.ts index 5bbca56b4..fa8f175f6 100644 --- a/packages/server/src/database/seeds/core/20210810121909_seed_roles.ts +++ b/packages/server/src/database/seeds/core/20210810121909_seed_roles.ts @@ -6,7 +6,6 @@ export default class SeedRolesAndPermissions extends TenantSeeder { * @param knex * @returns */ - // eslint-disable-next-line class-methods-use-this async up(knex) { return knex('roles').insert([ { diff --git a/packages/server/src/database/seeds/core/20210812121909_seed_roles_permissions.ts b/packages/server/src/database/seeds/core/20210812121909_seed_roles_permissions.ts index 041057387..5622ad3b8 100644 --- a/packages/server/src/database/seeds/core/20210812121909_seed_roles_permissions.ts +++ b/packages/server/src/database/seeds/core/20210812121909_seed_roles_permissions.ts @@ -6,7 +6,6 @@ export default class SeedRolesAndPermissions extends TenantSeeder { * @param knex * @returns */ - // eslint-disable-next-line class-methods-use-this async up(knex) { return knex('role_permissions').insert([ // Assign sale invoice permissions to staff role. diff --git a/packages/server/src/models/Account.ts b/packages/server/src/models/Account.ts index 7e0d8d6e4..d00a616d1 100644 --- a/packages/server/src/models/Account.ts +++ b/packages/server/src/models/Account.ts @@ -1,26 +1,18 @@ -/* eslint-disable global-require */ -import { mixin, Model } from 'objection'; -import { castArray } from 'lodash'; -import TenantModel from '@/models/TenantModel'; +import { ACCOUNT_TYPES, getAccountsSupportsMultiCurrency } from '@/data/AccountTypes'; +import AccountTypesUtils from '@/lib/AccountTypes'; +import DependencyGraph from '@/lib/DependencyGraph'; import { buildFilterQuery, buildSortColumnQuery } from '@/lib/ViewRolesBuilder'; +import TenantModel from '@/models/TenantModel'; +import { DEFAULT_VIEWS } from '@/services/Accounts/constants'; +import { castArray } from 'lodash'; +import { Model, mixin } from 'objection'; import { flatToNestedArray } from 'utils'; -import DependencyGraph from '@/lib/DependencyGraph'; -import AccountTypesUtils from '@/lib/AccountTypes'; import AccountSettings from './Account.Settings'; -import ModelSettings from './ModelSetting'; -import { - ACCOUNT_TYPES, - getAccountsSupportsMultiCurrency, -} from '@/data/AccountTypes'; import CustomViewBaseModel from './CustomViewBaseModel'; -import { DEFAULT_VIEWS } from '@/services/Accounts/constants'; import ModelSearchable from './ModelSearchable'; +import ModelSettings from './ModelSetting'; -export default class Account extends mixin(TenantModel, [ - ModelSettings, - CustomViewBaseModel, - ModelSearchable, -]) { +export default class Account extends mixin(TenantModel, [ModelSettings, CustomViewBaseModel, ModelSearchable]) { /** * Table name. */ @@ -141,9 +133,9 @@ export default class Account extends mixin(TenantModel, [ * Filter by root type. */ filterByRootType(query, rootType) { - const filterTypes = ACCOUNT_TYPES.filter( - (accountType) => accountType.rootType === rootType - ).map((accountType) => accountType.key); + const filterTypes = ACCOUNT_TYPES.filter((accountType) => accountType.rootType === rootType).map( + (accountType) => accountType.key, + ); query.whereIn('account_type', filterTypes); }, @@ -152,9 +144,9 @@ export default class Account extends mixin(TenantModel, [ * Filter by account normal */ filterByAccountNormal(query, accountNormal) { - const filterTypes = ACCOUNT_TYPES.filter( - (accountType) => accountType.normal === accountNormal - ).map((accountType) => accountType.key); + const filterTypes = ACCOUNT_TYPES.filter((accountType) => accountType.normal === accountNormal).map( + (accountType) => accountType.key, + ); query.whereIn('account_type', filterTypes); }, @@ -177,10 +169,7 @@ export default class Account extends mixin(TenantModel, [ const accountsTypes = getAccountsSupportsMultiCurrency(); const accountsTypesKeys = accountsTypes.map((type) => type.key); - query - .whereIn('accountType', accountsTypesKeys) - .where('seededAt', null) - .first(); + query.whereIn('accountType', accountsTypesKeys).where('seededAt', null).first(); }, }; } @@ -349,10 +338,7 @@ export default class Account extends mixin(TenantModel, [ * @return {boolean} */ isParentType(parentType) { - return AccountTypesUtils.isParentTypeEqualsKey( - this.accountType, - parentType - ); + return AccountTypesUtils.isParentTypeEqualsKey(this.accountType, parentType); } /** diff --git a/packages/server/src/models/CashflowAccount.ts b/packages/server/src/models/CashflowAccount.ts index 132832bca..8955c55dc 100644 --- a/packages/server/src/models/CashflowAccount.ts +++ b/packages/server/src/models/CashflowAccount.ts @@ -1,19 +1,14 @@ -/* eslint-disable global-require */ -import { mixin, Model } from 'objection'; +import AccountTypesUtils from '@/lib/AccountTypes'; +import { DEFAULT_VIEWS } from '@/services/Accounts/constants'; import { castArray } from 'lodash'; import TenantModel from 'models/TenantModel'; -import AccountTypesUtils from '@/lib/AccountTypes'; +import { Model, mixin } from 'objection'; import CashflowAccountSettings from './CashflowAccount.Settings'; -import ModelSettings from './ModelSetting'; import CustomViewBaseModel from './CustomViewBaseModel'; -import { DEFAULT_VIEWS } from '@/services/Accounts/constants'; import ModelSearchable from './ModelSearchable'; +import ModelSettings from './ModelSetting'; -export default class CashflowAccount extends mixin(TenantModel, [ - ModelSettings, - CustomViewBaseModel, - ModelSearchable, -]) { +export default class CashflowAccount extends mixin(TenantModel, [ModelSettings, CustomViewBaseModel, ModelSearchable]) { /** * Table name. */ @@ -100,10 +95,7 @@ export default class CashflowAccount extends mixin(TenantModel, [ * @return {boolean} */ isParentType(parentType) { - return AccountTypesUtils.isParentTypeEqualsKey( - this.accountType, - parentType - ); + return AccountTypesUtils.isParentTypeEqualsKey(this.accountType, parentType); } /** diff --git a/packages/server/src/models/CashflowTransaction.ts b/packages/server/src/models/CashflowTransaction.ts index 3cc2baba7..0dcd46040 100644 --- a/packages/server/src/models/CashflowTransaction.ts +++ b/packages/server/src/models/CashflowTransaction.ts @@ -1,13 +1,9 @@ -/* eslint-disable global-require */ -import { Model } from 'objection'; -import TenantModel from 'models/TenantModel'; -import { - getCashflowAccountTransactionsTypes, - getCashflowTransactionType, -} from '@/services/Cashflow/utils'; -import AccountTransaction from './AccountTransaction'; import { CASHFLOW_DIRECTION } from '@/services/Cashflow/constants'; +import { getCashflowAccountTransactionsTypes, getCashflowTransactionType } from '@/services/Cashflow/utils'; import { getTransactionTypeLabel } from '@/utils/transactions-types'; +import TenantModel from 'models/TenantModel'; +import { Model } from 'objection'; +import AccountTransaction from './AccountTransaction'; export default class CashflowTransaction extends TenantModel { transactionType: string; amount: number; @@ -33,14 +29,7 @@ export default class CashflowTransaction extends TenantModel { * Virtual attributes. */ static get virtualAttributes() { - return [ - 'localAmount', - 'transactionTypeFormatted', - 'isPublished', - 'typeMeta', - 'isCashCredit', - 'isCashDebit', - ]; + return ['localAmount', 'transactionTypeFormatted', 'isPublished', 'typeMeta', 'isCashCredit', 'isCashDebit']; } /** diff --git a/packages/server/src/models/CashflowTransactionLine.ts b/packages/server/src/models/CashflowTransactionLine.ts index 4be809cc8..735eef3aa 100644 --- a/packages/server/src/models/CashflowTransactionLine.ts +++ b/packages/server/src/models/CashflowTransactionLine.ts @@ -1,6 +1,5 @@ -/* eslint-disable global-require */ -import { Model } from 'objection'; import TenantModel from 'models/TenantModel'; +import { Model } from 'objection'; export default class CashflowTransactionLine extends TenantModel { /** diff --git a/packages/server/src/models/UncategorizedCashflowTransaction.ts b/packages/server/src/models/UncategorizedCashflowTransaction.ts index 08c0975d4..577adc511 100644 --- a/packages/server/src/models/UncategorizedCashflowTransaction.ts +++ b/packages/server/src/models/UncategorizedCashflowTransaction.ts @@ -1,15 +1,11 @@ -/* eslint-disable global-require */ -import * as R from 'ramda'; -import { Model, ModelOptions, QueryContext, mixin } from 'objection'; import TenantModel from 'models/TenantModel'; -import ModelSettings from './ModelSetting'; +import { Model, ModelOptions, QueryContext, mixin } from 'objection'; +import * as R from 'ramda'; import Account from './Account'; +import ModelSettings from './ModelSetting'; import UncategorizedCashflowTransactionMeta from './UncategorizedCashflowTransaction.meta'; -export default class UncategorizedCashflowTransaction extends mixin( - TenantModel, - [ModelSettings] -) { +export default class UncategorizedCashflowTransaction extends mixin(TenantModel, [ModelSettings]) { id!: number; amount!: number; categorized!: boolean; @@ -33,12 +29,7 @@ export default class UncategorizedCashflowTransaction extends mixin( * Virtual attributes. */ static get virtualAttributes() { - return [ - 'withdrawal', - 'deposit', - 'isDepositTransaction', - 'isWithdrawalTransaction', - ]; + return ['withdrawal', 'deposit', 'isDepositTransaction', 'isWithdrawalTransaction']; } static get meta() { @@ -102,10 +93,7 @@ export default class UncategorizedCashflowTransaction extends mixin( * @param {QueryContext} queryContext - The query context for the transaction. * @param {boolean} increment - Indicates whether to increment or decrement the count. */ - private async updateUncategorizedTransactionCount( - queryContext: QueryContext, - increment: boolean - ) { + private async updateUncategorizedTransactionCount(queryContext: QueryContext, increment: boolean) { const operation = increment ? 'increment' : 'decrement'; const amount = increment ? 1 : -1; @@ -128,10 +116,7 @@ export default class UncategorizedCashflowTransaction extends mixin( * @param {ModelOptions} opt * @param {QueryContext} queryContext */ - public async $afterUpdate( - opt: ModelOptions, - queryContext: QueryContext - ): Promise { + public async $afterUpdate(opt: ModelOptions, queryContext: QueryContext): Promise { await super.$afterUpdate(opt, queryContext); if (this.id && this.categorized) { diff --git a/packages/server/src/services/Banking/Plaid/PlaidUpdateTransactions.ts b/packages/server/src/services/Banking/Plaid/PlaidUpdateTransactions.ts index c740e4705..87b4d8fb1 100644 --- a/packages/server/src/services/Banking/Plaid/PlaidUpdateTransactions.ts +++ b/packages/server/src/services/Banking/Plaid/PlaidUpdateTransactions.ts @@ -92,7 +92,6 @@ export class PlaidUpdateTransactions { const batchSize = 100; try { // Iterate through each page of new transaction updates for item - /* eslint-disable no-await-in-loop */ while (hasMore) { const request = { access_token: plaidAccessToken, diff --git a/packages/server/src/services/Currencies/constants.ts b/packages/server/src/services/Currencies/constants.ts index 702150303..d20f8703a 100644 --- a/packages/server/src/services/Currencies/constants.ts +++ b/packages/server/src/services/Currencies/constants.ts @@ -1,11 +1 @@ -// eslint-disable-next-line import/prefer-default-export -export const InitialCurrencies = [ - 'USD', - 'CAD', - 'EUR', - 'LYD', - 'GBP', - 'CNY', - 'AUD', - 'INR', -]; +export const InitialCurrencies = ['USD', 'CAD', 'EUR', 'LYD', 'GBP', 'CNY', 'AUD', 'INR']; diff --git a/packages/server/src/services/FinancialStatements/BalanceSheet/BalanceSheetSchema.ts b/packages/server/src/services/FinancialStatements/BalanceSheet/BalanceSheetSchema.ts index 5ef897506..f51d1e8ea 100644 --- a/packages/server/src/services/FinancialStatements/BalanceSheet/BalanceSheetSchema.ts +++ b/packages/server/src/services/FinancialStatements/BalanceSheet/BalanceSheetSchema.ts @@ -1,10 +1,6 @@ -/* eslint-disable import/prefer-default-export */ -import * as R from 'ramda'; -import { - BALANCE_SHEET_SCHEMA_NODE_ID, - BALANCE_SHEET_SCHEMA_NODE_TYPE, -} from '@/interfaces'; import { ACCOUNT_TYPE } from '@/data/AccountTypes'; +import { BALANCE_SHEET_SCHEMA_NODE_ID, BALANCE_SHEET_SCHEMA_NODE_TYPE } from '@/interfaces'; +import * as R from 'ramda'; import { FinancialSchema } from '../FinancialSchema'; export const BalanceSheetSchema = (Base) => diff --git a/packages/server/src/services/ItemCategories/constants.ts b/packages/server/src/services/ItemCategories/constants.ts index c92830805..cb0fc1736 100644 --- a/packages/server/src/services/ItemCategories/constants.ts +++ b/packages/server/src/services/ItemCategories/constants.ts @@ -1,4 +1,3 @@ -// eslint-disable-next-line import/prefer-default-export export const ERRORS = { ITEM_CATEGORIES_NOT_FOUND: 'ITEM_CATEGORIES_NOT_FOUND', CATEGORY_NAME_EXISTS: 'CATEGORY_NAME_EXISTS', @@ -19,17 +18,14 @@ export const ItemCategoriesSampleData = [ }, { Name: 'Crist, Mraz and Lueilwitz', - Description: - 'Dolores veniam deserunt sed commodi error quia veritatis non.', + Description: 'Dolores veniam deserunt sed commodi error quia veritatis non.', }, { Name: 'Gutmann and Sons', - Description: - 'Ratione aperiam voluptas rem adipisci assumenda eos neque veritatis tempora.', + Description: 'Ratione aperiam voluptas rem adipisci assumenda eos neque veritatis tempora.', }, { Name: 'Reichel - Raynor', - Description: - 'Necessitatibus repellendus placeat possimus dolores excepturi ut.', + Description: 'Necessitatibus repellendus placeat possimus dolores excepturi ut.', }, ]; diff --git a/packages/server/src/services/Subscription/utils.ts b/packages/server/src/services/Subscription/utils.ts index 56dc7e4b4..9fed827e5 100644 --- a/packages/server/src/services/Subscription/utils.ts +++ b/packages/server/src/services/Subscription/utils.ts @@ -6,24 +6,17 @@ import { lemonSqueezySetup } from '@lemonsqueezy/lemonsqueezy.js'; * if there's an error setting up the SDK. */ export function configureLemonSqueezy() { - const requiredVars = [ - 'LEMONSQUEEZY_API_KEY', - 'LEMONSQUEEZY_STORE_ID', - 'LEMONSQUEEZY_WEBHOOK_SECRET', - ]; + const requiredVars = ['LEMONSQUEEZY_API_KEY', 'LEMONSQUEEZY_STORE_ID', 'LEMONSQUEEZY_WEBHOOK_SECRET']; const missingVars = requiredVars.filter((varName) => !process.env[varName]); if (missingVars.length > 0) { throw new Error( - `Missing required LEMONSQUEEZY env variables: ${missingVars.join( - ', ' - )}. Please, set them in your .env file.` + `Missing required LEMONSQUEEZY env variables: ${missingVars.join(', ')}. Please, set them in your .env file.`, ); } lemonSqueezySetup({ apiKey: process.env.LEMONSQUEEZY_API_KEY, onError: (error) => { - // eslint-disable-next-line no-console -- allow logging console.error(error); throw new Error(`Lemon Squeezy API error: ${error.message}`); }, @@ -78,19 +71,11 @@ export function webhookHasData(obj: unknown): obj is { id: string; }; } { - return ( - isObject(obj) && - 'data' in obj && - isObject(obj.data) && - 'attributes' in obj.data - ); + return isObject(obj) && 'data' in obj && isObject(obj.data) && 'attributes' in obj.data; } export function createHmacSignature(secretKey, body) { - return require('crypto') - .createHmac('sha256', secretKey) - .update(body) - .digest('hex'); + return require('crypto').createHmac('sha256', secretKey).update(body).digest('hex'); } export function compareSignatures(signature, comparison_signature) { diff --git a/packages/server/src/services/Warehouses/Subscribers/Activate/index.ts b/packages/server/src/services/Warehouses/Subscribers/Activate/index.ts index 16febf17c..98306ee55 100644 --- a/packages/server/src/services/Warehouses/Subscribers/Activate/index.ts +++ b/packages/server/src/services/Warehouses/Subscribers/Activate/index.ts @@ -1,4 +1,3 @@ -/* eslint-disable import/extensions */ export * from './BillWarehousesActivateSubscriber'; export * from './CreditNoteWarehousesActivateSubscriber'; export * from './EstimateWarehousesActivateSubscriber'; diff --git a/packages/server/tests/models/Item.test.js b/packages/server/tests/models/Item.test.js index 8ce26771c..c661d96cc 100644 --- a/packages/server/tests/models/Item.test.js +++ b/packages/server/tests/models/Item.test.js @@ -1,13 +1,8 @@ -import { create, expect } from '~/testInit'; import Item from 'models/Item'; -// eslint-disable-next-line no-unused-vars -import itemCategory from 'models/ItemCategory'; -import { - tenantWebsite, - tenantFactory, - loginRes -} from '~/dbInit'; +import { create, expect } from '~/testInit'; +import itemCategory from 'models/ItemCategory'; +import { loginRes, tenantFactory, tenantWebsite } from '~/dbInit'; describe('Model: Item', () => { it('Should item model belongs to the associated category model.', async () => { diff --git a/packages/webapp/.env.example b/packages/webapp/.env.example index e7efa5766..ce069f0ed 100644 --- a/packages/webapp/.env.example +++ b/packages/webapp/.env.example @@ -1,3 +1,2 @@ REACT_APP_VERSION=$npm_package_version TSC_COMPILE_ON_ERROR=true -ESLINT_NO_DEV_ERRORS=true \ No newline at end of file diff --git a/packages/webapp/biome.json b/packages/webapp/biome.json new file mode 100644 index 000000000..a657befab --- /dev/null +++ b/packages/webapp/biome.json @@ -0,0 +1,15 @@ +{ + "$schema": "../../node_modules/@biomejs/biome/configuration_schema.json", + "extends": ["../../biome.json"], + "organizeImports": { + "enabled": false + }, + "linter": { + "enabled": true, + "rules": { + "correctness": { + "noUnusedImports": "off" + } + } + } +} diff --git a/packages/webapp/package.json b/packages/webapp/package.json index 5d8e33da8..d06767340 100644 --- a/packages/webapp/package.json +++ b/packages/webapp/package.json @@ -2,6 +2,21 @@ "name": "@bigcapital/webapp", "version": "0.10.2", "private": true, + "scripts": { + "build": "craco build", + "dev": "PORT=4000 craco start", + "format": "biome format --write ./", + "lint": "biome check --apply ./", + "storybook": "start-storybook -p 6006", + "test": "node scripts/test.js" + }, + "browserslist": { + "production": [">0.2%", "not dead", "not op_mini all"], + "development": ["last 1 chrome version", "last 1 firefox version", "last 1 safari version"] + }, + "resolutions": { + "react-error-overlay": "6.0.9" + }, "dependencies": { "@blueprintjs-formik/core": "^0.3.6", "@blueprintjs-formik/datetime": "^0.3.7", @@ -41,8 +56,6 @@ "@types/socket.io-client": "^3.0.0", "@types/styled-components": "^5.1.25", "@types/yup": "^0.29.13", - "@typescript-eslint/eslint-plugin": "^2.10.0", - "@typescript-eslint/parser": "^2.10.0", "@welldone-software/why-did-you-render": "^6.0.0-rc.1", "accounting": "^0.4.1", "axios": "^1.6.0", @@ -53,7 +66,6 @@ "deepdash": "^5.3.9", "dependency-graph": "^0.11.0", "dotenv-webpack": "^8.0.1", - "eslint": "^8.33.0", "fast-deep-equal": "^3.1.3", "flat": "^5.0.2", "formik": "^2.2.5", @@ -120,32 +132,5 @@ "typescript": "^4.8.3", "yup": "^0.28.1" }, - "scripts": { - "dev": "PORT=4000 craco start", - "build": "craco build", - "test": "node scripts/test.js", - "storybook": "start-storybook -p 6006" - }, - "proxy": "http://localhost:3000/", - "resolutions": { - "react-error-overlay": "6.0.9" - }, - "eslintConfig": { - "extends": [ - "react-app", - "react-app/jest" - ] - }, - "browserslist": { - "production": [ - ">0.2%", - "not dead", - "not op_mini all" - ], - "development": [ - "last 1 chrome version", - "last 1 firefox version", - "last 1 safari version" - ] - } + "proxy": "http://localhost:3000/" } diff --git a/packages/webapp/src/containers/Entries/withExRateItemEntriesPriceRecalc.tsx b/packages/webapp/src/containers/Entries/withExRateItemEntriesPriceRecalc.tsx index a1fd7af39..eae5972af 100644 --- a/packages/webapp/src/containers/Entries/withExRateItemEntriesPriceRecalc.tsx +++ b/packages/webapp/src/containers/Entries/withExRateItemEntriesPriceRecalc.tsx @@ -1,32 +1,28 @@ +import { useCurrentOrganization } from '@/hooks/state'; // @ts-nocheck import { useFormikContext } from 'formik'; -import { useUpdateEntriesOnExchangeRateChange } from './useUpdateEntriesOnExchangeRateChange'; -import { useAutoExRateContext } from './AutoExchangeProvider'; import { useCallback, useEffect } from 'react'; -import { useCurrentOrganization } from '@/hooks/state'; +import { useAutoExRateContext } from './AutoExchangeProvider'; +import { useUpdateEntriesOnExchangeRateChange } from './useUpdateEntriesOnExchangeRateChange'; /** * Re-calculate the item entries prices based on the old exchange rate. * @param {InvoiceExchangeRateInputFieldRoot} Component * @returns {JSX.Element} */ -export const withExchangeRateItemEntriesPriceRecalc = - (Component) => (props) => { - const { setFieldValue } = useFormikContext(); - const updateChangeExRate = useUpdateEntriesOnExchangeRateChange(); +export const withExchangeRateItemEntriesPriceRecalc = (Component) => (props) => { + const { setFieldValue } = useFormikContext(); + const updateChangeExRate = useUpdateEntriesOnExchangeRateChange(); - return ( - { - setFieldValue( - 'entries', - updateChangeExRate(oldExchangeRate, exchangeRate), - ); - }} - {...props} - /> - ); - }; + return ( + { + setFieldValue('entries', updateChangeExRate(oldExchangeRate, exchangeRate)); + }} + {...props} + /> + ); +}; /** * Injects the loading props to the exchange rate field. @@ -67,22 +63,13 @@ export const useCustomerUpdateExRate = () => { // If the customer's currency code equals the same base currency. if (customer.currency_code === currentCompany.base_currency) { setFieldValue('exchange_rate', DEFAULT_EX_RATE + ''); - setFieldValue( - 'entries', - updateEntriesOnExChange(values.exchange_rate, DEFAULT_EX_RATE), - ); + setFieldValue('entries', updateEntriesOnExChange(values.exchange_rate, DEFAULT_EX_RATE)); } else { // Sets the currency code to fetch exchange rate of the given currency code. setAutoExRateCurrency(customer?.currency_code); } }, - [ - currentCompany.base_currency, - setAutoExRateCurrency, - setFieldValue, - updateEntriesOnExChange, - values.exchange_rate, - ], + [currentCompany.base_currency, setAutoExRateCurrency, setFieldValue, updateEntriesOnExChange, values.exchange_rate], ); }; @@ -98,8 +85,7 @@ interface UseSyncExRateToFormProps { */ export const useSyncExRateToForm = ({ onSynced }: UseSyncExRateToFormProps) => { const { setFieldValue, values } = useFormikContext(); - const { autoExRateCurrency, autoExchangeRate, isAutoExchangeRateLoading } = - useAutoExRateContext(); + const { autoExRateCurrency, autoExchangeRate, isAutoExchangeRateLoading } = useAutoExRateContext(); const updateEntriesOnExChange = useUpdateEntriesOnExchangeRateChange(); // Sync the fetched real-time exchanage rate to the form. @@ -110,18 +96,10 @@ export const useSyncExRateToForm = ({ onSynced }: UseSyncExRateToFormProps) => { const exchangeRate = autoExchangeRate?.exchange_rate || 1; setFieldValue('exchange_rate', exchangeRate + ''); - setFieldValue( - 'entries', - updateEntriesOnExChange(values.exchange_rate, exchangeRate), - ); + setFieldValue('entries', updateEntriesOnExChange(values.exchange_rate, exchangeRate)); onSynced?.(); } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [ - autoExchangeRate?.exchange_rate, - autoExRateCurrency, - isAutoExchangeRateLoading, - ]); + }, [autoExchangeRate?.exchange_rate, autoExRateCurrency, isAutoExchangeRateLoading]); return null; }; diff --git a/packages/webapp/src/hooks/utils/useWatch.tsx b/packages/webapp/src/hooks/utils/useWatch.tsx index 5acedcdb1..15ce195c1 100644 --- a/packages/webapp/src/hooks/utils/useWatch.tsx +++ b/packages/webapp/src/hooks/utils/useWatch.tsx @@ -10,13 +10,11 @@ export function useWatch(callback, argument) { return; } callback(argument); - // eslint-disable-next-line react-hooks/exhaustive-deps }, [argument]); } export function useWatchImmediate(callback, argument) { useEffect(() => { callback(argument); - // eslint-disable-next-line react-hooks/exhaustive-deps }, [argument]); } diff --git a/packages/website/.eslintrc.json b/packages/website/.eslintrc.json deleted file mode 100644 index bffb357a7..000000000 --- a/packages/website/.eslintrc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "next/core-web-vitals" -} diff --git a/packages/website/package.json b/packages/website/package.json index 443853312..4b4680336 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -3,10 +3,10 @@ "version": "0.1.0", "private": true, "scripts": { - "dev": "next dev", "build": "next build", - "start": "next start", - "lint": "next lint" + "dev": "next dev", + "lint": "next lint", + "start": "next start" }, "dependencies": { "@material-tailwind/react": "^2.1.9", @@ -26,8 +26,6 @@ "@types/react": "^18", "@types/react-dom": "^18", "@types/react-wow": "^1.0.6", - "eslint": "^8", - "eslint-config-next": "14.2.2", "postcss": "^8", "tailwindcss": "^3.4.1", "typescript": "^5"