chore: Remove shamefully-hoist (#32569)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Matsu 2026-06-25 13:03:07 +03:00 committed by GitHub
parent c605ea6955
commit 024d04397b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
72 changed files with 953 additions and 305 deletions

1
.npmrc
View File

@ -6,7 +6,6 @@ strict-peer-dependencies = false
prefer-workspace-packages = true
link-workspace-packages = deep
hoist = true
shamefully-hoist = true
hoist-workspace-packages = false
loglevel = warn
package-manager-strict=false

View File

@ -37,6 +37,7 @@ const esmDependencies = [
'p-retry',
'is-network-error',
'uuid',
'change-case',
// Add other ESM dependencies that need to be transformed here
];

View File

@ -89,7 +89,9 @@
"nodemon": "^3.0.1",
"npm-run-all2": "^7.0.2",
"p-limit": "^3.1.0",
"prettier": "catalog:",
"rimraf": "^5.0.1",
"stylelint": "catalog:",
"supertest": "^7.1.1",
"ts-jest": "^29.4.9",
"tsc-alias": "^1.8.10",
@ -118,6 +120,7 @@
"@opentelemetry/core": "2.8.0",
"@types/node": "^20.17.50",
"chokidar": "4.0.3",
"esbuild": "catalog:",
"multer": "^2.2.0",
"prebuild-install": "7.1.3",
"pug": "^3.0.3",
@ -126,7 +129,7 @@
"tslib": "^2.6.2",
"tsconfig-paths": "^4.2.0",
"typescript": "catalog:",
"vue-tsc": "^2.2.8",
"vue-tsc": "catalog:frontend",
"gaxios": ">=7.1.1",
"google-gax": "^4.3.7",
"ws": ">=8.20.1",
@ -155,7 +158,6 @@
"bn.js@4": "5.2.3",
"bn.js@5": "5.2.3",
"lodash": "4.18.1",
"lodash-es": "4.18.1",
"minimatch@<=5.1.8": "5.1.8",
"minimatch@10": "10.2.3",
"@hono/node-server": "1.19.13",
@ -191,7 +193,6 @@
"@turbo/darwin-64@<=2.9.18": "2.9.18",
"@turbo/linux-64@<=2.9.18": "2.9.18",
"@turbo/windows-64@<=2.9.18": "2.9.18",
"esbuild": "catalog:",
"undici@5": "catalog:undici-v6",
"undici@6": "catalog:undici-v6",
"undici@7": "catalog:undici-v7"

View File

@ -81,7 +81,7 @@
"@opentelemetry/exporter-trace-otlp-http": ">=0.50.0",
"@opentelemetry/sdk-trace-base": ">=1.0.0",
"@opentelemetry/sdk-trace-node": ">=1.0.0",
"ai": "^6.0.197",
"ai": "catalog:",
"ajv": "^8.18.0",
"langsmith": "catalog:",
"undici": "catalog:undici-v7",
@ -106,8 +106,9 @@
"devDependencies": {
"@n8n/typescript-config": "workspace:*",
"@n8n/vitest-config": "workspace:*",
"@types/json-schema": "^7.0.15",
"@types/json-schema": "catalog:",
"@vitest/coverage-v8": "catalog:",
"dotenv": "catalog:",
"cross-env": "catalog:",
"nock": "catalog:",
"vitest": "catalog:",

View File

@ -85,12 +85,15 @@
"dist"
],
"devDependencies": {
"@types/json-schema": "^7.0.15",
"@types/json-schema": "catalog:",
"@n8n/vitest-config": "workspace:*",
"@vitest/coverage-v8": "catalog:",
"vitest": "catalog:",
"vitest-mock-extended": "catalog:",
"@types/mime-types": "catalog:",
"@types/lodash": "catalog:",
"@types/proxy-from-env": "catalog:",
"fast-glob": "catalog:",
"tsx": "catalog:",
"axios": "catalog:",
"nock": "catalog:"

View File

@ -88,7 +88,10 @@
"@n8n/typescript-config": "workspace:*",
"@n8n/vitest-config": "workspace:*",
"@types/cli-progress": "^3.11.5",
"@types/turndown": "^5.0.6",
"@types/jsdom": "catalog:",
"@types/lodash": "catalog:",
"@types/proxy-from-env": "catalog:",
"@types/turndown": "catalog:",
"@vitest/coverage-v8": "catalog:",
"cli-progress": "^3.12.0",
"cli-table3": "^0.6.3",

View File

@ -32,6 +32,7 @@
"minifaker": "1.34.1"
},
"dependencies": {
"@n8n_io/ai-assistant-sdk": "catalog:",
"n8n-workflow": "workspace:*",
"xss": "catalog:",
"@n8n/permissions": "workspace:*",

View File

@ -29,6 +29,7 @@
"@n8n/di": "workspace:*",
"callsites": "catalog:",
"flatted": "catalog:",
"logform": "2.6.1",
"n8n-workflow": "workspace:*",
"stream-json": "catalog:",
"picocolors": "catalog:",

View File

@ -79,6 +79,7 @@
"@n8n/typescript-config": "workspace:*",
"@n8n/vitest-config": "workspace:*",
"@types/proxy-from-env": "catalog:",
"@types/qs": "catalog:",
"@vitest/coverage-v8": "catalog:",
"nock": "catalog:",
"vitest": "catalog:",

View File

@ -37,7 +37,7 @@
"dependencies": {
"@oclif/core": "4.0.7",
"axios": "catalog:",
"dotenv": "17.2.3",
"dotenv": "catalog:",
"nanoid": "catalog:",
"zx": "^8.8.5"
},

View File

@ -38,7 +38,9 @@
"@codemirror/language": "catalog:",
"@codemirror/state": "catalog:",
"@codemirror/view": "catalog:",
"@lezer/common": "catalog:"
"@lezer/common": "catalog:",
"@lezer/highlight": "catalog:",
"@lezer/lr": "catalog:"
},
"devDependencies": {
"@codemirror/buildhelper": "^0.1.5",
@ -46,6 +48,7 @@
"@n8n/typescript-config": "workspace:*",
"@rollup/plugin-node-resolve": "^9.0.0",
"@n8n/vitest-config": "workspace:*",
"ist": "1.1.7",
"vitest": "catalog:",
"rollup": "^2.52.2"
},

View File

@ -54,10 +54,11 @@
"devDependencies": {
"@n8n/typescript-config": "workspace:*",
"@n8n/vitest-config": "workspace:*",
"@types/express": "catalog:",
"@types/lodash": "catalog:",
"@testcontainers/postgresql": "catalog:",
"@vitest/coverage-v8": "catalog:",
"express": "5.1.0",
"express": "catalog:",
"testcontainers": "catalog:",
"typescript": "catalog:",
"vitest": "catalog:",

View File

@ -26,7 +26,7 @@
"dependencies": {
"@n8n/config": "workspace:*",
"@n8n/di": "workspace:*",
"express": "5.1.0",
"express": "catalog:",
"reflect-metadata": "catalog:"
},
"devDependencies": {

View File

@ -51,6 +51,7 @@
"globals": "^16.2.0",
"typescript": "catalog:",
"typescript-eslint": "^8.35.0",
"vite": "catalog:",
"vitest": "catalog:"
},
"peerDependencies": {

View File

@ -349,6 +349,7 @@ export const baseConfig = tseslint.config(
'**/*.config.js',
'**/scripts/*.ts',
'**/scripts/*.js',
'**/*.stories.ts',
],
optionalDependencies: false,
peerDependencies: false,

View File

@ -36,7 +36,6 @@ export const frontendConfig = tseslint.config(
{
files: ['**/*.test.ts', '**/test/**/*.ts', '**/__tests__/**/*.ts', '**/*.stories.ts'],
rules: {
'import-x/no-extraneous-dependencies': 'warn',
'vue/one-component-per-file': 'off',
// TODO: remove these

View File

@ -42,6 +42,7 @@
"eslint-plugin-eslint-plugin": "^7.0.0",
"rimraf": "catalog:",
"typescript": "catalog:",
"vite": "catalog:",
"vitest": "catalog:"
},
"peerDependencies": {

View File

@ -51,8 +51,9 @@
"@n8n/vitest-config": "workspace:*",
"@types/jmespath": "^0.15.0",
"@types/lodash": "catalog:",
"@types/luxon": "3.2.0",
"@types/luxon": "catalog:",
"@types/md5": "^2.3.5",
"esbuild": "catalog:",
"typescript": "catalog:",
"vitest": "catalog:"
},

View File

@ -34,6 +34,8 @@
"@types/imap": "^0.8.40",
"@types/quoted-printable": "^1.0.2",
"@types/utf8": "^3.0.3",
"vite": "catalog:",
"vitest": "catalog:",
"vitest-mock-extended": "catalog:"
},
"license": "LicenseRef-n8n-sustainable-use"

View File

@ -63,6 +63,7 @@
"@n8n/workflow-sdk": "workspace:*",
"@opentelemetry/api": "^1.9.0",
"@thednp/dommatrix": "^2.0.12",
"ai": "catalog:",
"csv-parse": "catalog:",
"fast-glob": "catalog:",
"flatted": "catalog:",
@ -87,9 +88,9 @@
"@n8n/ai-workflow-builder": "workspace:*",
"@n8n/typescript-config": "workspace:*",
"@n8n/vitest-config": "workspace:*",
"@types/luxon": "3.2.0",
"@types/luxon": "catalog:",
"@types/psl": "1.1.3",
"@types/turndown": "^5.0.5",
"@types/turndown": "catalog:",
"@vitest/coverage-v8": "catalog:",
"tsx": "catalog:",
"vitest": "catalog:",

View File

@ -65,7 +65,7 @@
},
"devDependencies": {
"@n8n/typescript-config": "workspace:*",
"@types/json-schema": "^7.0.15",
"@types/json-schema": "catalog:",
"zod": "catalog:",
"@n8n/vitest-config": "workspace:*",
"@vitest/coverage-v8": "catalog:",

View File

@ -41,14 +41,16 @@
"@n8n/design-system": "workspace:*",
"@n8n/utils": "workspace:*",
"vue": "catalog:frontend",
"vue-i18n": "catalog:frontend"
"vue-i18n": "catalog:frontend",
"zod": "catalog:"
},
"devDependencies": {
"@iconify-json/lucide": "catalog:",
"@modelcontextprotocol/sdk": "catalog:",
"@n8n/eslint-config": "workspace:*",
"@n8n/typescript-config": "workspace:*",
"@n8n/vitest-config": "workspace:*",
"@types/semver": "^7.7.0",
"@types/semver": "catalog:",
"@vitejs/plugin-vue": "catalog:frontend",
"@vue/test-utils": "catalog:frontend",
"rimraf": "catalog:",

View File

@ -22,6 +22,7 @@
"vue": "catalog:frontend"
},
"devDependencies": {
"@iconify-json/lucide": "catalog:",
"@n8n/typescript-config": "workspace:*",
"@n8n/vitest-config": "workspace:*",
"@types/chrome": "0.0.300",

View File

@ -41,8 +41,9 @@
"devDependencies": {
"@n8n/typescript-config": "workspace:*",
"@n8n/vitest-config": "workspace:*",
"@types/turndown": "^5.0.6",
"@types/ws": "^8.18.1",
"@types/jsdom": "catalog:",
"@types/turndown": "catalog:",
"@types/ws": "catalog:",
"@types/yargs-parser": "21.0.0",
"@vitest/coverage-v8": "catalog:",
"vitest": "catalog:"

View File

@ -51,11 +51,11 @@
"@n8n/eslint-plugin-community-nodes": "workspace:*",
"@n8n/ai-node-sdk": "workspace:*",
"@oclif/core": "^4.5.2",
"change-case": "^5.4.4",
"change-case": "catalog:",
"eslint": "catalog:",
"eslint-import-resolver-typescript": "^4.4.3",
"eslint-plugin-import-x": "^4.15.2",
"eslint-plugin-n8n-nodes-base": "1.16.7",
"eslint-plugin-n8n-nodes-base": "catalog:",
"fast-glob": "catalog:",
"handlebars": "4.7.9",
"picocolors": "catalog:",
@ -70,6 +70,7 @@
"@n8n/vitest-config": "workspace:*",
"@oclif/test": "^4.1.13",
"typescript": "catalog:",
"vite": "catalog:",
"vitest": "catalog:",
"vitest-mock-extended": "catalog:"
},

View File

@ -74,7 +74,7 @@ function createConfig(supportCloud = true): ConfigArray {
},
);
}
export const config = createConfig();
export const configWithoutCloudSupport = createConfig(false);
export const config: ConfigArray = createConfig();
export const configWithoutCloudSupport: ConfigArray = createConfig(false);
export default config;

View File

@ -214,13 +214,19 @@
"@n8n/vitest-config": "workspace:*",
"@typescript-eslint/typescript-estree": "^8.35.0",
"@types/basic-auth": "catalog:",
"@types/cheerio": "^0.22.15",
"@types/express": "catalog:",
"@types/html-to-text": "^9.0.1",
"@types/json-schema": "^7.0.15",
"@types/json-schema": "catalog:",
"@types/jsdom": "catalog:",
"@types/lodash": "catalog:",
"@types/mime-types": "catalog:",
"@types/oracledb": "catalog:",
"@types/pg": "^8.15.6",
"@types/sanitize-html": "catalog:",
"@types/temp": "^0.9.1",
"@vitest/coverage-v8": "catalog:",
"eslint-plugin-n8n-nodes-base": "catalog:",
"fast-glob": "catalog:",
"vitest": "catalog:",
"vitest-mock-extended": "catalog:"
@ -243,6 +249,7 @@
"@langchain/cohere": "1.0.1",
"@langchain/community": "catalog:",
"@langchain/core": "catalog:",
"@langchain/google-common": "2.1.24",
"@langchain/google-genai": "2.1.24",
"@langchain/google-vertexai": "2.1.24",
"@langchain/groq": "1.0.2",
@ -277,6 +284,7 @@
"@pinecone-database/pinecone": "^5.0.2",
"@qdrant/js-client-rest": "^1.16.2",
"@smithy/node-http-handler": "4.5.0",
"@smithy/types": "4.13.1",
"@supabase/supabase-js": "catalog:",
"@xata.io/client": "0.28.4",
"@zilliz/milvus2-sdk-node": "^2.5.7",
@ -287,6 +295,7 @@
"cohere-ai": "7.14.0",
"d3-dsv": "2.0.0",
"epub2": "3.0.2",
"express": "catalog:",
"form-data": "catalog:",
"generate-schema": "2.6.0",
"html-to-text": "9.0.5",
@ -303,6 +312,7 @@
"n8n-nodes-base": "workspace:*",
"n8n-workflow": "workspace:*",
"openai": "^6.34.0",
"oracledb": "catalog:",
"pg": "catalog:",
"redis": "4.6.14",
"sanitize-html": "catalog:",

View File

@ -27,7 +27,7 @@
"watch": "tsc --watch"
},
"dependencies": {
"stylelint": "^16.23.0",
"stylelint": "catalog:",
"stylelint-config-standard-scss": "^15.0.1",
"stylelint-scss": "^6.12.1",
"postcss-html": "^1.8.0",
@ -39,11 +39,9 @@
"rimraf": "catalog:",
"@n8n/vitest-config": "workspace:*",
"@vitest/coverage-v8": "catalog:",
"vite": "catalog:",
"vitest": "catalog:",
"vitest-mock-extended": "catalog:"
},
"peerDependencies": {
"stylelint": ">= 16"
},
"license": "LicenseRef-n8n-sustainable-use"
}

