mirror of
https://github.com/czlonkowski/n8n-mcp.git
synced 2026-03-26 04:03:07 +00:00
chore: add pre-built dist folder for npx usage
This commit is contained in:
committed by
Romuald Członkowski
parent
a70d96a373
commit
5057481e70
13
dist/utils/auth.d.ts
vendored
Normal file
13
dist/utils/auth.d.ts
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
export declare class AuthManager {
|
||||
private validTokens;
|
||||
private tokenExpiry;
|
||||
constructor();
|
||||
validateToken(token: string | undefined, expectedToken?: string): boolean;
|
||||
generateToken(expiryHours?: number): string;
|
||||
revokeToken(token: string): void;
|
||||
private cleanupExpiredTokens;
|
||||
static hashToken(token: string): string;
|
||||
static compareTokens(plainToken: string, hashedToken: string): boolean;
|
||||
static timingSafeCompare(plainToken: string, expectedToken: string): boolean;
|
||||
}
|
||||
//# sourceMappingURL=auth.d.ts.map
|
||||
1
dist/utils/auth.d.ts.map
vendored
Normal file
1
dist/utils/auth.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/utils/auth.ts"],"names":[],"mappings":"AAEA,qBAAa,WAAW;IACtB,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,WAAW,CAAsB;;IAUzC,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO;IAmCzE,aAAa,CAAC,WAAW,GAAE,MAAW,GAAG,MAAM;IAgB/C,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAQhC,OAAO,CAAC,oBAAoB;IAa5B,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAOvC,MAAM,CAAC,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO;IA2BtE,MAAM,CAAC,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO;CAuB7E"}
|
||||
82
dist/utils/auth.js
vendored
Normal file
82
dist/utils/auth.js
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.AuthManager = void 0;
|
||||
const crypto_1 = __importDefault(require("crypto"));
|
||||
class AuthManager {
|
||||
constructor() {
|
||||
this.validTokens = new Set();
|
||||
this.tokenExpiry = new Map();
|
||||
}
|
||||
validateToken(token, expectedToken) {
|
||||
if (!expectedToken) {
|
||||
return true;
|
||||
}
|
||||
if (!token) {
|
||||
return false;
|
||||
}
|
||||
if (AuthManager.timingSafeCompare(token, expectedToken)) {
|
||||
return true;
|
||||
}
|
||||
if (this.validTokens.has(token)) {
|
||||
const expiry = this.tokenExpiry.get(token);
|
||||
if (expiry && expiry > Date.now()) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
this.validTokens.delete(token);
|
||||
this.tokenExpiry.delete(token);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
generateToken(expiryHours = 24) {
|
||||
const token = crypto_1.default.randomBytes(32).toString('hex');
|
||||
const expiryTime = Date.now() + (expiryHours * 60 * 60 * 1000);
|
||||
this.validTokens.add(token);
|
||||
this.tokenExpiry.set(token, expiryTime);
|
||||
this.cleanupExpiredTokens();
|
||||
return token;
|
||||
}
|
||||
revokeToken(token) {
|
||||
this.validTokens.delete(token);
|
||||
this.tokenExpiry.delete(token);
|
||||
}
|
||||
cleanupExpiredTokens() {
|
||||
const now = Date.now();
|
||||
for (const [token, expiry] of this.tokenExpiry.entries()) {
|
||||
if (expiry <= now) {
|
||||
this.validTokens.delete(token);
|
||||
this.tokenExpiry.delete(token);
|
||||
}
|
||||
}
|
||||
}
|
||||
static hashToken(token) {
|
||||
return crypto_1.default.createHash('sha256').update(token).digest('hex');
|
||||
}
|
||||
static compareTokens(plainToken, hashedToken) {
|
||||
const hashedPlainToken = AuthManager.hashToken(plainToken);
|
||||
return crypto_1.default.timingSafeEqual(Buffer.from(hashedPlainToken), Buffer.from(hashedToken));
|
||||
}
|
||||
static timingSafeCompare(plainToken, expectedToken) {
|
||||
try {
|
||||
if (!plainToken || !expectedToken) {
|
||||
return false;
|
||||
}
|
||||
const plainBuffer = Buffer.from(plainToken, 'utf8');
|
||||
const expectedBuffer = Buffer.from(expectedToken, 'utf8');
|
||||
if (plainBuffer.length !== expectedBuffer.length) {
|
||||
return false;
|
||||
}
|
||||
return crypto_1.default.timingSafeEqual(plainBuffer, expectedBuffer);
|
||||
}
|
||||
catch (error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.AuthManager = AuthManager;
|
||||
//# sourceMappingURL=auth.js.map
|
||||
1
dist/utils/auth.js.map
vendored
Normal file
1
dist/utils/auth.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/utils/auth.ts"],"names":[],"mappings":";;;;;;AAAA,oDAA4B;AAE5B,MAAa,WAAW;IAItB;QACE,IAAI,CAAC,WAAW,GAAG,IAAI,GAAG,EAAE,CAAC;QAC7B,IAAI,CAAC,WAAW,GAAG,IAAI,GAAG,EAAE,CAAC;IAC/B,CAAC;IAKD,aAAa,CAAC,KAAyB,EAAE,aAAsB;QAC7D,IAAI,CAAC,aAAa,EAAE,CAAC;YAEnB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,KAAK,CAAC;QACf,CAAC;QAID,IAAI,WAAW,CAAC,iBAAiB,CAAC,KAAK,EAAE,aAAa,CAAC,EAAE,CAAC;YACxD,OAAO,IAAI,CAAC;QACd,CAAC;QAGD,IAAI,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YAChC,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YAC3C,IAAI,MAAM,IAAI,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;gBAClC,OAAO,IAAI,CAAC;YACd,CAAC;iBAAM,CAAC;gBAEN,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBAC/B,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBAC/B,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAKD,aAAa,CAAC,cAAsB,EAAE;QACpC,MAAM,KAAK,GAAG,gBAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACrD,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,WAAW,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;QAE/D,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC5B,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;QAGxC,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAE5B,OAAO,KAAK,CAAC;IACf,CAAC;IAKD,WAAW,CAAC,KAAa;QACvB,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC/B,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACjC,CAAC;IAKO,oBAAoB;QAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,KAAK,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,EAAE,CAAC;YACzD,IAAI,MAAM,IAAI,GAAG,EAAE,CAAC;gBAClB,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBAC/B,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACjC,CAAC;QACH,CAAC;IACH,CAAC;IAKD,MAAM,CAAC,SAAS,CAAC,KAAa;QAC5B,OAAO,gBAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACjE,CAAC;IAKD,MAAM,CAAC,aAAa,CAAC,UAAkB,EAAE,WAAmB;QAC1D,MAAM,gBAAgB,GAAG,WAAW,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QAC3D,OAAO,gBAAM,CAAC,eAAe,CAC3B,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,EAC7B,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CACzB,CAAC;IACJ,CAAC;IAqBD,MAAM,CAAC,iBAAiB,CAAC,UAAkB,EAAE,aAAqB;QAChE,IAAI,CAAC;YAEH,IAAI,CAAC,UAAU,IAAI,CAAC,aAAa,EAAE,CAAC;gBAClC,OAAO,KAAK,CAAC;YACf,CAAC;YAGD,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;YACpD,MAAM,cAAc,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;YAG1D,IAAI,WAAW,CAAC,MAAM,KAAK,cAAc,CAAC,MAAM,EAAE,CAAC;gBACjD,OAAO,KAAK,CAAC;YACf,CAAC;YAGD,OAAO,gBAAM,CAAC,eAAe,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;QAC7D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAEf,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;CACF;AA7ID,kCA6IC"}
|
||||
12
dist/utils/bridge.d.ts
vendored
Normal file
12
dist/utils/bridge.d.ts
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
import { INodeExecutionData, IDataObject } from 'n8n-workflow';
|
||||
export declare class N8NMCPBridge {
|
||||
static n8nToMCPToolArgs(data: IDataObject): any;
|
||||
static mcpToN8NExecutionData(mcpResponse: any, itemIndex?: number): INodeExecutionData;
|
||||
static n8nWorkflowToMCP(workflow: any): any;
|
||||
static mcpToN8NWorkflow(mcpWorkflow: any): any;
|
||||
static n8nExecutionToMCPResource(execution: any): any;
|
||||
static mcpPromptArgsToN8N(promptArgs: any): IDataObject;
|
||||
static sanitizeData(data: any): any;
|
||||
static formatError(error: any): any;
|
||||
}
|
||||
//# sourceMappingURL=bridge.d.ts.map
|
||||
1
dist/utils/bridge.d.ts.map
vendored
Normal file
1
dist/utils/bridge.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../../src/utils/bridge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE/D,qBAAa,YAAY;IAIvB,MAAM,CAAC,gBAAgB,CAAC,IAAI,EAAE,WAAW,GAAG,GAAG;IAc/C,MAAM,CAAC,qBAAqB,CAAC,WAAW,EAAE,GAAG,EAAE,SAAS,GAAE,MAAU,GAAG,kBAAkB;IAkCzF,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,GAAG,GAAG,GAAG;IAyB3C,MAAM,CAAC,gBAAgB,CAAC,WAAW,EAAE,GAAG,GAAG,GAAG;IAgB9C,MAAM,CAAC,yBAAyB,CAAC,SAAS,EAAE,GAAG,GAAG,GAAG;IAsBrD,MAAM,CAAC,kBAAkB,CAAC,UAAU,EAAE,GAAG,GAAG,WAAW;IAWvD,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,GAAG,GAAG,GAAG;IAyBnC,MAAM,CAAC,WAAW,CAAC,KAAK,EAAE,GAAG,GAAG,GAAG;CAYpC"}
|
||||
127
dist/utils/bridge.js
vendored
Normal file
127
dist/utils/bridge.js
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.N8NMCPBridge = void 0;
|
||||
class N8NMCPBridge {
|
||||
static n8nToMCPToolArgs(data) {
|
||||
if (data.json) {
|
||||
return data.json;
|
||||
}
|
||||
const { pairedItem, ...cleanData } = data;
|
||||
return cleanData;
|
||||
}
|
||||
static mcpToN8NExecutionData(mcpResponse, itemIndex = 0) {
|
||||
if (mcpResponse.content && Array.isArray(mcpResponse.content)) {
|
||||
const textContent = mcpResponse.content
|
||||
.filter((c) => c.type === 'text')
|
||||
.map((c) => c.text)
|
||||
.join('\n');
|
||||
try {
|
||||
const parsed = JSON.parse(textContent);
|
||||
return {
|
||||
json: parsed,
|
||||
pairedItem: itemIndex,
|
||||
};
|
||||
}
|
||||
catch {
|
||||
return {
|
||||
json: { result: textContent },
|
||||
pairedItem: itemIndex,
|
||||
};
|
||||
}
|
||||
}
|
||||
return {
|
||||
json: mcpResponse,
|
||||
pairedItem: itemIndex,
|
||||
};
|
||||
}
|
||||
static n8nWorkflowToMCP(workflow) {
|
||||
return {
|
||||
id: workflow.id,
|
||||
name: workflow.name,
|
||||
description: workflow.description || '',
|
||||
nodes: workflow.nodes?.map((node) => ({
|
||||
id: node.id,
|
||||
type: node.type,
|
||||
name: node.name,
|
||||
parameters: node.parameters,
|
||||
position: node.position,
|
||||
})),
|
||||
connections: workflow.connections,
|
||||
settings: workflow.settings,
|
||||
metadata: {
|
||||
createdAt: workflow.createdAt,
|
||||
updatedAt: workflow.updatedAt,
|
||||
active: workflow.active,
|
||||
},
|
||||
};
|
||||
}
|
||||
static mcpToN8NWorkflow(mcpWorkflow) {
|
||||
return {
|
||||
name: mcpWorkflow.name,
|
||||
nodes: mcpWorkflow.nodes || [],
|
||||
connections: mcpWorkflow.connections || {},
|
||||
settings: mcpWorkflow.settings || {
|
||||
executionOrder: 'v1',
|
||||
},
|
||||
staticData: null,
|
||||
pinData: {},
|
||||
};
|
||||
}
|
||||
static n8nExecutionToMCPResource(execution) {
|
||||
return {
|
||||
uri: `execution://${execution.id}`,
|
||||
name: `Execution ${execution.id}`,
|
||||
description: `Workflow: ${execution.workflowData?.name || 'Unknown'}`,
|
||||
mimeType: 'application/json',
|
||||
data: {
|
||||
id: execution.id,
|
||||
workflowId: execution.workflowId,
|
||||
status: execution.finished ? 'completed' : execution.stoppedAt ? 'stopped' : 'running',
|
||||
mode: execution.mode,
|
||||
startedAt: execution.startedAt,
|
||||
stoppedAt: execution.stoppedAt,
|
||||
error: execution.data?.resultData?.error,
|
||||
executionData: execution.data,
|
||||
},
|
||||
};
|
||||
}
|
||||
static mcpPromptArgsToN8N(promptArgs) {
|
||||
return {
|
||||
prompt: promptArgs.name || '',
|
||||
arguments: promptArgs.arguments || {},
|
||||
messages: promptArgs.messages || [],
|
||||
};
|
||||
}
|
||||
static sanitizeData(data) {
|
||||
if (data === null || data === undefined) {
|
||||
return {};
|
||||
}
|
||||
if (typeof data !== 'object') {
|
||||
return { value: data };
|
||||
}
|
||||
const seen = new WeakSet();
|
||||
return JSON.parse(JSON.stringify(data, (_key, value) => {
|
||||
if (typeof value === 'object' && value !== null) {
|
||||
if (seen.has(value)) {
|
||||
return '[Circular]';
|
||||
}
|
||||
seen.add(value);
|
||||
}
|
||||
return value;
|
||||
}));
|
||||
}
|
||||
static formatError(error) {
|
||||
return {
|
||||
message: error.message || 'Unknown error',
|
||||
type: error.name || 'Error',
|
||||
stack: error.stack,
|
||||
details: {
|
||||
code: error.code,
|
||||
statusCode: error.statusCode,
|
||||
data: error.data,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
exports.N8NMCPBridge = N8NMCPBridge;
|
||||
//# sourceMappingURL=bridge.js.map
|
||||
1
dist/utils/bridge.js.map
vendored
Normal file
1
dist/utils/bridge.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"bridge.js","sourceRoot":"","sources":["../../src/utils/bridge.ts"],"names":[],"mappings":"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"}
|
||||
58
dist/utils/cache-utils.d.ts
vendored
Normal file
58
dist/utils/cache-utils.d.ts
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
import { LRUCache } from 'lru-cache';
|
||||
export interface CacheMetrics {
|
||||
hits: number;
|
||||
misses: number;
|
||||
evictions: number;
|
||||
sets: number;
|
||||
deletes: number;
|
||||
clears: number;
|
||||
size: number;
|
||||
maxSize: number;
|
||||
avgHitRate: number;
|
||||
createdAt: Date;
|
||||
lastResetAt: Date;
|
||||
}
|
||||
export interface CacheConfig {
|
||||
max: number;
|
||||
ttlMinutes: number;
|
||||
}
|
||||
declare class CacheMetricsTracker {
|
||||
private metrics;
|
||||
private startTime;
|
||||
constructor();
|
||||
reset(): void;
|
||||
recordHit(): void;
|
||||
recordMiss(): void;
|
||||
recordEviction(): void;
|
||||
recordSet(): void;
|
||||
recordDelete(): void;
|
||||
recordClear(): void;
|
||||
updateSize(current: number, max: number): void;
|
||||
private updateHitRate;
|
||||
getMetrics(): CacheMetrics;
|
||||
getFormattedMetrics(): string;
|
||||
}
|
||||
export declare const cacheMetrics: CacheMetricsTracker;
|
||||
export declare function getCacheConfig(): CacheConfig;
|
||||
export declare function createCacheKey(input: string): string;
|
||||
export declare function createInstanceCache<T extends {}>(onDispose?: (value: T, key: string) => void): LRUCache<string, T>;
|
||||
export declare class CacheMutex {
|
||||
private locks;
|
||||
private lockTimeouts;
|
||||
private readonly timeout;
|
||||
acquire(key: string): Promise<() => void>;
|
||||
isLocked(key: string): boolean;
|
||||
clearAll(): void;
|
||||
}
|
||||
export interface RetryConfig {
|
||||
maxAttempts: number;
|
||||
baseDelayMs: number;
|
||||
maxDelayMs: number;
|
||||
jitterFactor: number;
|
||||
}
|
||||
export declare const DEFAULT_RETRY_CONFIG: RetryConfig;
|
||||
export declare function calculateBackoffDelay(attempt: number, config?: RetryConfig): number;
|
||||
export declare function withRetry<T>(fn: () => Promise<T>, config?: RetryConfig, context?: string): Promise<T>;
|
||||
export declare function getCacheStatistics(): string;
|
||||
export {};
|
||||
//# sourceMappingURL=cache-utils.d.ts.map
|
||||
1
dist/utils/cache-utils.d.ts.map
vendored
Normal file
1
dist/utils/cache-utils.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"cache-utils.d.ts","sourceRoot":"","sources":["../../src/utils/cache-utils.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAMrC,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,IAAI,CAAC;IAChB,WAAW,EAAE,IAAI,CAAC;CACnB;AAKD,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;CACpB;AAYD,cAAM,mBAAmB;IACvB,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,SAAS,CAAO;;IAUxB,KAAK,IAAI,IAAI;IAmBb,SAAS,IAAI,IAAI;IAQjB,UAAU,IAAI,IAAI;IAQlB,cAAc,IAAI,IAAI;IAOtB,SAAS,IAAI,IAAI;IAOjB,YAAY,IAAI,IAAI;IAOpB,WAAW,IAAI,IAAI;IAOnB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI;IAQ9C,OAAO,CAAC,aAAa;IAUrB,UAAU,IAAI,YAAY;IAO1B,mBAAmB,IAAI,MAAM;CAI9B;AAGD,eAAO,MAAM,YAAY,qBAA4B,CAAC;AAMtD,wBAAgB,cAAc,IAAI,WAAW,CAqB5C;AAOD,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAoBpD;AAOD,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,EAAE,EAC9C,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,GAC1C,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAkBrB;AAMD,qBAAa,UAAU;IACrB,OAAO,CAAC,KAAK,CAAyC;IACtD,OAAO,CAAC,YAAY,CAA0C;IAC9D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgB;IAOlC,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC;IAuC/C,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAO9B,QAAQ,IAAI,IAAI;CAKjB;AAKD,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AAKD,eAAO,MAAM,oBAAoB,EAAE,WAKlC,CAAC;AAQF,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,GAAE,WAAkC,GAAG,MAAM,CAUzG;AASD,wBAAsB,SAAS,CAAC,CAAC,EAC/B,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,MAAM,GAAE,WAAkC,EAC1C,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,CAAC,CAAC,CAmCZ;AAqCD,wBAAgB,kBAAkB,IAAI,MAAM,CAc3C"}
|
||||
243
dist/utils/cache-utils.js
vendored
Normal file
243
dist/utils/cache-utils.js
vendored
Normal file
@@ -0,0 +1,243 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.DEFAULT_RETRY_CONFIG = exports.CacheMutex = exports.cacheMetrics = void 0;
|
||||
exports.getCacheConfig = getCacheConfig;
|
||||
exports.createCacheKey = createCacheKey;
|
||||
exports.createInstanceCache = createInstanceCache;
|
||||
exports.calculateBackoffDelay = calculateBackoffDelay;
|
||||
exports.withRetry = withRetry;
|
||||
exports.getCacheStatistics = getCacheStatistics;
|
||||
const crypto_1 = require("crypto");
|
||||
const lru_cache_1 = require("lru-cache");
|
||||
const logger_1 = require("./logger");
|
||||
const hashMemoCache = new Map();
|
||||
const MAX_MEMO_SIZE = 1000;
|
||||
class CacheMetricsTracker {
|
||||
constructor() {
|
||||
this.startTime = new Date();
|
||||
this.reset();
|
||||
}
|
||||
reset() {
|
||||
this.metrics = {
|
||||
hits: 0,
|
||||
misses: 0,
|
||||
evictions: 0,
|
||||
sets: 0,
|
||||
deletes: 0,
|
||||
clears: 0,
|
||||
size: 0,
|
||||
maxSize: 0,
|
||||
avgHitRate: 0,
|
||||
createdAt: this.startTime,
|
||||
lastResetAt: new Date()
|
||||
};
|
||||
}
|
||||
recordHit() {
|
||||
this.metrics.hits++;
|
||||
this.updateHitRate();
|
||||
}
|
||||
recordMiss() {
|
||||
this.metrics.misses++;
|
||||
this.updateHitRate();
|
||||
}
|
||||
recordEviction() {
|
||||
this.metrics.evictions++;
|
||||
}
|
||||
recordSet() {
|
||||
this.metrics.sets++;
|
||||
}
|
||||
recordDelete() {
|
||||
this.metrics.deletes++;
|
||||
}
|
||||
recordClear() {
|
||||
this.metrics.clears++;
|
||||
}
|
||||
updateSize(current, max) {
|
||||
this.metrics.size = current;
|
||||
this.metrics.maxSize = max;
|
||||
}
|
||||
updateHitRate() {
|
||||
const total = this.metrics.hits + this.metrics.misses;
|
||||
if (total > 0) {
|
||||
this.metrics.avgHitRate = this.metrics.hits / total;
|
||||
}
|
||||
}
|
||||
getMetrics() {
|
||||
return { ...this.metrics };
|
||||
}
|
||||
getFormattedMetrics() {
|
||||
const { hits, misses, evictions, avgHitRate, size, maxSize } = this.metrics;
|
||||
return `Cache Metrics: Hits=${hits}, Misses=${misses}, HitRate=${(avgHitRate * 100).toFixed(2)}%, Size=${size}/${maxSize}, Evictions=${evictions}`;
|
||||
}
|
||||
}
|
||||
exports.cacheMetrics = new CacheMetricsTracker();
|
||||
function getCacheConfig() {
|
||||
const max = parseInt(process.env.INSTANCE_CACHE_MAX || '100', 10);
|
||||
const ttlMinutes = parseInt(process.env.INSTANCE_CACHE_TTL_MINUTES || '30', 10);
|
||||
const validatedMax = Math.max(1, Math.min(10000, max)) || 100;
|
||||
const validatedTtl = Math.max(1, Math.min(1440, ttlMinutes)) || 30;
|
||||
if (validatedMax !== max || validatedTtl !== ttlMinutes) {
|
||||
logger_1.logger.warn('Cache configuration adjusted to valid bounds', {
|
||||
requestedMax: max,
|
||||
requestedTtl: ttlMinutes,
|
||||
actualMax: validatedMax,
|
||||
actualTtl: validatedTtl
|
||||
});
|
||||
}
|
||||
return {
|
||||
max: validatedMax,
|
||||
ttlMinutes: validatedTtl
|
||||
};
|
||||
}
|
||||
function createCacheKey(input) {
|
||||
if (hashMemoCache.has(input)) {
|
||||
return hashMemoCache.get(input);
|
||||
}
|
||||
const hash = (0, crypto_1.createHash)('sha256').update(input).digest('hex');
|
||||
if (hashMemoCache.size >= MAX_MEMO_SIZE) {
|
||||
const firstKey = hashMemoCache.keys().next().value;
|
||||
if (firstKey) {
|
||||
hashMemoCache.delete(firstKey);
|
||||
}
|
||||
}
|
||||
hashMemoCache.set(input, hash);
|
||||
return hash;
|
||||
}
|
||||
function createInstanceCache(onDispose) {
|
||||
const config = getCacheConfig();
|
||||
return new lru_cache_1.LRUCache({
|
||||
max: config.max,
|
||||
ttl: config.ttlMinutes * 60 * 1000,
|
||||
updateAgeOnGet: true,
|
||||
dispose: (value, key) => {
|
||||
exports.cacheMetrics.recordEviction();
|
||||
if (onDispose) {
|
||||
onDispose(value, key);
|
||||
}
|
||||
logger_1.logger.debug('Cache eviction', {
|
||||
cacheKey: key.substring(0, 8) + '...',
|
||||
metrics: exports.cacheMetrics.getFormattedMetrics()
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
class CacheMutex {
|
||||
constructor() {
|
||||
this.locks = new Map();
|
||||
this.lockTimeouts = new Map();
|
||||
this.timeout = 5000;
|
||||
}
|
||||
async acquire(key) {
|
||||
while (this.locks.has(key)) {
|
||||
try {
|
||||
await this.locks.get(key);
|
||||
}
|
||||
catch {
|
||||
}
|
||||
}
|
||||
let releaseLock;
|
||||
const lockPromise = new Promise((resolve) => {
|
||||
releaseLock = () => {
|
||||
resolve();
|
||||
this.locks.delete(key);
|
||||
const timeout = this.lockTimeouts.get(key);
|
||||
if (timeout) {
|
||||
clearTimeout(timeout);
|
||||
this.lockTimeouts.delete(key);
|
||||
}
|
||||
};
|
||||
});
|
||||
this.locks.set(key, lockPromise);
|
||||
const timeout = setTimeout(() => {
|
||||
logger_1.logger.warn('Cache lock timeout, forcefully releasing', { key: key.substring(0, 8) + '...' });
|
||||
releaseLock();
|
||||
}, this.timeout);
|
||||
this.lockTimeouts.set(key, timeout);
|
||||
return releaseLock;
|
||||
}
|
||||
isLocked(key) {
|
||||
return this.locks.has(key);
|
||||
}
|
||||
clearAll() {
|
||||
this.lockTimeouts.forEach(timeout => clearTimeout(timeout));
|
||||
this.locks.clear();
|
||||
this.lockTimeouts.clear();
|
||||
}
|
||||
}
|
||||
exports.CacheMutex = CacheMutex;
|
||||
exports.DEFAULT_RETRY_CONFIG = {
|
||||
maxAttempts: 3,
|
||||
baseDelayMs: 1000,
|
||||
maxDelayMs: 10000,
|
||||
jitterFactor: 0.3
|
||||
};
|
||||
function calculateBackoffDelay(attempt, config = exports.DEFAULT_RETRY_CONFIG) {
|
||||
const exponentialDelay = Math.min(config.baseDelayMs * Math.pow(2, attempt), config.maxDelayMs);
|
||||
const jitter = exponentialDelay * config.jitterFactor * Math.random();
|
||||
return Math.floor(exponentialDelay + jitter);
|
||||
}
|
||||
async function withRetry(fn, config = exports.DEFAULT_RETRY_CONFIG, context) {
|
||||
let lastError;
|
||||
for (let attempt = 0; attempt < config.maxAttempts; attempt++) {
|
||||
try {
|
||||
return await fn();
|
||||
}
|
||||
catch (error) {
|
||||
lastError = error;
|
||||
if (!isRetryableError(error)) {
|
||||
throw error;
|
||||
}
|
||||
if (attempt < config.maxAttempts - 1) {
|
||||
const delay = calculateBackoffDelay(attempt, config);
|
||||
logger_1.logger.debug('Retrying operation after delay', {
|
||||
context,
|
||||
attempt: attempt + 1,
|
||||
maxAttempts: config.maxAttempts,
|
||||
delayMs: delay,
|
||||
error: lastError.message
|
||||
});
|
||||
await new Promise(resolve => setTimeout(resolve, delay));
|
||||
}
|
||||
}
|
||||
}
|
||||
logger_1.logger.error('All retry attempts exhausted', {
|
||||
context,
|
||||
attempts: config.maxAttempts,
|
||||
lastError: lastError.message
|
||||
});
|
||||
throw lastError;
|
||||
}
|
||||
function isRetryableError(error) {
|
||||
if (error.code === 'ECONNREFUSED' ||
|
||||
error.code === 'ECONNRESET' ||
|
||||
error.code === 'ETIMEDOUT' ||
|
||||
error.code === 'ENOTFOUND') {
|
||||
return true;
|
||||
}
|
||||
if (error.response?.status) {
|
||||
const status = error.response.status;
|
||||
return status === 429 ||
|
||||
status === 503 ||
|
||||
status === 504 ||
|
||||
(status >= 500 && status < 600);
|
||||
}
|
||||
if (error.message && error.message.toLowerCase().includes('timeout')) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function getCacheStatistics() {
|
||||
const metrics = exports.cacheMetrics.getMetrics();
|
||||
const runtime = Date.now() - metrics.createdAt.getTime();
|
||||
const runtimeMinutes = Math.floor(runtime / 60000);
|
||||
return `
|
||||
Cache Statistics:
|
||||
Runtime: ${runtimeMinutes} minutes
|
||||
Total Operations: ${metrics.hits + metrics.misses}
|
||||
Hit Rate: ${(metrics.avgHitRate * 100).toFixed(2)}%
|
||||
Current Size: ${metrics.size}/${metrics.maxSize}
|
||||
Total Evictions: ${metrics.evictions}
|
||||
Sets: ${metrics.sets}, Deletes: ${metrics.deletes}, Clears: ${metrics.clears}
|
||||
`.trim();
|
||||
}
|
||||
//# sourceMappingURL=cache-utils.js.map
|
||||
1
dist/utils/cache-utils.js.map
vendored
Normal file
1
dist/utils/cache-utils.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
10
dist/utils/console-manager.d.ts
vendored
Normal file
10
dist/utils/console-manager.d.ts
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
export declare class ConsoleManager {
|
||||
private originalConsole;
|
||||
private isSilenced;
|
||||
silence(): void;
|
||||
restore(): void;
|
||||
wrapOperation<T>(operation: () => T | Promise<T>): Promise<T>;
|
||||
get isActive(): boolean;
|
||||
}
|
||||
export declare const consoleManager: ConsoleManager;
|
||||
//# sourceMappingURL=console-manager.d.ts.map
|
||||
1
dist/utils/console-manager.d.ts.map
vendored
Normal file
1
dist/utils/console-manager.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"console-manager.d.ts","sourceRoot":"","sources":["../../src/utils/console-manager.ts"],"names":[],"mappings":"AAMA,qBAAa,cAAc;IACzB,OAAO,CAAC,eAAe,CAOrB;IAEF,OAAO,CAAC,UAAU,CAAS;IAKpB,OAAO,IAAI,IAAI;IAkBf,OAAO,IAAI,IAAI;IAmBT,aAAa,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAkB1E,IAAW,QAAQ,IAAI,OAAO,CAE7B;CACF;AAGD,eAAO,MAAM,cAAc,gBAAuB,CAAC"}
|
||||
63
dist/utils/console-manager.js
vendored
Normal file
63
dist/utils/console-manager.js
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.consoleManager = exports.ConsoleManager = void 0;
|
||||
class ConsoleManager {
|
||||
constructor() {
|
||||
this.originalConsole = {
|
||||
log: console.log,
|
||||
error: console.error,
|
||||
warn: console.warn,
|
||||
info: console.info,
|
||||
debug: console.debug,
|
||||
trace: console.trace
|
||||
};
|
||||
this.isSilenced = false;
|
||||
}
|
||||
silence() {
|
||||
if (this.isSilenced || process.env.MCP_MODE !== 'http') {
|
||||
return;
|
||||
}
|
||||
this.isSilenced = true;
|
||||
process.env.MCP_REQUEST_ACTIVE = 'true';
|
||||
console.log = () => { };
|
||||
console.error = () => { };
|
||||
console.warn = () => { };
|
||||
console.info = () => { };
|
||||
console.debug = () => { };
|
||||
console.trace = () => { };
|
||||
}
|
||||
restore() {
|
||||
if (!this.isSilenced) {
|
||||
return;
|
||||
}
|
||||
this.isSilenced = false;
|
||||
process.env.MCP_REQUEST_ACTIVE = 'false';
|
||||
console.log = this.originalConsole.log;
|
||||
console.error = this.originalConsole.error;
|
||||
console.warn = this.originalConsole.warn;
|
||||
console.info = this.originalConsole.info;
|
||||
console.debug = this.originalConsole.debug;
|
||||
console.trace = this.originalConsole.trace;
|
||||
}
|
||||
async wrapOperation(operation) {
|
||||
this.silence();
|
||||
try {
|
||||
const result = operation();
|
||||
if (result instanceof Promise) {
|
||||
return await result.finally(() => this.restore());
|
||||
}
|
||||
this.restore();
|
||||
return result;
|
||||
}
|
||||
catch (error) {
|
||||
this.restore();
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
get isActive() {
|
||||
return this.isSilenced;
|
||||
}
|
||||
}
|
||||
exports.ConsoleManager = ConsoleManager;
|
||||
exports.consoleManager = new ConsoleManager();
|
||||
//# sourceMappingURL=console-manager.js.map
|
||||
1
dist/utils/console-manager.js.map
vendored
Normal file
1
dist/utils/console-manager.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"console-manager.js","sourceRoot":"","sources":["../../src/utils/console-manager.ts"],"names":[],"mappings":";;;AAMA,MAAa,cAAc;IAA3B;QACU,oBAAe,GAAG;YACxB,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,KAAK,EAAE,OAAO,CAAC,KAAK;SACrB,CAAC;QAEM,eAAU,GAAG,KAAK,CAAC;IA+D7B,CAAC;IA1DQ,OAAO;QACZ,IAAI,IAAI,CAAC,UAAU,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,MAAM,EAAE,CAAC;YACvD,OAAO;QACT,CAAC;QAED,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,kBAAkB,GAAG,MAAM,CAAC;QACxC,OAAO,CAAC,GAAG,GAAG,GAAG,EAAE,GAAE,CAAC,CAAC;QACvB,OAAO,CAAC,KAAK,GAAG,GAAG,EAAE,GAAE,CAAC,CAAC;QACzB,OAAO,CAAC,IAAI,GAAG,GAAG,EAAE,GAAE,CAAC,CAAC;QACxB,OAAO,CAAC,IAAI,GAAG,GAAG,EAAE,GAAE,CAAC,CAAC;QACxB,OAAO,CAAC,KAAK,GAAG,GAAG,EAAE,GAAE,CAAC,CAAC;QACzB,OAAO,CAAC,KAAK,GAAG,GAAG,EAAE,GAAE,CAAC,CAAC;IAC3B,CAAC;IAKM,OAAO;QACZ,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACrB,OAAO;QACT,CAAC;QAED,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;QACxB,OAAO,CAAC,GAAG,CAAC,kBAAkB,GAAG,OAAO,CAAC;QACzC,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC;QACvC,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC;QAC3C,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC;QACzC,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC;QACzC,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC;QAC3C,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC;IAC7C,CAAC;IAMM,KAAK,CAAC,aAAa,CAAI,SAA+B;QAC3D,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;YAC3B,IAAI,MAAM,YAAY,OAAO,EAAE,CAAC;gBAC9B,OAAO,MAAM,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;YACpD,CAAC;YACD,IAAI,CAAC,OAAO,EAAE,CAAC;YACf,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,OAAO,EAAE,CAAC;YACf,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAKD,IAAW,QAAQ;QACjB,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;CACF;AAzED,wCAyEC;AAGY,QAAA,cAAc,GAAG,IAAI,cAAc,EAAE,CAAC"}
|
||||
2
dist/utils/documentation-fetcher.d.ts
vendored
Normal file
2
dist/utils/documentation-fetcher.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from './enhanced-documentation-fetcher';
|
||||
//# sourceMappingURL=documentation-fetcher.d.ts.map
|
||||
1
dist/utils/documentation-fetcher.d.ts.map
vendored
Normal file
1
dist/utils/documentation-fetcher.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"documentation-fetcher.d.ts","sourceRoot":"","sources":["../../src/utils/documentation-fetcher.ts"],"names":[],"mappings":"AACA,cAAc,kCAAkC,CAAC"}
|
||||
18
dist/utils/documentation-fetcher.js
vendored
Normal file
18
dist/utils/documentation-fetcher.js
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
||||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
__exportStar(require("./enhanced-documentation-fetcher"), exports);
|
||||
//# sourceMappingURL=documentation-fetcher.js.map
|
||||
1
dist/utils/documentation-fetcher.js.map
vendored
Normal file
1
dist/utils/documentation-fetcher.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"documentation-fetcher.js","sourceRoot":"","sources":["../../src/utils/documentation-fetcher.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AACA,mEAAiD"}
|
||||
74
dist/utils/enhanced-documentation-fetcher.d.ts
vendored
Normal file
74
dist/utils/enhanced-documentation-fetcher.d.ts
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
export interface EnhancedNodeDocumentation {
|
||||
markdown: string;
|
||||
url: string;
|
||||
title?: string;
|
||||
description?: string;
|
||||
operations?: OperationInfo[];
|
||||
apiMethods?: ApiMethodMapping[];
|
||||
examples?: CodeExample[];
|
||||
templates?: TemplateInfo[];
|
||||
relatedResources?: RelatedResource[];
|
||||
requiredScopes?: string[];
|
||||
metadata?: DocumentationMetadata;
|
||||
}
|
||||
export interface OperationInfo {
|
||||
resource: string;
|
||||
operation: string;
|
||||
description: string;
|
||||
subOperations?: string[];
|
||||
}
|
||||
export interface ApiMethodMapping {
|
||||
resource: string;
|
||||
operation: string;
|
||||
apiMethod: string;
|
||||
apiUrl: string;
|
||||
}
|
||||
export interface CodeExample {
|
||||
title?: string;
|
||||
description?: string;
|
||||
type: 'json' | 'javascript' | 'yaml' | 'text';
|
||||
code: string;
|
||||
language?: string;
|
||||
}
|
||||
export interface TemplateInfo {
|
||||
name: string;
|
||||
description?: string;
|
||||
url?: string;
|
||||
}
|
||||
export interface RelatedResource {
|
||||
title: string;
|
||||
url: string;
|
||||
type: 'documentation' | 'api' | 'tutorial' | 'external';
|
||||
}
|
||||
export interface DocumentationMetadata {
|
||||
contentType?: string[];
|
||||
priority?: string;
|
||||
tags?: string[];
|
||||
lastUpdated?: Date;
|
||||
}
|
||||
export declare class EnhancedDocumentationFetcher {
|
||||
private docsPath;
|
||||
private readonly docsRepoUrl;
|
||||
private cloned;
|
||||
constructor(docsPath?: string);
|
||||
private sanitizePath;
|
||||
ensureDocsRepository(): Promise<void>;
|
||||
getEnhancedNodeDocumentation(nodeType: string): Promise<EnhancedNodeDocumentation | null>;
|
||||
private parseEnhancedDocumentation;
|
||||
private extractFrontmatter;
|
||||
private extractTitle;
|
||||
private extractDescription;
|
||||
private extractOperations;
|
||||
private extractApiMethods;
|
||||
private extractCodeExamples;
|
||||
private extractTemplates;
|
||||
private extractRelatedResources;
|
||||
private extractRequiredScopes;
|
||||
private mapLanguageToType;
|
||||
private isCredentialDoc;
|
||||
private extractNodeName;
|
||||
private searchForNodeDoc;
|
||||
private generateDocUrl;
|
||||
cleanup(): Promise<void>;
|
||||
}
|
||||
//# sourceMappingURL=enhanced-documentation-fetcher.d.ts.map
|
||||
1
dist/utils/enhanced-documentation-fetcher.d.ts.map
vendored
Normal file
1
dist/utils/enhanced-documentation-fetcher.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"enhanced-documentation-fetcher.d.ts","sourceRoot":"","sources":["../../src/utils/enhanced-documentation-fetcher.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,aAAa,EAAE,CAAC;IAC7B,UAAU,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAChC,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC;IACzB,SAAS,CAAC,EAAE,YAAY,EAAE,CAAC;IAC3B,gBAAgB,CAAC,EAAE,eAAe,EAAE,CAAC;IACrC,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,QAAQ,CAAC,EAAE,qBAAqB,CAAC;CAClC;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,MAAM,GAAG,MAAM,CAAC;IAC9C,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,eAAe,GAAG,KAAK,GAAG,UAAU,GAAG,UAAU,CAAC;CACzD;AAED,MAAM,WAAW,qBAAqB;IACpC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,CAAC,EAAE,IAAI,CAAC;CACpB;AAED,qBAAa,4BAA4B;IACvC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA4C;IACxE,OAAO,CAAC,MAAM,CAAS;gBAEX,QAAQ,CAAC,EAAE,MAAM;IA2C7B,OAAO,CAAC,YAAY;IAuBd,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC;IAuErC,4BAA4B,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,yBAAyB,GAAG,IAAI,CAAC;IA4D/F,OAAO,CAAC,0BAA0B;IA8ClC,OAAO,CAAC,kBAAkB;IA8B1B,OAAO,CAAC,YAAY;IAQpB,OAAO,CAAC,kBAAkB;IA2B1B,OAAO,CAAC,iBAAiB;IA8EzB,OAAO,CAAC,iBAAiB;IAiDzB,OAAO,CAAC,mBAAmB;IA6C3B,OAAO,CAAC,gBAAgB;IAkBxB,OAAO,CAAC,uBAAuB;IAkC/B,OAAO,CAAC,qBAAqB;IA0B7B,OAAO,CAAC,iBAAiB;IAoBzB,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,eAAe;YAWT,gBAAgB;IA+G9B,OAAO,CAAC,cAAc;IAahB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAS/B"}
|
||||
521
dist/utils/enhanced-documentation-fetcher.js
vendored
Normal file
521
dist/utils/enhanced-documentation-fetcher.js
vendored
Normal file
@@ -0,0 +1,521 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.EnhancedDocumentationFetcher = void 0;
|
||||
const fs_1 = require("fs");
|
||||
const path_1 = __importDefault(require("path"));
|
||||
const logger_1 = require("./logger");
|
||||
const child_process_1 = require("child_process");
|
||||
class EnhancedDocumentationFetcher {
|
||||
constructor(docsPath) {
|
||||
this.docsRepoUrl = 'https://github.com/n8n-io/n8n-docs.git';
|
||||
this.cloned = false;
|
||||
const defaultPath = path_1.default.join(__dirname, '../../temp', 'n8n-docs');
|
||||
if (!docsPath) {
|
||||
this.docsPath = defaultPath;
|
||||
}
|
||||
else {
|
||||
const sanitized = this.sanitizePath(docsPath);
|
||||
if (!sanitized) {
|
||||
logger_1.logger.error('Invalid docsPath rejected in constructor', { docsPath });
|
||||
throw new Error('Invalid docsPath: path contains disallowed characters or patterns');
|
||||
}
|
||||
const absolutePath = path_1.default.resolve(sanitized);
|
||||
if (absolutePath.startsWith('/etc') ||
|
||||
absolutePath.startsWith('/sys') ||
|
||||
absolutePath.startsWith('/proc') ||
|
||||
absolutePath.startsWith('/var/log')) {
|
||||
logger_1.logger.error('docsPath points to system directory - blocked', { docsPath, absolutePath });
|
||||
throw new Error('Invalid docsPath: cannot use system directories');
|
||||
}
|
||||
this.docsPath = absolutePath;
|
||||
logger_1.logger.info('docsPath validated and set', { docsPath: this.docsPath });
|
||||
}
|
||||
if (!this.docsRepoUrl.startsWith('https://')) {
|
||||
logger_1.logger.error('docsRepoUrl must use HTTPS protocol', { url: this.docsRepoUrl });
|
||||
throw new Error('Invalid repository URL: must use HTTPS protocol');
|
||||
}
|
||||
}
|
||||
sanitizePath(inputPath) {
|
||||
const dangerousChars = /[;&|`$(){}[\]<>'"\\#\n\r\t]/;
|
||||
if (dangerousChars.test(inputPath)) {
|
||||
logger_1.logger.warn('Path contains shell metacharacters - rejected', { path: inputPath });
|
||||
return null;
|
||||
}
|
||||
if (inputPath.includes('..') || inputPath.startsWith('.')) {
|
||||
logger_1.logger.warn('Path traversal attempt blocked', { path: inputPath });
|
||||
return null;
|
||||
}
|
||||
return inputPath;
|
||||
}
|
||||
async ensureDocsRepository() {
|
||||
try {
|
||||
const exists = await fs_1.promises.access(this.docsPath).then(() => true).catch(() => false);
|
||||
if (!exists) {
|
||||
logger_1.logger.info('Cloning n8n-docs repository...', {
|
||||
url: this.docsRepoUrl,
|
||||
path: this.docsPath
|
||||
});
|
||||
await fs_1.promises.mkdir(path_1.default.dirname(this.docsPath), { recursive: true });
|
||||
const cloneResult = (0, child_process_1.spawnSync)('git', [
|
||||
'clone',
|
||||
'--depth', '1',
|
||||
this.docsRepoUrl,
|
||||
this.docsPath
|
||||
], {
|
||||
stdio: 'pipe',
|
||||
encoding: 'utf-8'
|
||||
});
|
||||
if (cloneResult.status !== 0) {
|
||||
const error = cloneResult.stderr || cloneResult.error?.message || 'Unknown error';
|
||||
logger_1.logger.error('Git clone failed', {
|
||||
status: cloneResult.status,
|
||||
stderr: error,
|
||||
url: this.docsRepoUrl,
|
||||
path: this.docsPath
|
||||
});
|
||||
throw new Error(`Git clone failed: ${error}`);
|
||||
}
|
||||
logger_1.logger.info('n8n-docs repository cloned successfully');
|
||||
}
|
||||
else {
|
||||
logger_1.logger.info('Updating n8n-docs repository...', { path: this.docsPath });
|
||||
const pullResult = (0, child_process_1.spawnSync)('git', [
|
||||
'pull',
|
||||
'--ff-only'
|
||||
], {
|
||||
cwd: this.docsPath,
|
||||
stdio: 'pipe',
|
||||
encoding: 'utf-8'
|
||||
});
|
||||
if (pullResult.status !== 0) {
|
||||
const error = pullResult.stderr || pullResult.error?.message || 'Unknown error';
|
||||
logger_1.logger.error('Git pull failed', {
|
||||
status: pullResult.status,
|
||||
stderr: error,
|
||||
cwd: this.docsPath
|
||||
});
|
||||
throw new Error(`Git pull failed: ${error}`);
|
||||
}
|
||||
logger_1.logger.info('n8n-docs repository updated');
|
||||
}
|
||||
this.cloned = true;
|
||||
}
|
||||
catch (error) {
|
||||
logger_1.logger.error('Failed to clone/update n8n-docs repository:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
async getEnhancedNodeDocumentation(nodeType) {
|
||||
if (!this.cloned) {
|
||||
await this.ensureDocsRepository();
|
||||
}
|
||||
try {
|
||||
const nodeName = this.extractNodeName(nodeType);
|
||||
const possiblePaths = [
|
||||
path_1.default.join(this.docsPath, 'docs', 'integrations', 'builtin', 'app-nodes', `${nodeType}.md`),
|
||||
path_1.default.join(this.docsPath, 'docs', 'integrations', 'builtin', 'core-nodes', `${nodeType}.md`),
|
||||
path_1.default.join(this.docsPath, 'docs', 'integrations', 'builtin', 'trigger-nodes', `${nodeType}.md`),
|
||||
path_1.default.join(this.docsPath, 'docs', 'integrations', 'builtin', 'core-nodes', `${nodeName}.md`),
|
||||
path_1.default.join(this.docsPath, 'docs', 'integrations', 'builtin', 'app-nodes', `${nodeName}.md`),
|
||||
path_1.default.join(this.docsPath, 'docs', 'integrations', 'builtin', 'trigger-nodes', `${nodeName}.md`),
|
||||
];
|
||||
for (const docPath of possiblePaths) {
|
||||
try {
|
||||
const content = await fs_1.promises.readFile(docPath, 'utf-8');
|
||||
logger_1.logger.debug(`Checking doc path: ${docPath}`);
|
||||
if (this.isCredentialDoc(docPath, content)) {
|
||||
logger_1.logger.debug(`Skipping credential doc: ${docPath}`);
|
||||
continue;
|
||||
}
|
||||
logger_1.logger.info(`Found documentation for ${nodeType} at: ${docPath}`);
|
||||
return this.parseEnhancedDocumentation(content, docPath);
|
||||
}
|
||||
catch (error) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
logger_1.logger.debug(`No exact match found, searching for ${nodeType}...`);
|
||||
const foundPath = await this.searchForNodeDoc(nodeType);
|
||||
if (foundPath) {
|
||||
logger_1.logger.info(`Found documentation via search at: ${foundPath}`);
|
||||
const content = await fs_1.promises.readFile(foundPath, 'utf-8');
|
||||
if (!this.isCredentialDoc(foundPath, content)) {
|
||||
return this.parseEnhancedDocumentation(content, foundPath);
|
||||
}
|
||||
}
|
||||
logger_1.logger.warn(`No documentation found for node: ${nodeType}`);
|
||||
return null;
|
||||
}
|
||||
catch (error) {
|
||||
logger_1.logger.error(`Failed to get documentation for ${nodeType}:`, error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
parseEnhancedDocumentation(markdown, filePath) {
|
||||
const doc = {
|
||||
markdown,
|
||||
url: this.generateDocUrl(filePath),
|
||||
};
|
||||
const metadata = this.extractFrontmatter(markdown);
|
||||
if (metadata) {
|
||||
doc.metadata = metadata;
|
||||
doc.title = metadata.title;
|
||||
doc.description = metadata.description;
|
||||
}
|
||||
if (!doc.title) {
|
||||
doc.title = this.extractTitle(markdown);
|
||||
}
|
||||
if (!doc.description) {
|
||||
doc.description = this.extractDescription(markdown);
|
||||
}
|
||||
doc.operations = this.extractOperations(markdown);
|
||||
doc.apiMethods = this.extractApiMethods(markdown);
|
||||
doc.examples = this.extractCodeExamples(markdown);
|
||||
doc.templates = this.extractTemplates(markdown);
|
||||
doc.relatedResources = this.extractRelatedResources(markdown);
|
||||
doc.requiredScopes = this.extractRequiredScopes(markdown);
|
||||
return doc;
|
||||
}
|
||||
extractFrontmatter(markdown) {
|
||||
const frontmatterMatch = markdown.match(/^---\n([\s\S]*?)\n---/);
|
||||
if (!frontmatterMatch)
|
||||
return null;
|
||||
const frontmatter = {};
|
||||
const lines = frontmatterMatch[1].split('\n');
|
||||
for (const line of lines) {
|
||||
if (line.includes(':')) {
|
||||
const [key, ...valueParts] = line.split(':');
|
||||
const value = valueParts.join(':').trim();
|
||||
if (value.startsWith('[') && value.endsWith(']')) {
|
||||
frontmatter[key.trim()] = value
|
||||
.slice(1, -1)
|
||||
.split(',')
|
||||
.map(v => v.trim());
|
||||
}
|
||||
else {
|
||||
frontmatter[key.trim()] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return frontmatter;
|
||||
}
|
||||
extractTitle(markdown) {
|
||||
const match = markdown.match(/^#\s+(.+)$/m);
|
||||
return match ? match[1].trim() : undefined;
|
||||
}
|
||||
extractDescription(markdown) {
|
||||
const content = markdown.replace(/^---[\s\S]*?---\n/, '');
|
||||
const lines = content.split('\n');
|
||||
let foundTitle = false;
|
||||
let description = '';
|
||||
for (const line of lines) {
|
||||
if (line.startsWith('#')) {
|
||||
foundTitle = true;
|
||||
continue;
|
||||
}
|
||||
if (foundTitle && line.trim() && !line.startsWith('#') && !line.startsWith('*') && !line.startsWith('-')) {
|
||||
description = line.trim();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return description || undefined;
|
||||
}
|
||||
extractOperations(markdown) {
|
||||
const operations = [];
|
||||
const operationsMatch = markdown.match(/##\s+Operations\s*\n([\s\S]*?)(?=\n##|\n#|$)/i);
|
||||
if (!operationsMatch)
|
||||
return operations;
|
||||
const operationsText = operationsMatch[1];
|
||||
let currentResource = null;
|
||||
const lines = operationsText.split('\n');
|
||||
for (const line of lines) {
|
||||
const trimmedLine = line.trim();
|
||||
if (!trimmedLine)
|
||||
continue;
|
||||
if (line.match(/^\*\s+\*\*[^*]+\*\*\s*$/) && !line.match(/^\s+/)) {
|
||||
const match = trimmedLine.match(/^\*\s+\*\*([^*]+)\*\*/);
|
||||
if (match) {
|
||||
currentResource = match[1].trim();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!currentResource)
|
||||
continue;
|
||||
if (line.match(/^\s+\*\s+/) && currentResource) {
|
||||
const operationMatch = trimmedLine.match(/^\*\s+\*\*([^*]+)\*\*(.*)$/);
|
||||
if (operationMatch) {
|
||||
const operation = operationMatch[1].trim();
|
||||
let description = operationMatch[2].trim();
|
||||
description = description.replace(/^:\s*/, '').replace(/\.$/, '').trim();
|
||||
operations.push({
|
||||
resource: currentResource,
|
||||
operation,
|
||||
description: description || operation,
|
||||
});
|
||||
}
|
||||
else {
|
||||
const simpleMatch = trimmedLine.match(/^\*\s+(.+)$/);
|
||||
if (simpleMatch) {
|
||||
const text = simpleMatch[1].trim();
|
||||
const colonIndex = text.indexOf(':');
|
||||
if (colonIndex > 0) {
|
||||
operations.push({
|
||||
resource: currentResource,
|
||||
operation: text.substring(0, colonIndex).trim(),
|
||||
description: text.substring(colonIndex + 1).trim() || text,
|
||||
});
|
||||
}
|
||||
else {
|
||||
operations.push({
|
||||
resource: currentResource,
|
||||
operation: text,
|
||||
description: text,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return operations;
|
||||
}
|
||||
extractApiMethods(markdown) {
|
||||
const apiMethods = [];
|
||||
const tableRegex = /\|.*Resource.*\|.*Operation.*\|.*(?:Slack API method|API method|Method).*\|[\s\S]*?\n(?=\n[^|]|$)/gi;
|
||||
const tables = markdown.match(tableRegex);
|
||||
if (!tables)
|
||||
return apiMethods;
|
||||
for (const table of tables) {
|
||||
const rows = table.split('\n').filter(row => row.trim() && !row.includes('---'));
|
||||
for (let i = 1; i < rows.length; i++) {
|
||||
const cells = rows[i].split('|').map(cell => cell.trim()).filter(Boolean);
|
||||
if (cells.length >= 3) {
|
||||
const resource = cells[0];
|
||||
const operation = cells[1];
|
||||
const apiMethodCell = cells[2];
|
||||
const linkMatch = apiMethodCell.match(/\[([^\]]+)\]\(([^)]+)\)/);
|
||||
if (linkMatch) {
|
||||
apiMethods.push({
|
||||
resource,
|
||||
operation,
|
||||
apiMethod: linkMatch[1],
|
||||
apiUrl: linkMatch[2],
|
||||
});
|
||||
}
|
||||
else {
|
||||
apiMethods.push({
|
||||
resource,
|
||||
operation,
|
||||
apiMethod: apiMethodCell,
|
||||
apiUrl: '',
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return apiMethods;
|
||||
}
|
||||
extractCodeExamples(markdown) {
|
||||
const examples = [];
|
||||
const codeBlockRegex = /```(\w+)?\n([\s\S]*?)```/g;
|
||||
let match;
|
||||
while ((match = codeBlockRegex.exec(markdown)) !== null) {
|
||||
const language = match[1] || 'text';
|
||||
const code = match[2].trim();
|
||||
const beforeCodeIndex = match.index;
|
||||
const beforeText = markdown.substring(Math.max(0, beforeCodeIndex - 200), beforeCodeIndex);
|
||||
const titleMatch = beforeText.match(/(?:###|####)\s+(.+)$/m);
|
||||
const example = {
|
||||
type: this.mapLanguageToType(language),
|
||||
language,
|
||||
code,
|
||||
};
|
||||
if (titleMatch) {
|
||||
example.title = titleMatch[1].trim();
|
||||
}
|
||||
if (language === 'json') {
|
||||
try {
|
||||
JSON.parse(code);
|
||||
examples.push(example);
|
||||
}
|
||||
catch (e) {
|
||||
}
|
||||
}
|
||||
else {
|
||||
examples.push(example);
|
||||
}
|
||||
}
|
||||
return examples;
|
||||
}
|
||||
extractTemplates(markdown) {
|
||||
const templates = [];
|
||||
const templateWidgetMatch = markdown.match(/\[\[\s*templatesWidget\s*\(\s*[^,]+,\s*'([^']+)'\s*\)\s*\]\]/);
|
||||
if (templateWidgetMatch) {
|
||||
templates.push({
|
||||
name: templateWidgetMatch[1],
|
||||
description: `Templates for ${templateWidgetMatch[1]}`,
|
||||
});
|
||||
}
|
||||
return templates;
|
||||
}
|
||||
extractRelatedResources(markdown) {
|
||||
const resources = [];
|
||||
const relatedMatch = markdown.match(/##\s+(?:Related resources|Related|Resources)\s*\n([\s\S]*?)(?=\n##|\n#|$)/i);
|
||||
if (!relatedMatch)
|
||||
return resources;
|
||||
const relatedText = relatedMatch[1];
|
||||
const linkRegex = /\[([^\]]+)\]\(([^)]+)\)/g;
|
||||
let match;
|
||||
while ((match = linkRegex.exec(relatedText)) !== null) {
|
||||
const title = match[1];
|
||||
const url = match[2];
|
||||
let type = 'external';
|
||||
if (url.includes('docs.n8n.io') || url.startsWith('/')) {
|
||||
type = 'documentation';
|
||||
}
|
||||
else if (url.includes('api.')) {
|
||||
type = 'api';
|
||||
}
|
||||
resources.push({ title, url, type });
|
||||
}
|
||||
return resources;
|
||||
}
|
||||
extractRequiredScopes(markdown) {
|
||||
const scopes = [];
|
||||
const scopesMatch = markdown.match(/##\s+(?:Required scopes|Scopes)\s*\n([\s\S]*?)(?=\n##|\n#|$)/i);
|
||||
if (!scopesMatch)
|
||||
return scopes;
|
||||
const scopesText = scopesMatch[1];
|
||||
const scopeRegex = /`([a-z:._-]+)`/gi;
|
||||
let match;
|
||||
while ((match = scopeRegex.exec(scopesText)) !== null) {
|
||||
const scope = match[1];
|
||||
if (scope.includes(':') || scope.includes('.')) {
|
||||
scopes.push(scope);
|
||||
}
|
||||
}
|
||||
return [...new Set(scopes)];
|
||||
}
|
||||
mapLanguageToType(language) {
|
||||
switch (language.toLowerCase()) {
|
||||
case 'json':
|
||||
return 'json';
|
||||
case 'js':
|
||||
case 'javascript':
|
||||
case 'typescript':
|
||||
case 'ts':
|
||||
return 'javascript';
|
||||
case 'yaml':
|
||||
case 'yml':
|
||||
return 'yaml';
|
||||
default:
|
||||
return 'text';
|
||||
}
|
||||
}
|
||||
isCredentialDoc(filePath, content) {
|
||||
return filePath.includes('/credentials/') ||
|
||||
(content.includes('title: ') &&
|
||||
content.includes(' credentials') &&
|
||||
!content.includes(' node documentation'));
|
||||
}
|
||||
extractNodeName(nodeType) {
|
||||
const parts = nodeType.split('.');
|
||||
const name = parts[parts.length - 1];
|
||||
return name.toLowerCase();
|
||||
}
|
||||
async searchForNodeDoc(nodeType) {
|
||||
try {
|
||||
const sanitized = nodeType.replace(/[^a-zA-Z0-9._-]/g, '');
|
||||
if (!sanitized) {
|
||||
logger_1.logger.warn('Invalid nodeType after sanitization', { nodeType });
|
||||
return null;
|
||||
}
|
||||
if (sanitized.includes('..') || sanitized.startsWith('.') || sanitized.startsWith('/')) {
|
||||
logger_1.logger.warn('Path traversal attempt blocked', { nodeType, sanitized });
|
||||
return null;
|
||||
}
|
||||
if (sanitized !== nodeType) {
|
||||
logger_1.logger.warn('nodeType was sanitized (potential injection attempt)', {
|
||||
original: nodeType,
|
||||
sanitized,
|
||||
});
|
||||
}
|
||||
const safeName = path_1.default.basename(sanitized);
|
||||
const searchPath = path_1.default.join(this.docsPath, 'docs', 'integrations', 'builtin');
|
||||
const files = await fs_1.promises.readdir(searchPath, {
|
||||
recursive: true,
|
||||
encoding: 'utf-8'
|
||||
});
|
||||
let match = files.find(f => f.endsWith(`${safeName}.md`) &&
|
||||
!f.includes('credentials') &&
|
||||
!f.includes('trigger'));
|
||||
if (match) {
|
||||
const fullPath = path_1.default.join(searchPath, match);
|
||||
if (!fullPath.startsWith(searchPath)) {
|
||||
logger_1.logger.error('Path traversal blocked in final path', { fullPath, searchPath });
|
||||
return null;
|
||||
}
|
||||
logger_1.logger.info('Found documentation (exact match)', { path: fullPath });
|
||||
return fullPath;
|
||||
}
|
||||
const lowerSafeName = safeName.toLowerCase();
|
||||
match = files.find(f => f.endsWith(`${lowerSafeName}.md`) &&
|
||||
!f.includes('credentials') &&
|
||||
!f.includes('trigger'));
|
||||
if (match) {
|
||||
const fullPath = path_1.default.join(searchPath, match);
|
||||
if (!fullPath.startsWith(searchPath)) {
|
||||
logger_1.logger.error('Path traversal blocked in final path', { fullPath, searchPath });
|
||||
return null;
|
||||
}
|
||||
logger_1.logger.info('Found documentation (lowercase match)', { path: fullPath });
|
||||
return fullPath;
|
||||
}
|
||||
const nodeName = this.extractNodeName(safeName);
|
||||
match = files.find(f => f.toLowerCase().includes(nodeName.toLowerCase()) &&
|
||||
f.endsWith('.md') &&
|
||||
!f.includes('credentials') &&
|
||||
!f.includes('trigger'));
|
||||
if (match) {
|
||||
const fullPath = path_1.default.join(searchPath, match);
|
||||
if (!fullPath.startsWith(searchPath)) {
|
||||
logger_1.logger.error('Path traversal blocked in final path', { fullPath, searchPath });
|
||||
return null;
|
||||
}
|
||||
logger_1.logger.info('Found documentation (partial match)', { path: fullPath });
|
||||
return fullPath;
|
||||
}
|
||||
logger_1.logger.debug('No documentation found', { nodeType: safeName });
|
||||
return null;
|
||||
}
|
||||
catch (error) {
|
||||
logger_1.logger.error('Error searching for node documentation:', {
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
nodeType,
|
||||
});
|
||||
return null;
|
||||
}
|
||||
}
|
||||
generateDocUrl(filePath) {
|
||||
const relativePath = path_1.default.relative(this.docsPath, filePath);
|
||||
const urlPath = relativePath
|
||||
.replace(/^docs\//, '')
|
||||
.replace(/\.md$/, '')
|
||||
.replace(/\\/g, '/');
|
||||
return `https://docs.n8n.io/${urlPath}`;
|
||||
}
|
||||
async cleanup() {
|
||||
try {
|
||||
await fs_1.promises.rm(this.docsPath, { recursive: true, force: true });
|
||||
this.cloned = false;
|
||||
logger_1.logger.info('Cleaned up documentation repository');
|
||||
}
|
||||
catch (error) {
|
||||
logger_1.logger.error('Failed to cleanup docs repository:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.EnhancedDocumentationFetcher = EnhancedDocumentationFetcher;
|
||||
//# sourceMappingURL=enhanced-documentation-fetcher.js.map
|
||||
1
dist/utils/enhanced-documentation-fetcher.js.map
vendored
Normal file
1
dist/utils/enhanced-documentation-fetcher.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
24
dist/utils/error-handler.d.ts
vendored
Normal file
24
dist/utils/error-handler.d.ts
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
export declare class MCPError extends Error {
|
||||
code: string;
|
||||
statusCode?: number;
|
||||
data?: any;
|
||||
constructor(message: string, code: string, statusCode?: number, data?: any);
|
||||
}
|
||||
export declare class N8NConnectionError extends MCPError {
|
||||
constructor(message: string, data?: any);
|
||||
}
|
||||
export declare class AuthenticationError extends MCPError {
|
||||
constructor(message?: string);
|
||||
}
|
||||
export declare class ValidationError extends MCPError {
|
||||
constructor(message: string, data?: any);
|
||||
}
|
||||
export declare class ToolNotFoundError extends MCPError {
|
||||
constructor(toolName: string);
|
||||
}
|
||||
export declare class ResourceNotFoundError extends MCPError {
|
||||
constructor(resourceUri: string);
|
||||
}
|
||||
export declare function handleError(error: any): MCPError;
|
||||
export declare function withErrorHandling<T>(operation: () => Promise<T>, context: string): Promise<T>;
|
||||
//# sourceMappingURL=error-handler.d.ts.map
|
||||
1
dist/utils/error-handler.d.ts.map
vendored
Normal file
1
dist/utils/error-handler.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"error-handler.d.ts","sourceRoot":"","sources":["../../src/utils/error-handler.ts"],"names":[],"mappings":"AAEA,qBAAa,QAAS,SAAQ,KAAK;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,GAAG,CAAC;gBAEN,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG;CAO3E;AAED,qBAAa,kBAAmB,SAAQ,QAAQ;gBAClC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG;CAIxC;AAED,qBAAa,mBAAoB,SAAQ,QAAQ;gBACnC,OAAO,GAAE,MAAgC;CAItD;AAED,qBAAa,eAAgB,SAAQ,QAAQ;gBAC/B,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG;CAIxC;AAED,qBAAa,iBAAkB,SAAQ,QAAQ;gBACjC,QAAQ,EAAE,MAAM;CAI7B;AAED,qBAAa,qBAAsB,SAAQ,QAAQ;gBACrC,WAAW,EAAE,MAAM;CAIhC;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,GAAG,GAAG,QAAQ,CA+BhD;AAED,wBAAsB,iBAAiB,CAAC,CAAC,EACvC,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAC3B,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,CAAC,CAAC,CAOZ"}
|
||||
84
dist/utils/error-handler.js
vendored
Normal file
84
dist/utils/error-handler.js
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.ResourceNotFoundError = exports.ToolNotFoundError = exports.ValidationError = exports.AuthenticationError = exports.N8NConnectionError = exports.MCPError = void 0;
|
||||
exports.handleError = handleError;
|
||||
exports.withErrorHandling = withErrorHandling;
|
||||
const logger_1 = require("./logger");
|
||||
class MCPError extends Error {
|
||||
constructor(message, code, statusCode, data) {
|
||||
super(message);
|
||||
this.name = 'MCPError';
|
||||
this.code = code;
|
||||
this.statusCode = statusCode;
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
exports.MCPError = MCPError;
|
||||
class N8NConnectionError extends MCPError {
|
||||
constructor(message, data) {
|
||||
super(message, 'N8N_CONNECTION_ERROR', 503, data);
|
||||
this.name = 'N8NConnectionError';
|
||||
}
|
||||
}
|
||||
exports.N8NConnectionError = N8NConnectionError;
|
||||
class AuthenticationError extends MCPError {
|
||||
constructor(message = 'Authentication failed') {
|
||||
super(message, 'AUTH_ERROR', 401);
|
||||
this.name = 'AuthenticationError';
|
||||
}
|
||||
}
|
||||
exports.AuthenticationError = AuthenticationError;
|
||||
class ValidationError extends MCPError {
|
||||
constructor(message, data) {
|
||||
super(message, 'VALIDATION_ERROR', 400, data);
|
||||
this.name = 'ValidationError';
|
||||
}
|
||||
}
|
||||
exports.ValidationError = ValidationError;
|
||||
class ToolNotFoundError extends MCPError {
|
||||
constructor(toolName) {
|
||||
super(`Tool '${toolName}' not found`, 'TOOL_NOT_FOUND', 404);
|
||||
this.name = 'ToolNotFoundError';
|
||||
}
|
||||
}
|
||||
exports.ToolNotFoundError = ToolNotFoundError;
|
||||
class ResourceNotFoundError extends MCPError {
|
||||
constructor(resourceUri) {
|
||||
super(`Resource '${resourceUri}' not found`, 'RESOURCE_NOT_FOUND', 404);
|
||||
this.name = 'ResourceNotFoundError';
|
||||
}
|
||||
}
|
||||
exports.ResourceNotFoundError = ResourceNotFoundError;
|
||||
function handleError(error) {
|
||||
if (error instanceof MCPError) {
|
||||
return error;
|
||||
}
|
||||
if (error.response) {
|
||||
const status = error.response.status;
|
||||
const message = error.response.data?.message || error.message;
|
||||
if (status === 401) {
|
||||
return new AuthenticationError(message);
|
||||
}
|
||||
else if (status === 404) {
|
||||
return new MCPError(message, 'NOT_FOUND', 404);
|
||||
}
|
||||
else if (status >= 500) {
|
||||
return new N8NConnectionError(message);
|
||||
}
|
||||
return new MCPError(message, 'API_ERROR', status);
|
||||
}
|
||||
if (error.code === 'ECONNREFUSED') {
|
||||
return new N8NConnectionError('Cannot connect to n8n API');
|
||||
}
|
||||
return new MCPError(error.message || 'An unexpected error occurred', 'UNKNOWN_ERROR', 500);
|
||||
}
|
||||
async function withErrorHandling(operation, context) {
|
||||
try {
|
||||
return await operation();
|
||||
}
|
||||
catch (error) {
|
||||
logger_1.logger.error(`Error in ${context}:`, error);
|
||||
throw handleError(error);
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=error-handler.js.map
|
||||
1
dist/utils/error-handler.js.map
vendored
Normal file
1
dist/utils/error-handler.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"error-handler.js","sourceRoot":"","sources":["../../src/utils/error-handler.ts"],"names":[],"mappings":"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"}
|
||||
8
dist/utils/example-generator.d.ts
vendored
Normal file
8
dist/utils/example-generator.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
export declare class ExampleGenerator {
|
||||
static generateFromNodeDefinition(nodeDefinition: any): any;
|
||||
static generateExampleParameters(nodeDefinition: any): any;
|
||||
private static generateExampleValue;
|
||||
private static generateNodeId;
|
||||
static generateFromOperations(operations: any[]): any;
|
||||
}
|
||||
//# sourceMappingURL=example-generator.d.ts.map
|
||||
1
dist/utils/example-generator.d.ts.map
vendored
Normal file
1
dist/utils/example-generator.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"example-generator.d.ts","sourceRoot":"","sources":["../../src/utils/example-generator.ts"],"names":[],"mappings":"AAGA,qBAAa,gBAAgB;IAI3B,MAAM,CAAC,0BAA0B,CAAC,cAAc,EAAE,GAAG,GAAG,GAAG;IA0B3D,MAAM,CAAC,yBAAyB,CAAC,cAAc,EAAE,GAAG,GAAG,GAAG;IA6B1D,OAAO,CAAC,MAAM,CAAC,oBAAoB;IAsCnC,OAAO,CAAC,MAAM,CAAC,cAAc;IAQ7B,MAAM,CAAC,sBAAsB,CAAC,UAAU,EAAE,GAAG,EAAE,GAAG,GAAG;CA+BtD"}
|
||||
106
dist/utils/example-generator.js
vendored
Normal file
106
dist/utils/example-generator.js
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.ExampleGenerator = void 0;
|
||||
class ExampleGenerator {
|
||||
static generateFromNodeDefinition(nodeDefinition) {
|
||||
const nodeName = nodeDefinition.displayName || 'Example Node';
|
||||
const nodeType = nodeDefinition.name || 'n8n-nodes-base.exampleNode';
|
||||
return {
|
||||
name: `${nodeName} Example Workflow`,
|
||||
nodes: [
|
||||
{
|
||||
parameters: this.generateExampleParameters(nodeDefinition),
|
||||
id: this.generateNodeId(),
|
||||
name: nodeName,
|
||||
type: nodeType,
|
||||
typeVersion: nodeDefinition.version || 1,
|
||||
position: [250, 300],
|
||||
},
|
||||
],
|
||||
connections: {},
|
||||
active: false,
|
||||
settings: {},
|
||||
tags: ['example', 'generated'],
|
||||
};
|
||||
}
|
||||
static generateExampleParameters(nodeDefinition) {
|
||||
const params = {};
|
||||
if (Array.isArray(nodeDefinition.properties)) {
|
||||
for (const prop of nodeDefinition.properties) {
|
||||
if (prop.name && prop.type) {
|
||||
params[prop.name] = this.generateExampleValue(prop);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nodeDefinition.displayName?.toLowerCase().includes('trigger')) {
|
||||
params.pollTimes = {
|
||||
item: [
|
||||
{
|
||||
mode: 'everyMinute',
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
return params;
|
||||
}
|
||||
static generateExampleValue(property) {
|
||||
switch (property.type) {
|
||||
case 'string':
|
||||
if (property.name.toLowerCase().includes('url')) {
|
||||
return 'https://example.com';
|
||||
}
|
||||
if (property.name.toLowerCase().includes('email')) {
|
||||
return 'user@example.com';
|
||||
}
|
||||
if (property.name.toLowerCase().includes('name')) {
|
||||
return 'Example Name';
|
||||
}
|
||||
return property.default || 'example-value';
|
||||
case 'number':
|
||||
return property.default || 10;
|
||||
case 'boolean':
|
||||
return property.default !== undefined ? property.default : true;
|
||||
case 'options':
|
||||
if (property.options && property.options.length > 0) {
|
||||
return property.options[0].value;
|
||||
}
|
||||
return property.default || '';
|
||||
case 'collection':
|
||||
case 'fixedCollection':
|
||||
return {};
|
||||
default:
|
||||
return property.default || null;
|
||||
}
|
||||
}
|
||||
static generateNodeId() {
|
||||
return Math.random().toString(36).substring(2, 15) +
|
||||
Math.random().toString(36).substring(2, 15);
|
||||
}
|
||||
static generateFromOperations(operations) {
|
||||
const examples = [];
|
||||
if (!operations || operations.length === 0) {
|
||||
return examples;
|
||||
}
|
||||
const resourceMap = new Map();
|
||||
for (const op of operations) {
|
||||
if (!resourceMap.has(op.resource)) {
|
||||
resourceMap.set(op.resource, []);
|
||||
}
|
||||
resourceMap.get(op.resource).push(op);
|
||||
}
|
||||
for (const [resource, ops] of resourceMap) {
|
||||
examples.push({
|
||||
resource,
|
||||
operation: ops[0].operation,
|
||||
description: `Example: ${ops[0].description}`,
|
||||
parameters: {
|
||||
resource,
|
||||
operation: ops[0].operation,
|
||||
},
|
||||
});
|
||||
}
|
||||
return examples;
|
||||
}
|
||||
}
|
||||
exports.ExampleGenerator = ExampleGenerator;
|
||||
//# sourceMappingURL=example-generator.js.map
|
||||
1
dist/utils/example-generator.js.map
vendored
Normal file
1
dist/utils/example-generator.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"example-generator.js","sourceRoot":"","sources":["../../src/utils/example-generator.ts"],"names":[],"mappings":"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"}
|
||||
6
dist/utils/expression-utils.d.ts
vendored
Normal file
6
dist/utils/expression-utils.d.ts
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
export declare function isExpression(value: unknown): value is string;
|
||||
export declare function containsExpression(value: unknown): boolean;
|
||||
export declare function shouldSkipLiteralValidation(value: unknown): boolean;
|
||||
export declare function extractExpressionContent(value: string): string;
|
||||
export declare function hasMixedContent(value: unknown): boolean;
|
||||
//# sourceMappingURL=expression-utils.d.ts.map
|
||||
1
dist/utils/expression-utils.d.ts.map
vendored
Normal file
1
dist/utils/expression-utils.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"expression-utils.d.ts","sourceRoot":"","sources":["../../src/utils/expression-utils.ts"],"names":[],"mappings":"AAeA,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAE5D;AAWD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAM1D;AAaD,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAEnE;AAYD,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAc9D;AAYD,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAqBvD"}
|
||||
47
dist/utils/expression-utils.js
vendored
Normal file
47
dist/utils/expression-utils.js
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.isExpression = isExpression;
|
||||
exports.containsExpression = containsExpression;
|
||||
exports.shouldSkipLiteralValidation = shouldSkipLiteralValidation;
|
||||
exports.extractExpressionContent = extractExpressionContent;
|
||||
exports.hasMixedContent = hasMixedContent;
|
||||
function isExpression(value) {
|
||||
return typeof value === 'string' && value.startsWith('=');
|
||||
}
|
||||
function containsExpression(value) {
|
||||
if (typeof value !== 'string') {
|
||||
return false;
|
||||
}
|
||||
return /\{\{.*\}\}/s.test(value);
|
||||
}
|
||||
function shouldSkipLiteralValidation(value) {
|
||||
return isExpression(value) || containsExpression(value);
|
||||
}
|
||||
function extractExpressionContent(value) {
|
||||
if (!isExpression(value)) {
|
||||
return value;
|
||||
}
|
||||
const withoutPrefix = value.substring(1);
|
||||
const match = withoutPrefix.match(/^\{\{(.+)\}\}$/s);
|
||||
if (match) {
|
||||
return match[1].trim();
|
||||
}
|
||||
return withoutPrefix;
|
||||
}
|
||||
function hasMixedContent(value) {
|
||||
if (typeof value !== 'string') {
|
||||
return false;
|
||||
}
|
||||
if (!containsExpression(value)) {
|
||||
return false;
|
||||
}
|
||||
const trimmed = value.trim();
|
||||
if (trimmed.startsWith('={{') && trimmed.endsWith('}}')) {
|
||||
const count = (trimmed.match(/\{\{/g) || []).length;
|
||||
if (count === 1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//# sourceMappingURL=expression-utils.js.map
|
||||
1
dist/utils/expression-utils.js.map
vendored
Normal file
1
dist/utils/expression-utils.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"expression-utils.js","sourceRoot":"","sources":["../../src/utils/expression-utils.ts"],"names":[],"mappings":";;AAeA,oCAEC;AAWD,gDAMC;AAaD,kEAEC;AAYD,4DAcC;AAYD,0CAqBC;AA7FD,SAAgB,YAAY,CAAC,KAAc;IACzC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;AAC5D,CAAC;AAWD,SAAgB,kBAAkB,CAAC,KAAc;IAC/C,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACnC,CAAC;AAaD,SAAgB,2BAA2B,CAAC,KAAc;IACxD,OAAO,YAAY,CAAC,KAAK,CAAC,IAAI,kBAAkB,CAAC,KAAK,CAAC,CAAC;AAC1D,CAAC;AAYD,SAAgB,wBAAwB,CAAC,KAAa;IACpD,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,aAAa,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IAGzC,MAAM,KAAK,GAAG,aAAa,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;IACrD,IAAI,KAAK,EAAE,CAAC;QACV,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACzB,CAAC;IAED,OAAO,aAAa,CAAC;AACvB,CAAC;AAYD,SAAgB,eAAe,CAAC,KAAc;IAE5C,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,KAAK,CAAC;IACf,CAAC;IAGD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAExD,MAAM,KAAK,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;QACpD,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;YAChB,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
|
||||
35
dist/utils/fixed-collection-validator.d.ts
vendored
Normal file
35
dist/utils/fixed-collection-validator.d.ts
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
export type NodeConfigValue = string | number | boolean | null | undefined | NodeConfig | NodeConfigValue[];
|
||||
export interface NodeConfig {
|
||||
[key: string]: NodeConfigValue;
|
||||
}
|
||||
export interface FixedCollectionPattern {
|
||||
nodeType: string;
|
||||
property: string;
|
||||
subProperty?: string;
|
||||
expectedStructure: string;
|
||||
invalidPatterns: string[];
|
||||
}
|
||||
export interface FixedCollectionValidationResult {
|
||||
isValid: boolean;
|
||||
errors: Array<{
|
||||
pattern: string;
|
||||
message: string;
|
||||
fix: string;
|
||||
}>;
|
||||
autofix?: NodeConfig | NodeConfigValue[];
|
||||
}
|
||||
export declare class FixedCollectionValidator {
|
||||
private static isNodeConfig;
|
||||
private static getNestedValue;
|
||||
private static readonly KNOWN_PATTERNS;
|
||||
static validate(nodeType: string, config: NodeConfig): FixedCollectionValidationResult;
|
||||
static applyAutofix(config: NodeConfig, pattern: FixedCollectionPattern): NodeConfig | NodeConfigValue[];
|
||||
private static normalizeNodeType;
|
||||
private static getPatternForNode;
|
||||
private static hasInvalidStructure;
|
||||
private static generateFixMessage;
|
||||
private static generateAutofix;
|
||||
static getAllPatterns(): FixedCollectionPattern[];
|
||||
static isNodeSusceptible(nodeType: string): boolean;
|
||||
}
|
||||
//# sourceMappingURL=fixed-collection-validator.d.ts.map
|
||||
1
dist/utils/fixed-collection-validator.d.ts.map
vendored
Normal file
1
dist/utils/fixed-collection-validator.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"fixed-collection-validator.d.ts","sourceRoot":"","sources":["../../src/utils/fixed-collection-validator.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,GAAG,UAAU,GAAG,eAAe,EAAE,CAAC;AAE5G,MAAM,WAAW,UAAU;IACzB,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAAC;CAChC;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,+BAA+B;IAC9C,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,KAAK,CAAC;QACZ,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;QAChB,GAAG,EAAE,MAAM,CAAC;KACb,CAAC,CAAC;IACH,OAAO,CAAC,EAAE,UAAU,GAAG,eAAe,EAAE,CAAC;CAC1C;AAED,qBAAa,wBAAwB;IAInC,OAAO,CAAC,MAAM,CAAC,YAAY;IAO3B,OAAO,CAAC,MAAM,CAAC,cAAc;IAgB7B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CA6EpC;IAMF,MAAM,CAAC,QAAQ,CACb,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,UAAU,GACjB,+BAA+B;IAyClC,MAAM,CAAC,YAAY,CACjB,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,sBAAsB,GAC9B,UAAU,GAAG,eAAe,EAAE;IAmBjC,OAAO,CAAC,MAAM,CAAC,iBAAiB;IAWhC,OAAO,CAAC,MAAM,CAAC,iBAAiB;IAQhC,OAAO,CAAC,MAAM,CAAC,mBAAmB;IA8ClC,OAAO,CAAC,MAAM,CAAC,kBAAkB;IA+BjC,OAAO,CAAC,MAAM,CAAC,eAAe;IAkK9B,MAAM,CAAC,cAAc,IAAI,sBAAsB,EAAE;IAUjD,MAAM,CAAC,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;CAIpD"}
|
||||
358
dist/utils/fixed-collection-validator.js
vendored
Normal file
358
dist/utils/fixed-collection-validator.js
vendored
Normal file
@@ -0,0 +1,358 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.FixedCollectionValidator = void 0;
|
||||
class FixedCollectionValidator {
|
||||
static isNodeConfig(value) {
|
||||
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
||||
}
|
||||
static getNestedValue(obj, path) {
|
||||
const parts = path.split('.');
|
||||
let current = obj;
|
||||
for (const part of parts) {
|
||||
if (!this.isNodeConfig(current)) {
|
||||
return undefined;
|
||||
}
|
||||
current = current[part];
|
||||
}
|
||||
return current;
|
||||
}
|
||||
static validate(nodeType, config) {
|
||||
if (typeof config !== 'object' || config === null || Array.isArray(config)) {
|
||||
return { isValid: true, errors: [] };
|
||||
}
|
||||
const normalizedNodeType = this.normalizeNodeType(nodeType);
|
||||
const pattern = this.getPatternForNode(normalizedNodeType);
|
||||
if (!pattern) {
|
||||
return { isValid: true, errors: [] };
|
||||
}
|
||||
const result = {
|
||||
isValid: true,
|
||||
errors: []
|
||||
};
|
||||
for (const invalidPattern of pattern.invalidPatterns) {
|
||||
if (this.hasInvalidStructure(config, invalidPattern)) {
|
||||
result.isValid = false;
|
||||
result.errors.push({
|
||||
pattern: invalidPattern,
|
||||
message: `Invalid structure for nodes-base.${pattern.nodeType} node: found nested "${invalidPattern}" but expected "${pattern.expectedStructure}". This causes "propertyValues[itemName] is not iterable" error in n8n.`,
|
||||
fix: this.generateFixMessage(pattern)
|
||||
});
|
||||
if (!result.autofix) {
|
||||
result.autofix = this.generateAutofix(config, pattern);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
static applyAutofix(config, pattern) {
|
||||
const fixedConfig = this.generateAutofix(config, pattern);
|
||||
if (pattern.nodeType === 'if' || pattern.nodeType === 'filter') {
|
||||
const conditions = config.conditions;
|
||||
if (conditions && typeof conditions === 'object' && !Array.isArray(conditions) && 'values' in conditions) {
|
||||
const values = conditions.values;
|
||||
if (values !== undefined && values !== null &&
|
||||
(Array.isArray(values) || typeof values === 'object')) {
|
||||
return values;
|
||||
}
|
||||
}
|
||||
}
|
||||
return fixedConfig;
|
||||
}
|
||||
static normalizeNodeType(nodeType) {
|
||||
return nodeType
|
||||
.replace('n8n-nodes-base.', '')
|
||||
.replace('nodes-base.', '')
|
||||
.replace('@n8n/n8n-nodes-langchain.', '')
|
||||
.toLowerCase();
|
||||
}
|
||||
static getPatternForNode(nodeType) {
|
||||
return this.KNOWN_PATTERNS.find(p => p.nodeType === nodeType);
|
||||
}
|
||||
static hasInvalidStructure(config, pattern) {
|
||||
const parts = pattern.split('.');
|
||||
let current = config;
|
||||
const visited = new WeakSet();
|
||||
for (const part of parts) {
|
||||
if (current === null || current === undefined) {
|
||||
return false;
|
||||
}
|
||||
if (typeof current !== 'object' || Array.isArray(current)) {
|
||||
return false;
|
||||
}
|
||||
if (visited.has(current)) {
|
||||
return false;
|
||||
}
|
||||
visited.add(current);
|
||||
if (!Object.prototype.hasOwnProperty.call(current, part)) {
|
||||
return false;
|
||||
}
|
||||
const nextValue = current[part];
|
||||
if (typeof nextValue !== 'object' || nextValue === null) {
|
||||
if (parts.indexOf(part) < parts.length - 1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
current = nextValue;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
static generateFixMessage(pattern) {
|
||||
switch (pattern.nodeType) {
|
||||
case 'switch':
|
||||
return 'Use: { "rules": { "values": [{ "conditions": {...}, "outputKey": "output1" }] } }';
|
||||
case 'if':
|
||||
case 'filter':
|
||||
return 'Use: { "conditions": {...} } or { "conditions": [...] } directly, not nested under "values"';
|
||||
case 'summarize':
|
||||
return 'Use: { "fieldsToSummarize": { "values": [...] } } not nested values.values';
|
||||
case 'comparedatasets':
|
||||
return 'Use: { "mergeByFields": { "values": [...] } } not nested values.values';
|
||||
case 'sort':
|
||||
return 'Use: { "sortFieldsUi": { "sortField": [...] } } not sortField.values';
|
||||
case 'aggregate':
|
||||
return 'Use: { "fieldsToAggregate": { "fieldToAggregate": [...] } } not fieldToAggregate.values';
|
||||
case 'set':
|
||||
return 'Use: { "fields": { "values": [...] } } not nested values.values';
|
||||
case 'html':
|
||||
return 'Use: { "extractionValues": { "values": [...] } } not nested values.values';
|
||||
case 'httprequest':
|
||||
return 'Use: { "body": { "parameters": [...] } } not parameters.values';
|
||||
case 'airtable':
|
||||
return 'Use: { "sort": { "sortField": [...] } } not sortField.values';
|
||||
default:
|
||||
return `Use ${pattern.expectedStructure} structure`;
|
||||
}
|
||||
}
|
||||
static generateAutofix(config, pattern) {
|
||||
const fixedConfig = { ...config };
|
||||
switch (pattern.nodeType) {
|
||||
case 'switch': {
|
||||
const rules = config.rules;
|
||||
if (this.isNodeConfig(rules)) {
|
||||
const conditions = rules.conditions;
|
||||
if (this.isNodeConfig(conditions) && 'values' in conditions) {
|
||||
const values = conditions.values;
|
||||
fixedConfig.rules = {
|
||||
values: Array.isArray(values)
|
||||
? values.map((condition, index) => ({
|
||||
conditions: condition,
|
||||
outputKey: `output${index + 1}`
|
||||
}))
|
||||
: [{
|
||||
conditions: values,
|
||||
outputKey: 'output1'
|
||||
}]
|
||||
};
|
||||
}
|
||||
else if (conditions) {
|
||||
fixedConfig.rules = {
|
||||
values: [{
|
||||
conditions: conditions,
|
||||
outputKey: 'output1'
|
||||
}]
|
||||
};
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'if':
|
||||
case 'filter': {
|
||||
const conditions = config.conditions;
|
||||
if (this.isNodeConfig(conditions) && 'values' in conditions) {
|
||||
const values = conditions.values;
|
||||
if (values !== undefined && values !== null &&
|
||||
(Array.isArray(values) || typeof values === 'object')) {
|
||||
return values;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'summarize': {
|
||||
const fieldsToSummarize = config.fieldsToSummarize;
|
||||
if (this.isNodeConfig(fieldsToSummarize)) {
|
||||
const values = fieldsToSummarize.values;
|
||||
if (this.isNodeConfig(values) && 'values' in values) {
|
||||
fixedConfig.fieldsToSummarize = {
|
||||
values: values.values
|
||||
};
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'comparedatasets': {
|
||||
const mergeByFields = config.mergeByFields;
|
||||
if (this.isNodeConfig(mergeByFields)) {
|
||||
const values = mergeByFields.values;
|
||||
if (this.isNodeConfig(values) && 'values' in values) {
|
||||
fixedConfig.mergeByFields = {
|
||||
values: values.values
|
||||
};
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'sort': {
|
||||
const sortFieldsUi = config.sortFieldsUi;
|
||||
if (this.isNodeConfig(sortFieldsUi)) {
|
||||
const sortField = sortFieldsUi.sortField;
|
||||
if (this.isNodeConfig(sortField) && 'values' in sortField) {
|
||||
fixedConfig.sortFieldsUi = {
|
||||
sortField: sortField.values
|
||||
};
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'aggregate': {
|
||||
const fieldsToAggregate = config.fieldsToAggregate;
|
||||
if (this.isNodeConfig(fieldsToAggregate)) {
|
||||
const fieldToAggregate = fieldsToAggregate.fieldToAggregate;
|
||||
if (this.isNodeConfig(fieldToAggregate) && 'values' in fieldToAggregate) {
|
||||
fixedConfig.fieldsToAggregate = {
|
||||
fieldToAggregate: fieldToAggregate.values
|
||||
};
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'set': {
|
||||
const fields = config.fields;
|
||||
if (this.isNodeConfig(fields)) {
|
||||
const values = fields.values;
|
||||
if (this.isNodeConfig(values) && 'values' in values) {
|
||||
fixedConfig.fields = {
|
||||
values: values.values
|
||||
};
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'html': {
|
||||
const extractionValues = config.extractionValues;
|
||||
if (this.isNodeConfig(extractionValues)) {
|
||||
const values = extractionValues.values;
|
||||
if (this.isNodeConfig(values) && 'values' in values) {
|
||||
fixedConfig.extractionValues = {
|
||||
values: values.values
|
||||
};
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'httprequest': {
|
||||
const body = config.body;
|
||||
if (this.isNodeConfig(body)) {
|
||||
const parameters = body.parameters;
|
||||
if (this.isNodeConfig(parameters) && 'values' in parameters) {
|
||||
fixedConfig.body = {
|
||||
...body,
|
||||
parameters: parameters.values
|
||||
};
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'airtable': {
|
||||
const sort = config.sort;
|
||||
if (this.isNodeConfig(sort)) {
|
||||
const sortField = sort.sortField;
|
||||
if (this.isNodeConfig(sortField) && 'values' in sortField) {
|
||||
fixedConfig.sort = {
|
||||
sortField: sortField.values
|
||||
};
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return fixedConfig;
|
||||
}
|
||||
static getAllPatterns() {
|
||||
return this.KNOWN_PATTERNS.map(pattern => ({
|
||||
...pattern,
|
||||
invalidPatterns: [...pattern.invalidPatterns]
|
||||
}));
|
||||
}
|
||||
static isNodeSusceptible(nodeType) {
|
||||
const normalizedType = this.normalizeNodeType(nodeType);
|
||||
return this.KNOWN_PATTERNS.some(p => p.nodeType === normalizedType);
|
||||
}
|
||||
}
|
||||
exports.FixedCollectionValidator = FixedCollectionValidator;
|
||||
FixedCollectionValidator.KNOWN_PATTERNS = [
|
||||
{
|
||||
nodeType: 'switch',
|
||||
property: 'rules',
|
||||
expectedStructure: 'rules.values array',
|
||||
invalidPatterns: ['rules.conditions', 'rules.conditions.values']
|
||||
},
|
||||
{
|
||||
nodeType: 'if',
|
||||
property: 'conditions',
|
||||
expectedStructure: 'conditions array/object',
|
||||
invalidPatterns: ['conditions.values']
|
||||
},
|
||||
{
|
||||
nodeType: 'filter',
|
||||
property: 'conditions',
|
||||
expectedStructure: 'conditions array/object',
|
||||
invalidPatterns: ['conditions.values']
|
||||
},
|
||||
{
|
||||
nodeType: 'summarize',
|
||||
property: 'fieldsToSummarize',
|
||||
subProperty: 'values',
|
||||
expectedStructure: 'fieldsToSummarize.values array',
|
||||
invalidPatterns: ['fieldsToSummarize.values.values']
|
||||
},
|
||||
{
|
||||
nodeType: 'comparedatasets',
|
||||
property: 'mergeByFields',
|
||||
subProperty: 'values',
|
||||
expectedStructure: 'mergeByFields.values array',
|
||||
invalidPatterns: ['mergeByFields.values.values']
|
||||
},
|
||||
{
|
||||
nodeType: 'sort',
|
||||
property: 'sortFieldsUi',
|
||||
subProperty: 'sortField',
|
||||
expectedStructure: 'sortFieldsUi.sortField array',
|
||||
invalidPatterns: ['sortFieldsUi.sortField.values']
|
||||
},
|
||||
{
|
||||
nodeType: 'aggregate',
|
||||
property: 'fieldsToAggregate',
|
||||
subProperty: 'fieldToAggregate',
|
||||
expectedStructure: 'fieldsToAggregate.fieldToAggregate array',
|
||||
invalidPatterns: ['fieldsToAggregate.fieldToAggregate.values']
|
||||
},
|
||||
{
|
||||
nodeType: 'set',
|
||||
property: 'fields',
|
||||
subProperty: 'values',
|
||||
expectedStructure: 'fields.values array',
|
||||
invalidPatterns: ['fields.values.values']
|
||||
},
|
||||
{
|
||||
nodeType: 'html',
|
||||
property: 'extractionValues',
|
||||
subProperty: 'values',
|
||||
expectedStructure: 'extractionValues.values array',
|
||||
invalidPatterns: ['extractionValues.values.values']
|
||||
},
|
||||
{
|
||||
nodeType: 'httprequest',
|
||||
property: 'body',
|
||||
subProperty: 'parameters',
|
||||
expectedStructure: 'body.parameters array',
|
||||
invalidPatterns: ['body.parameters.values']
|
||||
},
|
||||
{
|
||||
nodeType: 'airtable',
|
||||
property: 'sort',
|
||||
subProperty: 'sortField',
|
||||
expectedStructure: 'sort.sortField array',
|
||||
invalidPatterns: ['sort.sortField.values']
|
||||
}
|
||||
];
|
||||
//# sourceMappingURL=fixed-collection-validator.js.map
|
||||
1
dist/utils/fixed-collection-validator.js.map
vendored
Normal file
1
dist/utils/fixed-collection-validator.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
33
dist/utils/logger.d.ts
vendored
Normal file
33
dist/utils/logger.d.ts
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
export declare enum LogLevel {
|
||||
ERROR = 0,
|
||||
WARN = 1,
|
||||
INFO = 2,
|
||||
DEBUG = 3
|
||||
}
|
||||
export interface LoggerConfig {
|
||||
level: LogLevel;
|
||||
prefix?: string;
|
||||
timestamp?: boolean;
|
||||
}
|
||||
export declare class Logger {
|
||||
private config;
|
||||
private static instance;
|
||||
private useFileLogging;
|
||||
private fileStream;
|
||||
private readonly isStdio;
|
||||
private readonly isDisabled;
|
||||
private readonly isHttp;
|
||||
private readonly isTest;
|
||||
constructor(config?: Partial<LoggerConfig>);
|
||||
static getInstance(config?: Partial<LoggerConfig>): Logger;
|
||||
private formatMessage;
|
||||
private log;
|
||||
error(message: string, ...args: any[]): void;
|
||||
warn(message: string, ...args: any[]): void;
|
||||
info(message: string, ...args: any[]): void;
|
||||
debug(message: string, ...args: any[]): void;
|
||||
setLevel(level: LogLevel): void;
|
||||
static parseLogLevel(level: string): LogLevel;
|
||||
}
|
||||
export declare const logger: Logger;
|
||||
//# sourceMappingURL=logger.d.ts.map
|
||||
1
dist/utils/logger.d.ts.map
vendored
Normal file
1
dist/utils/logger.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA,oBAAY,QAAQ;IAClB,KAAK,IAAI;IACT,IAAI,IAAI;IACR,IAAI,IAAI;IACR,KAAK,IAAI;CACV;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,QAAQ,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,qBAAa,MAAM;IACjB,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAS;IAChC,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,UAAU,CAAa;IAE/B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoC;IAC5D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAiD;IAC5E,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmC;IAC1D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA8E;gBAEzF,MAAM,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC;IAS1C,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,MAAM;IAO1D,OAAO,CAAC,aAAa;IAiBrB,OAAO,CAAC,GAAG;IAqCX,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAI5C,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAI3C,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAI3C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAI5C,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAI/B,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ;CAa9C;AAGD,eAAO,MAAM,MAAM,QAEjB,CAAC"}
|
||||
101
dist/utils/logger.js
vendored
Normal file
101
dist/utils/logger.js
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.logger = exports.Logger = exports.LogLevel = void 0;
|
||||
var LogLevel;
|
||||
(function (LogLevel) {
|
||||
LogLevel[LogLevel["ERROR"] = 0] = "ERROR";
|
||||
LogLevel[LogLevel["WARN"] = 1] = "WARN";
|
||||
LogLevel[LogLevel["INFO"] = 2] = "INFO";
|
||||
LogLevel[LogLevel["DEBUG"] = 3] = "DEBUG";
|
||||
})(LogLevel || (exports.LogLevel = LogLevel = {}));
|
||||
class Logger {
|
||||
constructor(config) {
|
||||
this.useFileLogging = false;
|
||||
this.fileStream = null;
|
||||
this.isStdio = process.env.MCP_MODE === 'stdio';
|
||||
this.isDisabled = process.env.DISABLE_CONSOLE_OUTPUT === 'true';
|
||||
this.isHttp = process.env.MCP_MODE === 'http';
|
||||
this.isTest = process.env.NODE_ENV === 'test' || process.env.TEST_ENVIRONMENT === 'true';
|
||||
this.config = {
|
||||
level: LogLevel.INFO,
|
||||
prefix: 'n8n-mcp',
|
||||
timestamp: true,
|
||||
...config,
|
||||
};
|
||||
}
|
||||
static getInstance(config) {
|
||||
if (!Logger.instance) {
|
||||
Logger.instance = new Logger(config);
|
||||
}
|
||||
return Logger.instance;
|
||||
}
|
||||
formatMessage(level, message) {
|
||||
const parts = [];
|
||||
if (this.config.timestamp) {
|
||||
parts.push(`[${new Date().toISOString()}]`);
|
||||
}
|
||||
if (this.config.prefix) {
|
||||
parts.push(`[${this.config.prefix}]`);
|
||||
}
|
||||
parts.push(`[${level}]`);
|
||||
parts.push(message);
|
||||
return parts.join(' ');
|
||||
}
|
||||
log(level, levelName, message, ...args) {
|
||||
const allowErrorLogs = level === LogLevel.ERROR && (this.isHttp || process.env.DEBUG === 'true');
|
||||
if (this.isStdio || this.isDisabled || (this.isTest && process.env.DEBUG !== 'true')) {
|
||||
if (!allowErrorLogs) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (level <= this.config.level || allowErrorLogs) {
|
||||
const formattedMessage = this.formatMessage(levelName, message);
|
||||
if (this.isHttp && process.env.MCP_REQUEST_ACTIVE === 'true' && !allowErrorLogs) {
|
||||
return;
|
||||
}
|
||||
switch (level) {
|
||||
case LogLevel.ERROR:
|
||||
console.error(formattedMessage, ...args);
|
||||
break;
|
||||
case LogLevel.WARN:
|
||||
console.warn(formattedMessage, ...args);
|
||||
break;
|
||||
default:
|
||||
console.log(formattedMessage, ...args);
|
||||
}
|
||||
}
|
||||
}
|
||||
error(message, ...args) {
|
||||
this.log(LogLevel.ERROR, 'ERROR', message, ...args);
|
||||
}
|
||||
warn(message, ...args) {
|
||||
this.log(LogLevel.WARN, 'WARN', message, ...args);
|
||||
}
|
||||
info(message, ...args) {
|
||||
this.log(LogLevel.INFO, 'INFO', message, ...args);
|
||||
}
|
||||
debug(message, ...args) {
|
||||
this.log(LogLevel.DEBUG, 'DEBUG', message, ...args);
|
||||
}
|
||||
setLevel(level) {
|
||||
this.config.level = level;
|
||||
}
|
||||
static parseLogLevel(level) {
|
||||
switch (level.toLowerCase()) {
|
||||
case 'error':
|
||||
return LogLevel.ERROR;
|
||||
case 'warn':
|
||||
return LogLevel.WARN;
|
||||
case 'debug':
|
||||
return LogLevel.DEBUG;
|
||||
case 'info':
|
||||
default:
|
||||
return LogLevel.INFO;
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.Logger = Logger;
|
||||
exports.logger = Logger.getInstance({
|
||||
level: Logger.parseLogLevel(process.env.LOG_LEVEL || 'info'),
|
||||
});
|
||||
//# sourceMappingURL=logger.js.map
|
||||
1
dist/utils/logger.js.map
vendored
Normal file
1
dist/utils/logger.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"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"}
|
||||
21
dist/utils/mcp-client.d.ts
vendored
Normal file
21
dist/utils/mcp-client.d.ts
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
export interface MCPClientConfig {
|
||||
serverUrl: string;
|
||||
authToken?: string;
|
||||
connectionType: 'http' | 'websocket' | 'stdio';
|
||||
}
|
||||
export declare class MCPClient {
|
||||
private client;
|
||||
private config;
|
||||
private connected;
|
||||
constructor(config: MCPClientConfig);
|
||||
connect(): Promise<void>;
|
||||
disconnect(): Promise<void>;
|
||||
listTools(): Promise<any>;
|
||||
callTool(name: string, args: any): Promise<any>;
|
||||
listResources(): Promise<any>;
|
||||
readResource(uri: string): Promise<any>;
|
||||
listPrompts(): Promise<any>;
|
||||
getPrompt(name: string, args?: any): Promise<any>;
|
||||
private ensureConnected;
|
||||
}
|
||||
//# sourceMappingURL=mcp-client.d.ts.map
|
||||
1
dist/utils/mcp-client.d.ts.map
vendored
Normal file
1
dist/utils/mcp-client.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"mcp-client.d.ts","sourceRoot":"","sources":["../../src/utils/mcp-client.ts"],"names":[],"mappings":"AAkBA,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,GAAG,WAAW,GAAG,OAAO,CAAC;CAChD;AAED,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,SAAS,CAAkB;gBAEvB,MAAM,EAAE,eAAe;IAa7B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IA8BxB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAO3B,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC;IAQzB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;IAc/C,aAAa,IAAI,OAAO,CAAC,GAAG,CAAC;IAQ7B,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAavC,WAAW,IAAI,OAAO,CAAC,GAAG,CAAC;IAQ3B,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;YAczC,eAAe;CAK9B"}
|
||||
96
dist/utils/mcp-client.js
vendored
Normal file
96
dist/utils/mcp-client.js
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.MCPClient = void 0;
|
||||
const index_js_1 = require("@modelcontextprotocol/sdk/client/index.js");
|
||||
const stdio_js_1 = require("@modelcontextprotocol/sdk/client/stdio.js");
|
||||
const websocket_js_1 = require("@modelcontextprotocol/sdk/client/websocket.js");
|
||||
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
|
||||
class MCPClient {
|
||||
constructor(config) {
|
||||
this.connected = false;
|
||||
this.config = config;
|
||||
this.client = new index_js_1.Client({
|
||||
name: 'n8n-mcp-client',
|
||||
version: '1.0.0',
|
||||
}, {
|
||||
capabilities: {},
|
||||
});
|
||||
}
|
||||
async connect() {
|
||||
if (this.connected) {
|
||||
return;
|
||||
}
|
||||
let transport;
|
||||
switch (this.config.connectionType) {
|
||||
case 'websocket':
|
||||
const wsUrl = this.config.serverUrl.replace(/^http/, 'ws');
|
||||
transport = new websocket_js_1.WebSocketClientTransport(new URL(wsUrl));
|
||||
break;
|
||||
case 'stdio':
|
||||
const [command, ...args] = this.config.serverUrl.split(' ');
|
||||
transport = new stdio_js_1.StdioClientTransport({
|
||||
command,
|
||||
args,
|
||||
});
|
||||
break;
|
||||
default:
|
||||
throw new Error(`HTTP transport is not yet supported for MCP clients`);
|
||||
}
|
||||
await this.client.connect(transport);
|
||||
this.connected = true;
|
||||
}
|
||||
async disconnect() {
|
||||
if (this.connected) {
|
||||
await this.client.close();
|
||||
this.connected = false;
|
||||
}
|
||||
}
|
||||
async listTools() {
|
||||
await this.ensureConnected();
|
||||
return await this.client.request({ method: 'tools/list' }, types_js_1.ListToolsResultSchema);
|
||||
}
|
||||
async callTool(name, args) {
|
||||
await this.ensureConnected();
|
||||
return await this.client.request({
|
||||
method: 'tools/call',
|
||||
params: {
|
||||
name,
|
||||
arguments: args,
|
||||
},
|
||||
}, types_js_1.CallToolResultSchema);
|
||||
}
|
||||
async listResources() {
|
||||
await this.ensureConnected();
|
||||
return await this.client.request({ method: 'resources/list' }, types_js_1.ListResourcesResultSchema);
|
||||
}
|
||||
async readResource(uri) {
|
||||
await this.ensureConnected();
|
||||
return await this.client.request({
|
||||
method: 'resources/read',
|
||||
params: {
|
||||
uri,
|
||||
},
|
||||
}, types_js_1.ReadResourceResultSchema);
|
||||
}
|
||||
async listPrompts() {
|
||||
await this.ensureConnected();
|
||||
return await this.client.request({ method: 'prompts/list' }, types_js_1.ListPromptsResultSchema);
|
||||
}
|
||||
async getPrompt(name, args) {
|
||||
await this.ensureConnected();
|
||||
return await this.client.request({
|
||||
method: 'prompts/get',
|
||||
params: {
|
||||
name,
|
||||
arguments: args,
|
||||
},
|
||||
}, types_js_1.GetPromptResultSchema);
|
||||
}
|
||||
async ensureConnected() {
|
||||
if (!this.connected) {
|
||||
await this.connect();
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.MCPClient = MCPClient;
|
||||
//# sourceMappingURL=mcp-client.js.map
|
||||
1
dist/utils/mcp-client.js.map
vendored
Normal file
1
dist/utils/mcp-client.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"mcp-client.js","sourceRoot":"","sources":["../../src/utils/mcp-client.ts"],"names":[],"mappings":"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"}
|
||||
27
dist/utils/n8n-errors.d.ts
vendored
Normal file
27
dist/utils/n8n-errors.d.ts
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
export declare class N8nApiError extends Error {
|
||||
statusCode?: number | undefined;
|
||||
code?: string | undefined;
|
||||
details?: unknown | undefined;
|
||||
constructor(message: string, statusCode?: number | undefined, code?: string | undefined, details?: unknown | undefined);
|
||||
}
|
||||
export declare class N8nAuthenticationError extends N8nApiError {
|
||||
constructor(message?: string);
|
||||
}
|
||||
export declare class N8nNotFoundError extends N8nApiError {
|
||||
constructor(resource: string, id?: string);
|
||||
}
|
||||
export declare class N8nValidationError extends N8nApiError {
|
||||
constructor(message: string, details?: unknown);
|
||||
}
|
||||
export declare class N8nRateLimitError extends N8nApiError {
|
||||
constructor(retryAfter?: number);
|
||||
}
|
||||
export declare class N8nServerError extends N8nApiError {
|
||||
constructor(message?: string, statusCode?: number);
|
||||
}
|
||||
export declare function handleN8nApiError(error: unknown): N8nApiError;
|
||||
export declare function formatExecutionError(executionId: string, workflowId?: string): string;
|
||||
export declare function formatNoExecutionError(): string;
|
||||
export declare function getUserFriendlyErrorMessage(error: N8nApiError): string;
|
||||
export declare function logN8nError(error: N8nApiError, context?: string): void;
|
||||
//# sourceMappingURL=n8n-errors.d.ts.map
|
||||
1
dist/utils/n8n-errors.d.ts.map
vendored
Normal file
1
dist/utils/n8n-errors.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"n8n-errors.d.ts","sourceRoot":"","sources":["../../src/utils/n8n-errors.ts"],"names":[],"mappings":"AAIA,qBAAa,WAAY,SAAQ,KAAK;IAG3B,UAAU,CAAC,EAAE,MAAM;IACnB,IAAI,CAAC,EAAE,MAAM;IACb,OAAO,CAAC,EAAE,OAAO;gBAHxB,OAAO,EAAE,MAAM,EACR,UAAU,CAAC,EAAE,MAAM,YAAA,EACnB,IAAI,CAAC,EAAE,MAAM,YAAA,EACb,OAAO,CAAC,EAAE,OAAO,YAAA;CAK3B;AAED,qBAAa,sBAAuB,SAAQ,WAAW;gBACzC,OAAO,SAA0B;CAI9C;AAED,qBAAa,gBAAiB,SAAQ,WAAW;gBACnC,QAAQ,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM;CAK1C;AAED,qBAAa,kBAAmB,SAAQ,WAAW;gBACrC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO;CAI/C;AAED,qBAAa,iBAAkB,SAAQ,WAAW;gBACpC,UAAU,CAAC,EAAE,MAAM;CAOhC;AAED,qBAAa,cAAe,SAAQ,WAAW;gBACjC,OAAO,SAA0B,EAAE,UAAU,SAAM;CAIhE;AAGD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,CAuC7D;AAQD,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAGrF;AAMD,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C;AAGD,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAmBtE;AAGD,wBAAgB,WAAW,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAiBtE"}
|
||||
138
dist/utils/n8n-errors.js
vendored
Normal file
138
dist/utils/n8n-errors.js
vendored
Normal file
@@ -0,0 +1,138 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.N8nServerError = exports.N8nRateLimitError = exports.N8nValidationError = exports.N8nNotFoundError = exports.N8nAuthenticationError = exports.N8nApiError = void 0;
|
||||
exports.handleN8nApiError = handleN8nApiError;
|
||||
exports.formatExecutionError = formatExecutionError;
|
||||
exports.formatNoExecutionError = formatNoExecutionError;
|
||||
exports.getUserFriendlyErrorMessage = getUserFriendlyErrorMessage;
|
||||
exports.logN8nError = logN8nError;
|
||||
const logger_1 = require("./logger");
|
||||
class N8nApiError extends Error {
|
||||
constructor(message, statusCode, code, details) {
|
||||
super(message);
|
||||
this.statusCode = statusCode;
|
||||
this.code = code;
|
||||
this.details = details;
|
||||
this.name = 'N8nApiError';
|
||||
}
|
||||
}
|
||||
exports.N8nApiError = N8nApiError;
|
||||
class N8nAuthenticationError extends N8nApiError {
|
||||
constructor(message = 'Authentication failed') {
|
||||
super(message, 401, 'AUTHENTICATION_ERROR');
|
||||
this.name = 'N8nAuthenticationError';
|
||||
}
|
||||
}
|
||||
exports.N8nAuthenticationError = N8nAuthenticationError;
|
||||
class N8nNotFoundError extends N8nApiError {
|
||||
constructor(resource, id) {
|
||||
const message = id ? `${resource} with ID ${id} not found` : `${resource} not found`;
|
||||
super(message, 404, 'NOT_FOUND');
|
||||
this.name = 'N8nNotFoundError';
|
||||
}
|
||||
}
|
||||
exports.N8nNotFoundError = N8nNotFoundError;
|
||||
class N8nValidationError extends N8nApiError {
|
||||
constructor(message, details) {
|
||||
super(message, 400, 'VALIDATION_ERROR', details);
|
||||
this.name = 'N8nValidationError';
|
||||
}
|
||||
}
|
||||
exports.N8nValidationError = N8nValidationError;
|
||||
class N8nRateLimitError extends N8nApiError {
|
||||
constructor(retryAfter) {
|
||||
const message = retryAfter
|
||||
? `Rate limit exceeded. Retry after ${retryAfter} seconds`
|
||||
: 'Rate limit exceeded';
|
||||
super(message, 429, 'RATE_LIMIT_ERROR', { retryAfter });
|
||||
this.name = 'N8nRateLimitError';
|
||||
}
|
||||
}
|
||||
exports.N8nRateLimitError = N8nRateLimitError;
|
||||
class N8nServerError extends N8nApiError {
|
||||
constructor(message = 'Internal server error', statusCode = 500) {
|
||||
super(message, statusCode, 'SERVER_ERROR');
|
||||
this.name = 'N8nServerError';
|
||||
}
|
||||
}
|
||||
exports.N8nServerError = N8nServerError;
|
||||
function handleN8nApiError(error) {
|
||||
if (error instanceof N8nApiError) {
|
||||
return error;
|
||||
}
|
||||
if (error instanceof Error) {
|
||||
const axiosError = error;
|
||||
if (axiosError.response) {
|
||||
const { status, data } = axiosError.response;
|
||||
const message = data?.message || axiosError.message;
|
||||
switch (status) {
|
||||
case 401:
|
||||
return new N8nAuthenticationError(message);
|
||||
case 404:
|
||||
return new N8nNotFoundError('Resource', message);
|
||||
case 400:
|
||||
return new N8nValidationError(message, data);
|
||||
case 429:
|
||||
const retryAfter = axiosError.response.headers['retry-after'];
|
||||
return new N8nRateLimitError(retryAfter ? parseInt(retryAfter) : undefined);
|
||||
default:
|
||||
if (status >= 500) {
|
||||
return new N8nServerError(message, status);
|
||||
}
|
||||
return new N8nApiError(message, status, 'API_ERROR', data);
|
||||
}
|
||||
}
|
||||
else if (axiosError.request) {
|
||||
return new N8nApiError('No response from n8n server', undefined, 'NO_RESPONSE');
|
||||
}
|
||||
else {
|
||||
return new N8nApiError(axiosError.message, undefined, 'REQUEST_ERROR');
|
||||
}
|
||||
}
|
||||
return new N8nApiError('Unknown error occurred', undefined, 'UNKNOWN_ERROR', error);
|
||||
}
|
||||
function formatExecutionError(executionId, workflowId) {
|
||||
const workflowPrefix = workflowId ? `Workflow ${workflowId} execution ` : 'Execution ';
|
||||
return `${workflowPrefix}${executionId} failed. Use n8n_get_execution({id: '${executionId}', mode: 'preview'}) to investigate the error.`;
|
||||
}
|
||||
function formatNoExecutionError() {
|
||||
return "Workflow failed to execute. Use n8n_list_executions to find recent executions, then n8n_get_execution with mode='preview' to investigate.";
|
||||
}
|
||||
function getUserFriendlyErrorMessage(error) {
|
||||
switch (error.code) {
|
||||
case 'AUTHENTICATION_ERROR':
|
||||
return 'Failed to authenticate with n8n. Please check your API key.';
|
||||
case 'NOT_FOUND':
|
||||
return error.message;
|
||||
case 'VALIDATION_ERROR':
|
||||
return `Invalid request: ${error.message}`;
|
||||
case 'RATE_LIMIT_ERROR':
|
||||
return 'Too many requests. Please wait a moment and try again.';
|
||||
case 'NO_RESPONSE':
|
||||
return 'Unable to connect to n8n. Please check the server URL and ensure n8n is running.';
|
||||
case 'SERVER_ERROR':
|
||||
return error.message || 'n8n server error occurred';
|
||||
default:
|
||||
return error.message || 'An unexpected error occurred';
|
||||
}
|
||||
}
|
||||
function logN8nError(error, context) {
|
||||
const errorInfo = {
|
||||
name: error.name,
|
||||
message: error.message,
|
||||
code: error.code,
|
||||
statusCode: error.statusCode,
|
||||
details: error.details,
|
||||
context,
|
||||
};
|
||||
if (error.statusCode && error.statusCode >= 500) {
|
||||
logger_1.logger.error('n8n API server error', errorInfo);
|
||||
}
|
||||
else if (error.statusCode && error.statusCode >= 400) {
|
||||
logger_1.logger.warn('n8n API client error', errorInfo);
|
||||
}
|
||||
else {
|
||||
logger_1.logger.error('n8n API error', errorInfo);
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=n8n-errors.js.map
|
||||
1
dist/utils/n8n-errors.js.map
vendored
Normal file
1
dist/utils/n8n-errors.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"n8n-errors.js","sourceRoot":"","sources":["../../src/utils/n8n-errors.ts"],"names":[],"mappings":"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"}
|
||||
5
dist/utils/node-classification.d.ts
vendored
Normal file
5
dist/utils/node-classification.d.ts
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
export declare function isStickyNote(nodeType: string): boolean;
|
||||
export declare function isTriggerNode(nodeType: string): boolean;
|
||||
export declare function isNonExecutableNode(nodeType: string): boolean;
|
||||
export declare function requiresIncomingConnection(nodeType: string): boolean;
|
||||
//# sourceMappingURL=node-classification.d.ts.map
|
||||
1
dist/utils/node-classification.d.ts.map
vendored
Normal file
1
dist/utils/node-classification.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"node-classification.d.ts","sourceRoot":"","sources":["../../src/utils/node-classification.ts"],"names":[],"mappings":"AA8BA,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAOtD;AAwBD,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEvD;AAmBD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAI7D;AAqBD,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAapE"}
|
||||
31
dist/utils/node-classification.js
vendored
Normal file
31
dist/utils/node-classification.js
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.isStickyNote = isStickyNote;
|
||||
exports.isTriggerNode = isTriggerNode;
|
||||
exports.isNonExecutableNode = isNonExecutableNode;
|
||||
exports.requiresIncomingConnection = requiresIncomingConnection;
|
||||
const node_type_utils_1 = require("./node-type-utils");
|
||||
function isStickyNote(nodeType) {
|
||||
const stickyNoteTypes = [
|
||||
'n8n-nodes-base.stickyNote',
|
||||
'nodes-base.stickyNote',
|
||||
'@n8n/n8n-nodes-base.stickyNote'
|
||||
];
|
||||
return stickyNoteTypes.includes(nodeType);
|
||||
}
|
||||
function isTriggerNode(nodeType) {
|
||||
return (0, node_type_utils_1.isTriggerNode)(nodeType);
|
||||
}
|
||||
function isNonExecutableNode(nodeType) {
|
||||
return isStickyNote(nodeType);
|
||||
}
|
||||
function requiresIncomingConnection(nodeType) {
|
||||
if (isNonExecutableNode(nodeType)) {
|
||||
return false;
|
||||
}
|
||||
if (isTriggerNode(nodeType)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//# sourceMappingURL=node-classification.js.map
|
||||
1
dist/utils/node-classification.js.map
vendored
Normal file
1
dist/utils/node-classification.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"node-classification.js","sourceRoot":"","sources":["../../src/utils/node-classification.ts"],"names":[],"mappings":";;AA8BA,oCAOC;AAwBD,sCAEC;AAmBD,kDAIC;AAqBD,gEAaC;AA7GD,uDAAuE;AAmBvE,SAAgB,YAAY,CAAC,QAAgB;IAC3C,MAAM,eAAe,GAAG;QACtB,2BAA2B;QAC3B,uBAAuB;QACvB,gCAAgC;KACjC,CAAC;IACF,OAAO,eAAe,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAC5C,CAAC;AAwBD,SAAgB,aAAa,CAAC,QAAgB;IAC5C,OAAO,IAAA,+BAAiB,EAAC,QAAQ,CAAC,CAAC;AACrC,CAAC;AAmBD,SAAgB,mBAAmB,CAAC,QAAgB;IAClD,OAAO,YAAY,CAAC,QAAQ,CAAC,CAAC;AAGhC,CAAC;AAqBD,SAAgB,0BAA0B,CAAC,QAAgB;IAEzD,IAAI,mBAAmB,CAAC,QAAQ,CAAC,EAAE,CAAC;QAClC,OAAO,KAAK,CAAC;IACf,CAAC;IAGD,IAAI,aAAa,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,OAAO,KAAK,CAAC;IACf,CAAC;IAGD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
||||
21
dist/utils/node-source-extractor.d.ts
vendored
Normal file
21
dist/utils/node-source-extractor.d.ts
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
export interface NodeSourceInfo {
|
||||
nodeType: string;
|
||||
sourceCode: string;
|
||||
credentialCode?: string;
|
||||
packageInfo?: any;
|
||||
location: string;
|
||||
}
|
||||
export declare class NodeSourceExtractor {
|
||||
private n8nBasePaths;
|
||||
extractNodeSource(nodeType: string): Promise<NodeSourceInfo>;
|
||||
private parseNodeType;
|
||||
private searchNodeInPath;
|
||||
private searchInPnpm;
|
||||
private searchWithGlobPattern;
|
||||
private tryLoadNodeFile;
|
||||
listAvailableNodes(category?: string, search?: string): Promise<any[]>;
|
||||
private scanDirectoryForNodes;
|
||||
private scanPnpmDirectory;
|
||||
extractAIAgentNode(): Promise<NodeSourceInfo>;
|
||||
}
|
||||
//# sourceMappingURL=node-source-extractor.d.ts.map
|
||||
1
dist/utils/node-source-extractor.d.ts.map
vendored
Normal file
1
dist/utils/node-source-extractor.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"node-source-extractor.d.ts","sourceRoot":"","sources":["../../src/utils/node-source-extractor.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,GAAG,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,YAAY,CAYF;IAKZ,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAyBlE,OAAO,CAAC,aAAa;YAkBP,gBAAgB;YAoEhB,YAAY;YA8CZ,qBAAqB;YAoErB,eAAe;IA4FvB,kBAAkB,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;YAiC9D,qBAAqB;YAsErB,iBAAiB;IA2BzB,kBAAkB,IAAI,OAAO,CAAC,cAAc,CAAC;CAIpD"}
|
||||
377
dist/utils/node-source-extractor.js
vendored
Normal file
377
dist/utils/node-source-extractor.js
vendored
Normal file
@@ -0,0 +1,377 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || (function () {
|
||||
var ownKeys = function(o) {
|
||||
ownKeys = Object.getOwnPropertyNames || function (o) {
|
||||
var ar = [];
|
||||
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
||||
return ar;
|
||||
};
|
||||
return ownKeys(o);
|
||||
};
|
||||
return function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
})();
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.NodeSourceExtractor = void 0;
|
||||
const fs = __importStar(require("fs/promises"));
|
||||
const path = __importStar(require("path"));
|
||||
const logger_1 = require("./logger");
|
||||
class NodeSourceExtractor {
|
||||
constructor() {
|
||||
this.n8nBasePaths = [
|
||||
'/usr/local/lib/node_modules/n8n/node_modules',
|
||||
'/app/node_modules',
|
||||
'/home/node/.n8n/custom/nodes',
|
||||
'./node_modules',
|
||||
'/var/lib/docker/volumes/n8n-mcp_n8n_modules/_data',
|
||||
'/n8n-modules',
|
||||
process.env.N8N_CUSTOM_EXTENSIONS || '',
|
||||
path.join(process.cwd(), 'node_modules'),
|
||||
].filter(Boolean);
|
||||
}
|
||||
async extractNodeSource(nodeType) {
|
||||
logger_1.logger.info(`Extracting source code for node: ${nodeType}`);
|
||||
const { packageName, nodeName } = this.parseNodeType(nodeType);
|
||||
for (const basePath of this.n8nBasePaths) {
|
||||
try {
|
||||
const nodeInfo = await this.searchNodeInPath(basePath, packageName, nodeName);
|
||||
if (nodeInfo) {
|
||||
logger_1.logger.info(`Found node source at: ${nodeInfo.location}`);
|
||||
return nodeInfo;
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
logger_1.logger.debug(`Failed to search in ${basePath}: ${error}`);
|
||||
}
|
||||
}
|
||||
throw new Error(`Node source code not found for: ${nodeType}`);
|
||||
}
|
||||
parseNodeType(nodeType) {
|
||||
if (nodeType.includes('.')) {
|
||||
const [pkg, node] = nodeType.split('.');
|
||||
return { packageName: pkg, nodeName: node };
|
||||
}
|
||||
return { packageName: 'n8n-nodes-base', nodeName: nodeType };
|
||||
}
|
||||
async searchNodeInPath(basePath, packageName, nodeName) {
|
||||
try {
|
||||
const nodeNameVariants = [
|
||||
nodeName,
|
||||
nodeName.charAt(0).toUpperCase() + nodeName.slice(1),
|
||||
nodeName.toLowerCase(),
|
||||
nodeName.toUpperCase(),
|
||||
];
|
||||
for (const nameVariant of nodeNameVariants) {
|
||||
const standardPatterns = [
|
||||
`${packageName}/dist/nodes/${nameVariant}/${nameVariant}.node.js`,
|
||||
`${packageName}/dist/nodes/${nameVariant}.node.js`,
|
||||
`${packageName}/nodes/${nameVariant}/${nameVariant}.node.js`,
|
||||
`${packageName}/nodes/${nameVariant}.node.js`,
|
||||
`${nameVariant}/${nameVariant}.node.js`,
|
||||
`${nameVariant}.node.js`,
|
||||
];
|
||||
const nestedPatterns = [
|
||||
`${packageName}/dist/nodes/*/${nameVariant}/${nameVariant}.node.js`,
|
||||
`${packageName}/dist/nodes/**/${nameVariant}/${nameVariant}.node.js`,
|
||||
`${packageName}/nodes/*/${nameVariant}/${nameVariant}.node.js`,
|
||||
`${packageName}/nodes/**/${nameVariant}/${nameVariant}.node.js`,
|
||||
];
|
||||
for (const pattern of standardPatterns) {
|
||||
const fullPath = path.join(basePath, pattern);
|
||||
const result = await this.tryLoadNodeFile(fullPath, packageName, nodeName, basePath);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
for (const pattern of nestedPatterns) {
|
||||
const result = await this.searchWithGlobPattern(basePath, pattern, packageName, nodeName);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
if (basePath.includes('node_modules')) {
|
||||
const pnpmPath = path.join(basePath, '.pnpm');
|
||||
try {
|
||||
await fs.access(pnpmPath);
|
||||
const result = await this.searchInPnpm(pnpmPath, packageName, nodeName);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
catch {
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
logger_1.logger.debug(`Error searching in path ${basePath}: ${error}`);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
async searchInPnpm(pnpmPath, packageName, nodeName) {
|
||||
try {
|
||||
const entries = await fs.readdir(pnpmPath);
|
||||
const packageEntries = entries.filter(entry => entry.includes(packageName.replace('/', '+')) ||
|
||||
entry.includes(packageName));
|
||||
for (const entry of packageEntries) {
|
||||
const entryPath = path.join(pnpmPath, entry, 'node_modules', packageName);
|
||||
const patterns = [
|
||||
`dist/nodes/${nodeName}/${nodeName}.node.js`,
|
||||
`dist/nodes/${nodeName}.node.js`,
|
||||
`dist/nodes/*/${nodeName}/${nodeName}.node.js`,
|
||||
`dist/nodes/**/${nodeName}/${nodeName}.node.js`,
|
||||
];
|
||||
for (const pattern of patterns) {
|
||||
if (pattern.includes('*')) {
|
||||
const result = await this.searchWithGlobPattern(entryPath, pattern, packageName, nodeName);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
const fullPath = path.join(entryPath, pattern);
|
||||
const result = await this.tryLoadNodeFile(fullPath, packageName, nodeName, entryPath);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
logger_1.logger.debug(`Error searching in pnpm directory: ${error}`);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
async searchWithGlobPattern(basePath, pattern, packageName, nodeName) {
|
||||
const parts = pattern.split('/');
|
||||
const targetFile = `${nodeName}.node.js`;
|
||||
async function searchDir(currentPath, remainingParts) {
|
||||
if (remainingParts.length === 0)
|
||||
return null;
|
||||
const part = remainingParts[0];
|
||||
const isLastPart = remainingParts.length === 1;
|
||||
try {
|
||||
if (isLastPart && part === targetFile) {
|
||||
const fullPath = path.join(currentPath, part);
|
||||
await fs.access(fullPath);
|
||||
return fullPath;
|
||||
}
|
||||
const entries = await fs.readdir(currentPath, { withFileTypes: true });
|
||||
for (const entry of entries) {
|
||||
if (!entry.isDirectory() && !isLastPart)
|
||||
continue;
|
||||
if (part === '*' || part === '**') {
|
||||
if (entry.isDirectory()) {
|
||||
const result = await searchDir(path.join(currentPath, entry.name), part === '**' ? remainingParts : remainingParts.slice(1));
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else if (entry.name === part || (isLastPart && entry.name === targetFile)) {
|
||||
if (isLastPart && entry.isFile()) {
|
||||
return path.join(currentPath, entry.name);
|
||||
}
|
||||
else if (!isLastPart && entry.isDirectory()) {
|
||||
const result = await searchDir(path.join(currentPath, entry.name), remainingParts.slice(1));
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
const foundPath = await searchDir(basePath, parts);
|
||||
if (foundPath) {
|
||||
return this.tryLoadNodeFile(foundPath, packageName, nodeName, basePath);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
async tryLoadNodeFile(fullPath, packageName, nodeName, packageBasePath) {
|
||||
try {
|
||||
const sourceCode = await fs.readFile(fullPath, 'utf-8');
|
||||
let credentialCode;
|
||||
const credentialPath = fullPath.replace('.node.js', '.credentials.js');
|
||||
try {
|
||||
credentialCode = await fs.readFile(credentialPath, 'utf-8');
|
||||
}
|
||||
catch {
|
||||
const possibleCredentialPaths = [
|
||||
path.join(packageBasePath, packageName, 'dist/credentials', `${nodeName}Api.credentials.js`),
|
||||
path.join(packageBasePath, packageName, 'dist/credentials', `${nodeName}OAuth2Api.credentials.js`),
|
||||
path.join(packageBasePath, packageName, 'credentials', `${nodeName}Api.credentials.js`),
|
||||
path.join(packageBasePath, packageName, 'credentials', `${nodeName}OAuth2Api.credentials.js`),
|
||||
path.join(packageBasePath, 'dist/credentials', `${nodeName}Api.credentials.js`),
|
||||
path.join(packageBasePath, 'dist/credentials', `${nodeName}OAuth2Api.credentials.js`),
|
||||
path.join(packageBasePath, 'credentials', `${nodeName}Api.credentials.js`),
|
||||
path.join(packageBasePath, 'credentials', `${nodeName}OAuth2Api.credentials.js`),
|
||||
path.join(path.dirname(path.dirname(fullPath)), 'credentials', `${nodeName}Api.credentials.js`),
|
||||
path.join(path.dirname(path.dirname(fullPath)), 'credentials', `${nodeName}OAuth2Api.credentials.js`),
|
||||
path.join(path.dirname(path.dirname(path.dirname(fullPath))), 'credentials', `${nodeName}Api.credentials.js`),
|
||||
path.join(path.dirname(path.dirname(path.dirname(fullPath))), 'credentials', `${nodeName}OAuth2Api.credentials.js`),
|
||||
];
|
||||
const allCredentials = [];
|
||||
for (const credPath of possibleCredentialPaths) {
|
||||
try {
|
||||
const content = await fs.readFile(credPath, 'utf-8');
|
||||
allCredentials.push(content);
|
||||
logger_1.logger.debug(`Found credential file at: ${credPath}`);
|
||||
}
|
||||
catch {
|
||||
}
|
||||
}
|
||||
if (allCredentials.length > 0) {
|
||||
credentialCode = allCredentials.join('\n\n// --- Next Credential File ---\n\n');
|
||||
}
|
||||
}
|
||||
let packageInfo;
|
||||
const possiblePackageJsonPaths = [
|
||||
path.join(packageBasePath, 'package.json'),
|
||||
path.join(packageBasePath, packageName, 'package.json'),
|
||||
path.join(path.dirname(path.dirname(fullPath)), 'package.json'),
|
||||
path.join(path.dirname(path.dirname(path.dirname(fullPath))), 'package.json'),
|
||||
path.join(fullPath.split('/dist/')[0], 'package.json'),
|
||||
path.join(fullPath.split('/nodes/')[0], 'package.json'),
|
||||
];
|
||||
for (const packageJsonPath of possiblePackageJsonPaths) {
|
||||
try {
|
||||
const packageJson = await fs.readFile(packageJsonPath, 'utf-8');
|
||||
packageInfo = JSON.parse(packageJson);
|
||||
logger_1.logger.debug(`Found package.json at: ${packageJsonPath}`);
|
||||
break;
|
||||
}
|
||||
catch {
|
||||
}
|
||||
}
|
||||
return {
|
||||
nodeType: `${packageName}.${nodeName}`,
|
||||
sourceCode,
|
||||
credentialCode,
|
||||
packageInfo,
|
||||
location: fullPath,
|
||||
};
|
||||
}
|
||||
catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
async listAvailableNodes(category, search) {
|
||||
const nodes = [];
|
||||
const seenNodes = new Set();
|
||||
for (const basePath of this.n8nBasePaths) {
|
||||
try {
|
||||
const n8nNodesBasePath = path.join(basePath, 'n8n-nodes-base', 'dist', 'nodes');
|
||||
try {
|
||||
await fs.access(n8nNodesBasePath);
|
||||
await this.scanDirectoryForNodes(n8nNodesBasePath, nodes, category, search, seenNodes);
|
||||
}
|
||||
catch {
|
||||
const altPath = path.join(basePath, 'n8n-nodes-base', 'nodes');
|
||||
try {
|
||||
await fs.access(altPath);
|
||||
await this.scanDirectoryForNodes(altPath, nodes, category, search, seenNodes);
|
||||
}
|
||||
catch {
|
||||
await this.scanDirectoryForNodes(basePath, nodes, category, search, seenNodes);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
logger_1.logger.debug(`Failed to scan ${basePath}: ${error}`);
|
||||
}
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
async scanDirectoryForNodes(dirPath, nodes, category, search, seenNodes) {
|
||||
try {
|
||||
const entries = await fs.readdir(dirPath, { withFileTypes: true });
|
||||
for (const entry of entries) {
|
||||
if (entry.isFile() && entry.name.endsWith('.node.js')) {
|
||||
try {
|
||||
const fullPath = path.join(dirPath, entry.name);
|
||||
const content = await fs.readFile(fullPath, 'utf-8');
|
||||
const nameMatch = content.match(/displayName:\s*['"`]([^'"`]+)['"`]/);
|
||||
const descriptionMatch = content.match(/description:\s*['"`]([^'"`]+)['"`]/);
|
||||
if (nameMatch) {
|
||||
const nodeName = entry.name.replace('.node.js', '');
|
||||
if (seenNodes && seenNodes.has(nodeName)) {
|
||||
continue;
|
||||
}
|
||||
const nodeInfo = {
|
||||
name: nodeName,
|
||||
displayName: nameMatch[1],
|
||||
description: descriptionMatch ? descriptionMatch[1] : '',
|
||||
location: fullPath,
|
||||
};
|
||||
if (category && !nodeInfo.displayName.toLowerCase().includes(category.toLowerCase())) {
|
||||
continue;
|
||||
}
|
||||
if (search && !nodeInfo.displayName.toLowerCase().includes(search.toLowerCase()) &&
|
||||
!nodeInfo.description.toLowerCase().includes(search.toLowerCase())) {
|
||||
continue;
|
||||
}
|
||||
nodes.push(nodeInfo);
|
||||
if (seenNodes) {
|
||||
seenNodes.add(nodeName);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {
|
||||
}
|
||||
}
|
||||
else if (entry.isDirectory()) {
|
||||
if (entry.name === '.pnpm') {
|
||||
await this.scanPnpmDirectory(path.join(dirPath, entry.name), nodes, category, search, seenNodes);
|
||||
}
|
||||
else if (entry.name !== 'node_modules') {
|
||||
await this.scanDirectoryForNodes(path.join(dirPath, entry.name), nodes, category, search, seenNodes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
logger_1.logger.debug(`Error scanning directory ${dirPath}: ${error}`);
|
||||
}
|
||||
}
|
||||
async scanPnpmDirectory(pnpmPath, nodes, category, search, seenNodes) {
|
||||
try {
|
||||
const entries = await fs.readdir(pnpmPath);
|
||||
for (const entry of entries) {
|
||||
const entryPath = path.join(pnpmPath, entry, 'node_modules');
|
||||
try {
|
||||
await fs.access(entryPath);
|
||||
await this.scanDirectoryForNodes(entryPath, nodes, category, search, seenNodes);
|
||||
}
|
||||
catch {
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
logger_1.logger.debug(`Error scanning pnpm directory ${pnpmPath}: ${error}`);
|
||||
}
|
||||
}
|
||||
async extractAIAgentNode() {
|
||||
return this.extractNodeSource('@n8n/n8n-nodes-langchain.Agent');
|
||||
}
|
||||
}
|
||||
exports.NodeSourceExtractor = NodeSourceExtractor;
|
||||
//# sourceMappingURL=node-source-extractor.js.map
|
||||
1
dist/utils/node-source-extractor.js.map
vendored
Normal file
1
dist/utils/node-source-extractor.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
16
dist/utils/node-type-normalizer.d.ts
vendored
Normal file
16
dist/utils/node-type-normalizer.d.ts
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
export interface NodeTypeNormalizationResult {
|
||||
original: string;
|
||||
normalized: string;
|
||||
wasNormalized: boolean;
|
||||
package: 'base' | 'langchain' | 'community' | 'unknown';
|
||||
}
|
||||
export declare class NodeTypeNormalizer {
|
||||
static normalizeToFullForm(type: string): string;
|
||||
static normalizeWithDetails(type: string): NodeTypeNormalizationResult;
|
||||
private static detectPackage;
|
||||
static normalizeBatch(types: string[]): Map<string, string>;
|
||||
static normalizeWorkflowNodeTypes(workflow: any): any;
|
||||
static isFullForm(type: string): boolean;
|
||||
static isShortForm(type: string): boolean;
|
||||
}
|
||||
//# sourceMappingURL=node-type-normalizer.d.ts.map
|
||||
1
dist/utils/node-type-normalizer.d.ts.map
vendored
Normal file
1
dist/utils/node-type-normalizer.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"node-type-normalizer.d.ts","sourceRoot":"","sources":["../../src/utils/node-type-normalizer.ts"],"names":[],"mappings":"AA2CA,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,OAAO,CAAC;IACvB,OAAO,EAAE,MAAM,GAAG,WAAW,GAAG,WAAW,GAAG,SAAS,CAAC;CACzD;AAED,qBAAa,kBAAkB;IAyB7B,MAAM,CAAC,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAuChD,MAAM,CAAC,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,2BAA2B;IAkBtE,OAAO,CAAC,MAAM,CAAC,aAAa;IAuB5B,MAAM,CAAC,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;IA8B3D,MAAM,CAAC,0BAA0B,CAAC,QAAQ,EAAE,GAAG,GAAG,GAAG;IAoBrD,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAkBxC,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;CAU1C"}
|
||||
75
dist/utils/node-type-normalizer.js
vendored
Normal file
75
dist/utils/node-type-normalizer.js
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.NodeTypeNormalizer = void 0;
|
||||
class NodeTypeNormalizer {
|
||||
static normalizeToFullForm(type) {
|
||||
if (!type || typeof type !== 'string') {
|
||||
return type;
|
||||
}
|
||||
if (type.startsWith('n8n-nodes-base.')) {
|
||||
return type.replace(/^n8n-nodes-base\./, 'nodes-base.');
|
||||
}
|
||||
if (type.startsWith('@n8n/n8n-nodes-langchain.')) {
|
||||
return type.replace(/^@n8n\/n8n-nodes-langchain\./, 'nodes-langchain.');
|
||||
}
|
||||
if (type.startsWith('n8n-nodes-langchain.')) {
|
||||
return type.replace(/^n8n-nodes-langchain\./, 'nodes-langchain.');
|
||||
}
|
||||
return type;
|
||||
}
|
||||
static normalizeWithDetails(type) {
|
||||
const original = type;
|
||||
const normalized = this.normalizeToFullForm(type);
|
||||
return {
|
||||
original,
|
||||
normalized,
|
||||
wasNormalized: original !== normalized,
|
||||
package: this.detectPackage(normalized)
|
||||
};
|
||||
}
|
||||
static detectPackage(type) {
|
||||
if (type.startsWith('nodes-base.') || type.startsWith('n8n-nodes-base.'))
|
||||
return 'base';
|
||||
if (type.startsWith('nodes-langchain.') || type.startsWith('@n8n/n8n-nodes-langchain.') || type.startsWith('n8n-nodes-langchain.'))
|
||||
return 'langchain';
|
||||
if (type.includes('.'))
|
||||
return 'community';
|
||||
return 'unknown';
|
||||
}
|
||||
static normalizeBatch(types) {
|
||||
const result = new Map();
|
||||
for (const type of types) {
|
||||
result.set(type, this.normalizeToFullForm(type));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
static normalizeWorkflowNodeTypes(workflow) {
|
||||
if (!workflow?.nodes || !Array.isArray(workflow.nodes)) {
|
||||
return workflow;
|
||||
}
|
||||
return {
|
||||
...workflow,
|
||||
nodes: workflow.nodes.map((node) => ({
|
||||
...node,
|
||||
type: this.normalizeToFullForm(node.type)
|
||||
}))
|
||||
};
|
||||
}
|
||||
static isFullForm(type) {
|
||||
if (!type || typeof type !== 'string') {
|
||||
return false;
|
||||
}
|
||||
return (type.startsWith('n8n-nodes-base.') ||
|
||||
type.startsWith('@n8n/n8n-nodes-langchain.') ||
|
||||
type.startsWith('n8n-nodes-langchain.'));
|
||||
}
|
||||
static isShortForm(type) {
|
||||
if (!type || typeof type !== 'string') {
|
||||
return false;
|
||||
}
|
||||
return (type.startsWith('nodes-base.') ||
|
||||
type.startsWith('nodes-langchain.'));
|
||||
}
|
||||
}
|
||||
exports.NodeTypeNormalizer = NodeTypeNormalizer;
|
||||
//# sourceMappingURL=node-type-normalizer.js.map
|
||||
1
dist/utils/node-type-normalizer.js.map
vendored
Normal file
1
dist/utils/node-type-normalizer.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"node-type-normalizer.js","sourceRoot":"","sources":["../../src/utils/node-type-normalizer.ts"],"names":[],"mappings":"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"}
|
||||
12
dist/utils/node-type-utils.d.ts
vendored
Normal file
12
dist/utils/node-type-utils.d.ts
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
export declare function normalizeNodeType(type: string): string;
|
||||
export declare function denormalizeNodeType(type: string, packageType: 'base' | 'langchain'): string;
|
||||
export declare function extractNodeName(type: string): string;
|
||||
export declare function getNodePackage(type: string): string | null;
|
||||
export declare function isBaseNode(type: string): boolean;
|
||||
export declare function isLangChainNode(type: string): boolean;
|
||||
export declare function isValidNodeTypeFormat(type: string): boolean;
|
||||
export declare function getNodeTypeVariations(type: string): string[];
|
||||
export declare function isTriggerNode(nodeType: string): boolean;
|
||||
export declare function isActivatableTrigger(nodeType: string): boolean;
|
||||
export declare function getTriggerTypeDescription(nodeType: string): string;
|
||||
//# sourceMappingURL=node-type-utils.d.ts.map
|
||||
1
dist/utils/node-type-utils.d.ts.map
vendored
Normal file
1
dist/utils/node-type-utils.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"node-type-utils.d.ts","sourceRoot":"","sources":["../../src/utils/node-type-utils.ts"],"names":[],"mappings":"AAcA,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMtD;AASD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,WAAW,GAAG,MAAM,CAQ3F;AASD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CASpD;AASD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAS1D;AAKD,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGhD;AAKD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGrD;AAMD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAa3D;AAUD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAwB5D;AAkBD,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAsBvD;AAoBD,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAW9D;AAQD,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAiClE"}
|
||||
131
dist/utils/node-type-utils.js
vendored
Normal file
131
dist/utils/node-type-utils.js
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.normalizeNodeType = normalizeNodeType;
|
||||
exports.denormalizeNodeType = denormalizeNodeType;
|
||||
exports.extractNodeName = extractNodeName;
|
||||
exports.getNodePackage = getNodePackage;
|
||||
exports.isBaseNode = isBaseNode;
|
||||
exports.isLangChainNode = isLangChainNode;
|
||||
exports.isValidNodeTypeFormat = isValidNodeTypeFormat;
|
||||
exports.getNodeTypeVariations = getNodeTypeVariations;
|
||||
exports.isTriggerNode = isTriggerNode;
|
||||
exports.isActivatableTrigger = isActivatableTrigger;
|
||||
exports.getTriggerTypeDescription = getTriggerTypeDescription;
|
||||
function normalizeNodeType(type) {
|
||||
if (!type)
|
||||
return type;
|
||||
return type
|
||||
.replace(/^n8n-nodes-base\./, 'nodes-base.')
|
||||
.replace(/^@n8n\/n8n-nodes-langchain\./, 'nodes-langchain.');
|
||||
}
|
||||
function denormalizeNodeType(type, packageType) {
|
||||
if (!type)
|
||||
return type;
|
||||
if (packageType === 'base') {
|
||||
return type.replace(/^nodes-base\./, 'n8n-nodes-base.');
|
||||
}
|
||||
return type.replace(/^nodes-langchain\./, '@n8n/n8n-nodes-langchain.');
|
||||
}
|
||||
function extractNodeName(type) {
|
||||
if (!type)
|
||||
return '';
|
||||
const normalized = normalizeNodeType(type);
|
||||
const parts = normalized.split('.');
|
||||
return parts[parts.length - 1] || '';
|
||||
}
|
||||
function getNodePackage(type) {
|
||||
if (!type || !type.includes('.'))
|
||||
return null;
|
||||
const normalized = normalizeNodeType(type);
|
||||
const parts = normalized.split('.');
|
||||
return parts[0] || null;
|
||||
}
|
||||
function isBaseNode(type) {
|
||||
const normalized = normalizeNodeType(type);
|
||||
return normalized.startsWith('nodes-base.');
|
||||
}
|
||||
function isLangChainNode(type) {
|
||||
const normalized = normalizeNodeType(type);
|
||||
return normalized.startsWith('nodes-langchain.');
|
||||
}
|
||||
function isValidNodeTypeFormat(type) {
|
||||
if (!type || typeof type !== 'string')
|
||||
return false;
|
||||
if (!type.includes('.'))
|
||||
return false;
|
||||
const parts = type.split('.');
|
||||
if (parts.length !== 2)
|
||||
return false;
|
||||
return parts[0].length > 0 && parts[1].length > 0;
|
||||
}
|
||||
function getNodeTypeVariations(type) {
|
||||
const variations = [];
|
||||
if (type.includes('.')) {
|
||||
variations.push(normalizeNodeType(type));
|
||||
const normalized = normalizeNodeType(type);
|
||||
if (normalized.startsWith('nodes-base.')) {
|
||||
variations.push(denormalizeNodeType(normalized, 'base'));
|
||||
}
|
||||
else if (normalized.startsWith('nodes-langchain.')) {
|
||||
variations.push(denormalizeNodeType(normalized, 'langchain'));
|
||||
}
|
||||
}
|
||||
else {
|
||||
variations.push(`nodes-base.${type}`);
|
||||
variations.push(`n8n-nodes-base.${type}`);
|
||||
variations.push(`nodes-langchain.${type}`);
|
||||
variations.push(`@n8n/n8n-nodes-langchain.${type}`);
|
||||
}
|
||||
return [...new Set(variations)];
|
||||
}
|
||||
function isTriggerNode(nodeType) {
|
||||
const normalized = normalizeNodeType(nodeType);
|
||||
const lowerType = normalized.toLowerCase();
|
||||
if (lowerType.includes('trigger')) {
|
||||
return true;
|
||||
}
|
||||
if (lowerType.includes('webhook') && !lowerType.includes('respond')) {
|
||||
return true;
|
||||
}
|
||||
const specificTriggers = [
|
||||
'nodes-base.start',
|
||||
'nodes-base.manualTrigger',
|
||||
'nodes-base.formTrigger'
|
||||
];
|
||||
return specificTriggers.includes(normalized);
|
||||
}
|
||||
function isActivatableTrigger(nodeType) {
|
||||
const normalized = normalizeNodeType(nodeType);
|
||||
const lowerType = normalized.toLowerCase();
|
||||
if (lowerType.includes('executeworkflow')) {
|
||||
return false;
|
||||
}
|
||||
return isTriggerNode(nodeType);
|
||||
}
|
||||
function getTriggerTypeDescription(nodeType) {
|
||||
const normalized = normalizeNodeType(nodeType);
|
||||
const lowerType = normalized.toLowerCase();
|
||||
if (lowerType.includes('executeworkflow')) {
|
||||
return 'Execute Workflow Trigger (invoked by other workflows)';
|
||||
}
|
||||
if (lowerType.includes('webhook')) {
|
||||
return 'Webhook Trigger (HTTP requests)';
|
||||
}
|
||||
if (lowerType.includes('schedule') || lowerType.includes('cron')) {
|
||||
return 'Schedule Trigger (time-based)';
|
||||
}
|
||||
if (lowerType.includes('manual') || normalized === 'nodes-base.start') {
|
||||
return 'Manual Trigger (manual execution)';
|
||||
}
|
||||
if (lowerType.includes('email') || lowerType.includes('imap') || lowerType.includes('gmail')) {
|
||||
return 'Email Trigger (polling)';
|
||||
}
|
||||
if (lowerType.includes('form')) {
|
||||
return 'Form Trigger (form submissions)';
|
||||
}
|
||||
if (lowerType.includes('trigger')) {
|
||||
return 'Trigger (event-based)';
|
||||
}
|
||||
return 'Unknown trigger type';
|
||||
}
|
||||
//# sourceMappingURL=node-type-utils.js.map
|
||||
1
dist/utils/node-type-utils.js.map
vendored
Normal file
1
dist/utils/node-type-utils.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"node-type-utils.js","sourceRoot":"","sources":["../../src/utils/node-type-utils.ts"],"names":[],"mappings":"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"}
|
||||
4
dist/utils/node-utils.d.ts
vendored
Normal file
4
dist/utils/node-utils.d.ts
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
export declare function normalizeNodeType(nodeType: string): string;
|
||||
export declare function getNodeTypeAlternatives(nodeType: string): string[];
|
||||
export declare function getWorkflowNodeType(packageName: string, nodeType: string): string;
|
||||
//# sourceMappingURL=node-utils.d.ts.map
|
||||
1
dist/utils/node-utils.d.ts.map
vendored
Normal file
1
dist/utils/node-utils.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"node-utils.d.ts","sourceRoot":"","sources":["../../src/utils/node-utils.ts"],"names":[],"mappings":"AAYA,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAkB1D;AAQD,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAiDlE;AAwDD,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAajF"}
|
||||
81
dist/utils/node-utils.js
vendored
Normal file
81
dist/utils/node-utils.js
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.normalizeNodeType = normalizeNodeType;
|
||||
exports.getNodeTypeAlternatives = getNodeTypeAlternatives;
|
||||
exports.getWorkflowNodeType = getWorkflowNodeType;
|
||||
function normalizeNodeType(nodeType) {
|
||||
if (nodeType.startsWith('n8n-nodes-base.')) {
|
||||
return nodeType.replace('n8n-nodes-base.', 'nodes-base.');
|
||||
}
|
||||
if (nodeType.startsWith('@n8n/n8n-nodes-langchain.')) {
|
||||
return nodeType.replace('@n8n/n8n-nodes-langchain.', 'nodes-langchain.');
|
||||
}
|
||||
if (nodeType.startsWith('n8n-nodes-langchain.')) {
|
||||
return nodeType.replace('n8n-nodes-langchain.', 'nodes-langchain.');
|
||||
}
|
||||
return nodeType;
|
||||
}
|
||||
function getNodeTypeAlternatives(nodeType) {
|
||||
if (!nodeType || typeof nodeType !== 'string' || nodeType.trim() === '') {
|
||||
return [];
|
||||
}
|
||||
const alternatives = [];
|
||||
alternatives.push(nodeType.toLowerCase());
|
||||
if (nodeType.includes('.')) {
|
||||
const [prefix, nodeName] = nodeType.split('.');
|
||||
if (nodeName && nodeName.toLowerCase() !== nodeName) {
|
||||
alternatives.push(`${prefix}.${nodeName.toLowerCase()}`);
|
||||
}
|
||||
if (nodeName && nodeName.toLowerCase() === nodeName && nodeName.length > 1) {
|
||||
const camelCaseVariants = generateCamelCaseVariants(nodeName);
|
||||
camelCaseVariants.forEach(variant => {
|
||||
alternatives.push(`${prefix}.${variant}`);
|
||||
});
|
||||
}
|
||||
}
|
||||
if (!nodeType.includes('.')) {
|
||||
alternatives.push(`nodes-base.${nodeType}`);
|
||||
alternatives.push(`nodes-langchain.${nodeType}`);
|
||||
const camelCaseVariants = generateCamelCaseVariants(nodeType);
|
||||
camelCaseVariants.forEach(variant => {
|
||||
alternatives.push(`nodes-base.${variant}`);
|
||||
alternatives.push(`nodes-langchain.${variant}`);
|
||||
});
|
||||
}
|
||||
const normalizedAlternatives = alternatives.map(alt => normalizeNodeType(alt));
|
||||
return [...new Set([...alternatives, ...normalizedAlternatives])];
|
||||
}
|
||||
function generateCamelCaseVariants(str) {
|
||||
const variants = [];
|
||||
const patterns = [
|
||||
/^(.+)(trigger|node|request|response)$/i,
|
||||
/^(http|mysql|postgres|mongo|redis|mqtt|smtp|imap|ftp|ssh|api)(.+)$/i,
|
||||
/^(google|microsoft|amazon|slack|discord|telegram)(.+)$/i,
|
||||
];
|
||||
for (const pattern of patterns) {
|
||||
const match = str.toLowerCase().match(pattern);
|
||||
if (match) {
|
||||
const [, first, second] = match;
|
||||
variants.push(first.toLowerCase() + second.charAt(0).toUpperCase() + second.slice(1).toLowerCase());
|
||||
}
|
||||
}
|
||||
if (variants.length === 0) {
|
||||
const words = str.split(/[-_\s]+/);
|
||||
if (words.length > 1) {
|
||||
const camelCase = words[0].toLowerCase() + words.slice(1).map(w => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join('');
|
||||
variants.push(camelCase);
|
||||
}
|
||||
}
|
||||
return variants;
|
||||
}
|
||||
function getWorkflowNodeType(packageName, nodeType) {
|
||||
const nodeName = nodeType.split('.').pop() || nodeType;
|
||||
if (packageName === 'n8n-nodes-base') {
|
||||
return `n8n-nodes-base.${nodeName}`;
|
||||
}
|
||||
else if (packageName === '@n8n/n8n-nodes-langchain') {
|
||||
return `@n8n/n8n-nodes-langchain.${nodeName}`;
|
||||
}
|
||||
return nodeType;
|
||||
}
|
||||
//# sourceMappingURL=node-utils.js.map
|
||||
1
dist/utils/node-utils.js.map
vendored
Normal file
1
dist/utils/node-utils.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"node-utils.js","sourceRoot":"","sources":["../../src/utils/node-utils.ts"],"names":[],"mappings":"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"}
|
||||
14
dist/utils/npm-version-checker.d.ts
vendored
Normal file
14
dist/utils/npm-version-checker.d.ts
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
export interface VersionCheckResult {
|
||||
currentVersion: string;
|
||||
latestVersion: string | null;
|
||||
isOutdated: boolean;
|
||||
updateAvailable: boolean;
|
||||
error: string | null;
|
||||
checkedAt: Date;
|
||||
updateCommand?: string;
|
||||
}
|
||||
export declare function checkNpmVersion(forceRefresh?: boolean): Promise<VersionCheckResult>;
|
||||
export declare function compareVersions(v1: string, v2: string): number;
|
||||
export declare function clearVersionCheckCache(): void;
|
||||
export declare function formatVersionMessage(result: VersionCheckResult): string;
|
||||
//# sourceMappingURL=npm-version-checker.d.ts.map
|
||||
1
dist/utils/npm-version-checker.d.ts.map
vendored
Normal file
1
dist/utils/npm-version-checker.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"npm-version-checker.d.ts","sourceRoot":"","sources":["../../src/utils/npm-version-checker.ts"],"names":[],"mappings":"AAkBA,MAAM,WAAW,kBAAkB;IACjC,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,UAAU,EAAE,OAAO,CAAC;IACpB,eAAe,EAAE,OAAO,CAAC;IACzB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,EAAE,IAAI,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAcD,wBAAsB,eAAe,CAAC,YAAY,GAAE,OAAe,GAAG,OAAO,CAAC,kBAAkB,CAAC,CA4GhG;AAUD,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAmB9D;AAKD,wBAAgB,sBAAsB,IAAI,IAAI,CAG7C;AAQD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,kBAAkB,GAAG,MAAM,CAcvE"}
|
||||
125
dist/utils/npm-version-checker.js
vendored
Normal file
125
dist/utils/npm-version-checker.js
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.checkNpmVersion = checkNpmVersion;
|
||||
exports.compareVersions = compareVersions;
|
||||
exports.clearVersionCheckCache = clearVersionCheckCache;
|
||||
exports.formatVersionMessage = formatVersionMessage;
|
||||
const logger_1 = require("./logger");
|
||||
let versionCheckCache = null;
|
||||
let lastCheckTime = 0;
|
||||
const CACHE_TTL_MS = 1 * 60 * 60 * 1000;
|
||||
async function checkNpmVersion(forceRefresh = false) {
|
||||
const now = Date.now();
|
||||
if (!forceRefresh && versionCheckCache && (now - lastCheckTime) < CACHE_TTL_MS) {
|
||||
logger_1.logger.debug('Returning cached npm version check result');
|
||||
return versionCheckCache;
|
||||
}
|
||||
const packageJson = require('../../package.json');
|
||||
const currentVersion = packageJson.version;
|
||||
try {
|
||||
const response = await fetch('https://registry.npmjs.org/n8n-mcp/latest', {
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
signal: AbortSignal.timeout(5000)
|
||||
});
|
||||
if (!response.ok) {
|
||||
logger_1.logger.warn('Failed to fetch npm version info', {
|
||||
status: response.status,
|
||||
statusText: response.statusText
|
||||
});
|
||||
const result = {
|
||||
currentVersion,
|
||||
latestVersion: null,
|
||||
isOutdated: false,
|
||||
updateAvailable: false,
|
||||
error: `npm registry returned ${response.status}`,
|
||||
checkedAt: new Date()
|
||||
};
|
||||
versionCheckCache = result;
|
||||
lastCheckTime = now;
|
||||
return result;
|
||||
}
|
||||
let data;
|
||||
try {
|
||||
data = await response.json();
|
||||
}
|
||||
catch (error) {
|
||||
throw new Error('Failed to parse npm registry response as JSON');
|
||||
}
|
||||
if (!data || typeof data !== 'object' || !('version' in data)) {
|
||||
throw new Error('Invalid response format from npm registry');
|
||||
}
|
||||
const registryData = data;
|
||||
const latestVersion = registryData.version;
|
||||
if (!latestVersion || !/^\d+\.\d+\.\d+/.test(latestVersion)) {
|
||||
throw new Error(`Invalid version format from npm registry: ${latestVersion}`);
|
||||
}
|
||||
const isOutdated = compareVersions(currentVersion, latestVersion) < 0;
|
||||
const result = {
|
||||
currentVersion,
|
||||
latestVersion,
|
||||
isOutdated,
|
||||
updateAvailable: isOutdated,
|
||||
error: null,
|
||||
checkedAt: new Date(),
|
||||
updateCommand: isOutdated ? `npm install -g n8n-mcp@${latestVersion}` : undefined
|
||||
};
|
||||
versionCheckCache = result;
|
||||
lastCheckTime = now;
|
||||
logger_1.logger.debug('npm version check completed', {
|
||||
current: currentVersion,
|
||||
latest: latestVersion,
|
||||
outdated: isOutdated
|
||||
});
|
||||
return result;
|
||||
}
|
||||
catch (error) {
|
||||
logger_1.logger.warn('Error checking npm version', {
|
||||
error: error instanceof Error ? error.message : String(error)
|
||||
});
|
||||
const result = {
|
||||
currentVersion,
|
||||
latestVersion: null,
|
||||
isOutdated: false,
|
||||
updateAvailable: false,
|
||||
error: error instanceof Error ? error.message : 'Unknown error',
|
||||
checkedAt: new Date()
|
||||
};
|
||||
versionCheckCache = result;
|
||||
lastCheckTime = now;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
function compareVersions(v1, v2) {
|
||||
const clean1 = v1.replace(/^v/, '');
|
||||
const clean2 = v2.replace(/^v/, '');
|
||||
const parts1 = clean1.split('.').map(n => parseInt(n, 10) || 0);
|
||||
const parts2 = clean2.split('.').map(n => parseInt(n, 10) || 0);
|
||||
for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
|
||||
const p1 = parts1[i] || 0;
|
||||
const p2 = parts2[i] || 0;
|
||||
if (p1 < p2)
|
||||
return -1;
|
||||
if (p1 > p2)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
function clearVersionCheckCache() {
|
||||
versionCheckCache = null;
|
||||
lastCheckTime = 0;
|
||||
}
|
||||
function formatVersionMessage(result) {
|
||||
if (result.error) {
|
||||
return `Version check failed: ${result.error}. Current version: ${result.currentVersion}`;
|
||||
}
|
||||
if (!result.latestVersion) {
|
||||
return `Current version: ${result.currentVersion} (latest version unknown)`;
|
||||
}
|
||||
if (result.isOutdated) {
|
||||
return `⚠️ Update available! Current: ${result.currentVersion} → Latest: ${result.latestVersion}`;
|
||||
}
|
||||
return `✓ You're up to date! Current version: ${result.currentVersion}`;
|
||||
}
|
||||
//# sourceMappingURL=npm-version-checker.js.map
|
||||
1
dist/utils/npm-version-checker.js.map
vendored
Normal file
1
dist/utils/npm-version-checker.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"npm-version-checker.js","sourceRoot":"","sources":["../../src/utils/npm-version-checker.ts"],"names":[],"mappings":"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"}
|
||||
19
dist/utils/protocol-version.d.ts
vendored
Normal file
19
dist/utils/protocol-version.d.ts
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
export interface ClientInfo {
|
||||
name?: string;
|
||||
version?: string;
|
||||
[key: string]: any;
|
||||
}
|
||||
export interface ProtocolNegotiationResult {
|
||||
version: string;
|
||||
isN8nClient: boolean;
|
||||
reasoning: string;
|
||||
}
|
||||
export declare const STANDARD_PROTOCOL_VERSION = "2025-03-26";
|
||||
export declare const N8N_PROTOCOL_VERSION = "2024-11-05";
|
||||
export declare const SUPPORTED_VERSIONS: string[];
|
||||
export declare function isN8nClient(clientInfo?: ClientInfo, userAgent?: string, headers?: Record<string, string | string[] | undefined>): boolean;
|
||||
export declare function negotiateProtocolVersion(clientRequestedVersion?: string, clientInfo?: ClientInfo, userAgent?: string, headers?: Record<string, string | string[] | undefined>): ProtocolNegotiationResult;
|
||||
export declare function isVersionSupported(version: string): boolean;
|
||||
export declare function getCompatibleVersion(targetVersion?: string): string;
|
||||
export declare function logProtocolNegotiation(result: ProtocolNegotiationResult, logger: any, context?: string): void;
|
||||
//# sourceMappingURL=protocol-version.d.ts.map
|
||||
1
dist/utils/protocol-version.d.ts.map
vendored
Normal file
1
dist/utils/protocol-version.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"protocol-version.d.ts","sourceRoot":"","sources":["../../src/utils/protocol-version.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,MAAM,WAAW,yBAAyB;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB;AAKD,eAAO,MAAM,yBAAyB,eAAe,CAAC;AAKtD,eAAO,MAAM,oBAAoB,eAAe,CAAC;AAKjD,eAAO,MAAM,kBAAkB,UAI9B,CAAC;AAKF,wBAAgB,WAAW,CACzB,UAAU,CAAC,EAAE,UAAU,EACvB,SAAS,CAAC,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,GACtD,OAAO,CAqCT;AAKD,wBAAgB,wBAAwB,CACtC,sBAAsB,CAAC,EAAE,MAAM,EAC/B,UAAU,CAAC,EAAE,UAAU,EACvB,SAAS,CAAC,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,GACtD,yBAAyB,CAqC3B;AAKD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAE3D;AAMD,wBAAgB,oBAAoB,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAWnE;AAKD,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,yBAAyB,EACjC,MAAM,EAAE,GAAG,EACX,OAAO,CAAC,EAAE,MAAM,GACf,IAAI,CAYN"}
|
||||
95
dist/utils/protocol-version.js
vendored
Normal file
95
dist/utils/protocol-version.js
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.SUPPORTED_VERSIONS = exports.N8N_PROTOCOL_VERSION = exports.STANDARD_PROTOCOL_VERSION = void 0;
|
||||
exports.isN8nClient = isN8nClient;
|
||||
exports.negotiateProtocolVersion = negotiateProtocolVersion;
|
||||
exports.isVersionSupported = isVersionSupported;
|
||||
exports.getCompatibleVersion = getCompatibleVersion;
|
||||
exports.logProtocolNegotiation = logProtocolNegotiation;
|
||||
exports.STANDARD_PROTOCOL_VERSION = '2025-03-26';
|
||||
exports.N8N_PROTOCOL_VERSION = '2024-11-05';
|
||||
exports.SUPPORTED_VERSIONS = [
|
||||
exports.STANDARD_PROTOCOL_VERSION,
|
||||
exports.N8N_PROTOCOL_VERSION,
|
||||
'2024-06-25',
|
||||
];
|
||||
function isN8nClient(clientInfo, userAgent, headers) {
|
||||
if (clientInfo?.name) {
|
||||
const clientName = clientInfo.name.toLowerCase();
|
||||
if (clientName.includes('n8n') || clientName.includes('langchain')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (userAgent) {
|
||||
const ua = userAgent.toLowerCase();
|
||||
if (ua.includes('n8n') || ua.includes('langchain')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (headers) {
|
||||
const headerValues = Object.values(headers).join(' ').toLowerCase();
|
||||
if (headerValues.includes('n8n') || headerValues.includes('langchain')) {
|
||||
return true;
|
||||
}
|
||||
if (headers['x-n8n-version'] || headers['x-langchain-version']) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (process.env.N8N_MODE === 'true') {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function negotiateProtocolVersion(clientRequestedVersion, clientInfo, userAgent, headers) {
|
||||
const isN8n = isN8nClient(clientInfo, userAgent, headers);
|
||||
if (isN8n) {
|
||||
return {
|
||||
version: exports.N8N_PROTOCOL_VERSION,
|
||||
isN8nClient: true,
|
||||
reasoning: 'n8n client detected, using n8n-compatible protocol version'
|
||||
};
|
||||
}
|
||||
if (clientRequestedVersion && exports.SUPPORTED_VERSIONS.includes(clientRequestedVersion)) {
|
||||
return {
|
||||
version: clientRequestedVersion,
|
||||
isN8nClient: false,
|
||||
reasoning: `Using client-requested version: ${clientRequestedVersion}`
|
||||
};
|
||||
}
|
||||
if (clientRequestedVersion) {
|
||||
return {
|
||||
version: exports.STANDARD_PROTOCOL_VERSION,
|
||||
isN8nClient: false,
|
||||
reasoning: `Client requested unsupported version ${clientRequestedVersion}, using standard version`
|
||||
};
|
||||
}
|
||||
return {
|
||||
version: exports.STANDARD_PROTOCOL_VERSION,
|
||||
isN8nClient: false,
|
||||
reasoning: 'No specific client detected, using standard protocol version'
|
||||
};
|
||||
}
|
||||
function isVersionSupported(version) {
|
||||
return exports.SUPPORTED_VERSIONS.includes(version);
|
||||
}
|
||||
function getCompatibleVersion(targetVersion) {
|
||||
if (!targetVersion) {
|
||||
return exports.STANDARD_PROTOCOL_VERSION;
|
||||
}
|
||||
if (exports.SUPPORTED_VERSIONS.includes(targetVersion)) {
|
||||
return targetVersion;
|
||||
}
|
||||
return exports.STANDARD_PROTOCOL_VERSION;
|
||||
}
|
||||
function logProtocolNegotiation(result, logger, context) {
|
||||
const logContext = context ? `[${context}] ` : '';
|
||||
logger.info(`${logContext}Protocol version negotiated`, {
|
||||
version: result.version,
|
||||
isN8nClient: result.isN8nClient,
|
||||
reasoning: result.reasoning
|
||||
});
|
||||
if (result.isN8nClient) {
|
||||
logger.info(`${logContext}Using n8n-compatible protocol version for better integration`);
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=protocol-version.js.map
|
||||
1
dist/utils/protocol-version.js.map
vendored
Normal file
1
dist/utils/protocol-version.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"protocol-version.js","sourceRoot":"","sources":["../../src/utils/protocol-version.ts"],"names":[],"mappings":"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"}
|
||||
10
dist/utils/simple-cache.d.ts
vendored
Normal file
10
dist/utils/simple-cache.d.ts
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
export declare class SimpleCache {
|
||||
private cache;
|
||||
private cleanupTimer;
|
||||
constructor();
|
||||
get(key: string): any;
|
||||
set(key: string, data: any, ttlSeconds?: number): void;
|
||||
clear(): void;
|
||||
destroy(): void;
|
||||
}
|
||||
//# sourceMappingURL=simple-cache.d.ts.map
|
||||
1
dist/utils/simple-cache.d.ts.map
vendored
Normal file
1
dist/utils/simple-cache.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"simple-cache.d.ts","sourceRoot":"","sources":["../../src/utils/simple-cache.ts"],"names":[],"mappings":"AAIA,qBAAa,WAAW;IACtB,OAAO,CAAC,KAAK,CAAqD;IAClE,OAAO,CAAC,YAAY,CAA+B;;IAYnD,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG;IASrB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,UAAU,GAAE,MAAY,GAAG,IAAI;IAO3D,KAAK,IAAI,IAAI;IAQb,OAAO,IAAI,IAAI;CAOhB"}
|
||||
42
dist/utils/simple-cache.js
vendored
Normal file
42
dist/utils/simple-cache.js
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.SimpleCache = void 0;
|
||||
class SimpleCache {
|
||||
constructor() {
|
||||
this.cache = new Map();
|
||||
this.cleanupTimer = null;
|
||||
this.cleanupTimer = setInterval(() => {
|
||||
const now = Date.now();
|
||||
for (const [key, item] of this.cache.entries()) {
|
||||
if (item.expires < now)
|
||||
this.cache.delete(key);
|
||||
}
|
||||
}, 60000);
|
||||
}
|
||||
get(key) {
|
||||
const item = this.cache.get(key);
|
||||
if (!item || item.expires < Date.now()) {
|
||||
this.cache.delete(key);
|
||||
return null;
|
||||
}
|
||||
return item.data;
|
||||
}
|
||||
set(key, data, ttlSeconds = 300) {
|
||||
this.cache.set(key, {
|
||||
data,
|
||||
expires: Date.now() + (ttlSeconds * 1000)
|
||||
});
|
||||
}
|
||||
clear() {
|
||||
this.cache.clear();
|
||||
}
|
||||
destroy() {
|
||||
if (this.cleanupTimer) {
|
||||
clearInterval(this.cleanupTimer);
|
||||
this.cleanupTimer = null;
|
||||
}
|
||||
this.cache.clear();
|
||||
}
|
||||
}
|
||||
exports.SimpleCache = SimpleCache;
|
||||
//# sourceMappingURL=simple-cache.js.map
|
||||
1
dist/utils/simple-cache.js.map
vendored
Normal file
1
dist/utils/simple-cache.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"simple-cache.js","sourceRoot":"","sources":["../../src/utils/simple-cache.ts"],"names":[],"mappings":";;;AAIA,MAAa,WAAW;IAItB;QAHQ,UAAK,GAAG,IAAI,GAAG,EAA0C,CAAC;QAC1D,iBAAY,GAA0B,IAAI,CAAC;QAIjD,IAAI,CAAC,YAAY,GAAG,WAAW,CAAC,GAAG,EAAE;YACnC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACvB,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;gBAC/C,IAAI,IAAI,CAAC,OAAO,GAAG,GAAG;oBAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjD,CAAC;QACH,CAAC,EAAE,KAAK,CAAC,CAAC;IACZ,CAAC;IAED,GAAG,CAAC,GAAW;QACb,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;YACvC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACvB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED,GAAG,CAAC,GAAW,EAAE,IAAS,EAAE,aAAqB,GAAG;QAClD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE;YAClB,IAAI;YACJ,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,UAAU,GAAG,IAAI,CAAC;SAC1C,CAAC,CAAC;IACL,CAAC;IAED,KAAK;QACH,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IAMD,OAAO;QACL,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YACjC,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QAC3B,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;CACF;AA7CD,kCA6CC"}
|
||||
7
dist/utils/ssrf-protection.d.ts
vendored
Normal file
7
dist/utils/ssrf-protection.d.ts
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
export declare class SSRFProtection {
|
||||
static validateWebhookUrl(urlString: string): Promise<{
|
||||
valid: boolean;
|
||||
reason?: string;
|
||||
}>;
|
||||
}
|
||||
//# sourceMappingURL=ssrf-protection.d.ts.map
|
||||
1
dist/utils/ssrf-protection.d.ts.map
vendored
Normal file
1
dist/utils/ssrf-protection.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"ssrf-protection.d.ts","sourceRoot":"","sources":["../../src/utils/ssrf-protection.ts"],"names":[],"mappings":"AAoDA,qBAAa,cAAc;WAoBZ,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;QAC1D,KAAK,EAAE,OAAO,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAA;KAChB,CAAC;CA+GH"}
|
||||
118
dist/utils/ssrf-protection.js
vendored
Normal file
118
dist/utils/ssrf-protection.js
vendored
Normal file
@@ -0,0 +1,118 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.SSRFProtection = void 0;
|
||||
const url_1 = require("url");
|
||||
const promises_1 = require("dns/promises");
|
||||
const logger_1 = require("./logger");
|
||||
const CLOUD_METADATA = new Set([
|
||||
'169.254.169.254',
|
||||
'169.254.170.2',
|
||||
'metadata.google.internal',
|
||||
'metadata',
|
||||
'100.100.100.200',
|
||||
'192.0.0.192',
|
||||
]);
|
||||
const LOCALHOST_PATTERNS = new Set([
|
||||
'localhost',
|
||||
'127.0.0.1',
|
||||
'::1',
|
||||
'0.0.0.0',
|
||||
'localhost.localdomain',
|
||||
]);
|
||||
const PRIVATE_IP_RANGES = [
|
||||
/^10\./,
|
||||
/^192\.168\./,
|
||||
/^172\.(1[6-9]|2[0-9]|3[0-1])\./,
|
||||
/^169\.254\./,
|
||||
/^127\./,
|
||||
/^0\./,
|
||||
];
|
||||
class SSRFProtection {
|
||||
static async validateWebhookUrl(urlString) {
|
||||
try {
|
||||
const url = new url_1.URL(urlString);
|
||||
const mode = (process.env.WEBHOOK_SECURITY_MODE || 'strict');
|
||||
if (!['http:', 'https:'].includes(url.protocol)) {
|
||||
return { valid: false, reason: 'Invalid protocol. Only HTTP/HTTPS allowed.' };
|
||||
}
|
||||
let hostname = url.hostname.toLowerCase();
|
||||
if (hostname.startsWith('[') && hostname.endsWith(']')) {
|
||||
hostname = hostname.slice(1, -1);
|
||||
}
|
||||
if (CLOUD_METADATA.has(hostname)) {
|
||||
logger_1.logger.warn('SSRF blocked: Cloud metadata endpoint', { hostname, mode });
|
||||
return { valid: false, reason: 'Cloud metadata endpoint blocked' };
|
||||
}
|
||||
let resolvedIP;
|
||||
try {
|
||||
const { address } = await (0, promises_1.lookup)(hostname);
|
||||
resolvedIP = address;
|
||||
logger_1.logger.debug('DNS resolved for SSRF check', { hostname, resolvedIP, mode });
|
||||
}
|
||||
catch (error) {
|
||||
logger_1.logger.warn('DNS resolution failed for webhook URL', {
|
||||
hostname,
|
||||
error: error instanceof Error ? error.message : String(error)
|
||||
});
|
||||
return { valid: false, reason: 'DNS resolution failed' };
|
||||
}
|
||||
if (CLOUD_METADATA.has(resolvedIP)) {
|
||||
logger_1.logger.warn('SSRF blocked: Hostname resolves to cloud metadata IP', {
|
||||
hostname,
|
||||
resolvedIP,
|
||||
mode
|
||||
});
|
||||
return { valid: false, reason: 'Hostname resolves to cloud metadata endpoint' };
|
||||
}
|
||||
if (mode === 'permissive') {
|
||||
logger_1.logger.warn('SSRF protection in permissive mode (localhost and private IPs allowed)', {
|
||||
hostname,
|
||||
resolvedIP
|
||||
});
|
||||
return { valid: true };
|
||||
}
|
||||
const isLocalhost = LOCALHOST_PATTERNS.has(hostname) ||
|
||||
resolvedIP === '::1' ||
|
||||
resolvedIP.startsWith('127.');
|
||||
if (mode === 'strict' && isLocalhost) {
|
||||
logger_1.logger.warn('SSRF blocked: Localhost not allowed in strict mode', {
|
||||
hostname,
|
||||
resolvedIP
|
||||
});
|
||||
return { valid: false, reason: 'Localhost access is blocked in strict mode' };
|
||||
}
|
||||
if (mode === 'moderate' && isLocalhost) {
|
||||
logger_1.logger.info('Localhost webhook allowed (moderate mode)', { hostname, resolvedIP });
|
||||
return { valid: true };
|
||||
}
|
||||
if (PRIVATE_IP_RANGES.some(regex => regex.test(resolvedIP))) {
|
||||
logger_1.logger.warn('SSRF blocked: Private IP address', { hostname, resolvedIP, mode });
|
||||
return {
|
||||
valid: false,
|
||||
reason: mode === 'strict'
|
||||
? 'Private IP addresses not allowed'
|
||||
: 'Private IP addresses not allowed (use WEBHOOK_SECURITY_MODE=permissive if needed)'
|
||||
};
|
||||
}
|
||||
if (resolvedIP === '::1' ||
|
||||
resolvedIP === '::' ||
|
||||
resolvedIP.startsWith('fe80:') ||
|
||||
resolvedIP.startsWith('fc00:') ||
|
||||
resolvedIP.startsWith('fd00:') ||
|
||||
resolvedIP.startsWith('::ffff:')) {
|
||||
logger_1.logger.warn('SSRF blocked: IPv6 private address', {
|
||||
hostname,
|
||||
resolvedIP,
|
||||
mode
|
||||
});
|
||||
return { valid: false, reason: 'IPv6 private address not allowed' };
|
||||
}
|
||||
return { valid: true };
|
||||
}
|
||||
catch (error) {
|
||||
return { valid: false, reason: 'Invalid URL format' };
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.SSRFProtection = SSRFProtection;
|
||||
//# sourceMappingURL=ssrf-protection.js.map
|
||||
1
dist/utils/ssrf-protection.js.map
vendored
Normal file
1
dist/utils/ssrf-protection.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"ssrf-protection.js","sourceRoot":"","sources":["../../src/utils/ssrf-protection.ts"],"names":[],"mappings":"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"}
|
||||
2
dist/utils/template-node-resolver.d.ts
vendored
Normal file
2
dist/utils/template-node-resolver.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export declare function resolveTemplateNodeTypes(nodeTypes: string[]): string[];
|
||||
//# sourceMappingURL=template-node-resolver.d.ts.map
|
||||
1
dist/utils/template-node-resolver.d.ts.map
vendored
Normal file
1
dist/utils/template-node-resolver.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"template-node-resolver.d.ts","sourceRoot":"","sources":["../../src/utils/template-node-resolver.ts"],"names":[],"mappings":"AAoBA,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAgBtE"}
|
||||
161
dist/utils/template-node-resolver.js
vendored
Normal file
161
dist/utils/template-node-resolver.js
vendored
Normal file
@@ -0,0 +1,161 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.resolveTemplateNodeTypes = resolveTemplateNodeTypes;
|
||||
const logger_1 = require("./logger");
|
||||
function resolveTemplateNodeTypes(nodeTypes) {
|
||||
const resolvedTypes = new Set();
|
||||
for (const nodeType of nodeTypes) {
|
||||
const variations = generateTemplateNodeVariations(nodeType);
|
||||
variations.forEach(v => resolvedTypes.add(v));
|
||||
}
|
||||
const result = Array.from(resolvedTypes);
|
||||
logger_1.logger.debug(`Resolved ${nodeTypes.length} input types to ${result.length} template variations`, {
|
||||
input: nodeTypes,
|
||||
output: result
|
||||
});
|
||||
return result;
|
||||
}
|
||||
function generateTemplateNodeVariations(nodeType) {
|
||||
const variations = new Set();
|
||||
if (nodeType.startsWith('n8n-nodes-base.') || nodeType.startsWith('@n8n/n8n-nodes-langchain.')) {
|
||||
variations.add(nodeType);
|
||||
return Array.from(variations);
|
||||
}
|
||||
if (nodeType.startsWith('nodes-base.')) {
|
||||
const nodeName = nodeType.replace('nodes-base.', '');
|
||||
variations.add(`n8n-nodes-base.${nodeName}`);
|
||||
addCamelCaseVariations(variations, nodeName, 'n8n-nodes-base');
|
||||
}
|
||||
else if (nodeType.startsWith('nodes-langchain.')) {
|
||||
const nodeName = nodeType.replace('nodes-langchain.', '');
|
||||
variations.add(`@n8n/n8n-nodes-langchain.${nodeName}`);
|
||||
addCamelCaseVariations(variations, nodeName, '@n8n/n8n-nodes-langchain');
|
||||
}
|
||||
else if (!nodeType.includes('.')) {
|
||||
variations.add(`n8n-nodes-base.${nodeType}`);
|
||||
addCamelCaseVariations(variations, nodeType, 'n8n-nodes-base');
|
||||
variations.add(`@n8n/n8n-nodes-langchain.${nodeType}`);
|
||||
addCamelCaseVariations(variations, nodeType, '@n8n/n8n-nodes-langchain');
|
||||
addRelatedNodeTypes(variations, nodeType);
|
||||
}
|
||||
return Array.from(variations);
|
||||
}
|
||||
function addCamelCaseVariations(variations, nodeName, packagePrefix) {
|
||||
const lowerName = nodeName.toLowerCase();
|
||||
const patterns = [
|
||||
{ suffix: 'trigger', capitalize: true },
|
||||
{ suffix: 'Trigger', capitalize: false },
|
||||
{ suffix: 'request', capitalize: true },
|
||||
{ suffix: 'Request', capitalize: false },
|
||||
{ suffix: 'database', capitalize: true },
|
||||
{ suffix: 'Database', capitalize: false },
|
||||
{ suffix: 'sheet', capitalize: true },
|
||||
{ suffix: 'Sheet', capitalize: false },
|
||||
{ suffix: 'sheets', capitalize: true },
|
||||
{ suffix: 'Sheets', capitalize: false },
|
||||
];
|
||||
for (const pattern of patterns) {
|
||||
const lowerSuffix = pattern.suffix.toLowerCase();
|
||||
if (lowerName.endsWith(lowerSuffix)) {
|
||||
const baseName = lowerName.slice(0, -lowerSuffix.length);
|
||||
if (baseName) {
|
||||
if (pattern.capitalize) {
|
||||
const capitalizedSuffix = pattern.suffix.charAt(0).toUpperCase() + pattern.suffix.slice(1).toLowerCase();
|
||||
variations.add(`${packagePrefix}.${baseName}${capitalizedSuffix}`);
|
||||
}
|
||||
else {
|
||||
variations.add(`${packagePrefix}.${baseName}${pattern.suffix}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!lowerName.includes(lowerSuffix)) {
|
||||
if (pattern.capitalize) {
|
||||
const capitalizedSuffix = pattern.suffix.charAt(0).toUpperCase() + pattern.suffix.slice(1).toLowerCase();
|
||||
variations.add(`${packagePrefix}.${lowerName}${capitalizedSuffix}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
const specificCases = {
|
||||
'http': ['httpRequest'],
|
||||
'httprequest': ['httpRequest'],
|
||||
'mysql': ['mysql', 'mysqlDatabase'],
|
||||
'postgres': ['postgres', 'postgresDatabase'],
|
||||
'postgresql': ['postgres', 'postgresDatabase'],
|
||||
'mongo': ['mongoDb', 'mongodb'],
|
||||
'mongodb': ['mongoDb', 'mongodb'],
|
||||
'google': ['googleSheets', 'googleDrive', 'googleCalendar'],
|
||||
'googlesheet': ['googleSheets'],
|
||||
'googlesheets': ['googleSheets'],
|
||||
'microsoft': ['microsoftTeams', 'microsoftExcel', 'microsoftOutlook'],
|
||||
'slack': ['slack'],
|
||||
'discord': ['discord'],
|
||||
'telegram': ['telegram'],
|
||||
'webhook': ['webhook'],
|
||||
'schedule': ['scheduleTrigger'],
|
||||
'cron': ['cron', 'scheduleTrigger'],
|
||||
'email': ['emailSend', 'emailReadImap', 'gmail'],
|
||||
'gmail': ['gmail', 'gmailTrigger'],
|
||||
'code': ['code'],
|
||||
'javascript': ['code'],
|
||||
'python': ['code'],
|
||||
'js': ['code'],
|
||||
'set': ['set'],
|
||||
'if': ['if'],
|
||||
'switch': ['switch'],
|
||||
'merge': ['merge'],
|
||||
'loop': ['splitInBatches'],
|
||||
'split': ['splitInBatches', 'splitOut'],
|
||||
'ai': ['openAi'],
|
||||
'openai': ['openAi'],
|
||||
'chatgpt': ['openAi'],
|
||||
'gpt': ['openAi'],
|
||||
'api': ['httpRequest', 'graphql', 'webhook'],
|
||||
'csv': ['spreadsheetFile', 'readBinaryFile'],
|
||||
'excel': ['microsoftExcel', 'spreadsheetFile'],
|
||||
'spreadsheet': ['spreadsheetFile', 'googleSheets', 'microsoftExcel'],
|
||||
};
|
||||
const cases = specificCases[lowerName];
|
||||
if (cases) {
|
||||
cases.forEach(c => variations.add(`${packagePrefix}.${c}`));
|
||||
}
|
||||
}
|
||||
function addRelatedNodeTypes(variations, nodeName) {
|
||||
const lowerName = nodeName.toLowerCase();
|
||||
const relatedTypes = {
|
||||
'slack': ['slack', 'slackTrigger'],
|
||||
'gmail': ['gmail', 'gmailTrigger'],
|
||||
'telegram': ['telegram', 'telegramTrigger'],
|
||||
'discord': ['discord', 'discordTrigger'],
|
||||
'webhook': ['webhook', 'webhookTrigger'],
|
||||
'http': ['httpRequest', 'webhook'],
|
||||
'email': ['emailSend', 'emailReadImap', 'gmail', 'gmailTrigger'],
|
||||
'google': ['googleSheets', 'googleDrive', 'googleCalendar', 'googleDocs'],
|
||||
'microsoft': ['microsoftTeams', 'microsoftExcel', 'microsoftOutlook', 'microsoftOneDrive'],
|
||||
'database': ['postgres', 'mysql', 'mongoDb', 'redis', 'postgresDatabase', 'mysqlDatabase'],
|
||||
'db': ['postgres', 'mysql', 'mongoDb', 'redis'],
|
||||
'sql': ['postgres', 'mysql', 'mssql'],
|
||||
'nosql': ['mongoDb', 'redis', 'couchDb'],
|
||||
'schedule': ['scheduleTrigger', 'cron'],
|
||||
'time': ['scheduleTrigger', 'cron', 'wait'],
|
||||
'file': ['readBinaryFile', 'writeBinaryFile', 'moveBinaryFile'],
|
||||
'binary': ['readBinaryFile', 'writeBinaryFile', 'moveBinaryFile'],
|
||||
'csv': ['spreadsheetFile', 'readBinaryFile'],
|
||||
'excel': ['microsoftExcel', 'spreadsheetFile'],
|
||||
'json': ['code', 'set'],
|
||||
'transform': ['code', 'set', 'merge', 'splitInBatches'],
|
||||
'ai': ['openAi', 'agent', 'lmChatOpenAi', 'lmChatAnthropic'],
|
||||
'llm': ['openAi', 'agent', 'lmChatOpenAi', 'lmChatAnthropic', 'lmChatGoogleGemini'],
|
||||
'agent': ['agent', 'toolAgent'],
|
||||
'chat': ['chatTrigger', 'agent'],
|
||||
};
|
||||
const related = relatedTypes[lowerName];
|
||||
if (related) {
|
||||
related.forEach(r => {
|
||||
variations.add(`n8n-nodes-base.${r}`);
|
||||
if (['agent', 'toolAgent', 'chatTrigger', 'lmChatOpenAi', 'lmChatAnthropic', 'lmChatGoogleGemini'].includes(r)) {
|
||||
variations.add(`@n8n/n8n-nodes-langchain.${r}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=template-node-resolver.js.map
|
||||
1
dist/utils/template-node-resolver.js.map
vendored
Normal file
1
dist/utils/template-node-resolver.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
21
dist/utils/template-sanitizer.d.ts
vendored
Normal file
21
dist/utils/template-sanitizer.d.ts
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
export interface SanitizerConfig {
|
||||
problematicTokens: string[];
|
||||
tokenPatterns: RegExp[];
|
||||
replacements: Map<string, string>;
|
||||
}
|
||||
export declare const defaultSanitizerConfig: SanitizerConfig;
|
||||
export declare class TemplateSanitizer {
|
||||
private config;
|
||||
constructor(config?: SanitizerConfig);
|
||||
addProblematicToken(token: string): void;
|
||||
addTokenPattern(pattern: RegExp, replacement: string): void;
|
||||
sanitizeWorkflow(workflow: any): {
|
||||
sanitized: any;
|
||||
wasModified: boolean;
|
||||
};
|
||||
needsSanitization(workflow: any): boolean;
|
||||
detectTokens(workflow: any): string[];
|
||||
private sanitizeObject;
|
||||
private replaceTokens;
|
||||
}
|
||||
//# sourceMappingURL=template-sanitizer.d.ts.map
|
||||
1
dist/utils/template-sanitizer.d.ts.map
vendored
Normal file
1
dist/utils/template-sanitizer.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"template-sanitizer.d.ts","sourceRoot":"","sources":["../../src/utils/template-sanitizer.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,eAAe;IAC9B,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC;AAKD,eAAO,MAAM,sBAAsB,EAAE,eAoBpC,CAAC;AAKF,qBAAa,iBAAiB;IAChB,OAAO,CAAC,MAAM;gBAAN,MAAM,GAAE,eAAwC;IAKpE,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAUxC,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI;IAW3D,gBAAgB,CAAC,QAAQ,EAAE,GAAG,GAAG;QAAE,SAAS,EAAE,GAAG,CAAC;QAAC,WAAW,EAAE,OAAO,CAAA;KAAE;IA2BzE,iBAAiB,CAAC,QAAQ,EAAE,GAAG,GAAG,OAAO;IAwBzC,YAAY,CAAC,QAAQ,EAAE,GAAG,GAAG,MAAM,EAAE;IAuBrC,OAAO,CAAC,cAAc;IAetB,OAAO,CAAC,aAAa;CAuBtB"}
|
||||
126
dist/utils/template-sanitizer.js
vendored
Normal file
126
dist/utils/template-sanitizer.js
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.TemplateSanitizer = exports.defaultSanitizerConfig = void 0;
|
||||
const logger_1 = require("./logger");
|
||||
exports.defaultSanitizerConfig = {
|
||||
problematicTokens: [],
|
||||
tokenPatterns: [
|
||||
/apify_api_[A-Za-z0-9]+/g,
|
||||
/sk-[A-Za-z0-9]+/g,
|
||||
/pat[A-Za-z0-9_]{40,}/g,
|
||||
/ghp_[A-Za-z0-9]{36,}/g,
|
||||
/gho_[A-Za-z0-9]{36,}/g,
|
||||
/Bearer\s+[A-Za-z0-9\-._~+\/]+=*/g
|
||||
],
|
||||
replacements: new Map([
|
||||
['apify_api_', 'apify_api_YOUR_TOKEN_HERE'],
|
||||
['sk-', 'sk-YOUR_OPENAI_KEY_HERE'],
|
||||
['pat', 'patYOUR_AIRTABLE_TOKEN_HERE'],
|
||||
['ghp_', 'ghp_YOUR_GITHUB_TOKEN_HERE'],
|
||||
['gho_', 'gho_YOUR_GITHUB_TOKEN_HERE'],
|
||||
['Bearer ', 'Bearer YOUR_TOKEN_HERE']
|
||||
])
|
||||
};
|
||||
class TemplateSanitizer {
|
||||
constructor(config = exports.defaultSanitizerConfig) {
|
||||
this.config = config;
|
||||
}
|
||||
addProblematicToken(token) {
|
||||
if (!this.config.problematicTokens.includes(token)) {
|
||||
this.config.problematicTokens.push(token);
|
||||
logger_1.logger.info(`Added problematic token to sanitizer: ${token.substring(0, 10)}...`);
|
||||
}
|
||||
}
|
||||
addTokenPattern(pattern, replacement) {
|
||||
this.config.tokenPatterns.push(pattern);
|
||||
const prefix = pattern.source.match(/^([^[]+)/)?.[1] || '';
|
||||
if (prefix) {
|
||||
this.config.replacements.set(prefix, replacement);
|
||||
}
|
||||
}
|
||||
sanitizeWorkflow(workflow) {
|
||||
if (!workflow) {
|
||||
return { sanitized: workflow, wasModified: false };
|
||||
}
|
||||
const original = JSON.stringify(workflow);
|
||||
let sanitized = this.sanitizeObject(workflow);
|
||||
if (sanitized && sanitized.pinData) {
|
||||
delete sanitized.pinData;
|
||||
}
|
||||
if (sanitized && sanitized.executionId) {
|
||||
delete sanitized.executionId;
|
||||
}
|
||||
if (sanitized && sanitized.staticData) {
|
||||
delete sanitized.staticData;
|
||||
}
|
||||
const wasModified = JSON.stringify(sanitized) !== original;
|
||||
return { sanitized, wasModified };
|
||||
}
|
||||
needsSanitization(workflow) {
|
||||
const workflowStr = JSON.stringify(workflow);
|
||||
for (const token of this.config.problematicTokens) {
|
||||
if (workflowStr.includes(token)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (const pattern of this.config.tokenPatterns) {
|
||||
pattern.lastIndex = 0;
|
||||
if (pattern.test(workflowStr)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
detectTokens(workflow) {
|
||||
const workflowStr = JSON.stringify(workflow);
|
||||
const detectedTokens = [];
|
||||
for (const token of this.config.problematicTokens) {
|
||||
if (workflowStr.includes(token)) {
|
||||
detectedTokens.push(token);
|
||||
}
|
||||
}
|
||||
for (const pattern of this.config.tokenPatterns) {
|
||||
pattern.lastIndex = 0;
|
||||
const matches = workflowStr.match(pattern);
|
||||
if (matches) {
|
||||
detectedTokens.push(...matches);
|
||||
}
|
||||
}
|
||||
return [...new Set(detectedTokens)];
|
||||
}
|
||||
sanitizeObject(obj) {
|
||||
if (typeof obj === 'string') {
|
||||
return this.replaceTokens(obj);
|
||||
}
|
||||
else if (Array.isArray(obj)) {
|
||||
return obj.map(item => this.sanitizeObject(item));
|
||||
}
|
||||
else if (obj && typeof obj === 'object') {
|
||||
const result = {};
|
||||
for (const key in obj) {
|
||||
result[key] = this.sanitizeObject(obj[key]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
replaceTokens(str) {
|
||||
let result = str;
|
||||
this.config.problematicTokens.forEach(token => {
|
||||
result = result.replace(new RegExp(token, 'g'), 'YOUR_API_TOKEN_HERE');
|
||||
});
|
||||
this.config.tokenPatterns.forEach(pattern => {
|
||||
result = result.replace(pattern, (match) => {
|
||||
for (const [prefix, replacement] of this.config.replacements) {
|
||||
if (match.startsWith(prefix)) {
|
||||
return replacement;
|
||||
}
|
||||
}
|
||||
return 'YOUR_TOKEN_HERE';
|
||||
});
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
exports.TemplateSanitizer = TemplateSanitizer;
|
||||
//# sourceMappingURL=template-sanitizer.js.map
|
||||
1
dist/utils/template-sanitizer.js.map
vendored
Normal file
1
dist/utils/template-sanitizer.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"template-sanitizer.js","sourceRoot":"","sources":["../../src/utils/template-sanitizer.ts"],"names":[],"mappings":"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"}
|
||||
9
dist/utils/url-detector.d.ts
vendored
Normal file
9
dist/utils/url-detector.d.ts
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
import { Request } from 'express';
|
||||
export declare function detectBaseUrl(req: Request | null, host: string, port: number): string;
|
||||
export declare function getStartupBaseUrl(host: string, port: number): string;
|
||||
export declare function formatEndpointUrls(baseUrl: string): {
|
||||
health: string;
|
||||
mcp: string;
|
||||
root: string;
|
||||
};
|
||||
//# sourceMappingURL=url-detector.d.ts.map
|
||||
1
dist/utils/url-detector.d.ts.map
vendored
Normal file
1
dist/utils/url-detector.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"url-detector.d.ts","sourceRoot":"","sources":["../../src/utils/url-detector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AA8BlC,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAyDrF;AAMD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAEpE;AAKD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG;IACnD,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACd,CAMA"}
|
||||
79
dist/utils/url-detector.js
vendored
Normal file
79
dist/utils/url-detector.js
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.detectBaseUrl = detectBaseUrl;
|
||||
exports.getStartupBaseUrl = getStartupBaseUrl;
|
||||
exports.formatEndpointUrls = formatEndpointUrls;
|
||||
const logger_1 = require("./logger");
|
||||
function isValidHostname(host) {
|
||||
return /^[a-zA-Z0-9.-]+(:[0-9]+)?$/.test(host) && host.length < 256;
|
||||
}
|
||||
function isValidUrl(url) {
|
||||
try {
|
||||
const parsed = new URL(url);
|
||||
return parsed.protocol === 'http:' || parsed.protocol === 'https:';
|
||||
}
|
||||
catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
function detectBaseUrl(req, host, port) {
|
||||
try {
|
||||
const configuredUrl = process.env.BASE_URL || process.env.PUBLIC_URL;
|
||||
if (configuredUrl) {
|
||||
if (isValidUrl(configuredUrl)) {
|
||||
logger_1.logger.debug('Using configured BASE_URL/PUBLIC_URL', { url: configuredUrl });
|
||||
return configuredUrl.replace(/\/$/, '');
|
||||
}
|
||||
else {
|
||||
logger_1.logger.warn('Invalid BASE_URL/PUBLIC_URL configured, falling back to auto-detection', { url: configuredUrl });
|
||||
}
|
||||
}
|
||||
if (req && process.env.TRUST_PROXY && Number(process.env.TRUST_PROXY) > 0) {
|
||||
const proto = req.get('X-Forwarded-Proto') || req.protocol || 'http';
|
||||
const forwardedHost = req.get('X-Forwarded-Host');
|
||||
const hostHeader = req.get('Host');
|
||||
const detectedHost = forwardedHost || hostHeader;
|
||||
if (detectedHost && isValidHostname(detectedHost)) {
|
||||
const baseUrl = `${proto}://${detectedHost}`;
|
||||
logger_1.logger.debug('Detected URL from proxy headers', {
|
||||
proto,
|
||||
forwardedHost,
|
||||
hostHeader,
|
||||
baseUrl
|
||||
});
|
||||
return baseUrl;
|
||||
}
|
||||
else if (detectedHost) {
|
||||
logger_1.logger.warn('Invalid hostname detected in proxy headers, using fallback', { detectedHost });
|
||||
}
|
||||
}
|
||||
const displayHost = host === '0.0.0.0' ? 'localhost' : host;
|
||||
const protocol = 'http';
|
||||
const needsPort = port !== 80;
|
||||
const baseUrl = needsPort ?
|
||||
`${protocol}://${displayHost}:${port}` :
|
||||
`${protocol}://${displayHost}`;
|
||||
logger_1.logger.debug('Using fallback URL from host/port', {
|
||||
host,
|
||||
displayHost,
|
||||
port,
|
||||
baseUrl
|
||||
});
|
||||
return baseUrl;
|
||||
}
|
||||
catch (error) {
|
||||
logger_1.logger.error('Error detecting base URL, using fallback', error);
|
||||
return `http://localhost:${port}`;
|
||||
}
|
||||
}
|
||||
function getStartupBaseUrl(host, port) {
|
||||
return detectBaseUrl(null, host, port);
|
||||
}
|
||||
function formatEndpointUrls(baseUrl) {
|
||||
return {
|
||||
health: `${baseUrl}/health`,
|
||||
mcp: `${baseUrl}/mcp`,
|
||||
root: baseUrl
|
||||
};
|
||||
}
|
||||
//# sourceMappingURL=url-detector.js.map
|
||||
1
dist/utils/url-detector.js.map
vendored
Normal file
1
dist/utils/url-detector.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"url-detector.js","sourceRoot":"","sources":["../../src/utils/url-detector.ts"],"names":[],"mappings":"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"}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user