fix: 修复TypeScript配置错误并更新项目文档
详细说明: - 修复了@n8n/config包的TypeScript配置错误 - 移除了不存在的jest-expect-message类型引用 - 清理了所有TypeScript构建缓存 - 更新了可行性分析文档,添加了技术实施方案 - 更新了Agent prompt文档 - 添加了会展策划工作流文档 - 包含了n8n-chinese-translation子项目 - 添加了exhibition-demo展示系统框架
This commit is contained in:
13
n8n-n8n-1.109.2/packages/workflow/README 2.md
Executable file
13
n8n-n8n-1.109.2/packages/workflow/README 2.md
Executable file
@@ -0,0 +1,13 @@
|
||||

|
||||
|
||||
# n8n-workflow
|
||||
|
||||
Workflow base code for n8n
|
||||
|
||||
```
|
||||
npm install n8n-workflow
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
You can find the license information [here](https://github.com/n8n-io/n8n/blob/master/README.md#license)
|
||||
4
n8n-n8n-1.109.2/packages/workflow/jest.config 2.js
Executable file
4
n8n-n8n-1.109.2/packages/workflow/jest.config 2.js
Executable file
@@ -0,0 +1,4 @@
|
||||
/** @type {import('jest').Config} */
|
||||
module.exports = {
|
||||
...require('../../jest.config'),
|
||||
};
|
||||
71
n8n-n8n-1.109.2/packages/workflow/package 2.json
Executable file
71
n8n-n8n-1.109.2/packages/workflow/package 2.json
Executable file
@@ -0,0 +1,71 @@
|
||||
{
|
||||
"name": "n8n-workflow",
|
||||
"version": "1.106.0",
|
||||
"description": "Workflow base code of n8n",
|
||||
"types": "dist/esm/index.d.ts",
|
||||
"module": "dist/esm/index.js",
|
||||
"main": "dist/cjs/index.js",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/esm/index.d.ts",
|
||||
"import": "./dist/esm/index.js",
|
||||
"require": "./dist/cjs/index.js"
|
||||
},
|
||||
"./common": {
|
||||
"types": "./dist/esm/common/index.d.ts",
|
||||
"import": "./dist/esm/common/index.js",
|
||||
"require": "./dist/cjs/common/index.js"
|
||||
},
|
||||
"./*": "./*"
|
||||
},
|
||||
"scripts": {
|
||||
"clean": "rimraf dist .turbo",
|
||||
"dev": "pnpm watch",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"build:vite": "vite build",
|
||||
"build": "tsc --build tsconfig.build.esm.json tsconfig.build.cjs.json",
|
||||
"format": "biome format --write .",
|
||||
"format:check": "biome ci .",
|
||||
"lint": "eslint src --quiet",
|
||||
"lint:fix": "eslint src --fix",
|
||||
"watch": "tsc --build tsconfig.build.esm.json tsconfig.build.cjs.json --watch",
|
||||
"test": "vitest run",
|
||||
"test:dev": "vitest --watch"
|
||||
},
|
||||
"files": [
|
||||
"dist/**/*"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@langchain/core": "catalog:",
|
||||
"@n8n/config": "workspace:*",
|
||||
"@n8n/typescript-config": "workspace:*",
|
||||
"@n8n/vitest-config": "workspace:*",
|
||||
"@types/express": "catalog:",
|
||||
"@types/jmespath": "^0.15.0",
|
||||
"@types/lodash": "catalog:",
|
||||
"@types/luxon": "3.2.0",
|
||||
"@types/md5": "^2.3.5",
|
||||
"@types/xml2js": "catalog:",
|
||||
"vitest": "catalog:",
|
||||
"vitest-mock-extended": "catalog:"
|
||||
},
|
||||
"dependencies": {
|
||||
"@n8n/errors": "workspace:^",
|
||||
"@n8n/tournament": "1.0.6",
|
||||
"ast-types": "0.15.2",
|
||||
"callsites": "catalog:",
|
||||
"esprima-next": "5.8.4",
|
||||
"form-data": "catalog:",
|
||||
"jmespath": "0.16.0",
|
||||
"js-base64": "catalog:",
|
||||
"jssha": "3.3.1",
|
||||
"lodash": "catalog:",
|
||||
"luxon": "catalog:",
|
||||
"md5": "2.3.0",
|
||||
"recast": "0.22.0",
|
||||
"title-case": "3.0.3",
|
||||
"transliteration": "2.3.5",
|
||||
"xml2js": "catalog:",
|
||||
"zod": "catalog:"
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
import { ApplicationError, type ReportingOptions } from '@n8n/errors';
|
||||
|
||||
import type { Functionality, IDataObject, JsonObject } from '../../interfaces';
|
||||
|
||||
interface ExecutionBaseErrorOptions extends ReportingOptions {
|
||||
cause?: Error;
|
||||
errorResponse?: JsonObject;
|
||||
}
|
||||
|
||||
export abstract class ExecutionBaseError extends ApplicationError {
|
||||
description: string | null | undefined;
|
||||
|
||||
override cause?: Error;
|
||||
|
||||
errorResponse?: JsonObject;
|
||||
|
||||
timestamp: number;
|
||||
|
||||
context: IDataObject = {};
|
||||
|
||||
lineNumber: number | undefined;
|
||||
|
||||
functionality: Functionality = 'regular';
|
||||
|
||||
constructor(message: string, options: ExecutionBaseErrorOptions = {}) {
|
||||
super(message, options);
|
||||
|
||||
this.name = this.constructor.name;
|
||||
this.timestamp = Date.now();
|
||||
|
||||
const { cause, errorResponse } = options;
|
||||
if (cause instanceof ExecutionBaseError) {
|
||||
this.context = cause.context;
|
||||
} else if (cause && !(cause instanceof Error)) {
|
||||
this.cause = cause;
|
||||
}
|
||||
|
||||
if (errorResponse) this.errorResponse = errorResponse;
|
||||
}
|
||||
|
||||
toJSON?() {
|
||||
return {
|
||||
message: this.message,
|
||||
lineNumber: this.lineNumber,
|
||||
timestamp: this.timestamp,
|
||||
name: this.name,
|
||||
description: this.description,
|
||||
context: this.context,
|
||||
cause: this.cause,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,187 +0,0 @@
|
||||
import { ExecutionBaseError } from './execution-base.error';
|
||||
import type { IDataObject, INode, JsonObject } from '../../interfaces';
|
||||
import { isTraversableObject, jsonParse } from '../../utils';
|
||||
|
||||
/**
|
||||
* Descriptive messages for common errors.
|
||||
*/
|
||||
const COMMON_ERRORS: IDataObject = {
|
||||
// nodeJS errors
|
||||
ECONNREFUSED: 'The service refused the connection - perhaps it is offline',
|
||||
ECONNRESET:
|
||||
'The connection to the server was closed unexpectedly, perhaps it is offline. You can retry the request immediately or wait and retry later.',
|
||||
ENOTFOUND:
|
||||
'The connection cannot be established, this usually occurs due to an incorrect host (domain) value',
|
||||
ETIMEDOUT:
|
||||
"The connection timed out, consider setting the 'Retry on Fail' option in the node settings",
|
||||
ERRADDRINUSE:
|
||||
'The port is already occupied by some other application, if possible change the port or kill the application that is using it',
|
||||
EADDRNOTAVAIL: 'The address is not available, ensure that you have the right IP address',
|
||||
ECONNABORTED: 'The connection was aborted, perhaps the server is offline',
|
||||
EHOSTUNREACH: 'The host is unreachable, perhaps the server is offline',
|
||||
EAI_AGAIN: 'The DNS server returned an error, perhaps the server is offline',
|
||||
ENOENT: 'The file or directory does not exist',
|
||||
EISDIR: 'The file path was expected but the given path is a directory',
|
||||
ENOTDIR: 'The directory path was expected but the given path is a file',
|
||||
EACCES: 'Forbidden by access permissions, make sure you have the right permissions',
|
||||
EEXIST: 'The file or directory already exists',
|
||||
EPERM: 'Operation not permitted, make sure you have the right permissions',
|
||||
// other errors
|
||||
GETADDRINFO: 'The server closed the connection unexpectedly',
|
||||
};
|
||||
|
||||
/**
|
||||
* Base class for specific NodeError-types, with functionality for finding
|
||||
* a value recursively inside an error object.
|
||||
*/
|
||||
export abstract class NodeError extends ExecutionBaseError {
|
||||
messages: string[] = [];
|
||||
|
||||
constructor(
|
||||
readonly node: INode,
|
||||
error: Error | JsonObject,
|
||||
) {
|
||||
const isError = error instanceof Error;
|
||||
const message = isError ? error.message : '';
|
||||
const options = isError ? { cause: error } : { errorResponse: error };
|
||||
super(message, options);
|
||||
|
||||
if (error instanceof NodeError) {
|
||||
this.tags.reWrapped = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds property through exploration based on potential keys and traversal keys.
|
||||
* Depth-first approach.
|
||||
*
|
||||
* This method iterates over `potentialKeys` and, if the value at the key is a
|
||||
* truthy value, the type of the value is checked:
|
||||
* (1) if a string or number, the value is returned as a string; or
|
||||
* (2) if an array,
|
||||
* its string or number elements are collected as a long string,
|
||||
* its object elements are traversed recursively (restart this function
|
||||
* with each object as a starting point), or
|
||||
* (3) if it is an object, it traverses the object and nested ones recursively
|
||||
* based on the `potentialKeys` and returns a string if found.
|
||||
*
|
||||
* If nothing found via `potentialKeys` this method iterates over `traversalKeys` and
|
||||
* if the value at the key is a traversable object, it restarts with the object as the
|
||||
* new starting point (recursion).
|
||||
* If nothing found for any of the `traversalKeys`, exploration continues with remaining
|
||||
* `traversalKeys`.
|
||||
*
|
||||
* Otherwise, if all the paths have been exhausted and no value is eligible, `null` is
|
||||
* returned.
|
||||
*
|
||||
*/
|
||||
protected findProperty(
|
||||
jsonError: JsonObject,
|
||||
potentialKeys: string[],
|
||||
traversalKeys: string[] = [],
|
||||
): string | null {
|
||||
for (const key of potentialKeys) {
|
||||
let value = jsonError[key];
|
||||
if (value) {
|
||||
if (typeof value === 'string') {
|
||||
try {
|
||||
value = jsonParse(value);
|
||||
} catch (error) {
|
||||
return value as string;
|
||||
}
|
||||
if (typeof value === 'string') return value;
|
||||
}
|
||||
if (typeof value === 'number') return value.toString();
|
||||
if (Array.isArray(value)) {
|
||||
const resolvedErrors: string[] = value
|
||||
|
||||
.map((jsonError) => {
|
||||
if (typeof jsonError === 'string') return jsonError;
|
||||
if (typeof jsonError === 'number') return jsonError.toString();
|
||||
if (isTraversableObject(jsonError)) {
|
||||
return this.findProperty(jsonError, potentialKeys);
|
||||
}
|
||||
return null;
|
||||
})
|
||||
.filter((errorValue): errorValue is string => errorValue !== null);
|
||||
|
||||
if (resolvedErrors.length === 0) {
|
||||
return null;
|
||||
}
|
||||
return resolvedErrors.join(' | ');
|
||||
}
|
||||
if (isTraversableObject(value)) {
|
||||
const property = this.findProperty(value, potentialKeys);
|
||||
if (property) {
|
||||
return property;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const key of traversalKeys) {
|
||||
const value = jsonError[key];
|
||||
if (isTraversableObject(value)) {
|
||||
const property = this.findProperty(value, potentialKeys, traversalKeys);
|
||||
if (property) {
|
||||
return property;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Preserve the original error message before setting the new one
|
||||
*/
|
||||
protected addToMessages(message: string): void {
|
||||
if (message && !this.messages.includes(message)) {
|
||||
this.messages.push(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set descriptive error message if code is provided or if message contains any of the common errors,
|
||||
* update description to include original message plus the description
|
||||
*/
|
||||
protected setDescriptiveErrorMessage(
|
||||
message: string,
|
||||
messages: string[],
|
||||
code?: string | null,
|
||||
messageMapping?: { [key: string]: string },
|
||||
): [string, string[]] {
|
||||
let newMessage = message;
|
||||
|
||||
if (messageMapping) {
|
||||
for (const [mapKey, mapMessage] of Object.entries(messageMapping)) {
|
||||
if ((message || '').toUpperCase().includes(mapKey.toUpperCase())) {
|
||||
newMessage = mapMessage;
|
||||
messages.push(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (newMessage !== message) {
|
||||
return [newMessage, messages];
|
||||
}
|
||||
}
|
||||
|
||||
// if code is provided and it is in the list of common errors set the message and return early
|
||||
if (code && typeof code === 'string' && COMMON_ERRORS[code.toUpperCase()]) {
|
||||
newMessage = COMMON_ERRORS[code] as string;
|
||||
messages.push(message);
|
||||
return [newMessage, messages];
|
||||
}
|
||||
|
||||
// check if message contains any of the common errors and set the message and description
|
||||
for (const [errorCode, errorDescriptiveMessage] of Object.entries(COMMON_ERRORS)) {
|
||||
if ((message || '').toUpperCase().includes(errorCode.toUpperCase())) {
|
||||
newMessage = errorDescriptiveMessage as string;
|
||||
messages.push(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return [newMessage, messages];
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
import type { Event } from '@sentry/node';
|
||||
import callsites from 'callsites';
|
||||
|
||||
import type { ErrorTags, ErrorLevel, ReportingOptions } from '@n8n/errors';
|
||||
|
||||
export type BaseErrorOptions = { description?: string | undefined | null } & ErrorOptions &
|
||||
ReportingOptions;
|
||||
/**
|
||||
* Base class for all errors
|
||||
*/
|
||||
export abstract class BaseError extends Error {
|
||||
/**
|
||||
* Error level. Defines which level the error should be logged/reported
|
||||
* @default 'error'
|
||||
*/
|
||||
level: ErrorLevel;
|
||||
|
||||
/**
|
||||
* Whether the error should be reported to Sentry.
|
||||
* @default true
|
||||
*/
|
||||
readonly shouldReport: boolean;
|
||||
|
||||
readonly description: string | null | undefined;
|
||||
|
||||
readonly tags: ErrorTags;
|
||||
|
||||
readonly extra?: Event['extra'];
|
||||
|
||||
readonly packageName?: string;
|
||||
|
||||
constructor(
|
||||
message: string,
|
||||
{
|
||||
level = 'error',
|
||||
description,
|
||||
shouldReport,
|
||||
tags = {},
|
||||
extra,
|
||||
...rest
|
||||
}: BaseErrorOptions = {},
|
||||
) {
|
||||
super(message, rest);
|
||||
|
||||
this.level = level;
|
||||
this.shouldReport = shouldReport ?? (level === 'error' || level === 'fatal');
|
||||
this.description = description;
|
||||
this.tags = tags;
|
||||
this.extra = extra;
|
||||
|
||||
try {
|
||||
const filePath = callsites()[2].getFileName() ?? '';
|
||||
const match = /packages\/([^\/]+)\//.exec(filePath)?.[1];
|
||||
|
||||
if (match) this.tags.packageName = match;
|
||||
} catch {}
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
import type { BaseErrorOptions } from './base.error';
|
||||
import { BaseError } from './base.error';
|
||||
|
||||
export type OperationalErrorOptions = Omit<BaseErrorOptions, 'level'> & {
|
||||
level?: 'info' | 'warning' | 'error';
|
||||
};
|
||||
|
||||
/**
|
||||
* Error that indicates a transient issue, like a network request failing,
|
||||
* a database query timing out, etc. These are expected to happen, are
|
||||
* transient by nature and should be handled gracefully.
|
||||
*
|
||||
* Default level: warning
|
||||
*/
|
||||
export class OperationalError extends BaseError {
|
||||
constructor(message: string, opts: OperationalErrorOptions = {}) {
|
||||
opts.level = opts.level ?? 'warning';
|
||||
|
||||
super(message, opts);
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
import type { BaseErrorOptions } from './base.error';
|
||||
import { BaseError } from './base.error';
|
||||
|
||||
export type UnexpectedErrorOptions = Omit<BaseErrorOptions, 'level'> & {
|
||||
level?: 'error' | 'fatal';
|
||||
};
|
||||
|
||||
/**
|
||||
* Error that indicates something is wrong in the code: logic mistakes,
|
||||
* unhandled cases, assertions that fail. These are not recoverable and
|
||||
* should be brought to developers' attention.
|
||||
*
|
||||
* Default level: error
|
||||
*/
|
||||
export class UnexpectedError extends BaseError {
|
||||
constructor(message: string, opts: UnexpectedErrorOptions = {}) {
|
||||
opts.level = opts.level ?? 'error';
|
||||
|
||||
super(message, opts);
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
import type { BaseErrorOptions } from './base.error';
|
||||
import { BaseError } from './base.error';
|
||||
|
||||
export type UserErrorOptions = Omit<BaseErrorOptions, 'level'> & {
|
||||
level?: 'info' | 'warning';
|
||||
description?: string | null | undefined;
|
||||
};
|
||||
|
||||
/**
|
||||
* Error that indicates the user performed an action that caused an error.
|
||||
* E.g. provided invalid input, tried to access a resource they’re not
|
||||
* authorized to, or violates a business rule.
|
||||
*
|
||||
* Default level: info
|
||||
*/
|
||||
export class UserError extends BaseError {
|
||||
declare readonly description: string | null | undefined;
|
||||
|
||||
constructor(message: string, opts: UserErrorOptions = {}) {
|
||||
opts.level = opts.level ?? 'info';
|
||||
|
||||
super(message, opts);
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
import { BaseError } from '../../../src/errors/base/base.error';
|
||||
import { OperationalError } from '../../../src/errors/base/operational.error';
|
||||
|
||||
describe('OperationalError', () => {
|
||||
it('should be an instance of OperationalError', () => {
|
||||
const error = new OperationalError('test');
|
||||
expect(error).toBeInstanceOf(OperationalError);
|
||||
});
|
||||
|
||||
it('should be an instance of BaseError', () => {
|
||||
const error = new OperationalError('test');
|
||||
expect(error).toBeInstanceOf(BaseError);
|
||||
});
|
||||
|
||||
it('should have correct defaults', () => {
|
||||
const error = new OperationalError('test');
|
||||
expect(error.level).toBe('warning');
|
||||
expect(error.shouldReport).toBe(false);
|
||||
});
|
||||
|
||||
it('should allow overriding the default level and shouldReport', () => {
|
||||
const error = new OperationalError('test', { level: 'error', shouldReport: true });
|
||||
expect(error.level).toBe('error');
|
||||
expect(error.shouldReport).toBe(true);
|
||||
});
|
||||
});
|
||||
@@ -1,26 +0,0 @@
|
||||
import { BaseError } from '../../../src/errors/base/base.error';
|
||||
import { UnexpectedError } from '../../../src/errors/base/unexpected.error';
|
||||
|
||||
describe('UnexpectedError', () => {
|
||||
it('should be an instance of UnexpectedError', () => {
|
||||
const error = new UnexpectedError('test');
|
||||
expect(error).toBeInstanceOf(UnexpectedError);
|
||||
});
|
||||
|
||||
it('should be an instance of BaseError', () => {
|
||||
const error = new UnexpectedError('test');
|
||||
expect(error).toBeInstanceOf(BaseError);
|
||||
});
|
||||
|
||||
it('should have correct defaults', () => {
|
||||
const error = new UnexpectedError('test');
|
||||
expect(error.level).toBe('error');
|
||||
expect(error.shouldReport).toBe(true);
|
||||
});
|
||||
|
||||
it('should allow overriding the default level and shouldReport', () => {
|
||||
const error = new UnexpectedError('test', { level: 'fatal', shouldReport: false });
|
||||
expect(error.level).toBe('fatal');
|
||||
expect(error.shouldReport).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -1,26 +0,0 @@
|
||||
import { BaseError } from '../../../src/errors/base/base.error';
|
||||
import { UserError } from '../../../src/errors/base/user.error';
|
||||
|
||||
describe('UserError', () => {
|
||||
it('should be an instance of UserError', () => {
|
||||
const error = new UserError('test');
|
||||
expect(error).toBeInstanceOf(UserError);
|
||||
});
|
||||
|
||||
it('should be an instance of BaseError', () => {
|
||||
const error = new UserError('test');
|
||||
expect(error).toBeInstanceOf(BaseError);
|
||||
});
|
||||
|
||||
it('should have correct defaults', () => {
|
||||
const error = new UserError('test');
|
||||
expect(error.level).toBe('info');
|
||||
expect(error.shouldReport).toBe(false);
|
||||
});
|
||||
|
||||
it('should allow overriding the default level and shouldReport', () => {
|
||||
const error = new UserError('test', { level: 'warning', shouldReport: true });
|
||||
expect(error.level).toBe('warning');
|
||||
expect(error.shouldReport).toBe(true);
|
||||
});
|
||||
});
|
||||
3
n8n-n8n-1.109.2/packages/workflow/vitest.config 2.ts
Executable file
3
n8n-n8n-1.109.2/packages/workflow/vitest.config 2.ts
Executable file
@@ -0,0 +1,3 @@
|
||||
import { createVitestConfig } from '@n8n/vitest-config/node';
|
||||
|
||||
export default createVitestConfig({ include: ['test/**/*.test.ts'] });
|
||||
Reference in New Issue
Block a user