fix: 修复TypeScript配置错误并更新项目文档
详细说明: - 修复了@n8n/config包的TypeScript配置错误 - 移除了不存在的jest-expect-message类型引用 - 清理了所有TypeScript构建缓存 - 更新了可行性分析文档,添加了技术实施方案 - 更新了Agent prompt文档 - 添加了会展策划工作流文档 - 包含了n8n-chinese-translation子项目 - 添加了exhibition-demo展示系统框架
This commit is contained in:
19
n8n-n8n-1.109.2/packages/@n8n/config/src/custom-types 2.ts
Executable file
19
n8n-n8n-1.109.2/packages/@n8n/config/src/custom-types 2.ts
Executable file
@@ -0,0 +1,19 @@
|
||||
abstract class StringArray<T extends string> extends Array<T> {
|
||||
constructor(str: string, delimiter: string) {
|
||||
super();
|
||||
const parsed = str.split(delimiter) as this;
|
||||
return parsed.filter((i) => typeof i === 'string' && i.length);
|
||||
}
|
||||
}
|
||||
|
||||
export class CommaSeparatedStringArray<T extends string> extends StringArray<T> {
|
||||
constructor(str: string) {
|
||||
super(str, ',');
|
||||
}
|
||||
}
|
||||
|
||||
export class ColonSeparatedStringArray<T extends string = string> extends StringArray<T> {
|
||||
constructor(str: string) {
|
||||
super(str, ':');
|
||||
}
|
||||
}
|
||||
118
n8n-n8n-1.109.2/packages/@n8n/config/src/decorators 2.ts
Executable file
118
n8n-n8n-1.109.2/packages/@n8n/config/src/decorators 2.ts
Executable file
@@ -0,0 +1,118 @@
|
||||
import 'reflect-metadata';
|
||||
import { Container, Service } from '@n8n/di';
|
||||
import { readFileSync } from 'fs';
|
||||
import { z } from 'zod';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-restricted-types
|
||||
type Class = Function;
|
||||
type Constructable<T = unknown> = new (rawValue: string) => T;
|
||||
type PropertyKey = string | symbol;
|
||||
type PropertyType = number | boolean | string | Class;
|
||||
interface PropertyMetadata {
|
||||
type: PropertyType;
|
||||
envName?: string;
|
||||
schema?: z.ZodType<unknown>;
|
||||
}
|
||||
|
||||
const globalMetadata = new Map<Class, Map<PropertyKey, PropertyMetadata>>();
|
||||
|
||||
const readEnv = (envName: string) => {
|
||||
if (envName in process.env) return process.env[envName];
|
||||
|
||||
// Read the value from a file, if "_FILE" environment variable is defined
|
||||
const filePath = process.env[`${envName}_FILE`];
|
||||
if (filePath) return readFileSync(filePath, 'utf8');
|
||||
|
||||
return undefined;
|
||||
};
|
||||
|
||||
export const Config: ClassDecorator = (ConfigClass: Class) => {
|
||||
const factory = function (...args: unknown[]) {
|
||||
const config = new (ConfigClass as new (...a: unknown[]) => Record<PropertyKey, unknown>)(
|
||||
...args,
|
||||
);
|
||||
const classMetadata = globalMetadata.get(ConfigClass);
|
||||
if (!classMetadata) {
|
||||
throw new Error('Invalid config class: ' + ConfigClass.name);
|
||||
}
|
||||
|
||||
for (const [key, { type, envName, schema }] of classMetadata) {
|
||||
if (typeof type === 'function' && globalMetadata.has(type)) {
|
||||
config[key] = Container.get(type as Constructable);
|
||||
} else if (envName) {
|
||||
const value = readEnv(envName);
|
||||
if (value === undefined) continue;
|
||||
|
||||
if (schema) {
|
||||
const result = schema.safeParse(value);
|
||||
if (result.error) {
|
||||
console.warn(
|
||||
`Invalid value for ${envName} - ${result.error.issues[0].message}. Falling back to default value.`,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
config[key] = result.data;
|
||||
} else if (type === Number) {
|
||||
const parsed = Number(value);
|
||||
if (isNaN(parsed)) {
|
||||
console.warn(`Invalid number value for ${envName}: ${value}`);
|
||||
} else {
|
||||
config[key] = parsed;
|
||||
}
|
||||
} else if (type === Boolean) {
|
||||
if (['true', '1'].includes(value.toLowerCase())) {
|
||||
config[key] = true;
|
||||
} else if (['false', '0'].includes(value.toLowerCase())) {
|
||||
config[key] = false;
|
||||
} else {
|
||||
console.warn(`Invalid boolean value for ${envName}: ${value}`);
|
||||
}
|
||||
} else if (type === Date) {
|
||||
const timestamp = Date.parse(value);
|
||||
if (isNaN(timestamp)) {
|
||||
console.warn(`Invalid timestamp value for ${envName}: ${value}`);
|
||||
} else {
|
||||
config[key] = new Date(timestamp);
|
||||
}
|
||||
} else if (type === String) {
|
||||
config[key] = value.trim().replace(/^(['"])(.*)\1$/, '$2');
|
||||
} else {
|
||||
config[key] = new (type as Constructable)(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof config.sanitize === 'function') config.sanitize();
|
||||
|
||||
return config;
|
||||
};
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
||||
return Service({ factory })(ConfigClass);
|
||||
};
|
||||
|
||||
export const Nested: PropertyDecorator = (target: object, key: PropertyKey) => {
|
||||
const ConfigClass = target.constructor;
|
||||
const classMetadata = globalMetadata.get(ConfigClass) ?? new Map<PropertyKey, PropertyMetadata>();
|
||||
const type = Reflect.getMetadata('design:type', target, key) as PropertyType;
|
||||
classMetadata.set(key, { type });
|
||||
globalMetadata.set(ConfigClass, classMetadata);
|
||||
};
|
||||
|
||||
export const Env =
|
||||
(envName: string, schema?: PropertyMetadata['schema']): PropertyDecorator =>
|
||||
(target: object, key: PropertyKey) => {
|
||||
const ConfigClass = target.constructor;
|
||||
const classMetadata =
|
||||
globalMetadata.get(ConfigClass) ?? new Map<PropertyKey, PropertyMetadata>();
|
||||
|
||||
const type = Reflect.getMetadata('design:type', target, key) as PropertyType;
|
||||
const isZodSchema = schema instanceof z.ZodType;
|
||||
if (type === Object && !isZodSchema) {
|
||||
throw new Error(
|
||||
`Invalid decorator metadata on key "${key as string}" on ${ConfigClass.name}\n Please use explicit typing on all config fields`,
|
||||
);
|
||||
}
|
||||
|
||||
classMetadata.set(key, { type, envName, schema });
|
||||
globalMetadata.set(ConfigClass, classMetadata);
|
||||
};
|
||||
211
n8n-n8n-1.109.2/packages/@n8n/config/src/index 2.ts
Executable file
211
n8n-n8n-1.109.2/packages/@n8n/config/src/index 2.ts
Executable file
@@ -0,0 +1,211 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { AiAssistantConfig } from './configs/ai-assistant.config';
|
||||
import { AiConfig } from './configs/ai.config';
|
||||
import { AuthConfig } from './configs/auth.config';
|
||||
import { CacheConfig } from './configs/cache.config';
|
||||
import { CredentialsConfig } from './configs/credentials.config';
|
||||
import { DatabaseConfig } from './configs/database.config';
|
||||
import { DeploymentConfig } from './configs/deployment.config';
|
||||
import { DiagnosticsConfig } from './configs/diagnostics.config';
|
||||
import { EndpointsConfig } from './configs/endpoints.config';
|
||||
import { EventBusConfig } from './configs/event-bus.config';
|
||||
import { ExecutionsConfig } from './configs/executions.config';
|
||||
import { ExternalHooksConfig } from './configs/external-hooks.config';
|
||||
import { GenericConfig } from './configs/generic.config';
|
||||
import { HiringBannerConfig } from './configs/hiring-banner.config';
|
||||
import { LicenseConfig } from './configs/license.config';
|
||||
import { LoggingConfig } from './configs/logging.config';
|
||||
import { MfaConfig } from './configs/mfa.config';
|
||||
import { MultiMainSetupConfig } from './configs/multi-main-setup.config';
|
||||
import { NodesConfig } from './configs/nodes.config';
|
||||
import { PartialExecutionsConfig } from './configs/partial-executions.config';
|
||||
import { PersonalizationConfig } from './configs/personalization.config';
|
||||
import { PublicApiConfig } from './configs/public-api.config';
|
||||
import { RedisConfig } from './configs/redis.config';
|
||||
import { TaskRunnersConfig } from './configs/runners.config';
|
||||
import { ScalingModeConfig } from './configs/scaling-mode.config';
|
||||
import { SecurityConfig } from './configs/security.config';
|
||||
import { SentryConfig } from './configs/sentry.config';
|
||||
import { SsoConfig } from './configs/sso.config';
|
||||
import { TagsConfig } from './configs/tags.config';
|
||||
import { TemplatesConfig } from './configs/templates.config';
|
||||
import { UserManagementConfig } from './configs/user-management.config';
|
||||
import { VersionNotificationsConfig } from './configs/version-notifications.config';
|
||||
import { WorkflowHistoryConfig } from './configs/workflow-history.config';
|
||||
import { WorkflowsConfig } from './configs/workflows.config';
|
||||
import { Config, Env, Nested } from './decorators';
|
||||
|
||||
export { Config, Env, Nested } from './decorators';
|
||||
export { DatabaseConfig } from './configs/database.config';
|
||||
export { InstanceSettingsConfig } from './configs/instance-settings-config';
|
||||
export { TaskRunnersConfig } from './configs/runners.config';
|
||||
export { SecurityConfig } from './configs/security.config';
|
||||
export { ExecutionsConfig } from './configs/executions.config';
|
||||
export { LOG_SCOPES } from './configs/logging.config';
|
||||
export type { LogScope } from './configs/logging.config';
|
||||
export { WorkflowsConfig } from './configs/workflows.config';
|
||||
export * from './custom-types';
|
||||
export { DeploymentConfig } from './configs/deployment.config';
|
||||
export { MfaConfig } from './configs/mfa.config';
|
||||
export { HiringBannerConfig } from './configs/hiring-banner.config';
|
||||
export { PersonalizationConfig } from './configs/personalization.config';
|
||||
export { NodesConfig } from './configs/nodes.config';
|
||||
export { CronLoggingConfig } from './configs/logging.config';
|
||||
|
||||
const protocolSchema = z.enum(['http', 'https']);
|
||||
|
||||
export type Protocol = z.infer<typeof protocolSchema>;
|
||||
|
||||
@Config
|
||||
export class GlobalConfig {
|
||||
@Nested
|
||||
auth: AuthConfig;
|
||||
|
||||
@Nested
|
||||
database: DatabaseConfig;
|
||||
|
||||
@Nested
|
||||
credentials: CredentialsConfig;
|
||||
|
||||
@Nested
|
||||
userManagement: UserManagementConfig;
|
||||
|
||||
@Nested
|
||||
versionNotifications: VersionNotificationsConfig;
|
||||
|
||||
@Nested
|
||||
publicApi: PublicApiConfig;
|
||||
|
||||
@Nested
|
||||
externalHooks: ExternalHooksConfig;
|
||||
|
||||
@Nested
|
||||
templates: TemplatesConfig;
|
||||
|
||||
@Nested
|
||||
eventBus: EventBusConfig;
|
||||
|
||||
@Nested
|
||||
nodes: NodesConfig;
|
||||
|
||||
@Nested
|
||||
workflows: WorkflowsConfig;
|
||||
|
||||
@Nested
|
||||
sentry: SentryConfig;
|
||||
|
||||
/** Path n8n is deployed to */
|
||||
@Env('N8N_PATH')
|
||||
path: string = '/';
|
||||
|
||||
/** Host name n8n can be reached */
|
||||
@Env('N8N_HOST')
|
||||
host: string = 'localhost';
|
||||
|
||||
/** HTTP port n8n can be reached */
|
||||
@Env('N8N_PORT')
|
||||
port: number = 5678;
|
||||
|
||||
/** IP address n8n should listen on */
|
||||
@Env('N8N_LISTEN_ADDRESS')
|
||||
listen_address: string = '::';
|
||||
|
||||
/** HTTP Protocol via which n8n can be reached */
|
||||
@Env('N8N_PROTOCOL', protocolSchema)
|
||||
protocol: Protocol = 'http';
|
||||
|
||||
@Nested
|
||||
endpoints: EndpointsConfig;
|
||||
|
||||
@Nested
|
||||
cache: CacheConfig;
|
||||
|
||||
@Nested
|
||||
queue: ScalingModeConfig;
|
||||
|
||||
@Nested
|
||||
logging: LoggingConfig;
|
||||
|
||||
@Nested
|
||||
taskRunners: TaskRunnersConfig;
|
||||
|
||||
@Nested
|
||||
multiMainSetup: MultiMainSetupConfig;
|
||||
|
||||
@Nested
|
||||
generic: GenericConfig;
|
||||
|
||||
@Nested
|
||||
license: LicenseConfig;
|
||||
|
||||
@Nested
|
||||
security: SecurityConfig;
|
||||
|
||||
@Nested
|
||||
executions: ExecutionsConfig;
|
||||
|
||||
@Nested
|
||||
diagnostics: DiagnosticsConfig;
|
||||
|
||||
@Nested
|
||||
aiAssistant: AiAssistantConfig;
|
||||
|
||||
@Nested
|
||||
tags: TagsConfig;
|
||||
|
||||
@Nested
|
||||
partialExecutions: PartialExecutionsConfig;
|
||||
|
||||
@Nested
|
||||
workflowHistory: WorkflowHistoryConfig;
|
||||
|
||||
@Nested
|
||||
deployment: DeploymentConfig;
|
||||
|
||||
@Nested
|
||||
mfa: MfaConfig;
|
||||
|
||||
@Nested
|
||||
hiringBanner: HiringBannerConfig;
|
||||
|
||||
@Nested
|
||||
personalization: PersonalizationConfig;
|
||||
|
||||
@Nested
|
||||
sso: SsoConfig;
|
||||
|
||||
/** Default locale for the UI. */
|
||||
@Env('N8N_DEFAULT_LOCALE')
|
||||
defaultLocale: string = 'en';
|
||||
|
||||
/** Whether to hide the page that shows active workflows and executions count. */
|
||||
@Env('N8N_HIDE_USAGE_PAGE')
|
||||
hideUsagePage: boolean = false;
|
||||
|
||||
/** Number of reverse proxies n8n is running behind. */
|
||||
@Env('N8N_PROXY_HOPS')
|
||||
proxy_hops: number = 0;
|
||||
|
||||
/** SSL key for HTTPS protocol. */
|
||||
@Env('N8N_SSL_KEY')
|
||||
ssl_key: string = '';
|
||||
|
||||
/** SSL cert for HTTPS protocol. */
|
||||
@Env('N8N_SSL_CERT')
|
||||
ssl_cert: string = '';
|
||||
|
||||
/** Public URL where the editor is accessible. Also used for emails sent from n8n. */
|
||||
@Env('N8N_EDITOR_BASE_URL')
|
||||
editorBaseUrl: string = '';
|
||||
|
||||
/** URLs to external frontend hooks files, separated by semicolons. */
|
||||
@Env('EXTERNAL_FRONTEND_HOOKS_URLS')
|
||||
externalFrontendHooksUrls: string = '';
|
||||
|
||||
@Nested
|
||||
redis: RedisConfig;
|
||||
|
||||
@Nested
|
||||
ai: AiConfig;
|
||||
}
|
||||
Reference in New Issue
Block a user