ci: Setup biome and pre-commit hooks for formatting (no-changelog) (#10795)
Some checks are pending
Test Master / install-and-build (push) Waiting to run
Test Master / Unit tests (18.x) (push) Blocked by required conditions
Test Master / Unit tests (20.x) (push) Blocked by required conditions
Test Master / Unit tests (22.4) (push) Blocked by required conditions
Test Master / Lint (push) Blocked by required conditions
Test Master / Notify Slack on failure (push) Blocked by required conditions
Benchmark Docker Image CI / build (push) Waiting to run

Co-authored-by: Tomi Turtiainen <10324676+tomi@users.noreply.github.com>
This commit is contained in:
कारतोफ्फेलस्क्रिप्ट™ 2024-09-17 14:10:22 +02:00 committed by GitHub
parent 57836cc17a
commit 6a35812f92
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
85 changed files with 701 additions and 465 deletions

View file

@ -30,6 +30,9 @@ jobs:
- name: Build - name: Build
run: pnpm build run: pnpm build
- name: Run formatcheck
run: pnpm format:check
- name: Run typecheck - name: Run typecheck
run: pnpm typecheck run: pnpm typecheck

View file

@ -7,3 +7,11 @@ packages/nodes-base/nodes/**/test
packages/cli/templates/form-trigger.handlebars packages/cli/templates/form-trigger.handlebars
cypress/fixtures cypress/fixtures
CHANGELOG.md CHANGELOG.md
.github/pull_request_template.md
# Ignored for now
**/*.md
# Handled by biome
**/*.ts
**/*.js
**/*.json
**/*.jsonc

View file

@ -1,5 +1,6 @@
{ {
"recommendations": [ "recommendations": [
"biomejs.biome",
"streetsidesoftware.code-spell-checker", "streetsidesoftware.code-spell-checker",
"dangmai.workspace-default-settings", "dangmai.workspace-default-settings",
"dbaeumer.vscode-eslint", "dbaeumer.vscode-eslint",

View file

@ -1,6 +1,22 @@
{ {
"editor.defaultFormatter": "esbenp.prettier-vscode", "editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true, "editor.formatOnSave": true,
"[javascript]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[typescript]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[json]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[jsonc]": {
"editor.defaultFormatter": "biomejs.biome"
},
"editor.codeActionsOnSave": {
"quickfix.biome": "explicit",
"source.organizeImports.biome": "never"
},
"search.exclude": { "search.exclude": {
"node_modules": true, "node_modules": true,
"dist": true, "dist": true,

48
biome.jsonc Normal file
View file

@ -0,0 +1,48 @@
{
"$schema": "./node_modules/@biomejs/biome/configuration_schema.json",
"vcs": {
"clientKind": "git",
"enabled": true,
"useIgnoreFile": true
},
"files": {
"ignore": [
"**/.turbo",
"**/coverage",
"**/dist",
"**/package.json",
"**/pnpm-lock.yaml",
"**/CHANGELOG.md"
]
},
"formatter": {
"enabled": true,
"formatWithErrors": false,
"indentStyle": "tab",
"indentWidth": 2,
"lineEnding": "lf",
"lineWidth": 100,
"attributePosition": "auto",
"ignore": [
// Handled by prettier
"**/*.vue"
]
},
"organizeImports": { "enabled": false },
"linter": {
"enabled": false
},
"javascript": {
"formatter": {
"jsxQuoteStyle": "double",
"quoteProperties": "asNeeded",
"trailingCommas": "all",
"semicolons": "always",
"arrowParentheses": "always",
"bracketSpacing": true,
"bracketSameLine": false,
"quoteStyle": "single",
"attributePosition": "auto"
}
}
}

7
cypress/biome.jsonc Normal file
View file

@ -0,0 +1,7 @@
{
"$schema": "../node_modules/@biomejs/biome/configuration_schema.json",
"extends": ["../biome.jsonc"],
"formatter": {
"ignore": ["fixtures/**"]
}
}

View file