View File

@ -40,6 +40,7 @@
"@n8n/config": "workspace:*",
"@n8n/di": "workspace:*",
"@n8n/errors": "workspace:*",
"@sentry/core": "catalog:sentry",
"@sentry/node": "catalog:sentry",
"acorn": "8.14.0",
"acorn-walk": "8.3.4",
@ -54,6 +55,8 @@
"@n8n/typescript-config": "workspace:*",
"@n8n/vitest-config": "workspace:*",
"@types/lodash": "catalog:",
"@types/luxon": "catalog:",
"@types/ws": "catalog:",
"@vitest/coverage-v8": "catalog:",
"vitest": "catalog:",
"vitest-mock-extended": "catalog:"

View File

@ -58,10 +58,5 @@
"ast-types": "^0.16.1",
"esprima-next": "^5.8.4",
"recast": "^0.22.0"
},
"pnpm": {
"overrides": {
"@babel/traverse": "^7.23.2"
}
}
}

View File

@ -1 +1 @@
import '@testing-library/jest-dom';
import '@testing-library/jest-dom/vitest';

View File

@ -90,7 +90,8 @@
"@n8n/typescript-config": "workspace:*",
"@n8n/vitest-config": "workspace:*",
"@types/adm-zip": "^0.5.7",
"@types/estree": "^1.0.8",
"@types/estree": "catalog:",
"@types/lodash": "catalog:",
"@vitest/coverage-v8": "catalog:",
"adm-zip": "^0.5.16",
"vitest": "catalog:"

