diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 2bc00912d2..0000000000 --- a/.eslintignore +++ /dev/null @@ -1,13 +0,0 @@ -node_modules -public -dist -packages/server/builder -packages/server/coverage -packages/worker/coverage -packages/backend-core/coverage -packages/server/client -packages/server/coverage -packages/builder/.routify -packages/sdk/sdk -**/*.ivm.bundle.js -packages/server/build/oldClientVersions/**/** diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 4e6a169dae..0000000000 --- a/.eslintrc.json +++ /dev/null @@ -1,129 +0,0 @@ -{ - "root": true, - "env": { - "browser": true, - "es6": true, - "jest": true, - "node": true - }, - "parser": "@babel/eslint-parser", - "parserOptions": { - "ecmaVersion": 2019, - "sourceType": "module", - "allowImportExportEverywhere": true - }, - "ignorePatterns": [ - "node_modules", - "dist", - "public", - "*.spec.js", - "bundle.js" - ], - "extends": ["eslint:recommended"], - "plugins": ["import", "eslint-plugin-local-rules"], - "overrides": [ - { - "files": ["**/*.svelte"], - "extends": "plugin:svelte/recommended", - "parser": "svelte-eslint-parser", - "parserOptions": { - "parser": "@typescript-eslint/parser", - "ecmaVersion": 2019, - "allowImportExportEverywhere": true - } - }, - { - "files": ["**/*.ts"], - "parser": "@typescript-eslint/parser", - "plugins": ["@typescript-eslint"], - "extends": ["eslint:recommended"], - "globals": { - "NodeJS": true - }, - "rules": { - "no-unused-vars": "off", - "local-rules/no-barrel-imports": "error", - "local-rules/no-budibase-imports": "error", - "local-rules/no-console-error": "error", - "@typescript-eslint/no-unused-vars": [ - "error", - { - "varsIgnorePattern": "^_", - "argsIgnorePattern": "^_", - "destructuredArrayIgnorePattern": "^_", - "ignoreRestSiblings": true - } - ], - "no-redeclare": "off", - "@typescript-eslint/no-redeclare": "error", - // have to turn this off to allow function overloading in typescript - "no-dupe-class-members": "off" - } - }, - { - "files": ["**/*.spec.ts"], - "parser": "@typescript-eslint/parser", - "plugins": ["jest", "@typescript-eslint"], - "extends": ["eslint:recommended", "plugin:jest/recommended"], - "env": { - "jest/globals": true - }, - "globals": { - "NodeJS": true - }, - "rules": { - "no-unused-vars": "off", - "@typescript-eslint/no-unused-vars": [ - "error", - { - "varsIgnorePattern": "^_", - "argsIgnorePattern": "^_", - "destructuredArrayIgnorePattern": "^_", - "ignoreRestSiblings": true - } - ], - "local-rules/no-test-com": "error", - "local-rules/email-domain-example-com": "error", - "no-console": "warn", - // We have a lot of tests that don't have assertions, they use our test - // API client that does the assertions for them - "jest/expect-expect": "off", - // We do this in some tests where the behaviour of internal tables - // differs to external, but the API is broadly the same - "jest/no-conditional-expect": "off", - // have to turn this off to allow function overloading in typescript - "no-dupe-class-members": "off", - "no-redeclare": "off" - } - }, - { - "files": [ - "packages/builder/**/*", - "packages/client/**/*", - "packages/frontend-core/**/*" - ], - "rules": { - "no-console": ["error", { "allow": ["warn", "error", "debug"] }] - } - } - ], - "rules": { - "no-self-assign": "off", - "no-unused-vars": [ - "error", - { - "varsIgnorePattern": "^_", - "argsIgnorePattern": "^_", - "destructuredArrayIgnorePattern": "^_", - "ignoreRestSiblings": true - } - ], - "import/no-relative-packages": "error", - "import/export": "error", - "import/no-duplicates": "error", - "import/newline-after-import": "error" - }, - "globals": { - "GeolocationPositionError": true - } -} diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000000..c497974612 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,197 @@ +import globals from "globals" +import babelParser from "@babel/eslint-parser" +import svelteParser from "svelte-eslint-parser" +import tsParser from "@typescript-eslint/parser" + +import eslintPluginJest from "eslint-plugin-jest" +import eslintPluginSvelte from "eslint-plugin-svelte" +import eslintPluginLocalRules from "eslint-plugin-local-rules" +import eslintPluginVitest from "@vitest/eslint-plugin" + +import eslint from "@eslint/js" +import tseslint from "typescript-eslint" + +export default [ + eslint.configs.recommended, + { + ignores: [ + "**/node_modules", + "**/dist", + "**/public", + "**/bundle.js", + "**/coverage", + "packages/server/builder", + "packages/server/client", + "packages/builder/.routify", + "packages/sdk/sdk", + "**/*.ivm.bundle.js", + "packages/server/build/oldClientVersions/**/**/*", + ], + }, + { + plugins: { + "local-rules": eslintPluginLocalRules, + }, + + languageOptions: { + globals: { + ...globals.browser, + ...globals.jest, + ...globals.node, + GeolocationPositionError: true, + }, + + parser: babelParser, + ecmaVersion: 2019, + sourceType: "module", + + parserOptions: { + allowImportExportEverywhere: true, + }, + }, + + rules: { + "no-self-compare": "error", + "no-template-curly-in-string": "error", + "no-unmodified-loop-condition": "error", + "no-unreachable-loop": "error", + "no-implied-eval": "error", + "no-extend-native": "error", + "no-labels": "error", + "no-lone-blocks": "error", + "no-new-wrappers": "error", + "no-octal-escape": "error", + "no-return-assign": "error", + "no-useless-concat": "error", + "no-useless-constructor": "error", + "no-useless-rename": "error", + "no-var": "error", + "no-void": "error", + + "no-unused-vars": [ + "error", + { + varsIgnorePattern: "^_", + argsIgnorePattern: "^_", + destructuredArrayIgnorePattern: "^_", + ignoreRestSiblings: true, + caughtErrors: "none", + }, + ], + }, + }, + ...eslintPluginSvelte.configs["flat/recommended"].map(config => ({ + ...config, + files: ["**/*.svelte"], + + languageOptions: { + parser: svelteParser, + ecmaVersion: 2019, + sourceType: "script", + + parserOptions: { + parser: "@typescript-eslint/parser", + allowImportExportEverywhere: true, + }, + }, + })), + ...tseslint.configs.strict.map(config => ({ + ...config, + files: ["**/*.ts"], + + languageOptions: { + globals: { + NodeJS: true, + }, + + parser: tsParser, + }, + + rules: { + "local-rules/no-barrel-imports": "error", + "local-rules/no-budibase-imports": "error", + "local-rules/no-console-error": "error", + + "@typescript-eslint/no-inferrable-types": "error", + "@typescript-eslint/adjacent-overload-signatures": "error", + "@typescript-eslint/class-literal-property-style": "error", + "@typescript-eslint/no-confusing-non-null-assertion": "error", + "@typescript-eslint/no-unnecessary-parameter-property-assignment": + "error", + "@typescript-eslint/no-useless-empty-export": "error", + + "no-unused-vars": "off", + "@typescript-eslint/no-unused-vars": [ + "error", + { + varsIgnorePattern: "^_", + argsIgnorePattern: "^_", + destructuredArrayIgnorePattern: "^_", + ignoreRestSiblings: true, + caughtErrors: "none", + }, + ], + + "no-redeclare": "off", + "@typescript-eslint/no-redeclare": "error", + + // @typescript-eslint/no-dupe-class-members supersedes no-dupe-class-members + "no-dupe-class-members": "off", + "@typescript-eslint/no-dupe-class-members": "error", + + "no-useless-constructor": "off", + "@typescript-eslint/no-useless-constructor": "error", + }, + })), + { + files: ["**/*.spec.ts", "**/*.spec.js"], + + plugins: { + jest: eslintPluginJest, + vitest: eslintPluginVitest, + }, + + languageOptions: { + globals: { + ...eslintPluginJest.environments.globals.globals, + ...eslintPluginVitest.environments.env.globals, + NodeJS: true, + }, + + parser: tsParser, + }, + + rules: { + ...eslintPluginVitest.configs.recommended.rules, + ...eslintPluginJest.configs.recommended.rules, + + "no-console": "warn", + + "vitest/expect-expect": "off", + + "jest/expect-expect": "off", + "jest/no-conditional-expect": "off", + "jest/no-disabled-tests": "off", + "jest/no-standalone-expect": "off", + + "local-rules/no-test-com": "error", + "local-rules/email-domain-example-com": "error", + }, + }, + { + files: [ + "packages/builder/**/*", + "packages/client/**/*", + "packages/frontend-core/**/*", + ], + + rules: { + "no-console": [ + "error", + { + allow: ["warn", "error", "debug"], + }, + ], + }, + }, +] diff --git a/examples/nextjs-api-sales/package.json b/examples/nextjs-api-sales/package.json index 21c548c6cc..1f4335462b 100644 --- a/examples/nextjs-api-sales/package.json +++ b/examples/nextjs-api-sales/package.json @@ -18,7 +18,7 @@ "react-notifications-component": "^3.4.1" }, "devDependencies": { - "@types/node": "17.0.21", + "@types/node": "^20.17.9", "@types/react": "17.0.39", "eslint": "8.10.0", "eslint-config-next": "12.1.0", diff --git a/examples/nextjs-api-sales/yarn.lock b/examples/nextjs-api-sales/yarn.lock index 867835a6b7..d4ba8a29a5 100644 --- a/examples/nextjs-api-sales/yarn.lock +++ b/examples/nextjs-api-sales/yarn.lock @@ -147,10 +147,12 @@ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= -"@types/node@17.0.21": - version "17.0.21" - resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.21.tgz#864b987c0c68d07b4345845c3e63b75edd143644" - integrity sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ== +"@types/node@^20.17.9": + version "20.17.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.17.9.tgz#5f141d4b7ee125cdee5faefe28de095398865bab" + integrity sha512-0JOXkRyLanfGPE2QRCwgxhzlBAvaRdCNMcvbd7jFfpmD4eEXll7LRwy5ymJmyeZqk7Nh7eD2LeUyQ68BbndmXw== + dependencies: + undici-types "~6.19.2" "@types/prop-types@*": version "15.7.4" @@ -1746,10 +1748,10 @@ type-fest@^0.20.2: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== -typescript@5.5.2: - version "5.5.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.2.tgz#c26f023cb0054e657ce04f72583ea2d85f8d0507" - integrity sha512-NcRtPEOsPFFWjobJEtfihkLCZCXZt/os3zf8nTxjVH3RvTSxjrCamJpbExGvYOF+tFHc3pA65qpdwPbzjohhew== +typescript@5.7.2: + version "5.7.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.7.2.tgz#3169cf8c4c8a828cde53ba9ecb3d2b1d5dd67be6" + integrity sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg== unbox-primitive@^1.0.1: version "1.0.1" @@ -1761,6 +1763,11 @@ unbox-primitive@^1.0.1: has-symbols "^1.0.2" which-boxed-primitive "^1.0.2" +undici-types@~6.19.2: + version "6.19.8" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" + integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== + uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" diff --git a/hosting/scripts/setup.js b/hosting/scripts/setup.js index c62ac14f29..35ee32bd64 100755 --- a/hosting/scripts/setup.js +++ b/hosting/scripts/setup.js @@ -2,7 +2,6 @@ const os = require("os") const exec = require("child_process").exec -const fs = require("fs") const platform = os.platform() const windows = platform === "win32" @@ -17,10 +16,11 @@ function execute(command) { async function commandExistsUnix(command) { const unixCmd = `command -v ${command} 2>/dev/null && { echo >&1 ${command}; exit 0; }` - return execute(command) + return execute(unixCmd) } async function commandExistsWindows(command) { + // eslint-disable-next-line no-control-regex if (/[\x00-\x1f<>:"|?*]/.test(command)) { return false } diff --git a/lerna.json b/lerna.json index 4192189369..afd0db6374 100644 --- a/lerna.json +++ b/lerna.json @@ -1,6 +1,6 @@ { "$schema": "node_modules/lerna/schemas/lerna-schema.json", - "version": "3.2.25", + "version": "3.2.26", "npmClient": "yarn", "concurrency": 20, "command": { diff --git a/nx.json b/nx.json index 22b23a7874..a71ee6961c 100644 --- a/nx.json +++ b/nx.json @@ -12,7 +12,8 @@ "inputs": [ "{workspaceRoot}/scripts/*", "{workspaceRoot}/lerna.json", - "{workspaceRoot}/.github/workflows/*" + "{workspaceRoot}/.github/workflows/*", + "{workspaceRoot}/tsconfig.build.json" ] }, "test": { diff --git a/package.json b/package.json index 69eeaaa681..771d3cefd5 100644 --- a/package.json +++ b/package.json @@ -3,33 +3,34 @@ "private": true, "devDependencies": { "@babel/core": "^7.22.5", - "@babel/eslint-parser": "^7.22.5", + "@babel/eslint-parser": "7.25.9", "@babel/preset-env": "^7.22.5", "@esbuild-plugins/tsconfig-paths": "^0.1.2", - "@types/node": "20.10.0", + "@types/node": "^20.17.9", "@types/proper-lockfile": "^4.1.4", - "@typescript-eslint/parser": "6.9.0", + "@typescript-eslint/parser": "8.17.0", + "@vitest/eslint-plugin": "^1.1.14", "cross-spawn": "7.0.6", "depcheck": "^1.4.7", "esbuild": "^0.18.17", "esbuild-node-externals": "^1.14.0", - "eslint": "^8.52.0", - "eslint-plugin-import": "^2.29.0", - "eslint-plugin-jest": "^27.9.0", - "eslint-plugin-local-rules": "^2.0.0", - "eslint-plugin-svelte": "^2.34.0", + "eslint": "9.16.0", + "eslint-plugin-jest": "28.9.0", + "eslint-plugin-local-rules": "3.0.2", + "eslint-plugin-svelte": "2.46.1", "husky": "^8.0.3", "kill-port": "^1.6.1", "lerna": "7.4.2", + "load-tsconfig": "^0.2.5", "madge": "^6.0.0", "nx-cloud": "16.0.5", "prettier": "2.8.8", "prettier-plugin-svelte": "^2.3.0", "proper-lockfile": "^4.1.2", "svelte": "4.2.19", - "svelte-eslint-parser": "^0.33.1", + "svelte-eslint-parser": "0.43.0", "typescript": "5.7.2", - "typescript-eslint": "^7.3.1", + "typescript-eslint": "8.17.0", "yargs": "^17.7.2" }, "scripts": { @@ -99,10 +100,10 @@ ] }, "resolutions": { - "@budibase/backend-core": "0.0.0", - "@budibase/shared-core": "0.0.0", - "@budibase/string-templates": "0.0.0", - "@budibase/types": "0.0.0", + "@budibase/backend-core": "*", + "@budibase/shared-core": "*", + "@budibase/string-templates": "*", + "@budibase/types": "*", "@budibase/pro": "npm:@budibase/pro@latest", "tough-cookie": "4.1.3", "node-fetch": "2.6.7", @@ -115,7 +116,8 @@ "passport": "0.6.0", "fast-xml-parser": "4.4.1", "@azure/identity": "4.2.1", - "kind-of": "6.0.3" + "kind-of": "6.0.3", + "globals": "15.13.0" }, "engines": { "node": ">=20.0.0 <21.0.0" diff --git a/packages/backend-core/package.json b/packages/backend-core/package.json index ba052a5fda..3e1b5f324b 100644 --- a/packages/backend-core/package.json +++ b/packages/backend-core/package.json @@ -21,9 +21,10 @@ "scripts": { "prebuild": "rimraf dist/", "prepack": "cp package.json dist", - "build": "tsc -p tsconfig.build.json --paths null && node ./scripts/build.js", + "build": "node ./scripts/build.js && tsc -p tsconfig.build.json --emitDeclarationOnly --paths null", "build:dev": "yarn prebuild && tsc --build --watch --preserveWatchOutput", - "check:types": "tsc -p tsconfig.json --noEmit --paths null --target es2020", + "build:oss": "node ./scripts/build.js", + "check:types": "tsc -p tsconfig.json --noEmit --paths null", "check:dependencies": "node ../../scripts/depcheck.js", "test": "bash scripts/test.sh", "test:watch": "jest --watchAll" @@ -31,8 +32,8 @@ "dependencies": { "@budibase/nano": "10.1.5", "@budibase/pouchdb-replication-stream": "1.2.11", - "@budibase/shared-core": "0.0.0", - "@budibase/types": "0.0.0", + "@budibase/shared-core": "*", + "@budibase/types": "*", "@techpass/passport-openidconnect": "0.3.3", "aws-cloudfront-sign": "3.0.2", "aws-sdk": "2.1692.0", @@ -76,7 +77,6 @@ "@types/cookies": "0.7.8", "@types/jest": "29.5.5", "@types/lodash": "4.14.200", - "@types/node": "^22.9.0", "@types/node-fetch": "2.6.4", "@types/pouchdb": "6.4.2", "@types/redlock": "4.0.7", diff --git a/packages/backend-core/src/db/couch/DatabaseImpl.ts b/packages/backend-core/src/db/couch/DatabaseImpl.ts index 371f3dc997..98e24e0996 100644 --- a/packages/backend-core/src/db/couch/DatabaseImpl.ts +++ b/packages/backend-core/src/db/couch/DatabaseImpl.ts @@ -289,7 +289,7 @@ export class DatabaseImpl implements Database { return } let errorFound = false - let errorMessage: string = "Unable to bulk remove documents: " + let errorMessage = "Unable to bulk remove documents: " for (let res of response) { if (res.error) { errorFound = true diff --git a/packages/backend-core/src/db/couch/utils.ts b/packages/backend-core/src/db/couch/utils.ts index 270d953320..2200024bb2 100644 --- a/packages/backend-core/src/db/couch/utils.ts +++ b/packages/backend-core/src/db/couch/utils.ts @@ -4,7 +4,7 @@ import { checkSlashesInUrl } from "../../helpers" export async function directCouchCall( path: string, - method: string = "GET", + method = "GET", body?: any ) { let { url, cookie } = getCouchInfo() @@ -43,7 +43,7 @@ export async function directCouchUrlCall({ export async function directCouchQuery( path: string, - method: string = "GET", + method = "GET", body?: any ) { const response = await directCouchCall(path, method, body) diff --git a/packages/backend-core/src/db/lucene.ts b/packages/backend-core/src/db/lucene.ts index 0206bb2140..9d897553dd 100644 --- a/packages/backend-core/src/db/lucene.ts +++ b/packages/backend-core/src/db/lucene.ts @@ -279,7 +279,7 @@ export class QueryBuilder { let query = allOr ? "" : "*:*" let allFiltersEmpty = true const allPreProcessingOpts = { escape: true, lowercase: true, wrap: true } - let tableId: string = "" + let tableId = "" if (this.#query.equal!.tableId) { tableId = this.#query.equal!.tableId delete this.#query.equal!.tableId diff --git a/packages/backend-core/src/environment.ts b/packages/backend-core/src/environment.ts index 56d9cd6e10..954fdd4135 100644 --- a/packages/backend-core/src/environment.ts +++ b/packages/backend-core/src/environment.ts @@ -134,10 +134,10 @@ const environment = { BUDIBASE_ENVIRONMENT: process.env.BUDIBASE_ENVIRONMENT, JS_BCRYPT: process.env.JS_BCRYPT, JWT_SECRET: process.env.JWT_SECRET - ? createSecretKey(Buffer.from(process.env.JWT_SECRET)) + ? createSecretKey(process.env.JWT_SECRET, "utf8") : undefined, JWT_SECRET_FALLBACK: process.env.JWT_SECRET_FALLBACK - ? createSecretKey(Buffer.from(process.env.JWT_SECRET_FALLBACK)) + ? createSecretKey(process.env.JWT_SECRET_FALLBACK, "utf8") : undefined, ENCRYPTION_KEY: process.env.ENCRYPTION_KEY, API_ENCRYPTION_KEY: getAPIEncryptionKey(), diff --git a/packages/backend-core/src/events/processors/Processors.ts b/packages/backend-core/src/events/processors/Processors.ts index 72de945d44..8fe8034280 100644 --- a/packages/backend-core/src/events/processors/Processors.ts +++ b/packages/backend-core/src/events/processors/Processors.ts @@ -2,7 +2,7 @@ import { Event, Identity, Group } from "@budibase/types" import { EventProcessor } from "./types" export default class Processor implements EventProcessor { - initialised: boolean = false + initialised = false processors: EventProcessor[] = [] constructor(processors: EventProcessor[]) { diff --git a/packages/backend-core/src/events/processors/posthog/PosthogProcessor.ts b/packages/backend-core/src/events/processors/posthog/PosthogProcessor.ts index 12d2bb7e2c..6c45da09e6 100644 --- a/packages/backend-core/src/events/processors/posthog/PosthogProcessor.ts +++ b/packages/backend-core/src/events/processors/posthog/PosthogProcessor.ts @@ -13,9 +13,7 @@ const EXCLUDED_EVENTS: Event[] = [ Event.ROLE_UPDATED, Event.DATASOURCE_UPDATED, Event.QUERY_UPDATED, - Event.TABLE_UPDATED, Event.VIEW_UPDATED, - Event.VIEW_FILTER_UPDATED, Event.VIEW_CALCULATION_UPDATED, Event.AUTOMATION_TRIGGER_UPDATED, Event.USER_GROUP_UPDATED, diff --git a/packages/backend-core/src/events/processors/types.ts b/packages/backend-core/src/events/processors/types.ts index 5256a1bc62..714bf0ef4e 100644 --- a/packages/backend-core/src/events/processors/types.ts +++ b/packages/backend-core/src/events/processors/types.ts @@ -1 +1 @@ -export { EventProcessor } from "@budibase/types" +export type { EventProcessor } from "@budibase/types" diff --git a/packages/backend-core/src/events/publishers/index.ts b/packages/backend-core/src/events/publishers/index.ts index 9c92b80499..aaec62f979 100644 --- a/packages/backend-core/src/events/publishers/index.ts +++ b/packages/backend-core/src/events/publishers/index.ts @@ -23,3 +23,4 @@ export { default as plugin } from "./plugin" export { default as backup } from "./backup" export { default as environmentVariable } from "./environmentVariable" export { default as auditLog } from "./auditLog" +export { default as rowAction } from "./rowAction" diff --git a/packages/backend-core/src/events/publishers/query.ts b/packages/backend-core/src/events/publishers/query.ts index 48603257d2..3bc8ffa5fd 100644 --- a/packages/backend-core/src/events/publishers/query.ts +++ b/packages/backend-core/src/events/publishers/query.ts @@ -12,8 +12,6 @@ import { QueriesRunEvent, } from "@budibase/types" -/* eslint-disable */ - const created = async ( datasource: Datasource, query: Query, diff --git a/packages/backend-core/src/events/publishers/rowAction.ts b/packages/backend-core/src/events/publishers/rowAction.ts new file mode 100644 index 0000000000..eac35cc489 --- /dev/null +++ b/packages/backend-core/src/events/publishers/rowAction.ts @@ -0,0 +1,13 @@ +import { publishEvent } from "../events" +import { Event, RowActionCreatedEvent } from "@budibase/types" + +async function created( + rowAction: RowActionCreatedEvent, + timestamp?: string | number +) { + await publishEvent(Event.ROW_ACTION_CREATED, rowAction, timestamp) +} + +export default { + created, +} diff --git a/packages/backend-core/src/events/publishers/rows.ts b/packages/backend-core/src/events/publishers/rows.ts index 9608613e89..e19681e5fe 100644 --- a/packages/backend-core/src/events/publishers/rows.ts +++ b/packages/backend-core/src/events/publishers/rows.ts @@ -6,8 +6,6 @@ import { Table, } from "@budibase/types" -/* eslint-disable */ - const created = async (count: number, timestamp?: string | number) => { const properties: RowsCreatedEvent = { count, diff --git a/packages/backend-core/src/events/publishers/table.ts b/packages/backend-core/src/events/publishers/table.ts index dc3200291a..77a2c3e1a4 100644 --- a/packages/backend-core/src/events/publishers/table.ts +++ b/packages/backend-core/src/events/publishers/table.ts @@ -1,13 +1,14 @@ import { publishEvent } from "../events" import { Event, - TableExportFormat, + FieldType, Table, TableCreatedEvent, - TableUpdatedEvent, TableDeletedEvent, TableExportedEvent, + TableExportFormat, TableImportedEvent, + TableUpdatedEvent, } from "@budibase/types" async function created(table: Table, timestamp?: string | number) { @@ -20,14 +21,34 @@ async function created(table: Table, timestamp?: string | number) { await publishEvent(Event.TABLE_CREATED, properties, timestamp) } -async function updated(table: Table) { +async function updated(oldTable: Table, newTable: Table) { + // only publish the event if it has fields we are interested in + let defaultValues, aiColumn + + // check that new fields have been added + for (const key in newTable.schema) { + if (!oldTable.schema[key]) { + const newColumn = newTable.schema[key] + if ("default" in newColumn && newColumn.default != null) { + defaultValues = true + } + if (newColumn.type === FieldType.AI) { + aiColumn = newColumn.operation + } + } + } + const properties: TableUpdatedEvent = { - tableId: table._id as string, + tableId: newTable._id as string, + defaultValues, + aiColumn, audited: { - name: table.name, + name: newTable.name, }, } - await publishEvent(Event.TABLE_UPDATED, properties) + if (defaultValues || aiColumn) { + await publishEvent(Event.TABLE_UPDATED, properties) + } } async function deleted(table: Table) { diff --git a/packages/backend-core/src/events/publishers/view.ts b/packages/backend-core/src/events/publishers/view.ts index ccbf960b04..503b011373 100644 --- a/packages/backend-core/src/events/publishers/view.ts +++ b/packages/backend-core/src/events/publishers/view.ts @@ -1,6 +1,11 @@ import { publishEvent } from "../events" import { + CalculationType, Event, + Table, + TableExportFormat, + View, + ViewCalculation, ViewCalculationCreatedEvent, ViewCalculationDeletedEvent, ViewCalculationUpdatedEvent, @@ -11,22 +16,20 @@ import { ViewFilterDeletedEvent, ViewFilterUpdatedEvent, ViewUpdatedEvent, - View, - ViewCalculation, - Table, - TableExportFormat, + ViewV2, + ViewJoinCreatedEvent, } from "@budibase/types" -/* eslint-disable */ - -async function created(view: View, timestamp?: string | number) { +async function created(view: ViewV2, timestamp?: string | number) { const properties: ViewCreatedEvent = { + name: view.name, + type: view.type, tableId: view.tableId, } await publishEvent(Event.VIEW_CREATED, properties, timestamp) } -async function updated(view: View) { +async function updated(view: ViewV2) { const properties: ViewUpdatedEvent = { tableId: view.tableId, } @@ -48,16 +51,27 @@ async function exported(table: Table, format: TableExportFormat) { await publishEvent(Event.VIEW_EXPORTED, properties) } -async function filterCreated(view: View, timestamp?: string | number) { +async function filterCreated( + { tableId, filterGroups }: { tableId: string; filterGroups: number }, + timestamp?: string | number +) { const properties: ViewFilterCreatedEvent = { - tableId: view.tableId, + tableId, + filterGroups, } await publishEvent(Event.VIEW_FILTER_CREATED, properties, timestamp) } -async function filterUpdated(view: View) { +async function filterUpdated({ + tableId, + filterGroups, +}: { + tableId: string + filterGroups: number +}) { const properties: ViewFilterUpdatedEvent = { - tableId: view.tableId, + tableId: tableId, + filterGroups, } await publishEvent(Event.VIEW_FILTER_UPDATED, properties) } @@ -69,10 +83,16 @@ async function filterDeleted(view: View) { await publishEvent(Event.VIEW_FILTER_DELETED, properties) } -async function calculationCreated(view: View, timestamp?: string | number) { +async function calculationCreated( + { + tableId, + calculationType, + }: { tableId: string; calculationType: CalculationType }, + timestamp?: string | number +) { const properties: ViewCalculationCreatedEvent = { - tableId: view.tableId, - calculation: view.calculation as ViewCalculation, + tableId, + calculation: calculationType, } await publishEvent(Event.VIEW_CALCULATION_CREATED, properties, timestamp) } @@ -93,6 +113,13 @@ async function calculationDeleted(existingView: View) { await publishEvent(Event.VIEW_CALCULATION_DELETED, properties) } +async function viewJoinCreated(tableId: any, timestamp?: string | number) { + const properties: ViewJoinCreatedEvent = { + tableId, + } + await publishEvent(Event.VIEW_JOIN_CREATED, properties, timestamp) +} + export default { created, updated, @@ -104,4 +131,5 @@ export default { calculationCreated, calculationUpdated, calculationDeleted, + viewJoinCreated, } diff --git a/packages/backend-core/src/middleware/authenticated.ts b/packages/backend-core/src/middleware/authenticated.ts index 6713cc7687..54d808de86 100644 --- a/packages/backend-core/src/middleware/authenticated.ts +++ b/packages/backend-core/src/middleware/authenticated.ts @@ -137,9 +137,9 @@ export default function ( } const tenantId = getHeader(ctx, Header.TENANT_ID) - let authenticated: boolean = false, + let authenticated = false, user: User | { tenantId: string } | undefined = undefined, - internal: boolean = false, + internal = false, loginMethod: LoginMethod | undefined = undefined if (authCookie && !apiKey) { const sessionId = authCookie.sessionId diff --git a/packages/backend-core/src/middleware/passport/sso/sso.ts b/packages/backend-core/src/middleware/passport/sso/sso.ts index 8901fcc56f..1bb43d4466 100644 --- a/packages/backend-core/src/middleware/passport/sso/sso.ts +++ b/packages/backend-core/src/middleware/passport/sso/sso.ts @@ -20,7 +20,7 @@ export const ssoSaveUserNoOp: SaveSSOUserFunction = (user: SSOUser) => */ export async function authenticate( details: SSOAuthDetails, - requireLocalAccount: boolean = true, + requireLocalAccount = true, done: any, saveUserFn: SaveSSOUserFunction ) { diff --git a/packages/backend-core/src/migrations/migrations.ts b/packages/backend-core/src/migrations/migrations.ts index fe6bc17386..c8320b5724 100644 --- a/packages/backend-core/src/migrations/migrations.ts +++ b/packages/backend-core/src/migrations/migrations.ts @@ -35,7 +35,7 @@ export const backPopulateMigrations = async (opts: MigrationNoOpOptions) => { // filter migrations to the type and populate a no-op migration const migrations: Migration[] = DEFINITIONS.filter( def => def.type === opts.type - ).map(d => ({ ...d, fn: () => {} })) + ).map(d => ({ ...d, fn: async () => {} })) await runMigrations(migrations, { noOp: opts }) } diff --git a/packages/backend-core/src/objectStore/objectStore.ts b/packages/backend-core/src/objectStore/objectStore.ts index 68b1b10ec2..79875b5e99 100644 --- a/packages/backend-core/src/objectStore/objectStore.ts +++ b/packages/backend-core/src/objectStore/objectStore.ts @@ -334,7 +334,7 @@ export async function listAllObjects(bucketName: string, path: string) { export function getPresignedUrl( bucketName: string, key: string, - durationSeconds: number = 3600 + durationSeconds = 3600 ) { const objectStore = ObjectStore(bucketName, { presigning: true }) const params = { diff --git a/packages/backend-core/src/queue/queue.ts b/packages/backend-core/src/queue/queue.ts index f5d710f02d..4e1086823b 100644 --- a/packages/backend-core/src/queue/queue.ts +++ b/packages/backend-core/src/queue/queue.ts @@ -7,7 +7,7 @@ import { addListeners, StalledFn } from "./listeners" import { Duration } from "../utils" import * as timers from "../timers" -export { QueueOptions, Queue, JobOptions } from "bull" +export type { QueueOptions, Queue, JobOptions } from "bull" // the queue lock is held for 5 minutes const QUEUE_LOCK_MS = Duration.fromMinutes(5).toMs() diff --git a/packages/backend-core/src/redis/redlockImpl.ts b/packages/backend-core/src/redis/redlockImpl.ts index adeb5b12ec..a48fac0c3d 100644 --- a/packages/backend-core/src/redis/redlockImpl.ts +++ b/packages/backend-core/src/redis/redlockImpl.ts @@ -92,7 +92,7 @@ function getLockName(opts: LockOptions) { // determine lock name // by default use the tenantId for uniqueness, unless using a system lock const prefix = opts.systemLock ? "system" : context.getTenantId() - let name: string = `lock:${prefix}_${opts.name}` + let name = `lock:${prefix}_${opts.name}` // add additional unique name if required if (opts.resource) { name = name + `_${opts.resource}` diff --git a/packages/backend-core/tests/core/users/users.spec.js b/packages/backend-core/tests/core/users/users.spec.js index f08c435b95..dde0d87fb7 100644 --- a/packages/backend-core/tests/core/users/users.spec.js +++ b/packages/backend-core/tests/core/users/users.spec.js @@ -11,15 +11,15 @@ const { getCreatorCount } = require("../../../src/users/users") describe("Users", () => { let getGlobalDBMock - let getGlobalUserParamsMock let paginationMock beforeEach(() => { jest.resetAllMocks() getGlobalDBMock = jest.spyOn(context, "getGlobalDB") - getGlobalUserParamsMock = jest.spyOn(db, "getGlobalUserParams") paginationMock = jest.spyOn(db, "pagination") + + jest.spyOn(db, "getGlobalUserParams") }) it("Retrieves the number of creators", async () => { diff --git a/packages/backend-core/tests/core/utilities/mocks/events.ts b/packages/backend-core/tests/core/utilities/mocks/events.ts index 96f351de10..433986352e 100644 --- a/packages/backend-core/tests/core/utilities/mocks/events.ts +++ b/packages/backend-core/tests/core/utilities/mocks/events.ts @@ -117,6 +117,7 @@ beforeAll(async () => { jest.spyOn(events.view, "calculationCreated") jest.spyOn(events.view, "calculationUpdated") jest.spyOn(events.view, "calculationDeleted") + jest.spyOn(events.view, "viewJoinCreated") jest.spyOn(events.plugin, "init") jest.spyOn(events.plugin, "imported") diff --git a/packages/backend-core/tests/core/utilities/structures/quotas.ts b/packages/backend-core/tests/core/utilities/structures/quotas.ts index 83c3a8a766..4b3c357b13 100644 --- a/packages/backend-core/tests/core/utilities/structures/quotas.ts +++ b/packages/backend-core/tests/core/utilities/structures/quotas.ts @@ -1,6 +1,6 @@ import { MonthlyQuotaName, QuotaUsage } from "@budibase/types" -export const usage = (users: number = 0, creators: number = 0): QuotaUsage => { +export const usage = (users = 0, creators = 0): QuotaUsage => { return { _id: "usage_quota", quotaReset: new Date().toISOString(), diff --git a/packages/backend-core/tsconfig.build.json b/packages/backend-core/tsconfig.build.json index c714f4d942..45652a0354 100644 --- a/packages/backend-core/tsconfig.build.json +++ b/packages/backend-core/tsconfig.build.json @@ -1,24 +1,8 @@ { + "extends": "../../tsconfig.build.json", "compilerOptions": { - "target": "es6", - "module": "commonjs", - "lib": ["es2020"], - "strict": true, - "noImplicitAny": true, - "esModuleInterop": true, - "resolveJsonModule": true, - "incremental": true, - "sourceMap": true, - "declaration": true, - "types": ["node", "jest"], - "outDir": "dist", - "skipLibCheck": true, - "paths": { - "@budibase/types": ["../types/src"], - "@budibase/shared-core": ["../shared-core/src"] - } + "outDir": "dist" }, - "include": ["**/*.js", "**/*.ts"], "exclude": [ "node_modules", "dist", diff --git a/packages/bbui/package.json b/packages/bbui/package.json index 35f6676fdc..89f72bc46d 100644 --- a/packages/bbui/package.json +++ b/packages/bbui/package.json @@ -29,8 +29,8 @@ ], "dependencies": { "@adobe/spectrum-css-workflow-icons": "1.2.1", - "@budibase/shared-core": "0.0.0", - "@budibase/string-templates": "0.0.0", + "@budibase/shared-core": "*", + "@budibase/string-templates": "*", "@spectrum-css/accordion": "3.0.24", "@spectrum-css/actionbutton": "1.0.1", "@spectrum-css/actiongroup": "1.0.1", diff --git a/packages/bbui/src/Form/Core/Signature.svelte b/packages/bbui/src/Form/Core/Signature.svelte index 729d3ac5e2..e02560568c 100644 --- a/packages/bbui/src/Form/Core/Signature.svelte +++ b/packages/bbui/src/Form/Core/Signature.svelte @@ -85,7 +85,7 @@ } const getPos = e => { - var rect = canvasRef.getBoundingClientRect() + let rect = canvasRef.getBoundingClientRect() const canvasX = e.offsetX || e.targetTouches?.[0].pageX - rect.left const canvasY = e.offsetY || e.targetTouches?.[0].pageY - rect.top diff --git a/packages/builder/package.json b/packages/builder/package.json index c98e817486..485cced7ab 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -48,11 +48,11 @@ ] }, "dependencies": { - "@budibase/bbui": "0.0.0", - "@budibase/frontend-core": "0.0.0", - "@budibase/shared-core": "0.0.0", - "@budibase/string-templates": "0.0.0", - "@budibase/types": "0.0.0", + "@budibase/bbui": "*", + "@budibase/frontend-core": "*", + "@budibase/shared-core": "*", + "@budibase/string-templates": "*", + "@budibase/types": "*", "@codemirror/autocomplete": "^6.7.1", "@codemirror/commands": "^6.2.4", "@codemirror/lang-javascript": "^6.1.8", diff --git a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/TestDataModal.svelte b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/TestDataModal.svelte index 5ec66870a8..eebd977e6c 100644 --- a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/TestDataModal.svelte +++ b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/TestDataModal.svelte @@ -46,7 +46,7 @@ } } else { // Leave the core data as it is - return testData + return cloneDeep(testData) } } @@ -63,7 +63,10 @@ return true } - $: testData = testData || parseTestData($selectedAutomation.data.testData) + $: currentTestData = $selectedAutomation.data.testData + + // Can be updated locally to avoid race condition when testing + $: testData = parseTestData(currentTestData) $: { // clone the trigger so we're not mutating the reference @@ -85,7 +88,7 @@ required => testData?.[required] || required !== "row" ) - function parseTestJSON(e) { + async function parseTestJSON(e) { let jsonUpdate try { @@ -105,7 +108,9 @@ } } - automationStore.actions.addTestDataToAutomation(jsonUpdate) + const updatedAuto = + automationStore.actions.addTestDataToAutomation(jsonUpdate) + await automationStore.actions.save(updatedAuto) } const testAutomation = async () => { @@ -150,10 +155,14 @@ {#if selectedValues}
{ + const { testData: updatedTestData } = e.detail + testData = updatedTestData + }} />
{/if} @@ -162,7 +171,7 @@