@ -227,7 +227,7 @@ describe('NDV', () => {
workflowPage.actions.zoomToFit(); workflowPage.actions.zoomToFit();
/* prettier-ignore */ // biome-ignore format:
const PINNED_DATA = [ const PINNED_DATA = [
{ {
"id": "abc", "id": "abc",
@ -263,7 +263,6 @@ describe('NDV', () => {
] ]
} }
]; ];
/* prettier-ignore */
workflowPage.actions.openNode('Get thread details1'); workflowPage.actions.openNode('Get thread details1');
ndv.actions.pastePinnedData(PINNED_DATA); ndv.actions.pastePinnedData(PINNED_DATA);
ndv.actions.close(); ndv.actions.close();

View file

@ -43,7 +43,9 @@ describe('Code node', () => {
const getParameter = () => ndv.getters.parameterInput('jsCode').should('be.visible'); const getParameter = () => ndv.getters.parameterInput('jsCode').should('be.visible');
const getEditor = () => getParameter().find('.cm-content').should('exist'); const getEditor = () => getParameter().find('.cm-content').should('exist');
getEditor().type('{selectall}').paste(`$input.itemMatching() getEditor()
.type('{selectall}')
.paste(`$input.itemMatching()
$input.item $input.item
$('When clicking Test workflow').item $('When clicking Test workflow').item
$input.first(1) $input.first(1)
@ -68,7 +70,9 @@ return
ndv.getters.parameterInput('mode').click(); ndv.getters.parameterInput('mode').click();
ndv.actions.selectOptionInParameterDropdown('mode', 'Run Once for Each Item'); ndv.actions.selectOptionInParameterDropdown('mode', 'Run Once for Each Item');
getEditor().type('{selectall}').paste(`$input.itemMatching() getEditor()
.type('{selectall}')
.paste(`$input.itemMatching()
$input.all() $input.all()
$input.first() $input.first()
$input.item() $input.item()

View file

@ -7,7 +7,8 @@
"test:e2e:ui": "scripts/run-e2e.js ui", "test:e2e:ui": "scripts/run-e2e.js ui",
"test:e2e:dev": "scripts/run-e2e.js dev", "test:e2e:dev": "scripts/run-e2e.js dev",
"test:e2e:all": "scripts/run-e2e.js all", "test:e2e:all": "scripts/run-e2e.js all",
"format": "prettier --write . --ignore-path ../.prettierignore", "format": "biome format --write .",
"format:check": "biome ci .",
"lint": "eslint . --quiet", "lint": "eslint . --quiet",
"lintfix": "eslint . --fix", "lintfix": "eslint . --fix",
"develop": "cd ..; pnpm dev", "develop": "cd ..; pnpm dev",

10
lefthook.yml Normal file
View file

@ -0,0 +1,10 @@
pre-commit:
commands:
biome_check:
glob: 'packages/**/*.{js,ts,json}'
run: ./node_modules/.bin/biome check --write --no-errors-on-unmatched --files-ignore-unknown=true --colors=off {staged_files}
stage_fixed: true
prettier_check:
glob: 'packages/**/*.{vue,yml,md}'
run: ./node_modules/.bin/prettier --write --ignore-unknown --no-error-on-unmatched-pattern {staged_files}
stage_fixed: true

View file

@ -1,7 +1,7 @@
{ {
"folders": [ "folders": [
{ {
"path": ".", "path": "."
}, }
], ]
} }

View file

@ -8,6 +8,7 @@
}, },
"packageManager": "pnpm@9.6.0", "packageManager": "pnpm@9.6.0",
"scripts": { "scripts": {
"prepare": "lefthook install",
"preinstall": "node scripts/block-npm-install.js", "preinstall": "node scripts/block-npm-install.js",
"build": "turbo run build", "build": "turbo run build",
"build:backend": "turbo run build:backend", "build:backend": "turbo run build:backend",
@ -19,6 +20,7 @@
"clean": "turbo run clean --parallel", "clean": "turbo run clean --parallel",
"reset": "node scripts/ensure-zx.mjs && zx scripts/reset.mjs", "reset": "node scripts/ensure-zx.mjs && zx scripts/reset.mjs",
"format": "turbo run format && node scripts/format.mjs", "format": "turbo run format && node scripts/format.mjs",
"format:check": "turbo run format:check",
"lint": "turbo run lint", "lint": "turbo run lint",
"lintfix": "turbo run lintfix", "lintfix": "turbo run lintfix",
"lint:backend": "turbo run lint:backend", "lint:backend": "turbo run lint:backend",
@ -38,6 +40,7 @@
"worker": "./packages/cli/bin/n8n worker" "worker": "./packages/cli/bin/n8n worker"
}, },
"devDependencies": { "devDependencies": {
"@biomejs/biome": "^1.9.0",
"@n8n_io/eslint-config": "workspace:*", "@n8n_io/eslint-config": "workspace:*",
"@types/jest": "^29.5.3", "@types/jest": "^29.5.3",
"@types/supertest": "^6.0.2", "@types/supertest": "^6.0.2",
@ -46,6 +49,7 @@
"jest-expect-message": "^1.1.3", "jest-expect-message": "^1.1.3",
"jest-mock": "^29.6.2", "jest-mock": "^29.6.2",
"jest-mock-extended": "^3.0.4", "jest-mock-extended": "^3.0.4",
"lefthook": "^1.7.15",
"nock": "^13.3.2", "nock": "^13.3.2",
"nodemon": "^3.0.1", "nodemon": "^3.0.1",
"p-limit": "^3.1.0", "p-limit": "^3.1.0",

View file

@ -6,7 +6,8 @@
"dev": "pnpm watch", "dev": "pnpm watch",
"typecheck": "tsc --noEmit", "typecheck": "tsc --noEmit",
"build": "tsc -p tsconfig.build.json", "build": "tsc -p tsconfig.build.json",
"format": "prettier --write . --ignore-path ../../../.prettierignore", "format": "biome format --write .",
"format:check": "biome ci .",
"lint": "eslint .", "lint": "eslint .",
"lintfix": "eslint . --fix", "lintfix": "eslint . --fix",
"watch": "tsc -p tsconfig.build.json --watch", "watch": "tsc -p tsconfig.build.json --watch",

View file

@ -0,0 +1,7 @@
{
"$schema": "../node_modules/@biomejs/biome/configuration_schema.json",
"extends": ["../../../biome.jsonc"],
"files": {
"ignore": ["scripts/mock-api/**"]
}
}

View file

@ -5,6 +5,8 @@
"main": "dist/index", "main": "dist/index",
"scripts": { "scripts": {
"build": "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json", "build": "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json",
"format": "biome format --write .",
"format:check": "biome ci .",
"lint": "eslint .", "lint": "eslint .",
"lintfix": "eslint . --fix", "lintfix": "eslint . --fix",
"start": "./bin/n8n-benchmark", "start": "./bin/n8n-benchmark",

View file

@ -12,7 +12,8 @@
"typecheck": "vue-tsc --noEmit", "typecheck": "vue-tsc --noEmit",
"lint": "eslint . --ext .js,.ts,.vue --quiet", "lint": "eslint . --ext .js,.ts,.vue --quiet",
"lintfix": "eslint . --ext .js,.ts,.vue --fix", "lintfix": "eslint . --ext .js,.ts,.vue --fix",
"format": "prettier --write src/", "format": "biome format --write src .storybook && prettier --write src/ --ignore-path ../../.prettierignore",
"format:check": "biome ci src .storybook && prettier --check src/ --ignore-path ../../.prettierignore",
"storybook": "storybook dev -p 6006 --no-open", "storybook": "storybook dev -p 6006 --no-open",
"build:storybook": "storybook build" "build:storybook": "storybook build"
}, },

View file

@ -2,7 +2,7 @@
// https://github.com/pxlrbt/markdown-css // https://github.com/pxlrbt/markdown-css
.chat-message-markdown { .chat-message-markdown {
/* /*
universalize.css (v1.0.2) by Alexander Sandberg (https://alexandersandberg.com) universalize.css (v1.0.2) by Alexander Sandberg (https://alexandersandberg.com)
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
@ -45,8 +45,6 @@
vertical-align: inherit; /* 2 */ vertical-align: inherit; /* 2 */
} }
/* /*
Remove inconsistent and unnecessary margins Remove inconsistent and unnecessary margins
*/ */
@ -63,7 +61,8 @@
button, /* (Safari) 3 lines */ button, /* (Safari) 3 lines */
input, input,
select, select,
textarea { /* (Firefox, Safari) */ textarea {
/* (Firefox, Safari) */
margin: 0; margin: 0;
} }
@ -80,11 +79,13 @@
Add correct display Add correct display
*/ */
main, /* (IE11) */ main, /* (IE11) */
details { /* (Edge 18-, IE) */ details {
/* (Edge 18-, IE) */
display: block; display: block;
} }
summary { /* (all) */ summary {
/* (all) */
display: list-item; display: list-item;
} }
@ -106,18 +107,19 @@
kbd, kbd,
samp { samp {
font-family: font-family:
/* macOS 10.10+ */ "Menlo", /* macOS 10.10+ */
/* Windows 6+ */ "Consolas", 'Menlo',
/* Android 4+ */ "Roboto Mono", /* Windows 6+ */ 'Consolas',
/* Ubuntu 10.10+ */ "Ubuntu Monospace", /* Android 4+ */ 'Roboto Mono',
/* KDE Plasma 5+ */ "Noto Mono", /* Ubuntu 10.10+ */ 'Ubuntu Monospace',
/* KDE Plasma 4+ */ "Oxygen Mono", /* KDE Plasma 5+ */ 'Noto Mono',
/* Linux/OpenOffice fallback */ "Liberation Mono", /* KDE Plasma 4+ */ 'Oxygen Mono',
/* Linux/OpenOffice fallback */ 'Liberation Mono',
/* fallback */ monospace, /* fallback */ monospace,
/* macOS emoji */ "Apple Color Emoji", /* macOS emoji */ 'Apple Color Emoji',
/* Windows emoji */ "Segoe UI Emoji", /* Windows emoji */ 'Segoe UI Emoji',
/* Windows emoji */ "Segoe UI Symbol", /* Windows emoji */ 'Segoe UI Symbol',
/* Linux emoji */ "Noto Color Emoji"; /* 1 */ /* Linux emoji */ 'Noto Color Emoji'; /* 1 */
font-size: 1em; /* 2 */ font-size: 1em; /* 2 */
} }
@ -130,7 +132,7 @@
cursor: help; /* 1 */ cursor: help; /* 1 */
text-decoration: underline; /* 2 */ text-decoration: underline; /* 2 */
-webkit-text-decoration: underline dotted; -webkit-text-decoration: underline dotted;
text-decoration: underline dotted; /* 2 */ text-decoration: underline dotted; /* 2 */
} }
/* /*
@ -201,9 +203,9 @@
Correct inability to style buttons (iOS, Safari) Correct inability to style buttons (iOS, Safari)
*/ */
button, button,
[type="button"], [type='button'],
[type="reset"], [type='reset'],
[type="submit"] { [type='submit'] {
-webkit-appearance: button; -webkit-appearance: button;
} }
@ -249,7 +251,7 @@
1. Correct outline style (Safari) 1. Correct outline style (Safari)
2. Correct odd appearance (Chrome, Edge, Safari) 2. Correct odd appearance (Chrome, Edge, Safari)
*/ */
[type="search"] { [type='search'] {
outline-offset: -2px; /* 1 */ outline-offset: -2px; /* 1 */
-webkit-appearance: textfield; /* 2 */ -webkit-appearance: textfield; /* 2 */
} }
@ -311,7 +313,7 @@
/* /*
Change cursor on busy elements (all) Change cursor on busy elements (all)
*/ */
[aria-busy="true"] { [aria-busy='true'] {
cursor: progress; cursor: progress;
} }
@ -325,7 +327,7 @@
/* /*
Change cursor on disabled, non-editable, or inoperable elements (all) Change cursor on disabled, non-editable, or inoperable elements (all)
*/ */
[aria-disabled="true"], [aria-disabled='true'],
[disabled] { [disabled] {
cursor: not-allowed; cursor: not-allowed;
} }
@ -333,12 +335,12 @@
/* /*
Change display on visually hidden accessible elements (all) Change display on visually hidden accessible elements (all)
*/ */
[aria-hidden="false"][hidden] { [aria-hidden='false'][hidden] {
display: inline; display: inline;
display: initial; display: initial;
} }
[aria-hidden="false"][hidden]:not(:focus) { [aria-hidden='false'][hidden]:not(:focus) {
clip: rect(0, 0, 0, 0); clip: rect(0, 0, 0, 0);
position: absolute; position: absolute;
} }
@ -347,8 +349,8 @@
Print out URLs after links (all) Print out URLs after links (all)
*/ */
@media print { @media print {
a[href^="http"]::after { a[href^='http']::after {
content: " (" attr(href) ")"; content: ' (' attr(href) ')';
} }
} }
/* ----- Variables ----- */ /* ----- Variables ----- */
@ -484,8 +486,8 @@
*/ */
pre { pre {
-moz-tab-size: 4; -moz-tab-size: 4;
-o-tab-size: 4; -o-tab-size: 4;
tab-size: 4; tab-size: 4;
} }
/* /*
@ -563,7 +565,7 @@
padding: 0.1em 0.25em; padding: 0.1em 0.25em;
border-radius: 0.2rem; border-radius: 0.2rem;
-webkit-box-decoration-break: clone; -webkit-box-decoration-break: clone;
box-decoration-break: clone; box-decoration-break: clone;
} }
kbd > kbd { kbd > kbd {
@ -573,8 +575,8 @@
pre { pre {
-moz-tab-size: 4; -moz-tab-size: 4;
-o-tab-size: 4; -o-tab-size: 4;
tab-size: 4; tab-size: 4;
} }
pre code { pre code {
@ -586,7 +588,7 @@
/* ----- Forms ----- */ /* ----- Forms ----- */
/* ----- Misc ----- */ /* ----- Misc ----- */
[tabindex="-1"]:focus { [tabindex='-1']:focus {
outline: none; outline: none;
} }

View file

@ -6,7 +6,8 @@
"dev": "pnpm watch", "dev": "pnpm watch",
"typecheck": "tsc --noEmit", "typecheck": "tsc --noEmit",
"build": "tsc -p tsconfig.build.json", "build": "tsc -p tsconfig.build.json",
"format": "prettier --write . --ignore-path ../../../.prettierignore", "format": "biome format --write src test",
"format:check": "biome ci src test",
"lint": "eslint . --quiet", "lint": "eslint . --quiet",
"lintfix": "eslint . --fix", "lintfix": "eslint . --fix",
"watch": "tsc -p tsconfig.build.json --watch", "watch": "tsc -p tsconfig.build.json --watch",

View file

@ -8,7 +8,5 @@ module.exports = {
...sharedOptions(__dirname), ...sharedOptions(__dirname),
ignorePatterns: [ ignorePatterns: ['src/expressions/grammar*.ts'],
'src/expressions/grammar*.ts'
]
}; };

View file

@ -24,7 +24,8 @@
"test": "jest", "test": "jest",
"lint": "eslint . --ext .ts --quiet", "lint": "eslint . --ext .ts --quiet",
"lintfix": "eslint . --ext .ts --fix", "lintfix": "eslint . --ext .ts --fix",
"format": "prettier --write --ignore-path ../../.prettierignore src test" "format": "biome format --write src test",
"format:check": "biome ci src test"
}, },
"peerDependencies": { "peerDependencies": {
"@codemirror/language": "*", "@codemirror/language": "*",

View file

@ -6,7 +6,8 @@
"dev": "pnpm watch", "dev": "pnpm watch",
"typecheck": "tsc --noEmit", "typecheck": "tsc --noEmit",
"build": "tsc -p tsconfig.build.json", "build": "tsc -p tsconfig.build.json",
"format": "prettier --write . --ignore-path ../../../.prettierignore", "format": "biome format --write src test",
"format:check": "biome ci src test",
"lint": "eslint .", "lint": "eslint .",
"lintfix": "eslint . --fix", "lintfix": "eslint . --fix",
"watch": "tsc -p tsconfig.build.json --watch", "watch": "tsc -p tsconfig.build.json --watch",

View file

@ -6,7 +6,8 @@
"dev": "pnpm watch", "dev": "pnpm watch",
"typecheck": "tsc --noEmit", "typecheck": "tsc --noEmit",
"build": "tsc -p tsconfig.build.json", "build": "tsc -p tsconfig.build.json",
"format": "prettier --write . --ignore-path ../../../.prettierignore", "format": "biome format --write src test",
"format:check": "biome ci src test",
"lint": "eslint . --quiet", "lint": "eslint . --quiet",
"lintfix": "eslint . --fix", "lintfix": "eslint . --fix",
"watch": "tsc -p tsconfig.build.json --watch", "watch": "tsc -p tsconfig.build.json --watch",

View file

@ -1,51 +0,0 @@
module.exports = {
/**
* https://prettier.io/docs/en/options.html#semicolons
*/
semi: true,
/**
* https://prettier.io/docs/en/options.html#trailing-commas
*/
trailingComma: 'all',
/**
* https://prettier.io/docs/en/options.html#bracket-spacing
*/
bracketSpacing: true,
/**
* https://prettier.io/docs/en/options.html#tabs
*/
useTabs: true,
/**
* https://prettier.io/docs/en/options.html#tab-width
*/
tabWidth: 2,
/**
* https://prettier.io/docs/en/options.html#arrow-function-parentheses
*/
arrowParens: 'always',
/**
* https://prettier.io/docs/en/options.html#quotes
*/
singleQuote: true,
/**
* https://prettier.io/docs/en/options.html#quote-props
*/
quoteProps: 'as-needed',
/**
* https://prettier.io/docs/en/options.html#end-of-line
*/
endOfLine: 'lf',
/**
* https://prettier.io/docs/en/options.html#print-width
*/
printWidth: 100,
};

View file

@ -1,7 +1,3 @@
{ {
"recommendations": [ "recommendations": ["dbaeumer.vscode-eslint", "EditorConfig.EditorConfig", "biomejs.biome"]
"dbaeumer.vscode-eslint",
"EditorConfig.EditorConfig",
"esbenp.prettier-vscode",
]
} }

View file

@ -9,7 +9,8 @@
"typecheck": "tsc --noEmit", "typecheck": "tsc --noEmit",
"build": "tsc -p tsconfig.build.json && pnpm n8n-copy-icons && pnpm build:metadata", "build": "tsc -p tsconfig.build.json && pnpm n8n-copy-icons && pnpm build:metadata",
"build:metadata": "pnpm n8n-generate-known && pnpm n8n-generate-ui-types", "build:metadata": "pnpm n8n-generate-known && pnpm n8n-generate-ui-types",
"format": "prettier nodes credentials --write", "format": "biome format --write .",
"format:check": "biome ci .",
"lint": "eslint nodes credentials --quiet", "lint": "eslint nodes credentials --quiet",
"lintfix": "eslint nodes credentials --fix", "lintfix": "eslint nodes credentials --fix",
"watch": "tsc-watch -p tsconfig.build.json --onCompilationComplete \"tsc-alias -p tsconfig.build.json\" --onSuccess \"pnpm n8n-generate-ui-types\"", "watch": "tsc-watch -p tsconfig.build.json --onCompilationComplete \"tsc-alias -p tsconfig.build.json\" --onSuccess \"pnpm n8n-generate-ui-types\"",

View file

@ -6,7 +6,8 @@
"dev": "pnpm watch", "dev": "pnpm watch",
"typecheck": "tsc --noEmit", "typecheck": "tsc --noEmit",
"build": "tsc -p tsconfig.build.json", "build": "tsc -p tsconfig.build.json",
"format": "prettier --write . --ignore-path ../../../.prettierignore", "format": "biome format --write .",
"format:check": "biome ci .",
"lint": "eslint . --quiet", "lint": "eslint . --quiet",
"lintfix": "eslint . --fix", "lintfix": "eslint . --fix",
"watch": "tsc -p tsconfig.build.json --watch", "watch": "tsc -p tsconfig.build.json --watch",

View file

@ -22,12 +22,6 @@ const config = (module.exports = {
*/ */
'@typescript-eslint', '@typescript-eslint',
/**
* Plugin to report formatting violations as lint violations
* https://github.com/prettier/eslint-plugin-prettier
*/
'eslint-plugin-prettier',
/* /*
* Plugin to allow specifying local ESLint rules. * Plugin to allow specifying local ESLint rules.
* https://github.com/ivov/eslint-plugin-n8n-local-rules * https://github.com/ivov/eslint-plugin-n8n-local-rules
@ -76,28 +70,6 @@ const config = (module.exports = {
], ],
rules: { rules: {
// ******************************************************************
// required by prettier plugin
// ******************************************************************
// The following rule enables eslint-plugin-prettier
// See: https://github.com/prettier/eslint-plugin-prettier#recommended-configuration
'prettier/prettier': ['error', { endOfLine: 'auto' }],
// The following two rules must be disabled when using eslint-plugin-prettier:
// See: https://github.com/prettier/eslint-plugin-prettier#arrow-body-style-and-prefer-arrow-callback-issue
/**
* https://eslint.org/docs/rules/arrow-body-style
*/
'arrow-body-style': 'off',
/**
* https://eslint.org/docs/rules/prefer-arrow-callback
*/
'prefer-arrow-callback': 'off',
// ****************************************************************** // ******************************************************************
// additions to base ruleset // additions to base ruleset
// ****************************************************************** // ******************************************************************

View file

@ -15,7 +15,6 @@
"eslint-plugin-import": "^2.29.1", "eslint-plugin-import": "^2.29.1",
"eslint-plugin-lodash": "^7.4.0", "eslint-plugin-lodash": "^7.4.0",
"eslint-plugin-n8n-local-rules": "^1.0.0", "eslint-plugin-n8n-local-rules": "^1.0.0",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-unicorn": "^51.0.1", "eslint-plugin-unicorn": "^51.0.1",
"eslint-plugin-unused-imports": "^3.1.0", "eslint-plugin-unused-imports": "^3.1.0",
"eslint-plugin-vue": "^9.23.0", "eslint-plugin-vue": "^9.23.0",

View file

@ -13,7 +13,7 @@ module.exports = (tsconfigRootDir, mode) => {
vue: 'vue-eslint-parser', vue: 'vue-eslint-parser',
template: 'vue-eslint-parser', template: 'vue-eslint-parser',
}, },
} }
: {}; : {};
const settings = { const settings = {

View file

@ -17,7 +17,8 @@
"dev": "concurrently -k -n \"TypeScript,Node\" -c \"yellow.bold,cyan.bold\" \"npm run watch\" \"nodemon\"", "dev": "concurrently -k -n \"TypeScript,Node\" -c \"yellow.bold,cyan.bold\" \"npm run watch\" \"nodemon\"",
"dev:worker": "concurrently -k -n \"TypeScript,Node\" -c \"yellow.bold,cyan.bold\" \"npm run watch\" \"nodemon worker\"", "dev:worker": "concurrently -k -n \"TypeScript,Node\" -c \"yellow.bold,cyan.bold\" \"npm run watch\" \"nodemon worker\"",
"dev:webhook": "concurrently -k -n \"TypeScript,Node\" -c \"yellow.bold,cyan.bold\" \"npm run watch\" \"nodemon webhook\"", "dev:webhook": "concurrently -k -n \"TypeScript,Node\" -c \"yellow.bold,cyan.bold\" \"npm run watch\" \"nodemon webhook\"",
"format": "prettier --write . --ignore-path ../../.prettierignore", "format": "biome format --write .",
"format:check": "biome ci .",
"lint": "eslint . --quiet", "lint": "eslint . --quiet",
"lintfix": "eslint . --fix", "lintfix": "eslint . --fix",
"start": "run-script-os", "start": "run-script-os",

View file

@ -84,12 +84,11 @@ type ExceptionPaths = {
// string literals map // string literals map
// ----------------------------------- // -----------------------------------
type GetPathSegmentsWithUnions<T> = type GetPathSegmentsWithUnions<T> = T extends ReadonlyArray<infer C>
T extends ReadonlyArray<infer C> ? [C]
? [C] : {
: { [K in ValidKeys<T>]: [K, ...GetPathSegmentsWithUnions<T[K]>];
[K in ValidKeys<T>]: [K, ...GetPathSegmentsWithUnions<T[K]>]; }[ValidKeys<T>];
}[ValidKeys<T>];
type ToPathUnionPair<T extends string[]> = T extends [...infer Path, infer Union] type ToPathUnionPair<T extends string[]> = T extends [...infer Path, infer Union]
? Path extends string[] ? Path extends string[]

View file

@ -12,6 +12,7 @@ import { UserRepository } from '@/databases/repositories/user.repository';
import { Patch, Post, RestController } from '@/decorators'; import { Patch, Post, RestController } from '@/decorators';
import { MessageEventBus } from '@/eventbus/message-event-bus/message-event-bus'; import { MessageEventBus } from '@/eventbus/message-event-bus/message-event-bus';
import type { BooleanLicenseFeature, NumericLicenseFeature } from '@/interfaces'; import type { BooleanLicenseFeature, NumericLicenseFeature } from '@/interfaces';
import type { FeatureReturnType } from '@/license';
import { License } from '@/license'; import { License } from '@/license';
import { Logger } from '@/logger'; import { Logger } from '@/logger';
import { MfaService } from '@/mfa/mfa.service'; import { MfaService } from '@/mfa/mfa.service';
@ -115,10 +116,18 @@ export class E2EController {
) { ) {
license.isFeatureEnabled = (feature: BooleanLicenseFeature) => license.isFeatureEnabled = (feature: BooleanLicenseFeature) =>
this.enabledFeatures[feature] ?? false; this.enabledFeatures[feature] ?? false;
// @ts-expect-error Overriding method
// eslint-disable-next-line @typescript-eslint/unbound-method // Ugly hack to satisfy biome parser
license.getFeatureValue<NumericLicenseFeature> = (feature: NumericLicenseFeature) => const getFeatureValue = <T extends keyof FeatureReturnType>(
this.numericFeatures[feature] ?? UNLIMITED_LICENSE_QUOTA; feature: T,
): FeatureReturnType[T] => {
if (feature in this.numericFeatures) {
return this.numericFeatures[feature as NumericLicenseFeature] as FeatureReturnType[T];
} else {
return UNLIMITED_LICENSE_QUOTA as FeatureReturnType[T];
}
};
license.getFeatureValue = getFeatureValue;
license.getPlanName = () => 'Enterprise'; license.getPlanName = () => 'Enterprise';
} }

View file

@ -11,7 +11,10 @@ export class AuthIdentity extends WithTimestamps {
@Column() @Column()
userId: string; userId: string;
@ManyToOne(() => User, (user) => user.authIdentities) @ManyToOne(
() => User,
(user) => user.authIdentities,
)
user: User; user: User;
@PrimaryColumn() @PrimaryColumn()

View file

@ -8,6 +8,8 @@ export class AddStatusToExecutions1674138566000 implements ReversibleMigration {
} }
async down({ queryRunner, tablePrefix }: MigrationContext) { async down({ queryRunner, tablePrefix }: MigrationContext) {
await queryRunner.query(`ALTER TABLE \`${tablePrefix}execution_entity\` DROP COLUMN \`status\``); await queryRunner.query(
`ALTER TABLE \`${tablePrefix}execution_entity\` DROP COLUMN \`status\``,
);
} }
} }

View file

@ -8,9 +8,11 @@ import { EventService } from './event.service';
export class EventRelay { export class EventRelay {
constructor(readonly eventService: EventService) {} constructor(readonly eventService: EventService) {}
protected setupListeners<EventNames extends keyof RelayEventMap>(map: { protected setupListeners<EventNames extends keyof RelayEventMap>(
[EventName in EventNames]?: (event: RelayEventMap[EventName]) => void | Promise<void>; map: {
}) { [EventName in EventNames]?: (event: RelayEventMap[EventName]) => void | Promise<void>;
},
) {
for (const [eventName, handler] of Object.entries(map) as Array< for (const [eventName, handler] of Object.entries(map) as Array<
[EventNames, (event: RelayEventMap[EventNames]) => void | Promise<void>] [EventNames, (event: RelayEventMap[EventNames]) => void | Promise<void>]
>) { >) {

View file

@ -28,10 +28,10 @@ export function toSaveSettings(workflowSettings: IWorkflowSettings = {}) {
manual: manual:
workflowSettings === undefined || workflowSettings.saveManualExecutions === 'DEFAULT' workflowSettings === undefined || workflowSettings.saveManualExecutions === 'DEFAULT'
? DEFAULTS.MANUAL ? DEFAULTS.MANUAL
: workflowSettings.saveManualExecutions ?? DEFAULTS.MANUAL, : (workflowSettings.saveManualExecutions ?? DEFAULTS.MANUAL),
progress: progress:
workflowSettings === undefined || workflowSettings.saveExecutionProgress === 'DEFAULT' workflowSettings === undefined || workflowSettings.saveExecutionProgress === 'DEFAULT'
? DEFAULTS.PROGRESS ? DEFAULTS.PROGRESS
: workflowSettings.saveExecutionProgress ?? DEFAULTS.PROGRESS, : (workflowSettings.saveExecutionProgress ?? DEFAULTS.PROGRESS),
}; };
} }

View file

@ -292,7 +292,7 @@ export class ExternalSecretsManager {
} }
settings[provider] = { settings[provider] = {
connected, connected,
connectedAt: connected ? new Date() : settings[provider]?.connectedAt ?? null, connectedAt: connected ? new Date() : (settings[provider]?.connectedAt ?? null),
settings: settings[provider]?.settings ?? {}, settings: settings[provider]?.settings ?? {},
}; };

View file

@ -21,7 +21,7 @@ import type { BooleanLicenseFeature, NumericLicenseFeature } from './interfaces'
import type { RedisServicePubSubPublisher } from './services/redis/redis-service-pub-sub-publisher'; import type { RedisServicePubSubPublisher } from './services/redis/redis-service-pub-sub-publisher';
import { RedisService } from './services/redis.service'; import { RedisService } from './services/redis.service';
type FeatureReturnType = Partial< export type FeatureReturnType = Partial<
{ {
planName: string; planName: string;
} & { [K in NumericLicenseFeature]: number } & { [K in BooleanLicenseFeature]: boolean } } & { [K in NumericLicenseFeature]: number } & { [K in BooleanLicenseFeature]: boolean }

View file

@ -42,12 +42,9 @@ export class MultiMainSetup extends TypedEmitter<MultiMainEvents> {
await this.tryBecomeLeader(); // prevent initial wait await this.tryBecomeLeader(); // prevent initial wait
this.leaderCheckInterval = setInterval( this.leaderCheckInterval = setInterval(async () => {
async () => { await this.checkLeader();
await this.checkLeader(); }, config.getEnv('multiMainSetup.interval') * TIME.SECOND);
},
config.getEnv('multiMainSetup.interval') * TIME.SECOND,
);
} }
async shutdown() { async shutdown() {

View file

@ -15,7 +15,8 @@
"typecheck": "tsc --noEmit", "typecheck": "tsc --noEmit",
"build": "tsc -p tsconfig.build.json", "build": "tsc -p tsconfig.build.json",
"dev": "pnpm watch", "dev": "pnpm watch",
"format": "prettier --write . --ignore-path ../../.prettierignore", "format": "biome format --write .",
"format:check": "biome ci .",
"lint": "eslint . --quiet", "lint": "eslint . --quiet",
"lintfix": "eslint . --fix", "lintfix": "eslint . --fix",
"watch": "tsc -p tsconfig.build.json --watch", "watch": "tsc -p tsconfig.build.json --watch",

View file

@ -1651,9 +1651,9 @@ export class WorkflowExecute {
// array as this shows that the parent nodes executed but they did not have any // array as this shows that the parent nodes executed but they did not have any
// data to pass on. // data to pass on.
const inputsWithData = this.runExecutionData const inputsWithData = this.runExecutionData
.executionData!.waitingExecution[ .executionData!.waitingExecution[nodeName][firstRunIndex].main.map((data, index) =>
nodeName data === null ? null : index,
][firstRunIndex].main.map((data, index) => (data === null ? null : index)) )
.filter((data) => data !== null); .filter((data) => data !== null);
if (requiredInputs !== undefined) { if (requiredInputs !== undefined) {

View file

@ -8,7 +8,7 @@ import { library } from '@fortawesome/fontawesome-svg-core';
import { fas } from '@fortawesome/free-solid-svg-icons'; import { fas } from '@fortawesome/free-solid-svg-icons';
import ElementPlus from 'element-plus'; import ElementPlus from 'element-plus';
import lang from 'element-plus/dist/locale/en.mjs' import lang from 'element-plus/dist/locale/en.mjs';
import { N8nPlugin } from '../src/plugin'; import { N8nPlugin } from '../src/plugin';

View file

@ -0,0 +1,7 @@
{
"$schema": "../../node_modules/@biomejs/biome/configuration_schema.json",
"extends": ["../../biome.jsonc"],
"formatter": {
"ignore": ["theme/**"]
}
}

View file

@ -1,4 +1,4 @@
{ {
"projectId": "Project:65f085d72c13e4e1154414db", "projectId": "Project:65f085d72c13e4e1154414db",
"buildScriptName": "build:storybook" "buildScriptName": "build:storybook"
} }

View file

@ -13,7 +13,8 @@
"build:storybook": "storybook build", "build:storybook": "storybook build",
"storybook": "storybook dev -p 6006", "storybook": "storybook dev -p 6006",
"chromatic": "chromatic", "chromatic": "chromatic",
"format": "prettier --write . --ignore-path ../../.prettierignore", "format": "biome format --write . && prettier --write . --ignore-path ../../.prettierignore",
"format:check": "biome ci . && prettier --check . --ignore-path ../../.prettierignore",
"lint": "eslint src --ext .js,.ts,.vue --quiet", "lint": "eslint src --ext .js,.ts,.vue --quiet",
"lintfix": "eslint src --ext .js,.ts,.vue --fix" "lintfix": "eslint src --ext .js,.ts,.vue --fix"
}, },

View file

@ -37,7 +37,7 @@
--color-assistant-highlight-1: #8c90f2; --color-assistant-highlight-1: #8c90f2;
--color-assistant-highlight-2: #a977f0; --color-assistant-highlight-2: #a977f0;
--color-assistant-highlight-3: #f0778b; --color-assistant-highlight-3: #f0778b;
--color-askAssistant-button-background: #2E2E2E; --color-askAssistant-button-background: #2e2e2e;
--color-askAssistant-button-background-hover: #383839; --color-askAssistant-button-background-hover: #383839;
--color-askAssistant-button-background-active: #414244; --color-askAssistant-button-background-active: #414244;
--color-assistant-inner-highlight-hover: var(--color-askAssistant-button-background-hover); --color-assistant-inner-highlight-hover: var(--color-askAssistant-button-background-hover);

View file

@ -80,11 +80,11 @@
--color-canvas-read-only-line: var(--prim-gray-30); --color-canvas-read-only-line: var(--prim-gray-30);
--color-canvas-selected: var(--prim-gray-70); --color-canvas-selected: var(--prim-gray-70);
--color-canvas-selected-transparent: hsla(var(--prim-gray-h), 47%, 30%, 0.1); --color-canvas-selected-transparent: hsla(var(--prim-gray-h), 47%, 30%, 0.1);
--color-canvas-label-background: hsla( --color-canvas-label-background: hsla(
var(--color-canvas-background-h), var(--color-canvas-background-h),
var(--color-canvas-background-s), var(--color-canvas-background-s),
var(--color-canvas-background-l), var(--color-canvas-background-l),
0.85 0.85
); );
// Nodes // Nodes

View file

@ -11,7 +11,12 @@
"allowSyntheticDefaultImports": true, "allowSyntheticDefaultImports": true,
"baseUrl": ".", "baseUrl": ".",
"types": ["vitest/globals"], "types": ["vitest/globals"],
"typeRoots": ["./node_modules/@testing-library", "./node_modules/@types", "../../node_modules", "../../node_modules/@types"], "typeRoots": [
"./node_modules/@testing-library",
"./node_modules/@types",
"../../node_modules",
"../../node_modules/@types"
],
"paths": { "paths": {
"n8n-design-system/*": ["./src/*"] "n8n-design-system/*": ["./src/*"]
}, },

View file

@ -44,9 +44,9 @@ export default mergeConfig(
dts: false, dts: false,
resolvers: [ resolvers: [
iconsResolver({ iconsResolver({
prefix: 'icon' prefix: 'icon',
}) }),
] ],
}), }),
], ],
resolve: { resolve: {

View file

@ -0,0 +1,8 @@
{
"$schema": "../../node_modules/@biomejs/biome/configuration_schema.json",
"extends": ["../../biome.jsonc"]
// Although nothing is extended here, it is required so biome use the
// editor-ui gitignore file:
// > For now, Biome only takes the ignore file in the working directory into account.
// https://biomejs.dev/guides/integrate-in-vcs/#use-the-ignore-file
}

View file

@ -10,7 +10,8 @@
"dev": "pnpm serve", "dev": "pnpm serve",
"lint": "eslint src --ext .js,.ts,.vue --quiet", "lint": "eslint src --ext .js,.ts,.vue --quiet",
"lintfix": "eslint src --ext .js,.ts,.vue --fix", "lintfix": "eslint src --ext .js,.ts,.vue --fix",
"format": "prettier --write . --ignore-path ../../.prettierignore", "format": "biome format --write . && prettier --write . --ignore-path ../../.prettierignore",
"format:check": "biome ci . && prettier --check . --ignore-path ../../.prettierignore",
"serve": "cross-env VUE_APP_URL_BASE_API=http://localhost:5678/ vite --host 0.0.0.0 --port 8080 dev", "serve": "cross-env VUE_APP_URL_BASE_API=http://localhost:5678/ vite --host 0.0.0.0 --port 8080 dev",
"test": "vitest run", "test": "vitest run",
"test:dev": "vitest" "test:dev": "vitest"

View file

@ -95,7 +95,7 @@ export const codeNodeEditorTheme = ({
: { minHeight: rows && rows !== -1 ? `${Number(rows + 1) * 1.3}em` : 'auto' }), : { minHeight: rows && rows !== -1 ? `${Number(rows + 1) * 1.3}em` : 'auto' }),
}, },
'.cm-gutter,.cm-content': { '.cm-gutter,.cm-content': {
minHeight: rows && rows !== -1 ? 'auto' : minHeight ?? 'calc(35vh - var(--spacing-2xl))', minHeight: rows && rows !== -1 ? 'auto' : (minHeight ?? 'calc(35vh - var(--spacing-2xl))'),
}, },
'.cm-diagnosticAction': { '.cm-diagnosticAction': {
backgroundColor: BASE_STYLING.diagnosticButton.backgroundColor, backgroundColor: BASE_STYLING.diagnosticButton.backgroundColor,

View file

@ -142,7 +142,7 @@ export function groupItemsInSections(
title: section.title, title: section.title,
children: sortAlphabetically children: sortAlphabetically
? sortNodeCreateElements(children[section.key] ?? []) ? sortNodeCreateElements(children[section.key] ?? [])
: children[section.key] ?? [], : (children[section.key] ?? []),
}), }),
); );