View File

@ -77,18 +77,25 @@
"@types/flat": "^5.0.5",
"@types/formidable": "^3.4.5",
"@types/json-diff": "^1.0.0",
"@types/json-schema": "catalog:",
"@types/jsonwebtoken": "catalog:",
"@types/lodash": "catalog:",
"@types/luxon": "catalog:",
"@types/ms": "catalog:",
"@types/multer": "^2.1.0",
"@types/nodemailer": "catalog:",
"@types/psl": "^1.1.0",
"@types/replacestream": "^4.0.1",
"@types/semver": "catalog:",
"@types/shelljs": "^0.8.11",
"@types/sshpk": "^1.17.4",
"@types/superagent": "^8.1.9",
"@types/swagger-ui-express": "^4.1.8",
"@types/syslog-client": "^1.1.2",
"@types/turndown": "catalog:",
"@types/uuid": "catalog:",
"@types/validator": "^13.7.0",
"@types/ws": "^8.18.1",
"@types/ws": "catalog:",
"@types/xml2js": "catalog:",
"@types/yargs-parser": "21.0.0",
"@vvo/tzdb": "^6.141.0",
@ -121,6 +128,7 @@
"@chat-adapter/slack": "catalog:",
"@chat-adapter/state-memory": "catalog:",
"@chat-adapter/telegram": "catalog:",
"@daytona/sdk": "catalog:",
"@google-cloud/secret-manager": "5.6.0",
"@joplin/turndown-plugin-gfm": "catalog:",
"@langchain/core": "catalog:",
@ -168,7 +176,7 @@
"bcryptjs": "2.4.3",
"bull": "4.16.4",
"cache-manager": "catalog:",
"change-case": "4.1.2",
"change-case": "catalog:",
"chat": "catalog:",
"class-transformer": "0.5.1",
"class-validator": "0.14.0",
@ -178,8 +186,8 @@
"cron": "catalog:",
"csrf": "3.1.0",
"csv-parse": "catalog:",
"dotenv": "17.2.3",
"express": "5.1.0",
"dotenv": "catalog:",
"express": "catalog:",
"express-handlebars": "8.0.1",
"express-openapi-validator": "5.5.3",
"express-prom-bundle": "8.0.0",
@ -199,6 +207,7 @@
"isolated-vm": "catalog:",
"jose": "^6.2.2",
"json-diff": "1.0.6",
"json-schema": "catalog:",
"jsonschema": "1.4.1",
"jsonwebtoken": "catalog:",
"langsmith": "catalog:",
@ -207,6 +216,7 @@
"lodash": "catalog:",
"luxon": "catalog:",
"moment-timezone": "catalog:",
"ms": "catalog:",
"multer": "^2.2.0",
"n8n-core": "workspace:*",
"n8n-editor-ui": "workspace:*",

View File