View file

@ -405,7 +405,8 @@ export const useExpressionEditor = ({
if (pos === 'lastExpression') { if (pos === 'lastExpression') {
const END_OF_EXPRESSION = ' }}'; const END_OF_EXPRESSION = ' }}';
const endOfLastExpression = readEditorValue().lastIndexOf(END_OF_EXPRESSION); const endOfLastExpression = readEditorValue().lastIndexOf(END_OF_EXPRESSION);
pos = endOfLastExpression !== -1 ? endOfLastExpression : editor.value?.state.doc.length ?? 0; pos =
endOfLastExpression !== -1 ? endOfLastExpression : (editor.value?.state.doc.length ?? 0);
} else if (pos === 'end') { } else if (pos === 'end') {
pos = editor.value?.state.doc.length ?? 0; pos = editor.value?.state.doc.length ?? 0;
} }
@ -414,7 +415,7 @@ export const useExpressionEditor = ({
function select(anchor: number, head: number | 'end' = 'end'): void { function select(anchor: number, head: number | 'end' = 'end'): void {
editor.value?.dispatch({ editor.value?.dispatch({
selection: { anchor, head: head === 'end' ? editor.value?.state.doc.length ?? 0 : head }, selection: { anchor, head: head === 'end' ? (editor.value?.state.doc.length ?? 0) : head },
}); });
} }

View file

@ -433,12 +433,14 @@ export class N8nConnector extends AbstractConnector {
const sourceStubWithOffset = const sourceStubWithOffset =
sourceStub + sourceStub +
(this.getEndpointOffset && params.sourceEndpoint (this.getEndpointOffset && params.sourceEndpoint
? this.getEndpointOffset(params.sourceEndpoint) ?? 0 ? (this.getEndpointOffset(params.sourceEndpoint) ?? 0)
: 0); : 0);
const targetStubWithOffset = const targetStubWithOffset =
targetStub + targetStub +
(this.getEndpointOffset && targetEndpoint ? this.getEndpointOffset(targetEndpoint) ?? 0 : 0); (this.getEndpointOffset && targetEndpoint
? (this.getEndpointOffset(targetEndpoint) ?? 0)
: 0);
// same as paintinfo generated by jsplumb AbstractConnector type // same as paintinfo generated by jsplumb AbstractConnector type
const result = { const result = {

View file

@ -76,7 +76,7 @@ export class I18nClass {
* Render a string of dynamic text, i.e. a string with a constructed path to the localized value. * Render a string of dynamic text, i.e. a string with a constructed path to the localized value.
*/ */
private dynamicRender({ key, fallback }: { key: string; fallback?: string }) { private dynamicRender({ key, fallback }: { key: string; fallback?: string }) {
return this.i18n.te(key) ? this.i18n.t(key).toString() : fallback ?? ''; return this.i18n.te(key) ? this.i18n.t(key).toString() : (fallback ?? '');
} }
displayTimer(msPassed: number, showMs = false): string { displayTimer(msPassed: number, showMs = false): string {

View file

@ -739,7 +739,7 @@ function withCanvasReadOnlyMeta(route: RouteRecordRaw) {
} }
const router = createRouter({ const router = createRouter({
history: createWebHistory(import.meta.env.DEV ? '/' : window.BASE_PATH ?? '/'), history: createWebHistory(import.meta.env.DEV ? '/' : (window.BASE_PATH ?? '/')),
scrollBehavior(to: RouteLocationNormalized, _, savedPosition) { scrollBehavior(to: RouteLocationNormalized, _, savedPosition) {
// saved position == null means the page is NOT visited from history (back button) // saved position == null means the page is NOT visited from history (back button)
if (savedPosition === null && to.name === VIEWS.TEMPLATES && to.meta?.setScrollPosition) { if (savedPosition === null && to.name === VIEWS.TEMPLATES && to.meta?.setScrollPosition) {

View file

@ -189,7 +189,7 @@ export const useCredentialsStore = defineStore(STORES.CREDENTIALS, () => {
? email ? email
? `${name} (${email})` ? `${name} (${email})`
: name : name
: email ?? i18n.baseText('credentialEdit.credentialSharing.info.sharee.fallback'); : (email ?? i18n.baseText('credentialEdit.credentialSharing.info.sharee.fallback'));
}; };
}); });

View file

@ -91,7 +91,7 @@ export const useNDVStore = defineStore(STORES.NDV, {
ndvInputDataWithPinnedData(): INodeExecutionData[] { ndvInputDataWithPinnedData(): INodeExecutionData[] {
const data = this.ndvInputData; const data = this.ndvInputData;
return this.ndvInputNodeName return this.ndvInputNodeName
? useWorkflowsStore().pinDataByNodeName(this.ndvInputNodeName) ?? data ? (useWorkflowsStore().pinDataByNodeName(this.ndvInputNodeName) ?? data)
: data; : data;
}, },
hasInputData(): boolean { hasInputData(): boolean {

View file

@ -21,7 +21,7 @@ export const useWorkflowsEEStore = defineStore(STORES.WORKFLOWS_EE, {
const workflow = useWorkflowsStore().getWorkflowById(workflowId); const workflow = useWorkflowsStore().getWorkflowById(workflowId);
const { name, email } = splitName(workflow?.homeProject?.name ?? ''); const { name, email } = splitName(workflow?.homeProject?.name ?? '');
return name ? (email ? `${name} (${email})` : name) : email ?? fallback; return name ? (email ? `${name} (${email})` : name) : (email ?? fallback);
}; };
}, },
}, },

View file

@ -1,2 +1,2 @@
@import "codemirror"; @import 'codemirror';
@import "vueflow"; @import 'vueflow';

View file

@ -302,8 +302,10 @@ export type ExternalHooksKey = {
[K in keyof ExternalHooks]: `${K}.${Extract<keyof ExternalHooks[K], string>}`; [K in keyof ExternalHooks]: `${K}.${Extract<keyof ExternalHooks[K], string>}`;
}[keyof ExternalHooks]; }[keyof ExternalHooks];
type ExtractHookMethodArray<P extends keyof ExternalHooks, S extends keyof ExternalHooks[P]> = type ExtractHookMethodArray<
ExternalHooks[P][S] extends Array<infer U> ? U : never; P extends keyof ExternalHooks,
S extends keyof ExternalHooks[P],
> = ExternalHooks[P][S] extends Array<infer U> ? U : never;
type ExtractHookMethodFunction<T> = T extends ExternalHooksMethod ? T : never; type ExtractHookMethodFunction<T> = T extends ExternalHooksMethod ? T : never;

View file

@ -6,7 +6,7 @@ import { sentryVitePlugin } from '@sentry/vite-plugin';
import packageJSON from './package.json'; import packageJSON from './package.json';
import { vitestConfig } from '../design-system/vite.config.mts'; import { vitestConfig } from '../design-system/vite.config.mts';
import icons from 'unplugin-icons/vite'; import icons from 'unplugin-icons/vite';
import iconsResolver from 'unplugin-icons/resolver' import iconsResolver from 'unplugin-icons/resolver';
import components from 'unplugin-vue-components/vite'; import components from 'unplugin-vue-components/vite';
const vendorChunks = ['vue', 'vue-router']; const vendorChunks = ['vue', 'vue-router'];
@ -80,9 +80,9 @@ const plugins = [
dts: './src/components.d.ts', dts: './src/components.d.ts',
resolvers: [ resolvers: [
iconsResolver({ iconsResolver({
prefix: 'icon' prefix: 'icon',
}) }),
] ],
}), }),
vue(), vue(),
]; ];

View file

@ -13,7 +13,8 @@
"dev": "pnpm watch", "dev": "pnpm watch",
"build": "tsc --noEmit", "build": "tsc --noEmit",
"build-node-dev": "tsc", "build-node-dev": "tsc",
"format": "prettier --write . --ignore-path ../../.prettierignore", "format": "biome format --write .",
"format:check": "biome ci .",
"lint": "eslint . --quiet", "lint": "eslint . --quiet",
"lintfix": "eslint . --fix", "lintfix": "eslint . --fix",
"prepack": "echo \"Building project...\" && rm -rf dist && tsc -b", "prepack": "echo \"Building project...\" && rm -rf dist && tsc -b",

View file

@ -0,0 +1,7 @@
{
"$schema": "../../node_modules/@biomejs/biome/configuration_schema.json",
"extends": ["../../biome.jsonc"],
"formatter": {
"ignore": ["nodes/**/test/*.json"]
}
}

View file

@ -169,7 +169,7 @@ export class TableFieldMapper {
} }
setField(field: string) { setField(field: string) {
return this.mapIds ? field : this.nameToIdMapping[field] ?? field; return this.mapIds ? field : (this.nameToIdMapping[field] ?? field);
} }
idsToNames(obj: Record<string, unknown>) { idsToNames(obj: Record<string, unknown>) {

View file

@ -19,15 +19,15 @@ export namespace BrevoNode {
type ValidatedEmail = ToEmail | SenderEmail | CCEmail | BBCEmail; type ValidatedEmail = ToEmail | SenderEmail | CCEmail | BBCEmail;
const enum OVERRIDE_MAP_VALUES { const enum OVERRIDE_MAP_VALUES {
'CATEGORY' = 'category', CATEGORY = 'category',
'NORMAL' = 'boolean', NORMAL = 'boolean',
'TRANSACTIONAL' = 'id', TRANSACTIONAL = 'id',
} }
const enum OVERRIDE_MAP_TYPE { const enum OVERRIDE_MAP_TYPE {
'CATEGORY' = 'category', CATEGORY = 'category',
'NORMAL' = 'normal', NORMAL = 'normal',
'TRANSACTIONAL' = 'transactional', TRANSACTIONAL = 'transactional',
} }
export const INTERCEPTORS = new Map<string, (body: JsonObject) => void>([ export const INTERCEPTORS = new Map<string, (body: JsonObject) => void>([

View file

@ -16,19 +16,19 @@ export const enum TLP {
} }
export const enum ObservableDataType { export const enum ObservableDataType {
'domain' = 'domain', domain = 'domain',
'file' = 'file', file = 'file',
'filename' = 'filename', filename = 'filename',
'fqdn' = 'fqdn', fqdn = 'fqdn',
'hash' = 'hash', hash = 'hash',
'ip' = 'ip', ip = 'ip',
'mail' = 'mail', mail = 'mail',
'mail_subject' = 'mail_subject', mail_subject = 'mail_subject',
'other' = 'other', other = 'other',
'regexp' = 'regexp', regexp = 'regexp',
'registry' = 'registry', registry = 'registry',
'uri_path' = 'uri_path', uri_path = 'uri_path',
'url' = 'url', url = 'url',
'user-agent' = 'user-agent', 'user-agent' = 'user-agent',
} }
export interface IJob { export interface IJob {

View file

@ -32,9 +32,9 @@ export interface IUser {
isAnonymous?: boolean; isAnonymous?: boolean;
} }
const enum Type { const enum Type {
'TYPE_UNSPECIFIED', TYPE_UNSPECIFIED,
'HUMAN', HUMAN,
'BOT', BOT,
} }
// // TODO: define other interfaces // // TODO: define other interfaces

View file

@ -485,8 +485,7 @@ export class GoogleSheet {
columnValuesList?: string[]; columnValuesList?: string[];
}) { }) {
const decodedRange = this.getDecodedSheetRange(range); const decodedRange = this.getDecodedSheetRange(range);
// prettier-ignore const keyRowRange = `${decodedRange.name}!${decodedRange.start?.column || ''}${keyRowIndex + 1}:${decodedRange.end?.column || ''}${keyRowIndex + 1}`;
const keyRowRange = `${decodedRange.name}!${decodedRange.start?.column || ''}${keyRowIndex + 1}:${decodedRange.end?.column || ''}${keyRowIndex + 1}`;
const sheetDatakeyRow = columnNamesList || (await this.getData(keyRowRange, valueRenderMode)); const sheetDatakeyRow = columnNamesList || (await this.getData(keyRowRange, valueRenderMode));

View file

@ -84,7 +84,6 @@ export async function sheetsSearch(
returnData.push({ returnData.push({
name: sheet.properties!.title as string, name: sheet.properties!.title as string,
value: (sheet.properties!.sheetId as number) || 'gid=0', value: (sheet.properties!.sheetId as number) || 'gid=0',
//prettier-ignore
url: `https://docs.google.com/spreadsheets/d/${spreadsheetId}/edit#gid=${sheet.properties!.sheetId}`, url: `https://docs.google.com/spreadsheets/d/${spreadsheetId}/edit#gid=${sheet.properties!.sheetId}`,
}); });
} }

View file

@ -144,9 +144,12 @@ export class KoBoToolboxTrigger implements INodeType {
const req = this.getRequestObject(); const req = this.getRequestObject();
const formatOptions = this.getNodeParameter('formatOptions') as IDataObject; const formatOptions = this.getNodeParameter('formatOptions') as IDataObject;
// prettier-ignore
const responseData = formatOptions.reformat const responseData = formatOptions.reformat
? formatSubmission(req.body as IDataObject, parseStringList(formatOptions.selectMask as string), parseStringList(formatOptions.numberMask as string)) ? formatSubmission(
req.body as IDataObject,
parseStringList(formatOptions.selectMask as string),
parseStringList(formatOptions.numberMask as string),
)
: req.body; : req.body;
if (formatOptions.download) { if (formatOptions.download) {

View file

@ -27,7 +27,6 @@ import { filters } from './descriptions/Filters';
function uuidValidateWithoutDashes(this: IExecuteFunctions, value: string) { function uuidValidateWithoutDashes(this: IExecuteFunctions, value: string) {
if (uuidValidate(value)) return true; if (uuidValidate(value)) return true;
if (value.length == 32) { if (value.length == 32) {
//prettier-ignore
const strWithDashes = `${value.slice(0, 8)}-${value.slice(8, 12)}-${value.slice(12, 16)}-${value.slice(16, 20)}-${value.slice(20)}`; const strWithDashes = `${value.slice(0, 8)}-${value.slice(8, 12)}-${value.slice(12, 16)}-${value.slice(16, 20)}-${value.slice(20)}`;
if (uuidValidate(strWithDashes)) return true; if (uuidValidate(strWithDashes)) return true;
} }
@ -309,7 +308,6 @@ export function formatBlocks(blocks: IDataObject[]) {
[block.type as string]: { [block.type as string]: {
...(block.type === 'to_do' ? { checked: block.checked } : {}), ...(block.type === 'to_do' ? { checked: block.checked } : {}),
...(block.type === 'image' ? { type: 'external', external: { url: block.url } } : {}), ...(block.type === 'image' ? { type: 'external', external: { url: block.url } } : {}),
// prettier-ignore,
...(!['image'].includes(block.type as string) ? getTextBlocks(block) : {}), ...(!['image'].includes(block.type as string) ? getTextBlocks(block) : {}),
}, },
}); });
@ -867,9 +865,12 @@ export type FileRecord = {
}; };
}; };
}; };
// prettier-ignore
export async function downloadFiles(this: IExecuteFunctions | IPollFunctions, records: FileRecord[], pairedItem?: IPairedItemData[]): Promise<INodeExecutionData[]> {
export async function downloadFiles(
this: IExecuteFunctions | IPollFunctions,
records: FileRecord[],
pairedItem?: IPairedItemData[],
): Promise<INodeExecutionData[]> {
const elements: INodeExecutionData[] = []; const elements: INodeExecutionData[] = [];
for (const record of records) { for (const record of records) {
const element: INodeExecutionData = { json: {}, binary: {} }; const element: INodeExecutionData = { json: {}, binary: {} };
@ -887,10 +888,12 @@ export async function downloadFiles(this: IExecuteFunctions | IPollFunctions, re
'', '',
{}, {},
{}, {},
file?.file?.url as string || file?.external?.url as string, (file?.file?.url as string) || (file?.external?.url as string),
{ json: false, encoding: null }, { json: false, encoding: null },
); );
element.binary![`${key}_${index}`] = await this.helpers.prepareBinaryData(data as Buffer); element.binary![`${key}_${index}`] = await this.helpers.prepareBinaryData(
data as Buffer,
);
} }
} }
} }

View file

@ -536,8 +536,10 @@ export async function pgUpdate(
} else { } else {
const where = const where =
' WHERE ' + ' WHERE ' +
// eslint-disable-next-line n8n-local-rules/no-interpolation-in-regular-string updateKeys
updateKeys.map((entry) => pgp.as.name(entry.name) + ' = ${' + entry.prop + '}').join(' AND '); // eslint-disable-next-line n8n-local-rules/no-interpolation-in-regular-string
.map((entry) => pgp.as.name(entry.name) + ' = ${' + entry.prop + '}')
.join(' AND ');
if (mode === 'transaction') { if (mode === 'transaction') {
return await db.tx(async (t) => { return await db.tx(async (t) => {
const result: IDataObject[] = []; const result: IDataObject[] = [];
@ -664,8 +666,10 @@ export async function pgUpdateV2(
} else { } else {
const where = const where =
' WHERE ' + ' WHERE ' +
// eslint-disable-next-line n8n-local-rules/no-interpolation-in-regular-string updateKeys
updateKeys.map((entry) => pgp.as.name(entry.name) + ' = ${' + entry.prop + '}').join(' AND '); // eslint-disable-next-line n8n-local-rules/no-interpolation-in-regular-string
.map((entry) => pgp.as.name(entry.name) + ' = ${' + entry.prop + '}')
.join(' AND ');
if (mode === 'transaction') { if (mode === 'transaction') {
return await db.tx(async (t) => { return await db.tx(async (t) => {
const result: IDataObject[] = []; const result: IDataObject[] = [];

View file

@ -62,9 +62,10 @@ export async function quickbaseApiRequest(
} }
} }
//@ts-ignore export async function getFieldsObject(
// prettier-ignore this: IHookFunctions | ILoadOptionsFunctions | IExecuteFunctions,
export async function getFieldsObject(this: IHookFunctions | ILoadOptionsFunctions | IExecuteFunctions, tableId: string): any { tableId: string,
): Promise<any> {
const fieldsLabelKey: { [key: string]: number } = {}; const fieldsLabelKey: { [key: string]: number } = {};
const fieldsIdKey: { [key: number]: string } = {}; const fieldsIdKey: { [key: number]: string } = {};
const data = await quickbaseApiRequest.call(this, 'GET', '/fields', {}, { tableId }); const data = await quickbaseApiRequest.call(this, 'GET', '/fields', {}, { tableId });

View file

@ -158,9 +158,12 @@ export function addAdditionalFields(
} }
sendRows.push(sendButtonData); sendRows.push(sendButtonData);
} }
// @ts-ignore // @ts-ignore
// prettier-ignore const array = (body.reply_markup as ITelegramInlineReply | ITelegramReplyKeyboard)[
((body.reply_markup as ITelegramInlineReply | ITelegramReplyKeyboard)[setParameterName] as ITelegramKeyboardButton[][]).push(sendRows); setParameterName
] as ITelegramKeyboardButton[][];
array.push(sendRows);
} }
} }
} else if (replyMarkupOption === 'forceReply') { } else if (replyMarkupOption === 'forceReply') {

View file

@ -5,19 +5,19 @@ export const enum ObservableStatus {
DELETED = 'Deleted', DELETED = 'Deleted',
} }
export const enum ObservableDataType { export const enum ObservableDataType {
'domain' = 'domain', domain = 'domain',
'file' = 'file', file = 'file',
'filename' = 'filename', filename = 'filename',
'fqdn' = 'fqdn', fqdn = 'fqdn',
'hash' = 'hash', hash = 'hash',
'ip' = 'ip', ip = 'ip',
'mail' = 'mail', mail = 'mail',
'mail_subject' = 'mail_subject', mail_subject = 'mail_subject',
'other' = 'other', other = 'other',
'regexp' = 'regexp', regexp = 'regexp',
'registry' = 'registry', registry = 'registry',
'uri_path' = 'uri_path', uri_path = 'uri_path',
'url' = 'url', url = 'url',
'user-agent' = 'user-agent', 'user-agent' = 'user-agent',
} }

View file

@ -9,7 +9,8 @@
"typecheck": "tsc --noEmit", "typecheck": "tsc --noEmit",
"build": "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json && pnpm n8n-copy-icons && pnpm n8n-generate-translations && pnpm build:metadata", "build": "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json && pnpm n8n-copy-icons && pnpm n8n-generate-translations && pnpm build:metadata",
"build:metadata": "pnpm n8n-generate-known && pnpm n8n-generate-ui-types", "build:metadata": "pnpm n8n-generate-known && pnpm n8n-generate-ui-types",
"format": "prettier --write . --ignore-path ../../.prettierignore", "format": "biome format --write .",
"format:check": "biome ci .",
"lint": "eslint . --quiet && node ./scripts/validate-load-options-methods.js", "lint": "eslint . --quiet && node ./scripts/validate-load-options-methods.js",
"lintfix": "eslint . --fix", "lintfix": "eslint . --fix",
"watch": "tsc-watch -p tsconfig.build.json --onCompilationComplete \"tsc-alias -p tsconfig.build.json\" --onSuccess \"pnpm n8n-generate-ui-types\"", "watch": "tsc-watch -p tsconfig.build.json --onCompilationComplete \"tsc-alias -p tsconfig.build.json\" --onSuccess \"pnpm n8n-generate-ui-types\"",

View file

@ -18,7 +18,8 @@
"dev": "pnpm watch", "dev": "pnpm watch",
"typecheck": "tsc --noEmit", "typecheck": "tsc --noEmit",
"build": "tsc -p tsconfig.build.json", "build": "tsc -p tsconfig.build.json",
"format": "prettier --write . --ignore-path ../../.prettierignore", "format": "biome format --write .",
"format:check": "biome ci .",
"lint": "eslint . --quiet", "lint": "eslint . --quiet",
"lintfix": "eslint . --fix", "lintfix": "eslint . --fix",
"watch": "tsc -p tsconfig.build.json --watch", "watch": "tsc -p tsconfig.build.json --watch",

View file

@ -157,13 +157,11 @@ describe('tmpl Expression Parser', () => {
}); });
test('Multiple optional chains in an expression', () => { test('Multiple optional chains in an expression', () => {
expect(extendTransform('$json.test?.test2($json.test?.test2)')?.code) expect(extendTransform('$json.test?.test2($json.test?.test2)')?.code).toBe(`window.chainCancelToken2 = ((window.chainValue2 = $json.test) ?? undefined) === undefined, window.chainCancelToken2 === true ? undefined : window.chainValue2.test2(
.toBe(`window.chainCancelToken2 = ((window.chainValue2 = $json.test) ?? undefined) === undefined, window.chainCancelToken2 === true ? undefined : window.chainValue2.test2(
(window.chainCancelToken1 = ((window.chainValue1 = $json.test) ?? undefined) === undefined, window.chainCancelToken1 === true ? undefined : window.chainValue1.test2) (window.chainCancelToken1 = ((window.chainValue1 = $json.test) ?? undefined) === undefined, window.chainCancelToken1 === true ? undefined : window.chainValue1.test2)
);`); );`);
expect(extendTransform('$json.test?.test2($json.test.sum?.())')?.code) expect(extendTransform('$json.test?.test2($json.test.sum?.())')?.code).toBe(`window.chainCancelToken2 = ((window.chainValue2 = $json.test) ?? undefined) === undefined, window.chainCancelToken2 === true ? undefined : window.chainValue2.test2(
.toBe(`window.chainCancelToken2 = ((window.chainValue2 = $json.test) ?? undefined) === undefined, window.chainCancelToken2 === true ? undefined : window.chainValue2.test2(
(window.chainCancelToken1 = ((window.chainValue1 = extendOptional($json.test, "sum")) ?? undefined) === undefined, window.chainCancelToken1 === true ? undefined : window.chainValue1()) (window.chainCancelToken1 = ((window.chainValue1 = extendOptional($json.test, "sum")) ?? undefined) === undefined, window.chainCancelToken1 === true ? undefined : window.chainValue1())
);`); );`);
}); });

View file

@ -1959,7 +1959,7 @@ describe('RoutingNode', () => {
executeSingleFunctions.getNodeParameter = (parameterName: string) => executeSingleFunctions.getNodeParameter = (parameterName: string) =>
parameterName in testData.input.node.parameters parameterName in testData.input.node.parameters
? testData.input.node.parameters[parameterName] ? testData.input.node.parameters[parameterName]
: getNodeParameter(parameterName) ?? {}; : (getNodeParameter(parameterName) ?? {});
const result = await routingNode.runNode( const result = await routingNode.runNode(
inputData, inputData,

View file

@ -1,106 +1,97 @@
{ {
"meta": { "meta": {
"instanceId": "a786b722078489c1fa382391a9f3476c2784761624deb2dfb4634827256d51a0" "instanceId": "a786b722078489c1fa382391a9f3476c2784761624deb2dfb4634827256d51a0"
}, },
"nodes": [ "nodes": [
{ {
"parameters": { "parameters": {
"assignments": { "assignments": {
"assignments": [ "assignments": [
{ {
"id": "3058c300-b377-41b7-9c90-a01372f9b581", "id": "3058c300-b377-41b7-9c90-a01372f9b581",
"name": "firstName", "name": "firstName",
"value": "Joe", "value": "Joe",
"type": "string" "type": "string"
}, },
{ {
"id": "bb871662-c23c-4234-ac0c-b78c279bbf34", "id": "bb871662-c23c-4234-ac0c-b78c279bbf34",
"name": "lastName", "name": "lastName",
"value": "Smith", "value": "Smith",
"type": "string" "type": "string"
} }
] ]
}, },
"options": {} "options": {}
}, },
"id": "baee2bf4-5083-4cbe-8e51-4eddcf859ef5", "id": "baee2bf4-5083-4cbe-8e51-4eddcf859ef5",
"name": "PinnedSet", "name": "PinnedSet",
"type": "n8n-nodes-base.set", "type": "n8n-nodes-base.set",
"typeVersion": 3.3, "typeVersion": 3.3,
"position": [ "position": [1120, 380]
1120, },
380 {
] "parameters": {
}, "assignments": {
{ "assignments": [
"parameters": { {
"assignments": { "id": "a482f1fd-4815-4da4-a733-7beafb43c500",
"assignments": [ "name": "test",
{ "value": "={{ $('PinnedSet').all().json }}\n{{ $('PinnedSet').item.json.firstName }}\n{{ $('PinnedSet').first().json.firstName }}\n{{ $('PinnedSet').itemMatching(0).json.firstName }}\n{{ $('PinnedSet').itemMatching(1).json.firstName }}\n{{ $('PinnedSet').last().json.firstName }}\n{{ $('PinnedSet').all()[0].json.firstName }}\n{{ $('PinnedSet').all()[1].json.firstName }}\n\n{{ $input.first().json.firstName }}\n{{ $input.last().json.firstName }}\n{{ $input.item.json.firstName }}\n\n{{ $json.firstName }}\n{{ $data.firstName }}\n\n{{ $items()[0].json.firstName }}",
"id": "a482f1fd-4815-4da4-a733-7beafb43c500", "type": "string"
"name": "test", }
"value": "={{ $('PinnedSet').all().json }}\n{{ $('PinnedSet').item.json.firstName }}\n{{ $('PinnedSet').first().json.firstName }}\n{{ $('PinnedSet').itemMatching(0).json.firstName }}\n{{ $('PinnedSet').itemMatching(1).json.firstName }}\n{{ $('PinnedSet').last().json.firstName }}\n{{ $('PinnedSet').all()[0].json.firstName }}\n{{ $('PinnedSet').all()[1].json.firstName }}\n\n{{ $input.first().json.firstName }}\n{{ $input.last().json.firstName }}\n{{ $input.item.json.firstName }}\n\n{{ $json.firstName }}\n{{ $data.firstName }}\n\n{{ $items()[0].json.firstName }}", ]
"type": "string" },
} "options": {}
] },
}, "id": "2a543169-e2c1-4764-ac63-09534310b2b9",
"options": {} "name": "NotPinnedSet1",
}, "type": "n8n-nodes-base.set",
"id": "2a543169-e2c1-4764-ac63-09534310b2b9", "typeVersion": 3.3,
"name": "NotPinnedSet1", "position": [1360, 380]
"type": "n8n-nodes-base.set", },
"typeVersion": 3.3, {
"position": [ "parameters": {},
1360, "id": "f36672e5-8c87-480e-a5b8-de9da6b63192",
380 "name": "Start",
] "type": "n8n-nodes-base.manualTrigger",
}, "position": [920, 380],
{ "typeVersion": 1
"parameters": {}, }
"id": "f36672e5-8c87-480e-a5b8-de9da6b63192", ],
"name": "Start", "connections": {
"type": "n8n-nodes-base.manualTrigger", "PinnedSet": {
"position": [ "main": [
920, [
380 {
], "node": "NotPinnedSet1",
"typeVersion": 1 "type": "main",
} "index": 0
], }
"connections": { ]
"PinnedSet": { ]
"main": [ },
[ "Start": {
{ "main": [
"node": "NotPinnedSet1", [
"type": "main", {
"index": 0 "node": "PinnedSet",
} "type": "main",
] "index": 0
] }
}, ]
"Start": { ]
"main": [ }
[ },
{ "pinData": {
"node": "PinnedSet", "PinnedSet": [
"type": "main", {
"index": 0 "firstName": "Joe",
} "lastName": "Smith"
] },
] {
} "firstName": "Joan",
}, "lastName": "Summers"
"pinData": { }
"PinnedSet": [ ]
{ }
"firstName": "Joe",
"lastName": "Smith"
},
{
"firstName": "Joan",
"lastName": "Summers"
}
]
}
} }

View file

@ -123,6 +123,9 @@ importers:
.: .:
devDependencies: devDependencies:
'@biomejs/biome':
specifier: ^1.9.0
version: 1.9.0
'@n8n_io/eslint-config': '@n8n_io/eslint-config':
specifier: workspace:* specifier: workspace:*
version: link:packages/@n8n_io/eslint-config version: link:packages/@n8n_io/eslint-config
@ -147,6 +150,9 @@ importers:
jest-mock-extended: jest-mock-extended:
specifier: ^3.0.4 specifier: ^3.0.4
version: 3.0.4(jest@29.6.2(@types/node@18.16.16)(ts-node@10.9.2(@types/node@18.16.16)(typescript@5.6.2)))(typescript@5.6.2) version: 3.0.4(jest@29.6.2(@types/node@18.16.16)(ts-node@10.9.2(@types/node@18.16.16)(typescript@5.6.2)))(typescript@5.6.2)
lefthook:
specifier: ^1.7.15
version: 1.7.15
nock: nock:
specifier: ^13.3.2 specifier: ^13.3.2
version: 13.3.2 version: 13.3.2
@ -641,9 +647,6 @@ importers:
eslint-plugin-n8n-local-rules: eslint-plugin-n8n-local-rules:
specifier: ^1.0.0 specifier: ^1.0.0
version: 1.0.0 version: 1.0.0
eslint-plugin-prettier:
specifier: ^5.1.3
version: 5.1.3(@types/eslint@8.56.5)(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.2.5)
eslint-plugin-unicorn: eslint-plugin-unicorn:
specifier: ^51.0.1 specifier: ^51.0.1
version: 51.0.1(eslint@8.57.0) version: 51.0.1(eslint@8.57.0)
@ -1853,7 +1856,7 @@ importers:
devDependencies: devDependencies:
'@langchain/core': '@langchain/core':
specifier: 'catalog:' specifier: 'catalog:'
version: 0.2.31(langchain@0.2.18(axios@1.7.4)(openai@4.58.0))(openai@4.58.0) version: 0.2.31(langchain@0.2.18(axios@1.7.4)(openai@4.58.0(zod@3.23.8)))(openai@4.58.0(zod@3.23.8))
'@types/deep-equal': '@types/deep-equal':
specifier: ^1.0.1 specifier: ^1.0.1
version: 1.0.1 version: 1.0.1
@ -3137,6 +3140,59 @@ packages:
'@bcoe/v8-coverage@0.2.3': '@bcoe/v8-coverage@0.2.3':
resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==}
'@biomejs/biome@1.9.0':
resolution: {integrity: sha512-NlWh2F1wbxB3O/wE+aohGL0BziTS6e+6+dyFvpdeqLsbQZY7EsiklFb9W5Xs41U4vEmY7ANgdNp+oVDij6sQdA==}
engines: {node: '>=14.21.3'}
hasBin: true
'@biomejs/cli-darwin-arm64@1.9.0':
resolution: {integrity: sha512-2w9v/NRtYSmodx5QWQ49OGcyGKSECdWKbzc7n532Iq5sBhkKk996fd19icT6BuL54f01KFKRCRibAW+A2rg1Kw==}
engines: {node: '>=14.21.3'}
cpu: [arm64]
os: [darwin]
'@biomejs/cli-darwin-x64@1.9.0':
resolution: {integrity: sha512-fBVt8jJQi0zX0SJ1C+tdzUbRpuX/07sgtBXEhunWRkPjdi6W/2S1sYHQ1wKn4OKiRAKfHM2Cf2FNO7hQvY61dA==}
engines: {node: '>=14.21.3'}
cpu: [x64]
os: [darwin]
'@biomejs/cli-linux-arm64-musl@1.9.0':
resolution: {integrity: sha512-Jy84mZ4vcppdmWMgQWOCfd8qIVC/vHmlaS5gy7GXkdWlBKSQ56YxEXTU58MHTbZ16LwJQpK2IulqRCC/rqWLBA==}
engines: {node: '>=14.21.3'}
cpu: [arm64]
os: [linux]
'@biomejs/cli-linux-arm64@1.9.0':
resolution: {integrity: sha512-l8U2lcqsl9yKPP5WUdIrKH//C1pWyM2cSUfcTBn6GSvXmsSjBNEdGSdM4Wfne777Oe/9ONaD1Ga53U2HksHHLw==}
engines: {node: '>=14.21.3'}
cpu: [arm64]
os: [linux]
'@biomejs/cli-linux-x64-musl@1.9.0':
resolution: {integrity: sha512-N3enoFoIrkB6qJWyYfTiYmFdB1R/Mrij1dd1xBHqxxCKZY9GRkEswRX3F1Uqzo5T+9Iu8nAQobDqI/ygicYy/Q==}
engines: {node: '>=14.21.3'}
cpu: [x64]
os: [linux]
'@biomejs/cli-linux-x64@1.9.0':
resolution: {integrity: sha512-8jAzjrrJTj510pwq4aVs7ZKkOvEy1D+nzl9DKvrPh4TOyUw5Ie+0EDwXGE2RAkCKHkGNOQBZ78WtIdsATgz5sA==}
engines: {node: '>=14.21.3'}
cpu: [x64]
os: [linux]
'@biomejs/cli-win32-arm64@1.9.0':
resolution: {integrity: sha512-AIjwJTGfdWGMRluSQ9pDB29nzce077dfHh0/HMqzztKzgD3spyuo2R9VoaFpbR0hLHPWEH6g6OxxDO7hfkXNkQ==}
engines: {node: '>=14.21.3'}
cpu: [arm64]
os: [win32]
'@biomejs/cli-win32-x64@1.9.0':
resolution: {integrity: sha512-4/4wTjNSoyNkm1SzcUaStDx46baX1VJRXtUoeEHjX9LfedR5N3qwZz5KfrRUnCd2fl5bmXK1CwMqKBkoF6zEiA==}
engines: {node: '>=14.21.3'}
cpu: [x64]
os: [win32]
'@chromatic-com/storybook@1.5.0': '@chromatic-com/storybook@1.5.0':
resolution: {integrity: sha512-LkLKv7SWu/6kGep1ft2HA1T/cm14wU0zoW71gE4cZRcgUoRQJtyhITFTLHrjqAxz6bVqNgqzQtd5oBZ2nK3L3g==} resolution: {integrity: sha512-LkLKv7SWu/6kGep1ft2HA1T/cm14wU0zoW71gE4cZRcgUoRQJtyhITFTLHrjqAxz6bVqNgqzQtd5oBZ2nK3L3g==}
engines: {node: '>=16.0.0', yarn: '>=1.22.18'} engines: {node: '>=16.0.0', yarn: '>=1.22.18'}
@ -9956,6 +10012,60 @@ packages:
leac@0.6.0: leac@0.6.0:
resolution: {integrity: sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg==} resolution: {integrity: sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg==}
lefthook-darwin-arm64@1.7.15:
resolution: {integrity: sha512-o8JgCnLM7UgF9g0MwarHJFoj6aVSSkUInHpsQZegV1c7CVQY/LIXgSeAWRb9XBvuUjByJ/HiHFMp9/hAALTwxQ==}
cpu: [arm64]
os: [darwin]
lefthook-darwin-x64@1.7.15:
resolution: {integrity: sha512-nrdoex0icmXYl7AAvG7WtfEzjQtX/kWvM88jPu/gijH6VhAjp110Y8VScB7rWOcApb5kNNeqd1nKMAFgZ8KhAg==}
cpu: [x64]
os: [darwin]
lefthook-freebsd-arm64@1.7.15:
resolution: {integrity: sha512-zl1TPynklJZZ/YsWb2H0gfErQbey318i2W85wIKGEk8kC2UzOgYTuPffnfi7kANei9ntZnhvGgilc6tqYOPuGQ==}
cpu: [arm64]
os: [freebsd]
lefthook-freebsd-x64@1.7.15:
resolution: {integrity: sha512-/gKPwhWhZ3Q/efGs73/qw6nyR4WCT74oSTgn8wabAJO5+T/2FXTKzo7IiKkQmScmY5OcnD/0teJbJZ17VWSSOg==}
cpu: [x64]
os: [freebsd]
lefthook-linux-arm64@1.7.15:
resolution: {integrity: sha512-re2f8WmYw19n8ojit0rnKbERAzD1/iCpU/Y8anXOjD/ROw/cpSfO88uKQrUCNY9Rp4XLtkkp9oDJs3Eg7JS7vA==}
cpu: [arm64]
os: [linux]
lefthook-linux-x64@1.7.15:
resolution: {integrity: sha512-Kj6ieTlhFGlbPDyVFeOb296MS9x/Jj5y/xTPLBM+EKbdsTJSvUYu5FdtEWfhpLyWmPfkZtULHcTQE1hoo9Q4Cg==}
cpu: [x64]
os: [linux]
lefthook-openbsd-arm64@1.7.15:
resolution: {integrity: sha512-85amE23mJ4BC9OThLkt+QCeVwue2Cr0ezN9LSwP0h8+royyj7YRcSu0VM/Et3B9LO50T2bpdI9norOqTcPZ9yA==}
cpu: [arm64]
os: [openbsd]
lefthook-openbsd-x64@1.7.15:
resolution: {integrity: sha512-vXx/PpcalFgdvqkoHLI4KTGZp0ti+VCCL7RqDTA6n+GZpxPTWEXSOz3GuwNALX93Dn6MOYQYktKtXADwy24fcA==}
cpu: [x64]
os: [openbsd]
lefthook-windows-arm64@1.7.15:
resolution: {integrity: sha512-jPKdQOLWQLRPO3VfI3ptpmdQBBsXTwaCLKXMo/gcSyU0xE/ltPD4QqvHzTAFJo00VcKRHjv9QeH69qhENjJtjw==}
cpu: [arm64]
os: [win32]
lefthook-windows-x64@1.7.15:
resolution: {integrity: sha512-tlkSU669+b64AsqytGy1W3au7h8kFjt5ejLhTkErJpylTqThZIHm/GI0wUmpX+ud8kekM+9j407dweAHYOQ1XA==}
cpu: [x64]
os: [win32]
lefthook@1.7.15:
resolution: {integrity: sha512-HW2mYkhg0a3RH2t57+ZJwacJiSIuDEhsXQAaCw6iGeN7zowdUV7g5QtnRdFdPkaK2eaNFpG6Rp0GsTrl/v0gNg==}
hasBin: true
leven@3.1.0: leven@3.1.0:
resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==}
engines: {node: '>=6'} engines: {node: '>=6'}
@ -16142,6 +16252,41 @@ snapshots:
'@bcoe/v8-coverage@0.2.3': {} '@bcoe/v8-coverage@0.2.3': {}
'@biomejs/biome@1.9.0':
optionalDependencies:
'@biomejs/cli-darwin-arm64': 1.9.0
'@biomejs/cli-darwin-x64': 1.9.0
'@biomejs/cli-linux-arm64': 1.9.0
'@biomejs/cli-linux-arm64-musl': 1.9.0
'@biomejs/cli-linux-x64': 1.9.0
'@biomejs/cli-linux-x64-musl': 1.9.0
'@biomejs/cli-win32-arm64': 1.9.0
'@biomejs/cli-win32-x64': 1.9.0
'@biomejs/cli-darwin-arm64@1.9.0':
optional: true
'@biomejs/cli-darwin-x64@1.9.0':
optional: true
'@biomejs/cli-linux-arm64-musl@1.9.0':
optional: true
'@biomejs/cli-linux-arm64@1.9.0':
optional: true
'@biomejs/cli-linux-x64-musl@1.9.0':
optional: true
'@biomejs/cli-linux-x64@1.9.0':
optional: true
'@biomejs/cli-win32-arm64@1.9.0':
optional: true
'@biomejs/cli-win32-x64@1.9.0':
optional: true
'@chromatic-com/storybook@1.5.0(react@18.2.0)': '@chromatic-com/storybook@1.5.0(react@18.2.0)':
dependencies: dependencies:
chromatic: 11.4.1 chromatic: 11.4.1
@ -17149,20 +17294,7 @@ snapshots:
dependencies: dependencies:
'@langchain/core': 0.2.31(langchain@0.2.18(axios@1.7.4)(openai@4.58.0(zod@3.23.8)))(openai@4.58.0(zod@3.23.8)) '@langchain/core': 0.2.31(langchain@0.2.18(axios@1.7.4)(openai@4.58.0(zod@3.23.8)))(openai@4.58.0(zod@3.23.8))
js-tiktoken: 1.0.12 js-tiktoken: 1.0.12
openai: 4.58.0(zod@3.23.8) openai: 4.58.0(encoding@0.1.13)(zod@3.23.8)
zod: 3.23.8
zod-to-json-schema: 3.23.2(zod@3.23.8)
transitivePeerDependencies:
- encoding
- langchain
- supports-color
optional: true
'@langchain/openai@0.2.10(langchain@0.2.18(axios@1.7.4)(openai@4.58.0))':
dependencies:
'@langchain/core': 0.2.31(langchain@0.2.18(axios@1.7.4)(openai@4.58.0))(openai@4.58.0(zod@3.23.8))
js-tiktoken: 1.0.12
openai: 4.58.0(zod@3.23.8)
zod: 3.23.8 zod: 3.23.8
zod-to-json-schema: 3.23.2(zod@3.23.8) zod-to-json-schema: 3.23.2(zod@3.23.8)
transitivePeerDependencies: transitivePeerDependencies:
@ -22425,7 +22557,7 @@ snapshots:
eslint-import-resolver-node@0.3.9: eslint-import-resolver-node@0.3.9:
dependencies: dependencies:
debug: 3.2.7(supports-color@5.5.0) debug: 3.2.7(supports-color@8.1.1)
is-core-module: 2.13.1 is-core-module: 2.13.1
resolve: 1.22.8 resolve: 1.22.8
transitivePeerDependencies: transitivePeerDependencies:
@ -22450,7 +22582,7 @@ snapshots:
eslint-module-utils@2.8.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0): eslint-module-utils@2.8.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0):
dependencies: dependencies:
debug: 3.2.7(supports-color@5.5.0) debug: 3.2.7(supports-color@8.1.1)
optionalDependencies: optionalDependencies:
'@typescript-eslint/parser': 7.2.0(eslint@8.57.0)(typescript@5.6.2) '@typescript-eslint/parser': 7.2.0(eslint@8.57.0)(typescript@5.6.2)
eslint: 8.57.0 eslint: 8.57.0
@ -22470,7 +22602,7 @@ snapshots:
array.prototype.findlastindex: 1.2.3 array.prototype.findlastindex: 1.2.3
array.prototype.flat: 1.3.2 array.prototype.flat: 1.3.2
array.prototype.flatmap: 1.3.2 array.prototype.flatmap: 1.3.2
debug: 3.2.7(supports-color@5.5.0) debug: 3.2.7(supports-color@8.1.1)
doctrine: 2.1.0 doctrine: 2.1.0
eslint: 8.57.0 eslint: 8.57.0
eslint-import-resolver-node: 0.3.9 eslint-import-resolver-node: 0.3.9
@ -23336,7 +23468,7 @@ snapshots:
array-parallel: 0.1.3 array-parallel: 0.1.3
array-series: 0.1.5 array-series: 0.1.5
cross-spawn: 4.0.2 cross-spawn: 4.0.2
debug: 3.2.7(supports-color@5.5.0) debug: 3.2.7(supports-color@8.1.1)
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
@ -24816,34 +24948,7 @@ snapshots:
optionalDependencies: optionalDependencies:
'@langchain/core': 0.2.31(langchain@0.2.18(axios@1.7.4)(openai@4.58.0(zod@3.23.8)))(openai@4.58.0(zod@3.23.8)) '@langchain/core': 0.2.31(langchain@0.2.18(axios@1.7.4)(openai@4.58.0(zod@3.23.8)))(openai@4.58.0(zod@3.23.8))
langchain: 0.2.18(axios@1.7.4)(openai@4.58.0(zod@3.23.8)) langchain: 0.2.18(axios@1.7.4)(openai@4.58.0(zod@3.23.8))
openai: 4.58.0(zod@3.23.8) openai: 4.58.0(encoding@0.1.13)(zod@3.23.8)
langsmith@0.1.51(@langchain/core@0.2.31(langchain@0.2.18(axios@1.7.4)(openai@4.58.0))(openai@4.58.0(zod@3.23.8)))(langchain@0.2.18(axios@1.7.4)(openai@4.58.0))(openai@4.58.0(zod@3.23.8)):
dependencies:
'@types/uuid': 10.0.0
commander: 10.0.1
p-queue: 6.6.2
p-retry: 4.6.2
semver: 7.6.0
uuid: 10.0.0
optionalDependencies:
'@langchain/core': 0.2.31(langchain@0.2.18(axios@1.7.4)(openai@4.58.0))(openai@4.58.0(zod@3.23.8))
langchain: 0.2.18(axios@1.7.4)(openai@4.58.0)
openai: 4.58.0(zod@3.23.8)
optional: true
langsmith@0.1.51(@langchain/core@0.2.31(langchain@0.2.18(axios@1.7.4)(openai@4.58.0))(openai@4.58.0))(langchain@0.2.18(axios@1.7.4)(openai@4.58.0))(openai@4.58.0):
dependencies:
'@types/uuid': 10.0.0
commander: 10.0.1
p-queue: 6.6.2
p-retry: 4.6.2
semver: 7.6.0
uuid: 10.0.0
optionalDependencies:
'@langchain/core': 0.2.31(langchain@0.2.18(axios@1.7.4)(openai@4.58.0))(openai@4.58.0)
langchain: 0.2.18(axios@1.7.4)(openai@4.58.0)
openai: 4.58.0(zod@3.23.8)
lazy-ass@1.6.0: {} lazy-ass@1.6.0: {}
@ -24867,6 +24972,49 @@ snapshots:
leac@0.6.0: {} leac@0.6.0: {}
lefthook-darwin-arm64@1.7.15:
optional: true
lefthook-darwin-x64@1.7.15:
optional: true
lefthook-freebsd-arm64@1.7.15:
optional: true
lefthook-freebsd-x64@1.7.15:
optional: true
lefthook-linux-arm64@1.7.15:
optional: true
lefthook-linux-x64@1.7.15:
optional: true
lefthook-openbsd-arm64@1.7.15:
optional: true
lefthook-openbsd-x64@1.7.15:
optional: true
lefthook-windows-arm64@1.7.15:
optional: true
lefthook-windows-x64@1.7.15:
optional: true
lefthook@1.7.15:
optionalDependencies:
lefthook-darwin-arm64: 1.7.15
lefthook-darwin-x64: 1.7.15
lefthook-freebsd-arm64: 1.7.15
lefthook-freebsd-x64: 1.7.15
lefthook-linux-arm64: 1.7.15
lefthook-linux-x64: 1.7.15
lefthook-openbsd-arm64: 1.7.15
lefthook-openbsd-x64: 1.7.15
lefthook-windows-arm64: 1.7.15
lefthook-windows-x64: 1.7.15
leven@3.1.0: {} leven@3.1.0: {}
levn@0.3.0: levn@0.3.0:
@ -26152,24 +26300,6 @@ snapshots:
- encoding - encoding
- supports-color - supports-color
openai@4.58.0(zod@3.23.8):
dependencies:
'@types/node': 18.16.16
'@types/node-fetch': 2.6.4
'@types/qs': 6.9.15
abort-controller: 3.0.0
agentkeepalive: 4.2.1
form-data-encoder: 1.7.2
formdata-node: 4.4.1
node-fetch: 2.7.0(encoding@0.1.13)
qs: 6.11.0
optionalDependencies:
zod: 3.23.8
transitivePeerDependencies:
- encoding
- supports-color
optional: true
openapi-sampler@1.4.0: openapi-sampler@1.4.0:
dependencies: dependencies:
'@types/json-schema': 7.0.15 '@types/json-schema': 7.0.15
@ -26374,7 +26504,7 @@ snapshots:
pdf-parse@1.1.1: pdf-parse@1.1.1:
dependencies: dependencies:
debug: 3.2.7(supports-color@5.5.0) debug: 3.2.7(supports-color@8.1.1)
node-ensure: 0.0.0 node-ensure: 0.0.0
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
@ -27272,7 +27402,7 @@ snapshots:
rhea@1.0.24: rhea@1.0.24:
dependencies: dependencies:
debug: 3.2.7(supports-color@5.5.0) debug: 3.2.7(supports-color@8.1.1)
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color

View file

@ -5,42 +5,61 @@ import path from 'path';
import { execSync } from 'child_process'; import { execSync } from 'child_process';
const prettier = path.resolve('node_modules', '.bin', 'prettier'); const prettier = path.resolve('node_modules', '.bin', 'prettier');
const biome = path.resolve('node_modules', '.bin', 'biome');
if (!fs.existsSync(prettier)) { [prettier, biome].forEach((bin) => {
throw new Error( if (!fs.existsSync(bin)) {
[`Prettier not found at path: ${prettier}`, 'Please run `pnpm i` first'].join('\n'), throw new Error(
); [`${path.basename(bin)} not found at path: ${bin}`, 'Please run `pnpm i` first'].join('\n'),
} );
}
});
const config = path.resolve('.prettierrc.js'); const prettierConfig = path.resolve('.prettierrc.js');
const biomeConfig = path.resolve('biome.jsonc');
const ignore = path.resolve('.prettierignore'); const ignore = path.resolve('.prettierignore');
const ROOT_DIRS_TO_SKIP = ['.git', 'node_modules', 'packages']; const ROOT_DIRS_TO_SKIP = ['.git', 'node_modules', 'packages', '.turbo', 'cypress'];
const EXTENSIONS_TO_FORMAT = ['.md', '.yml', '.js', '.json', '.ts']; const EXTENSIONS_TO_FORMAT_WITH_PRETTIER = ['.yml'];
const EXTENSIONS_TO_FORMAT_WITH_BIOME = ['.js', '.json', '.ts'];
const isDir = (path) => fs.lstatSync(path).isDirectory(); const isDir = (path) => fs.lstatSync(path).isDirectory();
const isTarget = (path) => EXTENSIONS_TO_FORMAT.some((ext) => path.endsWith(ext)); const isPrettierTarget = (path) =>
EXTENSIONS_TO_FORMAT_WITH_PRETTIER.some((ext) => path.endsWith(ext));
const isBiomeTarget = (path) => EXTENSIONS_TO_FORMAT_WITH_BIOME.some((ext) => path.endsWith(ext));
const walk = (dir, test, found = []) => { const biomeTargets = [];
const prettierTargets = [];
const walk = (dir) => {
fs.readdirSync(dir).forEach((entry) => { fs.readdirSync(dir).forEach((entry) => {
const entryPath = path.resolve(dir, entry); const entryPath = path.resolve(dir, entry);
if (isDir(entryPath)) walk(entryPath, test, found); if (isDir(entryPath)) walk(entryPath);
if (test(entryPath)) found.push(entryPath); if (isPrettierTarget(entryPath)) prettierTargets.push(entryPath);
if (isBiomeTarget(entryPath)) biomeTargets.push(entryPath);
}); });
return found;
}; };
const targets = fs fs.readdirSync('.').forEach((cur) => {
.readdirSync('.') if (ROOT_DIRS_TO_SKIP.includes(cur)) return;
.reduce((acc, cur) => { if (isDir(cur)) walk(cur);
if (ROOT_DIRS_TO_SKIP.includes(cur)) return acc; if (isPrettierTarget(cur)) prettierTargets.push(cur);
if (isDir(cur)) return [...acc, ...walk(cur, isTarget)]; if (isBiomeTarget(cur)) biomeTargets.push(cur);
if (isTarget(cur)) return [...acc, cur]; });
return acc; execSync(
}, []) [
.join(' '); prettier,
'--config',
prettierConfig,
'--ignore-path',
ignore,
'--write',
prettierTargets.join(' '),
].join(' '),
);
execSync([prettier, '--config', config, '--ignore-path', ignore, '--write', targets].join(' ')); execSync(
[biome, 'format', '--write', `--config-path=${biomeConfig}`, biomeTargets.join(' ')].join(' '),
);

View file

@ -23,6 +23,7 @@
"dependsOn": ["^typecheck"] "dependsOn": ["^typecheck"]
}, },
"format": {}, "format": {},
"format:check": {},
"lint:backend": { "lint:backend": {
"dependsOn": [ "dependsOn": [
"@n8n/api-types#lint", "@n8n/api-types#lint",