@ -1,13 +1,13 @@
import { GlobalConfig } from '@n8n/config';
import { AuthenticatedRequest } from '@n8n/db';
import { RestController } from '@n8n/decorators';
import { RestController, StaticRouterMetadata } from '@n8n/decorators';
import { Container } from '@n8n/di';
import { Router } from 'express';
import { createProxyMiddleware } from 'http-proxy-middleware';
@RestController('/ph')
export class PostHogController {
static routers = [
static routers: StaticRouterMetadata[] = [
{
path: '/',
router: (() => {

View File

@ -1,14 +1,13 @@
import type { Sandbox, SandboxState } from '@daytona/sdk';
import { redactText } from '@n8n/agents';
import { loadDaytona } from '@n8n/agents/sandbox';
import { Logger } from '@n8n/backend-common';
import { AgentsConfig } from '@n8n/config';
import { Service } from '@n8n/di';
import type { Sandbox, SandboxState } from '@daytona/sdk';
import { nanoid } from 'nanoid';
import { InstanceSettings } from 'n8n-core';
import { createHash } from 'node:crypto';
import { OperationalError } from 'n8n-workflow';
import { nanoid } from 'nanoid';
import { createHash } from 'node:crypto';
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
import { NotFoundError } from '@/errors/response-errors/not-found.error';
@ -25,13 +24,6 @@ import {
parseRipgrepFilesOutput,
parseRipgrepOutput,
} from './agent-knowledge-commands';
import {
AGENT_KNOWLEDGE_VOLUME_MOUNT_PATH,
assertKnowledgePathSegment,
buildKnowledgeVolumeSubpath,
fromVolumeStorageReference,
type AgentKnowledgeFilesystem,
} from './agent-knowledge-storage';
import { isAgentKnowledgeBaseEnabled } from './agent-knowledge-gate';
import {
assertValidKnowledgeFilePath,
@ -48,6 +40,13 @@ import {
type SearchKnowledgeRequest,
type SearchKnowledgeResult,
} from './agent-knowledge-retrieval';
import {
AGENT_KNOWLEDGE_VOLUME_MOUNT_PATH,
assertKnowledgePathSegment,
buildKnowledgeVolumeSubpath,
fromVolumeStorageReference,
type AgentKnowledgeFilesystem,
} from './agent-knowledge-storage';
import { AgentFileRepository } from './repositories/agent-file.repository';
import { AgentRepository } from './repositories/agent.repository';

View File

@ -15,7 +15,6 @@ import { InstanceSettings } from 'n8n-core';
import { createRunExecutionData } from 'n8n-workflow';
import { InsightsByPeriodRepository } from '@/modules/insights/database/repositories/insights-by-period.repository';
import { InsightsRawRepository } from '@/modules/insights/database/repositories/insights-raw.repository';
import { InsightsCollectionService } from '@/modules/insights/insights-collection.service';
import { InsightsCompactionService } from '@/modules/insights/insights-compaction.service';
import { WorkflowStatisticsService } from '@/services/workflow-statistics.service';
@ -69,7 +68,6 @@ describe('Insights vs Workflow Statistics Integration', () => {
let insightsCollectionService: InsightsCollectionService;
let insightsCompactionService: InsightsCompactionService;
let insightsByPeriodRepository: InsightsByPeriodRepository;
let insightsRawRepository: InsightsRawRepository;
let workflowStatisticsRepository: WorkflowStatisticsRepository;
let workflowRunner: WorkflowRunner;
let executionRepository: ExecutionRepository;
@ -89,7 +87,6 @@ describe('Insights vs Workflow Statistics Integration', () => {
insightsCollectionService = Container.get(InsightsCollectionService);
insightsCompactionService = Container.get(InsightsCompactionService);
insightsByPeriodRepository = Container.get(InsightsByPeriodRepository);
insightsRawRepository = Container.get(InsightsRawRepository);
workflowStatisticsRepository = Container.get(WorkflowStatisticsRepository);
workflowRunner = Container.get(WorkflowRunner);
executionRepository = Container.get(ExecutionRepository);
@ -168,14 +165,20 @@ describe('Insights vs Workflow Statistics Integration', () => {
}
/**
* Helper to wait for insights to be compacted (raw insights cleared and compacted data available)
* Helper to wait for insights to be compacted.
*
* Polls until the compacted success count reaches the expected total. Waiting on the
* terminal count (rather than "some compacted data exists and raw is drained") avoids a
* race where events still buffered in the collection service haven't been flushed to
* InsightsRaw yet, so compaction runs on a partial set and the count comes up short.
*/
async function waitForCompaction(workflowId: string, timeout = 10000): Promise<void> {
async function waitForCompaction(
workflowId: string,
expectedSuccessCount: number,
timeout = 20000,
): Promise<void> {
const start = Date.now();
while (Date.now() - start < timeout) {
// Check if raw insights have been compacted (should be low or zero)
const rawInsights = await insightsRawRepository.find();
// Check if compacted insights exist for this workflow
const compactedInsights = await insightsByPeriodRepository.find({
where: {
metadata: { workflowId },
@ -183,13 +186,18 @@ describe('Insights vs Workflow Statistics Integration', () => {
relations: ['metadata'],
});
// Compaction is done if we have compacted data and few/no raw insights
if (compactedInsights.length > 0 && rawInsights.length < 10) {
const successCount = compactedInsights
.filter((insight) => insight.type === 'success')
.reduce((sum, insight) => sum + insight.value, 0);
if (successCount >= expectedSuccessCount) {
return;
}
await new Promise((resolve) => setTimeout(resolve, 500));
await new Promise((resolve) => setTimeout(resolve, 200));
}
throw new Error(`Insights compaction did not complete within ${timeout}ms`);
throw new Error(
`Insights compaction did not reach ${expectedSuccessCount} successes within ${timeout}ms`,
);
}
/**
@ -230,7 +238,7 @@ describe('Insights vs Workflow Statistics Integration', () => {
await waitForStatistics(workflow.id, 10);
// Wait for automatic compaction to complete
await waitForCompaction(workflow.id);
await waitForCompaction(workflow.id, 10);
// ============================================================
// ASSERT: Query workflow statistics

View File

@ -37,7 +37,10 @@
"@types/express": "catalog:",
"@types/jsonwebtoken": "catalog:",
"@types/lodash": "catalog:",
"@types/luxon": "catalog:",
"@types/mime-types": "catalog:",
"@types/ms": "catalog:",
"@types/ssh2": "catalog:",
"@types/uuid": "catalog:",
"@types/xml2js": "catalog:",
"@n8n/vitest-config": "workspace:*",
@ -65,6 +68,7 @@
"@n8n/decorators": "workspace:*",
"@n8n/di": "workspace:*",
"@n8n/errors": "workspace:*",
"@sentry/core": "catalog:sentry",
"@sentry/node": "catalog:sentry",
"@sentry/node-native": "catalog:sentry",
"@sentry/profiling-node": "catalog:sentry",
@ -79,6 +83,7 @@
"lodash": "catalog:",
"luxon": "catalog:",
"mime-types": "catalog:",
"ms": "catalog:",
"@n8n/workflow-sdk": "workspace:*",
"n8n-workflow": "workspace:*",
"nanoid": "catalog:",
@ -86,7 +91,7 @@
"p-cancelable": "2.1.1",
"picocolors": "catalog:",
"pretty-bytes": "5.6.0",
"ssh2": "1.15.0",
"ssh2": "catalog:",
"uuid": "catalog:",
"winston": "3.14.2",
"xml2js": "catalog:",

View File

@ -52,9 +52,12 @@
"@n8n/typescript-config": "workspace:*",
"@vitejs/plugin-vue": "catalog:frontend",
"@vue/tsconfig": "catalog:frontend",
"stylelint": "catalog:",
"tsdown": "catalog:",
"rimraf": "catalog:",
"vite": "catalog:",
"vitest": "catalog:",
"vite-plugin-dts": "catalog:",
"vue-tsc": "catalog:frontend"
},
"license": "LicenseRef-n8n-sustainable-use"

View File

@ -42,25 +42,33 @@
"@n8n/design-system": "workspace:*",
"@vueuse/core": "catalog:frontend",
"highlight.js": "catalog:frontend",
"markdown-it-link-attributes": "^4.0.1",
"markdown-it": "catalog:",
"markdown-it-link-attributes": "catalog:",
"uuid": "catalog:",
"vue": "catalog:frontend",
"vue-markdown-render": "catalog:frontend"
},
"devDependencies": {
"@iconify-json/mdi": "^1.1.54",
"@iconify-json/lucide": "catalog:",
"@iconify-json/mdi": "catalog:",
"@n8n/eslint-config": "workspace:*",
"@n8n/playwright-janitor": "workspace:*",
"@n8n/stylelint-config": "workspace:*",
"@n8n/typescript-config": "workspace:*",
"@n8n/vitest-config": "workspace:*",
"@storybook/vue3": "catalog:storybook",
"@storybook/vue3-vite": "catalog:storybook",
"@testing-library/jest-dom": "catalog:frontend",
"@testing-library/vue": "catalog:frontend",
"@types/markdown-it": "catalog:",
"@types/markdown-it-link-attributes": "catalog:",
"@vitejs/plugin-vue": "catalog:frontend",
"@vitest/coverage-v8": "catalog:",
"@vue/test-utils": "catalog:frontend",
"unplugin-icons": "^0.19.0",
"vite": "catalog:",
"vitest": "catalog:",
"vite-plugin-dts": "catalog:",
"vitest": "catalog:",
"vue-tsc": "catalog:frontend"
},
"files": [

View File

@ -1,3 +1,4 @@
import type { Mock } from 'vitest';
import { vi, describe, it, expect } from 'vitest';
import { createApp } from 'vue';
@ -25,7 +26,7 @@ describe('ChatPlugin', () => {
},
};
(api.sendMessage as jest.Mock).mockResolvedValue({ executionStarted: true });
(api.sendMessage as Mock).mockResolvedValue({ executionStarted: true });
app.use(ChatPlugin, options);
@ -53,7 +54,7 @@ describe('ChatPlugin', () => {
},
};
(api.sendMessage as jest.Mock).mockResolvedValue({});
(api.sendMessage as Mock).mockResolvedValue({});
app.use(ChatPlugin, options);

View File

@ -1,4 +1,4 @@
import '@testing-library/jest-dom';
import '@testing-library/jest-dom/vitest';
import { configure } from '@testing-library/vue';
configure({ testIdAttribute: 'data-test-id' });

View File

@ -11,7 +11,7 @@
"incremental": false,
"allowSyntheticDefaultImports": true,
"resolveJsonModule": true,
"types": ["vitest/globals"],
"types": ["vitest/globals", "vitest/browser", "@testing-library/vue"],
"paths": {
"@n8n/chat/*": ["./src/*"],
"@n8n/design-system*": ["../design-system/src*"]

View File

@ -29,25 +29,32 @@
"@n8n/stylelint-config": "workspace:*",
"@n8n/typescript-config": "workspace:*",
"@n8n/vitest-config": "workspace:*",
"@storybook/addon-docs": "catalog:storybook",
"@storybook/vue3": "catalog:storybook",
"@storybook/vue3-vite": "catalog:storybook",
"@testing-library/jest-dom": "catalog:frontend",
"@testing-library/user-event": "catalog:frontend",
"@testing-library/vue": "catalog:frontend",
"@types/lodash": "catalog:",
"@types/markdown-it": "^13.0.9",
"@types/markdown-it": "catalog:",
"@types/markdown-it-emoji": "^2.0.2",
"@types/markdown-it-link-attributes": "^3.0.5",
"@types/markdown-it-link-attributes": "catalog:",
"@types/sanitize-html": "catalog:",
"@vitejs/plugin-vue": "catalog:frontend",
"@vitest/coverage-v8": "catalog:",
"@vue/test-utils": "catalog:frontend",
"autoprefixer": "^10.4.19",
"emojibase-data": "^17.0.0",
"eslint-plugin-storybook": "catalog:storybook",
"postcss": "^8.4.38",
"sass": "^1.71.1",
"storybook": "catalog:storybook",
"storybook-addon-vue-mdx": "3.0.0",
"stylelint": "catalog:",
"tailwindcss": "^3.4.3",
"unplugin-icons": "catalog:frontend",
"vite": "catalog:",
"vite-svg-loader": "catalog:frontend",
"vitest": "catalog:",
"vitest-mock-extended": "catalog:",
"vue-tsc": "catalog:frontend"
@ -58,6 +65,7 @@
"@n8n/utils": "workspace:*",
"@tanstack/vue-table": "^8.21.2",
"@tiptap/core": "catalog:",
"@tiptap/pm": "catalog:",
"@tiptap/extension-link": "catalog:",
"@tiptap/extension-placeholder": "catalog:",
"@tiptap/extension-table": "catalog:",
@ -72,13 +80,15 @@
"@vueuse/core": "catalog:frontend",
"clsx": "^2.1.1",
"element-plus": "catalog:frontend",
"highlight.js": "catalog:frontend",
"is-emoji-supported": "^0.0.5",
"lodash": "catalog:",
"markdown-it": "^13.0.2",
"markdown-it": "catalog:",
"markdown-it-emoji": "^2.0.2",
"markdown-it-link-attributes": "^4.0.1",
"markdown-it-link-attributes": "catalog:",
"markdown-it-task-lists": "^2.1.1",
"parse-diff": "^0.11.1",
"pinia": "catalog:frontend",
"reka-ui": "^2.5.0",
"sanitize-html": "catalog:",
"vue": "catalog:frontend",

View File

@ -1,4 +1,4 @@
import '@testing-library/jest-dom';
import '@testing-library/jest-dom/vitest';
import { configure } from '@testing-library/vue';
import { config } from '@vue/test-utils';
import { beforeAll } from 'vitest';

View File

@ -5,12 +5,6 @@
"noEmit": true,
"moduleResolution": "bundler",
"types": ["vite/client", "unplugin-icons/types/vue", "vitest/globals"],
"typeRoots": [
"./node_modules/@testing-library",
"./node_modules/@types",
"../../../../node_modules",
"../../../../node_modules/@types"
],
"paths": {
"@n8n/design-system*": ["./src*"],
"@n8n/composables*": ["../composables/src*"],

View File

@ -56,7 +56,8 @@
"tsdown": "catalog:",
"typescript": "catalog:",
"vite": "catalog:",
"vitest": "catalog:"
"vitest": "catalog:",
"vue-tsc": "catalog:frontend"
},
"license": "LicenseRef-n8n-sustainable-use"
}

View File

@ -1,4 +1,4 @@
import '@testing-library/jest-dom';
import '@testing-library/jest-dom/vitest';
import { configure } from '@testing-library/vue';
// Avoid tests failing because of difference between local and GitHub actions timezone

View File

@ -1,15 +1,13 @@
import type { StorybookConfig } from '@storybook/vue3-vite';
import { dirname } from 'path';
import remarkGfm from 'remark-gfm';
import { fileURLToPath } from 'url';
/**
* This function is used to resolve the absolute path of a package.
* It is needed in projects that use Yarn PnP or are set up within a monorepo.
*/
function getAbsolutePath(value: string): any {
function getAbsolutePath(value: string): string {
return dirname(fileURLToPath(import.meta.resolve(`${value}/package.json`)));
}
const config: StorybookConfig = {

View File

@ -1,3 +1,6 @@
import { IconBodyLoaderKey, N8nPlugin } from '@n8n/design-system';
import { loadLucideIconBody } from '@n8n/design-system/icons/lucide';
import { i18nInstance } from '@n8n/i18n';
import { withThemeByDataAttribute } from '@storybook/addon-themes';
import { setup } from '@storybook/vue3';
import ElementPlus from 'element-plus';
@ -6,10 +9,6 @@ import lang from 'element-plus/dist/locale/en.mjs';
import { createPinia } from 'pinia';
import { createMemoryHistory, createRouter } from 'vue-router';
import { IconBodyLoaderKey, N8nPlugin } from '@n8n/design-system';
import { loadLucideIconBody } from '@n8n/design-system/icons/lucide';
import { i18nInstance } from '@n8n/i18n';
import './storybook.scss';
import { allModes } from './modes';
// import '../src/css/tailwind/index.css';
@ -28,6 +27,7 @@ setup((app) => {
app.use(router);
app.use(ElementPlus, {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- element-plus locale .mjs ships no types
locale: lang,
});

View File

@ -0,0 +1,21 @@
import storybook from 'eslint-plugin-storybook';
import { defineConfig } from 'eslint/config';
import { frontendConfig } from '@n8n/eslint-config/frontend';
export default defineConfig(
frontendConfig,
{
// Storybook entry/config files are build tooling — allow devDependency imports,
// and the Storybook API requires a default export from main.ts.
files: ['.storybook/**'],
rules: {
'import-x/no-extraneous-dependencies': [
'error',
{ devDependencies: true, optionalDependencies: false, peerDependencies: false },
],
'import-x/no-default-export': 'off',
},
},
storybook.configs['flat/recommended'],
);

View File

@ -8,7 +8,9 @@
"dev": "storybook dev -p 6006",
"build": "storybook build",
"build:unchecked": "pnpm run build",
"typecheck": "vue-tsc --noEmit -p tsconfig.app.json"
"typecheck": "vue-tsc --noEmit -p tsconfig.app.json",
"lint": "eslint . --quiet",
"lint:fix": "eslint . --fix"
},
"dependencies": {
"@n8n/chat": "workspace:*",
@ -17,6 +19,7 @@
"@n8n/i18n": "workspace:*",
"@n8n/stores": "workspace:*",
"@n8n/utils": "workspace:*",
"element-plus": "catalog:frontend",
"pinia": "catalog:frontend",
"vue": "catalog:frontend",
"vue-router": "catalog:frontend",
@ -24,13 +27,16 @@
},
"devDependencies": {
"@chromatic-com/storybook": "catalog:storybook",
"@iconify-json/lucide": "catalog:",
"@iconify-json/mdi": "catalog:",
"@n8n/eslint-config": "workspace:*",
"@n8n/typescript-config": "workspace:*",
"@storybook/addon-a11y": "catalog:storybook",
"@storybook/addon-docs": "catalog:storybook",
"@storybook/addon-themes": "catalog:storybook",
"@storybook/addon-vitest": "catalog:storybook",
"@storybook/vue3": "catalog:storybook",
"@storybook/vue3-vite": "catalog:storybook",
"storybook-addon-vue-mdx": "3.0.0",
"@types/node": "catalog:",
"@vitejs/plugin-vue": "catalog:frontend",
"@vitest/browser-playwright": "^4.0.16",
@ -38,19 +44,16 @@
"@vue/tsconfig": "catalog:frontend",
"eslint-plugin-storybook": "catalog:storybook",
"playwright": "catalog:e2e",
"prettier": "catalog:",
"remark-gfm": "^4.0.1",
"storybook": "catalog:storybook",
"storybook-addon-vue-mdx": "3.0.0",
"typescript": "catalog:",
"unplugin-icons": "catalog:frontend",
"vite": "catalog:",
"vite-svg-loader": "catalog:frontend",
"remark-gfm": "^4.0.1",
"vitest": "catalog:",
"vue-tsc": "catalog:frontend"
},
"eslintConfig": {
"extends": [
"plugin:storybook/recommended"
]
},
"license": "LicenseRef-n8n-sustainable-use"
}

View File

@ -26,6 +26,7 @@
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue",
".storybook/**/*.ts",
"../chat/src/**/*.stories.ts",
"../design-system/src/**/*.stories.ts",
"../../editor-ui/src/**/*.stories.ts"

View File

@ -38,6 +38,7 @@
"@dagrejs/dagre": "^1.1.4",
"@internationalized/date": "catalog:frontend",
"@lezer/common": "catalog:",
"@lezer/highlight": "catalog:",
"@n8n/api-types": "workspace:*",
"@n8n/chat": "workspace:*",
"@n8n/chat-hub": "workspace:*",
@ -55,7 +56,7 @@
"@pinecone-database/connect": "0.0.4",
"@replit/codemirror-indentation-markers": "^6.5.3",
"@sentry/vue": "catalog:frontend",
"@types/semver": "^7.7.0",
"@types/semver": "catalog:",
"@typescript/vfs": "^1.6.0",
"@vscode/markdown-it-katex": "^1.1.2",
"@vue-flow/background": "1.3.2",
@ -70,7 +71,7 @@
"array.prototype.tosorted": "1.1.4",
"axios": "catalog:",
"bowser": "2.11.0",
"change-case": "^5.4.4",
"change-case": "catalog:",
"chart.js": "^4.4.0",
"comlink": "^4.4.1",
"core-js": "^3.40.0",
@ -89,6 +90,7 @@
"katex": "0.16.27",
"lodash": "catalog:",
"luxon": "catalog:",
"markdown-it": "catalog:",
"markdown-it-footnote": "^4.0.0",
"n8n-workflow": "workspace:*",
"nanoid": "catalog:",
@ -100,6 +102,7 @@
"sanitize-html": "catalog:",
"semver": "catalog:",
"stream-browserify": "^3.0.0",
"stylelint": "catalog:",
"timeago.js": "^4.0.2",
"typescript": "catalog:",
"uuid": "catalog:",
@ -135,26 +138,37 @@
"@pinia/testing": "^0.1.6",
"@sentry/vite-plugin": "^4.3.0",
"@storybook/types": "^8.6.14",
"@storybook/vue3-vite": "catalog:storybook",
"@testing-library/dom": "catalog:frontend",
"@testing-library/jest-dom": "catalog:frontend",
"@testing-library/user-event": "catalog:frontend",
"@testing-library/vue": "catalog:frontend",
"@types/dateformat": "^3.0.0",
"@types/estree": "catalog:",
"@types/file-saver": "^2.0.1",
"@types/humanize-duration": "^3.27.1",
"@types/json-schema": "^7.0.15",
"@types/json-schema": "catalog:",
"@types/lodash": "catalog:",
"@types/lodash-es": "catalog:",
"@types/luxon": "catalog:",
"@types/markdown-it": "catalog:",
"@types/sanitize-html": "catalog:",
"@types/uuid": "catalog:",
"@vitejs/plugin-legacy": "^8.0.0",
"@vitejs/plugin-vue": "catalog:frontend",
"@vitest/coverage-v8": "catalog:",
"@vue/test-utils": "catalog:frontend",
"browserslist": "4.28.1",
"browserslist-to-esbuild": "^2.1.1",
"eslint-plugin-oxlint": "catalog:",
"fake-indexeddb": "^6.0.0",
"lodash-es": "catalog:",
"miragejs": "^0.1.48",
"oxlint": "catalog:",
"oxlint-tsgolint": "catalog:",
"sass-embedded": "catalog:",
"stylelint": "catalog:",
"storybook": "catalog:storybook",
"unplugin-icons": "catalog:frontend",
"vite": "catalog:",
"vite-plugin-node-polyfills": "^0.25.0",

View File

@ -1,4 +1,4 @@
import '@testing-library/jest-dom';
import '@testing-library/jest-dom/vitest';
import 'fake-indexeddb/auto';
import { configure } from '@testing-library/vue';
import 'core-js/proposals/set-methods-v2';

View File

@ -6,7 +6,7 @@ import type { IRunExecutionData } from 'n8n-workflow';
import type { INodeUi } from '@/Interface';
import type { IExecutionPushResponse } from '@/features/execution/executions/executions.types';
import type { RunWorkflowChatPayload } from '../composables/useChatMessaging';
import { vi } from 'vitest';
import { Mock, vi } from 'vitest';
import type { ChatMessage } from '@n8n/chat/types';
vi.mock('../logs.utils', () => {
@ -97,7 +97,7 @@ describe('useChatMessaging', () => {
parameters: { options: {} },
} as unknown as INodeUi;
(onRunChatWorkflow as jest.Mock).mockResolvedValue({
(onRunChatWorkflow as Mock).mockResolvedValue({
executionId: 'execution-id',
} as IExecutionPushResponse);
@ -125,7 +125,7 @@ describe('useChatMessaging', () => {
parameters: { options: { responseMode: 'responseNodes' } },
} as unknown as INodeUi;
(onRunChatWorkflow as jest.Mock).mockResolvedValue({
(onRunChatWorkflow as Mock).mockResolvedValue({
executionId: 'execution-id',
} as IExecutionPushResponse);

View File

@ -4,6 +4,9 @@ import { flushPromises } from '@vue/test-utils';
import RunDataJson from '@/features/ndv/runData/components/RunDataJson.vue';
import { createComponentRenderer } from '@/__tests__/render';
import { useElementSize } from '@vueuse/core'; // Import the composable to mock
import { Mock } from 'vitest';
import { computed } from 'vue';
import { WorkflowIdKey } from '@/app/constants/injectionKeys';
vi.mock('@vueuse/core', async () => {
const originalModule = await vi.importActual('@vueuse/core');
@ -14,7 +17,7 @@ vi.mock('@vueuse/core', async () => {
};
});
(useElementSize as jest.Mock).mockReturnValue({
(useElementSize as Mock).mockReturnValue({
height: 500, // Mocked height value
width: 300, // Mocked width value
});
@ -59,10 +62,17 @@ describe('RunDataJson.vue', () => {
const { container } = renderComponent({
global: {
plugins: [createTestingPinia()],
// RunDataJsonActions (lazy child) injects the workflow id on mount.
provide: {
[WorkflowIdKey as unknown as string]: computed(() => '1'),
},
},
});
// Resolve the defineAsyncComponent import to prevent EnvironmentTeardownError
// Resolve the defineAsyncComponent import to prevent EnvironmentTeardownError.
// flushPromises() only drains microtasks; dynamicImportSettled() waits for the
// dynamic import() itself to finish so it can't resolve after env teardown.
await flushPromises();
await vi.dynamicImportSettled();
expect(container).toMatchSnapshot();

View File

@ -5,7 +5,61 @@ exports[`RunDataJson.vue > renders json values properly 1`] = `
<div
class="jsonDisplay"
>
<!---->
<div
class="actionsGroup"
data-test-id="ndv-json-actions"
>
<button
aria-live="polite"
circle="false"
class="button button subtle medium iconOnly"
data-icon-only="true"
title="Copy to Clipboard"
type="button"
>
<transition-stub
appear="false"
css="true"
name="n8n-button-fade"
persisted="false"
>
<!--v-if-->
</transition-stub>
<div
class="button-inner"
>
<svg
aria-hidden="true"
class="n8n-icon"
data-icon="files"
focusable="false"
height="14px"
role="img"
viewBox="0 0 24 24"
width="14px"
>
<g
fill="none"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
>
<path
d="M15 2h-4a2 2 0 0 0-2 2v11a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V8"
/>
<path
d="M16.706 2.706A2.4 2.4 0 0 0 15 2v5a1 1 0 0 0 1 1h5a2.4 2.4 0 0 0-.706-1.706zM5 7a2 2 0 0 0-2 2v11a2 2 0 0 0 2 2h8a2 2 0 0 0 1.732-1"
/>
</g>
</svg>
</div>
</button>
</div>
<div
class=""
data-test-id="draggable"

View File

@ -1,4 +1,4 @@
import { describe, it, expect, vi } from 'vitest'; // Change to jest if needed
import { describe, it, expect, vi } from 'vitest';
import { pasteHandler } from './utils';
import type { EditorView } from '@codemirror/view';

View File

@ -100,7 +100,7 @@ describe('ItemsRenderer', () => {
) {
expect(emittedEvent[0].type).toBe(itemType);
} else {
fail('Emitted event is not an array or does not have a type property');
expect.fail('Emitted event is not an array or does not have a type property');
}
}
}

View File

@ -2,7 +2,6 @@ import vue from '@vitejs/plugin-vue';
import { resolve } from 'path';
import { defineConfig, mergeConfig, type UserConfig } from 'vite';
import { viteStaticCopy } from 'vite-plugin-static-copy';
import { nodePolyfills } from 'vite-plugin-node-polyfills';
import svgLoader from 'vite-svg-loader';
import { sentryVitePlugin } from '@sentry/vite-plugin';
import { codecovVitePlugin } from '@codecov/vite-plugin';
@ -158,9 +157,9 @@ const plugins: UserConfig['plugins'] = [
},
},
// For sanitize-html
nodePolyfills({
include: ['fs', 'path', 'url', 'util', 'timers'],
}),
// nodePolyfills({
// include: ['fs', 'path', 'url', 'util', 'timers'],
// }),
{
name: 'i18n-locales-hmr',
configureServer(server) {

View File

@ -29,7 +29,8 @@ export class New extends Command {
choices: ['Credentials', 'Node'],
};
const typeAnswers = await inquirer.prompt(typeQuestion);
type TypesAnswer = { type: 'Credentials' | 'Node' };
const typeAnswers = await inquirer.prompt<TypesAnswer>(typeQuestion);
let sourceFolder = '';
const sourceFileName = 'simple.ts';
@ -49,7 +50,8 @@ export class New extends Command {
choices: ['Execute', 'Trigger', 'Webhook'],
};
const nodeTypeAnswers = await inquirer.prompt(nodeTypeQuestion);
type NodeTypeAnswer = { nodeType: 'Trigger' | 'Webhook' };
const nodeTypeAnswers = await inquirer.prompt<NodeTypeAnswer>(nodeTypeQuestion);
// Choose a the template-source-file depending on user input.
sourceFolder = 'execute';
@ -89,7 +91,8 @@ export class New extends Command {
});
}
const additionalAnswers = await inquirer.prompt(
type AdditionalAnswer = { name: string; description: string };
const additionalAnswers = await inquirer.prompt<AdditionalAnswer>(
additionalQuestions as inquirer.QuestionCollection,
);
@ -99,7 +102,6 @@ export class New extends Command {
// node file
const destinationFilePath = join(
process.cwd(),
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
`${changeCase.pascalCase(nodeName)}.${typeAnswers.type.toLowerCase()}.ts`,
);
@ -120,9 +122,10 @@ export class New extends Command {
},
];
const overwriteAnswers = await inquirer.prompt(overwriteQuestion);
type OverwriteAnswer = { overwrite: boolean };
const overwriteAnswers = await inquirer.prompt<OverwriteAnswer>(overwriteQuestion);
if (overwriteAnswers.overwrite === false) {
if (!overwriteAnswers.overwrite) {
this.log('\nNode creation got canceled!');
return;
}

View File

@ -41,12 +41,12 @@
],
"devDependencies": {
"@n8n/typescript-config": "workspace:*",
"@types/inquirer": "^6.5.0"
"@types/inquirer": "^7.0.1"
},
"dependencies": {
"@n8n/di": "workspace:*",
"@oclif/core": "4.0.7",
"change-case": "^4.1.1",
"change-case": "catalog:",
"fast-glob": "catalog:",
"inquirer": "^7.0.1",
"n8n-core": "workspace:*",

View File

@ -1,4 +1,4 @@
import { paramCase, snakeCase } from 'change-case';
import { kebabCase, snakeCase } from 'change-case';
import { createHash } from 'crypto';
import type {
IDataObject,
@ -96,7 +96,7 @@ export class AwsS3V1 implements INodeType {
const name = this.getNodeParameter('name', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i);
if (additionalFields.acl) {
headers['x-amz-acl'] = paramCase(additionalFields.acl as string);
headers['x-amz-acl'] = kebabCase(additionalFields.acl as string);
}
if (additionalFields.bucketObjectLockEnabled) {
headers['x-amz-bucket-object-lock-enabled'] =
@ -488,7 +488,7 @@ export class AwsS3V1 implements INodeType {
).toUpperCase();
}
if (additionalFields.acl) {
headers['x-amz-acl'] = paramCase(additionalFields.acl as string);
headers['x-amz-acl'] = kebabCase(additionalFields.acl as string);
}
if (additionalFields.grantFullControl) {
headers['x-amz-grant-full-control'] = '';
@ -767,7 +767,7 @@ export class AwsS3V1 implements INodeType {
).toUpperCase();
}
if (additionalFields.acl) {
headers['x-amz-acl'] = paramCase(additionalFields.acl as string);
headers['x-amz-acl'] = kebabCase(additionalFields.acl as string);
}
if (additionalFields.grantFullControl) {
headers['x-amz-grant-full-control'] = '';

View File

@ -1,4 +1,4 @@
import { paramCase, snakeCase } from 'change-case';
import { kebabCase, snakeCase } from 'change-case';
import { createHash } from 'crypto';
import type {
IDataObject,
@ -96,7 +96,7 @@ export class AwsS3V2 implements INodeType {
const name = this.getNodeParameter('name', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i);
if (additionalFields.acl) {
headers['x-amz-acl'] = paramCase(additionalFields.acl as string);
headers['x-amz-acl'] = kebabCase(additionalFields.acl as string);
}
if (additionalFields.bucketObjectLockEnabled) {
headers['x-amz-bucket-object-lock-enabled'] =
@ -508,7 +508,7 @@ export class AwsS3V2 implements INodeType {
).toUpperCase();
}
if (additionalFields.acl) {
headers['x-amz-acl'] = paramCase(additionalFields.acl as string);
headers['x-amz-acl'] = kebabCase(additionalFields.acl as string);
}
if (additionalFields.grantFullControl) {
headers['x-amz-grant-full-control'] = '';
@ -805,7 +805,7 @@ export class AwsS3V2 implements INodeType {
}
if (additionalFields.acl) {
multipartHeaders['x-amz-acl'] = paramCase(additionalFields.acl as string);
multipartHeaders['x-amz-acl'] = kebabCase(additionalFields.acl as string);
}
if (additionalFields.grantFullControl) {
multipartHeaders['x-amz-grant-full-control'] = '';

View File

@ -13,6 +13,7 @@ import type {
Mysql2PoolConnection,
ParameterMatch,
QueryMode,
QueryRunner,
QueryValues,
QueryWithValues,
SortRule,
@ -322,7 +323,7 @@ export function configureQueryRunner(
this: IExecuteFunctions,
options: IDataObject,
pool: Mysql2Pool,
) {
): QueryRunner {
return async (queries: QueryWithValues[]) => {
if (queries.length === 0) {
return [];

View File

@ -5,7 +5,11 @@ import * as database from './database/Database.resource';
import type { PostgresType } from './node.type';
import { addExecutionHints } from '../../../../utils/utilities';
import { configurePostgres } from '../../transport';
import type { PostgresNodeCredentials, PostgresNodeOptions } from '../helpers/interfaces';
import type {
PostgresNodeCredentials,
PostgresNodeOptions,
QueriesRunner,
} from '../helpers/interfaces';
import { configureQueryRunner } from '../helpers/utils';
export async function router(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
@ -23,7 +27,7 @@ export async function router(this: IExecuteFunctions): Promise<INodeExecutionDat
const { db, pgp } = await configurePostgres.call(this, credentials, options);
const runQueries = configureQueryRunner.call(
const runQueries: QueriesRunner = configureQueryRunner.call(
this,
this.getNode(),
this.continueOnFail(),

View File

@ -362,7 +362,7 @@ export function configureQueryRunner(
continueOnFail: boolean,
pgp: PgpClient,
db: PgpDatabase,
) {
): QueriesRunner {
return async (queries: QueryWithValues[], options: IDataObject) => {
let returnData: INodeExecutionData[] = [];
const emptyReturnData: INodeExecutionData[] =

View File

@ -1,4 +1,4 @@
import { paramCase, snakeCase } from 'change-case';
import { kebabCase, snakeCase } from 'change-case';
import { createHash } from 'crypto';
import type {
IDataObject,
@ -103,7 +103,7 @@ export class S3 implements INodeType {
const name = this.getNodeParameter('name', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i);
if (additionalFields.acl) {
headers['x-amz-acl'] = paramCase(additionalFields.acl as string);
headers['x-amz-acl'] = kebabCase(additionalFields.acl as string);
}
if (additionalFields.bucketObjectLockEnabled) {
headers['x-amz-bucket-object-lock-enabled'] =
@ -497,7 +497,7 @@ export class S3 implements INodeType {
).toUpperCase();
}
if (additionalFields.acl) {
headers['x-amz-acl'] = paramCase(additionalFields.acl as string);
headers['x-amz-acl'] = kebabCase(additionalFields.acl as string);
}
if (additionalFields.grantFullControl) {
headers['x-amz-grant-full-control'] = '';
@ -781,7 +781,7 @@ export class S3 implements INodeType {
).toUpperCase();
}
if (additionalFields.acl) {
headers['x-amz-acl'] = paramCase(additionalFields.acl as string);
headers['x-amz-acl'] = kebabCase(additionalFields.acl as string);
}
if (additionalFields.grantFullControl) {
headers['x-amz-grant-full-control'] = '';

View File

@ -887,30 +887,38 @@
"@types/gm": "^1.25.0",
"@types/html-to-text": "^9.0.1",
"@types/js-nacl": "^1.3.0",
"@types/jsdom": "catalog:",
"@types/json-schema": "catalog:",
"@types/jsonwebtoken": "catalog:",
"@types/lodash": "catalog:",
"@types/lossless-json": "^1.0.0",
"@types/luxon": "catalog:",
"@types/mailparser": "^3.4.4",
"@types/mime-types": "catalog:",
"@types/mssql": "^9.1.5",
"@types/nodemailer": "^8.0.0",
"@types/oracledb": "^6.10.0",
"@types/nodemailer": "catalog:",
"@types/oracledb": "catalog:",
"@types/promise-ftp": "^1.3.4",
"@types/qs": "catalog:",
"@types/rfc2047": "^2.0.1",
"@types/sanitize-html": "catalog:",
"@types/semver": "catalog:",
"@types/showdown": "^1.9.4",
"@types/ssh2-sftp-client": "^9.0.5",
"@types/uuid": "catalog:",
"@types/xml2js": "catalog:",
"eslint-plugin-n8n-nodes-base": "^1.16.7",
"eslint-plugin-n8n-nodes-base": "catalog:",
"n8n-containers": "workspace:*",
"n8n-core": "workspace:*",
"reflect-metadata": "catalog:",
"vite": "catalog:",
"vitest": "catalog:",
"vitest-mock-extended": "catalog:"
},
"dependencies": {
"@n8n/backend-network": "workspace:*",
"@kafkajs/confluent-schema-registry": "3.8.0",
"@langchain/core": "catalog:",
"@mozilla/readability": "catalog:",
"@n8n/config": "workspace:*",
"@n8n/di": "workspace:*",
@ -922,7 +930,7 @@
"aws4": "1.11.0",
"axios": "catalog:",
"basic-auth": "catalog:",
"change-case": "4.1.2",
"change-case": "catalog:",
"cheerio": "catalog:",
"chokidar": "catalog:",
"cron": "catalog:",
@ -932,6 +940,7 @@
"fast-glob": "catalog:",
"fastest-levenshtein": "catalog:",
"fflate": "0.7.4",
"form-data": "catalog:",
"generate-schema": "2.6.0",
"get-system-fonts": "2.0.2",
"gm": "1.25.1",
@ -943,6 +952,7 @@
"isolated-vm": "catalog:",
"js-nacl": "1.4.0",
"jsdom": "23.0.1",
"json-schema": "catalog:",
"jsonwebtoken": "catalog:",
"kafkajs": "catalog:",
"ldapts": "catalog:",
@ -955,18 +965,20 @@
"moment-timezone": "catalog:",
"mongodb": "6.11.0",
"mqtt": "5.7.2",
"mqtt-packet": "catalog:",
"mssql": "10.0.2",
"mysql2": "catalog:",
"n8n-workflow": "workspace:*",
"node-html-markdown": "1.2.0",
"node-ssh": "13.2.0",
"nodemailer": "catalog:",
"oracledb": "6.10.0",
"oracledb": "catalog:",
"otpauth": "9.1.1",
"pdfjs-dist": "5.3.31",
"pg": "catalog:",
"pg-promise": "11.9.1",
"promise-ftp": "1.3.5",
"qs": "catalog:",
"redis": "4.6.14",
"rfc2047": "4.0.1",
"rhea": "3.0.4",
@ -986,7 +998,8 @@
"vm2": "catalog:",
"xlsx": "https://cdn.sheetjs.com/xlsx-0.20.2/xlsx-0.20.2.tgz",
"xml2js": "catalog:",
"xmlhttprequest-ssl": "3.1.0"
"xmlhttprequest-ssl": "3.1.0",
"zod": "catalog:"
},
"license": "LicenseRef-n8n-sustainable-use"
}

View File

@ -54,30 +54,39 @@
"@stryker-mutator/vitest-runner": "catalog:",
"@types/express": "catalog:",
"@types/jmespath": "^0.15.0",
"@types/json-schema": "catalog:",
"@types/lodash": "catalog:",
"@types/luxon": "3.2.0",
"@types/luxon": "catalog:",
"@types/md5": "^2.3.5",
"@types/ssh2": "catalog:",
"@types/xml2js": "catalog:",
"fast-check": "catalog:",
"vite": "catalog:",
"vitest": "catalog:",
"vitest-mock-extended": "catalog:",
"zod": "catalog:"
},
"dependencies": {
"@codemirror/autocomplete": "catalog:",
"@n8n/errors": "workspace:*",
"@n8n/expression-runtime": "workspace:*",
"@n8n/tournament": "workspace:*",
"@sentry/core": "catalog:sentry",
"@sentry/node": "catalog:sentry",
"ast-types": "0.16.1",
"axios": "catalog:",
"callsites": "catalog:",
"esprima-next": "5.8.4",
"form-data": "catalog:",
"jmespath": "0.16.0",
"js-base64": "catalog:",
"jssha": "3.3.1",
"json-schema": "catalog:",
"lodash": "catalog:",
"luxon": "catalog:",
"md5": "2.3.0",
"recast": "0.22.0",
"ssh2": "catalog:",
"title-case": "3.0.3",
"transliteration": "2.3.5",
"uuid": "catalog:",

File diff suppressed because it is too large Load Diff

View File

@ -37,6 +37,8 @@ catalog:
'@codemirror/state': 6.5.3
'@codemirror/view': 6.39.8
'@daytona/sdk': 0.187.0
'@iconify-json/lucide': ^1.2.112
'@iconify-json/mdi': ^1.1.63
'@joplin/turndown-plugin-gfm': 1.0.64
'@langchain/anthropic': 1.3.27
'@langchain/community': 1.1.27
@ -66,6 +68,7 @@ catalog:
'@testcontainers/postgresql': ^11.13.0
'@testcontainers/redis': ^11.13.0
'@tiptap/core': 3.22.5
'@tiptap/pm': 3.22.5
'@tiptap/extension-link': 3.22.5
'@tiptap/extension-placeholder': 3.22.5
'@tiptap/extension-strike': 3.22.5
@ -79,32 +82,52 @@ catalog:
'@tiptap/starter-kit': 3.22.5
'@tiptap/vue-3': 3.22.5
'@types/basic-auth': ^1.1.3
'@types/estree': ^1.0.8
'@types/express': ^5.0.1
'@types/jsdom': ^21.1.7
'@types/json-schema': ^7.0.15
'@types/jsonwebtoken': 9.0.10
'@types/lodash': 4.17.17
'@types/lodash-es': ^4.17.12
'@types/luxon': 3.2.0
'@types/markdown-it': ^13.0.2
'@types/markdown-it-link-attributes': "^3.0.5"
'@types/mime-types': 3.0.1
'@types/ms': 2.1.0
'@types/node': 24.10.1
'@types/nodemailer': 8.0.1
'@types/oracledb': 6.10.3
'@types/proxy-from-env': ^1.0.4
'@types/qs': 6.9.15
'@types/sanitize-html': ^2.11.0
'@types/semver': ^7.7.0
'@types/ssh2': 1.15.0
'@types/turndown': ^5.0.6
'@types/uuid': ^11.0.0
'@types/ws': ^8.18.1
'@types/xml2js': ^0.4.14
'@vitest/coverage-v8': 4.1.1
agent-browser: 0.26.0
ai: ^6.0.197
axios: 1.18.0
babel-jest: ^29.7.0
basic-auth: 2.0.1
cache-manager: 5.2.3
callsites: 3.1.0
change-case: ^5.4.4
chat: ^4.28.1
cheerio: 1.1.0
chokidar: 4.0.3
cron: 4.4.0
cross-env: ^7.0.3
csv-parse: 6.2.1
dotenv: 17.2.3
electron: ^41.7.2
esbuild: ^0.28.1
eslint: 9.29.0
eslint-plugin-oxlint: ^1.61.0
eslint-plugin-n8n-nodes-base: ^1.16.7
express: 5.1.0
fast-check: ^3.23.2
fast-glob: 3.2.12
fast-json-patch: ^3.1.1
@ -118,6 +141,7 @@ catalog:
isolated-vm: ^6.1.2
js-base64: 3.7.8
js-tiktoken: 1.0.21
json-schema: 0.4.0
jsonrepair: 3.13.2
jsonwebtoken: 9.0.3
kafkajs: 2.2.4
@ -125,14 +149,20 @@ catalog:
langsmith: 0.6.0
ldapts: 8.1.7
lodash: 4.18.1
lodash-es: 4.18.1
luxon: 3.7.2
markdown-it: ^13.0.2
markdown-it-link-attributes: ^4.0.1
mime-types: 3.0.2
moment-timezone: 0.5.48
mqtt-packet: 9.0.0
ms: 2.1.3
mysql2: 3.17.0
nanoid: 3.3.8
nock: 14.0.14
nodemailer: 8.0.10
openai: 6.19.0
oracledb: 6.10.0
oxlint: ^1.61.0
oxlint-tsgolint: ^0.21.1
pdf-parse: 2.4.5
@ -150,7 +180,9 @@ catalog:
semver: 7.7.3
simple-git: 3.36.0
source-map-support: 0.5.21
ssh2: 1.15.0
stream-json: 1.9.1
stylelint: ^16.23.0
tar: ^7.5.16
testcontainers: ^11.13.0
ts-morph: ^27.0.2
@ -185,6 +217,7 @@ catalogs:
'@internationalized/date': ^3.9.0
'@sentry/vue': ^10.36.0
'@testing-library/jest-dom': ^6.6.3
'@testing-library/dom': ^10.4.0
'@testing-library/user-event': ^14.6.1
'@testing-library/vue': ^8.1.0
'@vitejs/plugin-vue': ^5.2.4
@ -202,6 +235,7 @@ catalogs:
vue-router: ^4.5.0
vue-tsc: ^2.2.8
sentry:
'@sentry/core': ^10.55.0
'@sentry/node': ^10.55.0
'@sentry/node-native': ^10.55.0
'@sentry/profiling-node': ^10.55.0
@ -211,6 +245,7 @@ catalogs:
'@storybook/addon-docs': ^10.1.11
'@storybook/addon-themes': ^10.1.11
'@storybook/addon-vitest': ^10.1.11
'@storybook/vue3': ^10.1.11
'@storybook/vue3-vite': ^10.1.11
eslint-plugin-storybook: ^10.1.11
storybook: ^10.1.11