chore: add pre-built dist folder for npx usage

This commit is contained in:
thesved
2025-12-04 20:22:02 +02:00
committed by Romuald Członkowski
parent a70d96a373
commit 5057481e70
716 changed files with 48021 additions and 0 deletions

3
dist/scripts/debug-http-search.d.ts vendored Normal file
View File

@@ -0,0 +1,3 @@
#!/usr/bin/env npx tsx
export {};
//# sourceMappingURL=debug-http-search.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"debug-http-search.d.ts","sourceRoot":"","sources":["../../src/scripts/debug-http-search.ts"],"names":[],"mappings":""}

57
dist/scripts/debug-http-search.js vendored Normal file
View File

@@ -0,0 +1,57 @@
#!/usr/bin/env npx tsx
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const database_adapter_1 = require("../database/database-adapter");
const node_repository_1 = require("../database/node-repository");
const node_similarity_service_1 = require("../services/node-similarity-service");
const path_1 = __importDefault(require("path"));
async function debugHttpSearch() {
const dbPath = path_1.default.join(process.cwd(), 'data/nodes.db');
const db = await (0, database_adapter_1.createDatabaseAdapter)(dbPath);
const repository = new node_repository_1.NodeRepository(db);
const service = new node_similarity_service_1.NodeSimilarityService(repository);
console.log('Testing "http" search...\n');
const httpNode = repository.getNode('nodes-base.httpRequest');
console.log('HTTP Request node exists:', httpNode ? 'Yes' : 'No');
if (httpNode) {
console.log(' Display name:', httpNode.displayName);
}
const suggestions = await service.findSimilarNodes('http', 5);
console.log('\nSuggestions for "http":', suggestions.length);
suggestions.forEach(s => {
console.log(` - ${s.nodeType} (${Math.round(s.confidence * 100)}%)`);
});
console.log('\nManual score calculation for httpRequest:');
const testNode = {
nodeType: 'nodes-base.httpRequest',
displayName: 'HTTP Request',
category: 'Core Nodes'
};
const cleanInvalid = 'http';
const cleanValid = 'nodesbasehttprequest';
const displayNameClean = 'httprequest';
const hasSubstring = cleanValid.includes(cleanInvalid) || displayNameClean.includes(cleanInvalid);
console.log(` Substring match: ${hasSubstring}`);
const patternScore = hasSubstring ? 35 : 0;
console.log(` Pattern score: ${patternScore}`);
console.log(` Total score would need to be >= 50 to appear`);
const allNodes = repository.getAllNodes();
const httpNodes = allNodes.filter(n => n.nodeType.toLowerCase().includes('http') ||
(n.displayName && n.displayName.toLowerCase().includes('http')));
console.log('\n\nNodes containing "http" in name:');
httpNodes.slice(0, 5).forEach(n => {
console.log(` - ${n.nodeType} (${n.displayName})`);
const normalizedSearch = 'http';
const normalizedType = n.nodeType.toLowerCase().replace(/[^a-z0-9]/g, '');
const normalizedDisplay = (n.displayName || '').toLowerCase().replace(/[^a-z0-9]/g, '');
const containsInType = normalizedType.includes(normalizedSearch);
const containsInDisplay = normalizedDisplay.includes(normalizedSearch);
console.log(` Type check: "${normalizedType}" includes "${normalizedSearch}" = ${containsInType}`);
console.log(` Display check: "${normalizedDisplay}" includes "${normalizedSearch}" = ${containsInDisplay}`);
});
}
debugHttpSearch().catch(console.error);
//# sourceMappingURL=debug-http-search.js.map

1
dist/scripts/debug-http-search.js.map vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"debug-http-search.js","sourceRoot":"","sources":["../../src/scripts/debug-http-search.ts"],"names":[],"mappings":"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"}

3
dist/scripts/extract-from-docker.d.ts vendored Normal file
View File

@@ -0,0 +1,3 @@
#!/usr/bin/env node
export {};
//# sourceMappingURL=extract-from-docker.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"extract-from-docker.d.ts","sourceRoot":"","sources":["../../src/scripts/extract-from-docker.ts"],"names":[],"mappings":""}

210
dist/scripts/extract-from-docker.js vendored Normal file
View File

@@ -0,0 +1,210 @@
#!/usr/bin/env node
"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 });
const dotenv = __importStar(require("dotenv"));
const node_documentation_service_1 = require("../services/node-documentation-service");
const node_source_extractor_1 = require("../utils/node-source-extractor");
const logger_1 = require("../utils/logger");
const fs = __importStar(require("fs/promises"));
const path = __importStar(require("path"));
dotenv.config();
async function extractNodesFromDocker() {
logger_1.logger.info('🐳 Starting Docker-based node extraction...');
const dockerVolumePaths = [
process.env.N8N_MODULES_PATH || '/n8n-modules',
process.env.N8N_CUSTOM_PATH || '/n8n-custom',
];
logger_1.logger.info(`Docker volume paths: ${dockerVolumePaths.join(', ')}`);
for (const volumePath of dockerVolumePaths) {
try {
await fs.access(volumePath);
logger_1.logger.info(`✅ Volume mounted: ${volumePath}`);
const entries = await fs.readdir(volumePath);
logger_1.logger.info(`Contents of ${volumePath}: ${entries.slice(0, 10).join(', ')}${entries.length > 10 ? '...' : ''}`);
}
catch (error) {
logger_1.logger.warn(`❌ Volume not accessible: ${volumePath}`);
}
}
const docService = new node_documentation_service_1.NodeDocumentationService();
const extractor = new node_source_extractor_1.NodeSourceExtractor();
extractor.n8nBasePaths.unshift(...dockerVolumePaths);
logger_1.logger.info('🧹 Clearing existing nodes...');
const db = docService.db;
db.prepare('DELETE FROM nodes').run();
logger_1.logger.info('🔍 Searching for n8n nodes in Docker volumes...');
const n8nPackages = [
'n8n-nodes-base',
'@n8n/n8n-nodes-langchain',
'n8n-nodes-extras',
];
let totalExtracted = 0;
let ifNodeVersion = null;
for (const packageName of n8nPackages) {
logger_1.logger.info(`\n📦 Processing package: ${packageName}`);
try {
let packagePath = null;
for (const volumePath of dockerVolumePaths) {
const possiblePaths = [
path.join(volumePath, packageName),
path.join(volumePath, '.pnpm', `${packageName}@*`, 'node_modules', packageName),
];
for (const testPath of possiblePaths) {
try {
if (testPath.includes('*')) {
const baseDir = path.dirname(testPath.split('*')[0]);
const entries = await fs.readdir(baseDir);
for (const entry of entries) {
if (entry.includes(packageName.replace('/', '+'))) {
const fullPath = path.join(baseDir, entry, 'node_modules', packageName);
try {
await fs.access(fullPath);
packagePath = fullPath;
break;
}
catch { }
}
}
}
else {
await fs.access(testPath);
packagePath = testPath;
break;
}
}
catch { }
}
if (packagePath)
break;
}
if (!packagePath) {
logger_1.logger.warn(`Package ${packageName} not found in Docker volumes`);
continue;
}
logger_1.logger.info(`Found package at: ${packagePath}`);
try {
const packageJsonPath = path.join(packagePath, 'package.json');
const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf-8'));
logger_1.logger.info(`Package version: ${packageJson.version}`);
}
catch { }
const nodesPath = path.join(packagePath, 'dist', 'nodes');
try {
await fs.access(nodesPath);
logger_1.logger.info(`Scanning nodes directory: ${nodesPath}`);
const nodeEntries = await scanForNodes(nodesPath);
logger_1.logger.info(`Found ${nodeEntries.length} nodes in ${packageName}`);
for (const nodeEntry of nodeEntries) {
try {
const nodeName = nodeEntry.name.replace('.node.js', '');
const nodeType = `${packageName}.${nodeName}`;
logger_1.logger.info(`Extracting: ${nodeType}`);
const sourceInfo = await extractor.extractNodeSource(nodeType);
if (nodeName === 'If') {
const versionMatch = sourceInfo.sourceCode.match(/version:\s*(\d+)/);
if (versionMatch) {
ifNodeVersion = versionMatch[1];
logger_1.logger.info(`📍 Found If node version: ${ifNodeVersion}`);
}
}
await docService.storeNode({
nodeType: nodeType,
name: nodeName,
displayName: nodeName,
description: `${nodeName} node from ${packageName}`,
sourceCode: sourceInfo.sourceCode,
credentialCode: sourceInfo.credentialCode,
packageName: packageName,
version: ifNodeVersion || '1',
hasCredentials: !!sourceInfo.credentialCode,
isTrigger: sourceInfo.sourceCode.includes('trigger: true') || nodeName.toLowerCase().includes('trigger'),
isWebhook: sourceInfo.sourceCode.includes('webhook: true') || nodeName.toLowerCase().includes('webhook'),
});
totalExtracted++;
}
catch (error) {
logger_1.logger.error(`Failed to extract ${nodeEntry.name}: ${error}`);
}
}
}
catch (error) {
logger_1.logger.error(`Failed to scan nodes directory: ${error}`);
}
}
catch (error) {
logger_1.logger.error(`Failed to process package ${packageName}: ${error}`);
}
}
logger_1.logger.info(`\n✅ Extraction complete!`);
logger_1.logger.info(`📊 Total nodes extracted: ${totalExtracted}`);
if (ifNodeVersion) {
logger_1.logger.info(`📍 If node version: ${ifNodeVersion}`);
if (ifNodeVersion === '2' || ifNodeVersion === '2.2') {
logger_1.logger.info('✅ Successfully extracted latest If node (v2+)!');
}
else {
logger_1.logger.warn(`⚠️ If node version is ${ifNodeVersion}, expected v2 or higher`);
}
}
await docService.close();
}
async function scanForNodes(dirPath) {
const nodes = [];
async function scan(currentPath) {
try {
const entries = await fs.readdir(currentPath, { withFileTypes: true });
for (const entry of entries) {
const fullPath = path.join(currentPath, entry.name);
if (entry.isFile() && entry.name.endsWith('.node.js')) {
nodes.push({ name: entry.name, path: fullPath });
}
else if (entry.isDirectory() && entry.name !== 'node_modules') {
await scan(fullPath);
}
}
}
catch (error) {
logger_1.logger.debug(`Failed to scan directory ${currentPath}: ${error}`);
}
}
await scan(dirPath);
return nodes;
}
extractNodesFromDocker().catch(error => {
logger_1.logger.error('Extraction failed:', error);
process.exit(1);
});
//# sourceMappingURL=extract-from-docker.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,4 @@
#!/usr/bin/env node
declare function fetchTemplatesRobust(): Promise<void>;
export { fetchTemplatesRobust };
//# sourceMappingURL=fetch-templates-robust.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"fetch-templates-robust.d.ts","sourceRoot":"","sources":["../../src/scripts/fetch-templates-robust.ts"],"names":[],"mappings":";AAOA,iBAAe,oBAAoB,kBAwHlC;AAOD,OAAO,EAAE,oBAAoB,EAAE,CAAC"}

132
dist/scripts/fetch-templates-robust.js vendored Normal file
View File

@@ -0,0 +1,132 @@
#!/usr/bin/env node
"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.fetchTemplatesRobust = fetchTemplatesRobust;
const database_adapter_1 = require("../database/database-adapter");
const template_repository_1 = require("../templates/template-repository");
const template_fetcher_1 = require("../templates/template-fetcher");
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
async function fetchTemplatesRobust() {
console.log('🌐 Fetching n8n workflow templates (last year)...\n');
const dataDir = './data';
if (!fs.existsSync(dataDir)) {
fs.mkdirSync(dataDir, { recursive: true });
}
const db = await (0, database_adapter_1.createDatabaseAdapter)('./data/nodes.db');
try {
db.exec('DROP TABLE IF EXISTS templates');
db.exec('DROP TABLE IF EXISTS templates_fts');
console.log('🗑️ Dropped existing templates tables\n');
}
catch (error) {
}
const schema = fs.readFileSync(path.join(__dirname, '../../src/database/schema.sql'), 'utf8');
db.exec(schema);
const repository = new template_repository_1.TemplateRepository(db);
const fetcher = new template_fetcher_1.TemplateFetcher();
let lastMessage = '';
const startTime = Date.now();
try {
console.log('📋 Phase 1: Fetching template list from n8n.io API\n');
const templates = await fetcher.fetchTemplates((current, total) => {
if (lastMessage) {
process.stdout.write('\r' + ' '.repeat(lastMessage.length) + '\r');
}
const progress = Math.round((current / total) * 100);
lastMessage = `📊 Fetching template list: ${current}/${total} (${progress}%)`;
process.stdout.write(lastMessage);
});
console.log('\n');
console.log(`✅ Found ${templates.length} templates from last year\n`);
console.log('📥 Phase 2: Fetching details and saving to database\n');
let saved = 0;
let errors = 0;
for (let i = 0; i < templates.length; i++) {
const template = templates[i];
try {
if (lastMessage) {
process.stdout.write('\r' + ' '.repeat(lastMessage.length) + '\r');
}
const progress = Math.round(((i + 1) / templates.length) * 100);
lastMessage = `📊 Processing: ${i + 1}/${templates.length} (${progress}%) - Saved: ${saved}, Errors: ${errors}`;
process.stdout.write(lastMessage);
const detail = await fetcher.fetchTemplateDetail(template.id);
if (detail !== null) {
repository.saveTemplate(template, detail);
saved++;
}
else {
errors++;
console.error(`\n❌ Failed to fetch template ${template.id} (${template.name}) after retries`);
}
await new Promise(resolve => setTimeout(resolve, 200));
}
catch (error) {
errors++;
console.error(`\n❌ Error processing template ${template.id} (${template.name}): ${error.message}`);
}
}
console.log('\n');
const elapsed = Math.round((Date.now() - startTime) / 1000);
const stats = await repository.getTemplateStats();
console.log('✅ Template fetch complete!\n');
console.log('📈 Statistics:');
console.log(` - Templates found: ${templates.length}`);
console.log(` - Templates saved: ${saved}`);
console.log(` - Errors: ${errors}`);
console.log(` - Success rate: ${Math.round((saved / templates.length) * 100)}%`);
console.log(` - Time elapsed: ${elapsed} seconds`);
console.log(` - Average time per template: ${(elapsed / saved).toFixed(2)} seconds`);
if (stats.topUsedNodes && stats.topUsedNodes.length > 0) {
console.log('\n🔝 Top used nodes:');
stats.topUsedNodes.slice(0, 10).forEach((node, index) => {
console.log(` ${index + 1}. ${node.node} (${node.count} templates)`);
});
}
}
catch (error) {
console.error('\n❌ Fatal error:', error);
process.exit(1);
}
if ('close' in db && typeof db.close === 'function') {
db.close();
}
}
if (require.main === module) {
fetchTemplatesRobust().catch(console.error);
}
//# sourceMappingURL=fetch-templates-robust.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"fetch-templates-robust.js","sourceRoot":"","sources":["../../src/scripts/fetch-templates-robust.ts"],"names":[],"mappings":"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"}

4
dist/scripts/fetch-templates.d.ts vendored Normal file
View File

@@ -0,0 +1,4 @@
#!/usr/bin/env node
declare function fetchTemplates(mode?: 'rebuild' | 'update', generateMetadata?: boolean, metadataOnly?: boolean, extractOnly?: boolean): Promise<void>;
export { fetchTemplates };
//# sourceMappingURL=fetch-templates.d.ts.map

1
dist/scripts/fetch-templates.d.ts.map vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"fetch-templates.d.ts","sourceRoot":"","sources":["../../src/scripts/fetch-templates.ts"],"names":[],"mappings":";AA4LA,iBAAe,cAAc,CAC3B,IAAI,GAAE,SAAS,GAAG,QAAoB,EACtC,gBAAgB,GAAE,OAAe,EACjC,YAAY,GAAE,OAAe,EAC7B,WAAW,GAAE,OAAe,iBAgL7B;AA6KD,OAAO,EAAE,cAAc,EAAE,CAAC"}

411
dist/scripts/fetch-templates.js vendored Normal file
View File

@@ -0,0 +1,411 @@
#!/usr/bin/env node
"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.fetchTemplates = fetchTemplates;
const database_adapter_1 = require("../database/database-adapter");
const template_service_1 = require("../templates/template-service");
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const zlib = __importStar(require("zlib"));
const dotenv = __importStar(require("dotenv"));
dotenv.config();
function extractNodeConfigs(templateId, templateName, templateViews, workflowCompressed, metadata) {
try {
const decompressed = zlib.gunzipSync(Buffer.from(workflowCompressed, 'base64'));
const workflow = JSON.parse(decompressed.toString('utf-8'));
const configs = [];
for (const node of workflow.nodes || []) {
if (node.type.includes('stickyNote') || !node.parameters) {
continue;
}
configs.push({
node_type: node.type,
template_id: templateId,
template_name: templateName,
template_views: templateViews,
node_name: node.name,
parameters_json: JSON.stringify(node.parameters),
credentials_json: node.credentials ? JSON.stringify(node.credentials) : null,
has_credentials: node.credentials ? 1 : 0,
has_expressions: detectExpressions(node.parameters) ? 1 : 0,
complexity: metadata?.complexity || 'medium',
use_cases: JSON.stringify(metadata?.use_cases || [])
});
}
return configs;
}
catch (error) {
console.error(`Error extracting configs from template ${templateId}:`, error);
return [];
}
}
function detectExpressions(params) {
if (!params)
return false;
const json = JSON.stringify(params);
return json.includes('={{') || json.includes('$json') || json.includes('$node');
}
function insertAndRankConfigs(db, configs) {
if (configs.length === 0) {
console.log('No configs to insert');
return;
}
const templateIds = [...new Set(configs.map(c => c.template_id))];
const placeholders = templateIds.map(() => '?').join(',');
db.prepare(`DELETE FROM template_node_configs WHERE template_id IN (${placeholders})`).run(...templateIds);
const insertStmt = db.prepare(`
INSERT INTO template_node_configs (
node_type, template_id, template_name, template_views,
node_name, parameters_json, credentials_json,
has_credentials, has_expressions, complexity, use_cases
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`);
for (const config of configs) {
insertStmt.run(config.node_type, config.template_id, config.template_name, config.template_views, config.node_name, config.parameters_json, config.credentials_json, config.has_credentials, config.has_expressions, config.complexity, config.use_cases);
}
db.exec(`
UPDATE template_node_configs
SET rank = (
SELECT COUNT(*) + 1
FROM template_node_configs AS t2
WHERE t2.node_type = template_node_configs.node_type
AND t2.template_views > template_node_configs.template_views
)
`);
db.exec(`
DELETE FROM template_node_configs
WHERE id NOT IN (
SELECT id FROM template_node_configs
WHERE rank <= 10
ORDER BY node_type, rank
)
`);
console.log(`✅ Extracted and ranked ${configs.length} node configurations`);
}
async function extractTemplateConfigs(db, service) {
console.log('📦 Extracting node configurations from templates...');
const repository = service.repository;
const allTemplates = repository.getAllTemplates();
const allConfigs = [];
let configsExtracted = 0;
for (const template of allTemplates) {
if (template.workflow_json_compressed) {
const metadata = template.metadata_json ? JSON.parse(template.metadata_json) : null;
const configs = extractNodeConfigs(template.id, template.name, template.views, template.workflow_json_compressed, metadata);
allConfigs.push(...configs);
configsExtracted += configs.length;
}
}
if (allConfigs.length > 0) {
insertAndRankConfigs(db, allConfigs);
const configStats = db.prepare(`
SELECT
COUNT(DISTINCT node_type) as node_types,
COUNT(*) as total_configs,
AVG(rank) as avg_rank
FROM template_node_configs
`).get();
console.log(`📊 Node config stats:`);
console.log(` - Unique node types: ${configStats.node_types}`);
console.log(` - Total configs stored: ${configStats.total_configs}`);
console.log(` - Average rank: ${configStats.avg_rank?.toFixed(1) || 'N/A'}`);
}
else {
console.log('⚠️ No node configurations extracted');
}
}
async function fetchTemplates(mode = 'rebuild', generateMetadata = false, metadataOnly = false, extractOnly = false) {
if (extractOnly) {
console.log('📦 Extract-only mode: Extracting node configurations from existing templates...\n');
const db = await (0, database_adapter_1.createDatabaseAdapter)('./data/nodes.db');
try {
const tableExists = db.prepare(`
SELECT name FROM sqlite_master
WHERE type='table' AND name='template_node_configs'
`).get();
if (!tableExists) {
console.log('📋 Creating template_node_configs table...');
const migrationPath = path.join(__dirname, '../../src/database/migrations/add-template-node-configs.sql');
const migration = fs.readFileSync(migrationPath, 'utf8');
db.exec(migration);
console.log('✅ Table created successfully\n');
}
}
catch (error) {
console.error('❌ Error checking/creating template_node_configs table:', error);
if ('close' in db && typeof db.close === 'function') {
db.close();
}
process.exit(1);
}
const service = new template_service_1.TemplateService(db);
await extractTemplateConfigs(db, service);
if ('close' in db && typeof db.close === 'function') {
db.close();
}
return;
}
if (metadataOnly) {
console.log('🤖 Metadata-only mode: Generating metadata for existing templates...\n');
if (!process.env.OPENAI_API_KEY) {
console.error('❌ OPENAI_API_KEY not set in environment');
process.exit(1);
}
const db = await (0, database_adapter_1.createDatabaseAdapter)('./data/nodes.db');
const service = new template_service_1.TemplateService(db);
await generateTemplateMetadata(db, service);
if ('close' in db && typeof db.close === 'function') {
db.close();
}
return;
}
const modeEmoji = mode === 'rebuild' ? '🔄' : '⬆️';
const modeText = mode === 'rebuild' ? 'Rebuilding' : 'Updating';
console.log(`${modeEmoji} ${modeText} n8n workflow templates...\n`);
if (generateMetadata) {
console.log('🤖 Metadata generation enabled (using OpenAI)\n');
}
const dataDir = './data';
if (!fs.existsSync(dataDir)) {
fs.mkdirSync(dataDir, { recursive: true });
}
const db = await (0, database_adapter_1.createDatabaseAdapter)('./data/nodes.db');
if (mode === 'rebuild') {
try {
db.exec('DROP TABLE IF EXISTS templates');
db.exec('DROP TABLE IF EXISTS templates_fts');
console.log('🗑️ Dropped existing templates tables (rebuild mode)\n');
const schema = fs.readFileSync(path.join(__dirname, '../../src/database/schema.sql'), 'utf8');
db.exec(schema);
console.log('📋 Applied database schema\n');
}
catch (error) {
console.error('❌ Error setting up database schema:', error);
throw error;
}
}
else {
console.log('📊 Update mode: Keeping existing templates and schema\n');
try {
const columns = db.prepare("PRAGMA table_info(templates)").all();
const hasMetadataColumn = columns.some((col) => col.name === 'metadata_json');
if (!hasMetadataColumn) {
console.log('📋 Adding metadata columns to existing schema...');
db.exec(`
ALTER TABLE templates ADD COLUMN metadata_json TEXT;
ALTER TABLE templates ADD COLUMN metadata_generated_at DATETIME;
`);
console.log('✅ Metadata columns added\n');
}
}
catch (error) {
console.log('📋 Schema is up to date\n');
}
}
const service = new template_service_1.TemplateService(db);
let lastMessage = '';
const startTime = Date.now();
try {
await service.fetchAndUpdateTemplates((message, current, total) => {
if (lastMessage) {
process.stdout.write('\r' + ' '.repeat(lastMessage.length) + '\r');
}
const progress = total > 0 ? Math.round((current / total) * 100) : 0;
lastMessage = `📊 ${message}: ${current}/${total} (${progress}%)`;
process.stdout.write(lastMessage);
}, mode);
console.log('\n');
const stats = await service.getTemplateStats();
const elapsed = Math.round((Date.now() - startTime) / 1000);
console.log('✅ Template fetch complete!\n');
console.log('📈 Statistics:');
console.log(` - Total templates: ${stats.totalTemplates}`);
console.log(` - Average views: ${stats.averageViews}`);
console.log(` - Time elapsed: ${elapsed} seconds`);
console.log('\n🔝 Top used nodes:');
stats.topUsedNodes.forEach((node, index) => {
console.log(` ${index + 1}. ${node.node} (${node.count} templates)`);
});
console.log('');
await extractTemplateConfigs(db, service);
if (generateMetadata && process.env.OPENAI_API_KEY) {
console.log('\n🤖 Generating metadata for templates...');
await generateTemplateMetadata(db, service);
}
else if (generateMetadata && !process.env.OPENAI_API_KEY) {
console.log('\n⚠ Metadata generation requested but OPENAI_API_KEY not set');
}
}
catch (error) {
console.error('\n❌ Error fetching templates:', error);
process.exit(1);
}
if ('close' in db && typeof db.close === 'function') {
db.close();
}
}
async function generateTemplateMetadata(db, service) {
try {
const { BatchProcessor } = await Promise.resolve().then(() => __importStar(require('../templates/batch-processor')));
const repository = service.repository;
const limit = parseInt(process.env.METADATA_LIMIT || '0');
const templatesWithoutMetadata = limit > 0
? repository.getTemplatesWithoutMetadata(limit)
: repository.getTemplatesWithoutMetadata(999999);
if (templatesWithoutMetadata.length === 0) {
console.log('✅ All templates already have metadata');
return;
}
console.log(`Found ${templatesWithoutMetadata.length} templates without metadata`);
const batchSize = parseInt(process.env.OPENAI_BATCH_SIZE || '50');
console.log(`Processing in batches of ${batchSize} templates each`);
if (batchSize > 100) {
console.log(`⚠️ Large batch size (${batchSize}) may take longer to process`);
console.log(` Consider using OPENAI_BATCH_SIZE=50 for faster results`);
}
const processor = new BatchProcessor({
apiKey: process.env.OPENAI_API_KEY,
model: process.env.OPENAI_MODEL || 'gpt-4o-mini',
batchSize: batchSize,
outputDir: './temp/batch'
});
const requests = templatesWithoutMetadata.map((t) => {
let workflow = undefined;
try {
if (t.workflow_json_compressed) {
const decompressed = zlib.gunzipSync(Buffer.from(t.workflow_json_compressed, 'base64'));
workflow = JSON.parse(decompressed.toString());
}
else if (t.workflow_json) {
workflow = JSON.parse(t.workflow_json);
}
}
catch (error) {
console.warn(`Failed to parse workflow for template ${t.id}:`, error);
}
let nodes = [];
try {
if (t.nodes_used) {
nodes = JSON.parse(t.nodes_used);
if (!Array.isArray(nodes)) {
console.warn(`Template ${t.id} has invalid nodes_used (not an array), using empty array`);
nodes = [];
}
}
}
catch (error) {
console.warn(`Failed to parse nodes_used for template ${t.id}:`, error);
nodes = [];
}
return {
templateId: t.id,
name: t.name,
description: t.description,
nodes: nodes,
workflow
};
});
const results = await processor.processTemplates(requests, (message, current, total) => {
process.stdout.write(`\r📊 ${message}: ${current}/${total}`);
});
console.log('\n');
const metadataMap = new Map();
for (const [templateId, result] of results) {
if (!result.error) {
metadataMap.set(templateId, result.metadata);
}
}
if (metadataMap.size > 0) {
repository.batchUpdateMetadata(metadataMap);
console.log(`✅ Updated metadata for ${metadataMap.size} templates`);
}
const stats = repository.getMetadataStats();
console.log('\n📈 Metadata Statistics:');
console.log(` - Total templates: ${stats.total}`);
console.log(` - With metadata: ${stats.withMetadata}`);
console.log(` - Without metadata: ${stats.withoutMetadata}`);
console.log(` - Outdated (>30 days): ${stats.outdated}`);
}
catch (error) {
console.error('\n❌ Error generating metadata:', error);
}
}
function parseArgs() {
const args = process.argv.slice(2);
let mode = 'rebuild';
let generateMetadata = false;
let metadataOnly = false;
let extractOnly = false;
const modeIndex = args.findIndex(arg => arg.startsWith('--mode'));
if (modeIndex !== -1) {
const modeArg = args[modeIndex];
const modeValue = modeArg.includes('=') ? modeArg.split('=')[1] : args[modeIndex + 1];
if (modeValue === 'update') {
mode = 'update';
}
}
if (args.includes('--update')) {
mode = 'update';
}
if (args.includes('--generate-metadata') || args.includes('--metadata')) {
generateMetadata = true;
}
if (args.includes('--metadata-only')) {
metadataOnly = true;
}
if (args.includes('--extract-only') || args.includes('--extract')) {
extractOnly = true;
}
if (args.includes('--help') || args.includes('-h')) {
console.log('Usage: npm run fetch:templates [options]\n');
console.log('Options:');
console.log(' --mode=rebuild|update Rebuild from scratch or update existing (default: rebuild)');
console.log(' --update Shorthand for --mode=update');
console.log(' --generate-metadata Generate AI metadata after fetching templates');
console.log(' --metadata Shorthand for --generate-metadata');
console.log(' --metadata-only Only generate metadata, skip template fetching');
console.log(' --extract-only Only extract node configs, skip template fetching');
console.log(' --extract Shorthand for --extract-only');
console.log(' --help, -h Show this help message');
process.exit(0);
}
return { mode, generateMetadata, metadataOnly, extractOnly };
}
if (require.main === module) {
const { mode, generateMetadata, metadataOnly, extractOnly } = parseArgs();
fetchTemplates(mode, generateMetadata, metadataOnly, extractOnly).catch(console.error);
}
//# sourceMappingURL=fetch-templates.js.map

1
dist/scripts/fetch-templates.js.map vendored Normal file

File diff suppressed because one or more lines are too long

4
dist/scripts/rebuild-database.d.ts vendored Normal file
View File

@@ -0,0 +1,4 @@
#!/usr/bin/env node
declare function rebuildDocumentationDatabase(): Promise<void>;
export { rebuildDocumentationDatabase };
//# sourceMappingURL=rebuild-database.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"rebuild-database.d.ts","sourceRoot":"","sources":["../../src/scripts/rebuild-database.ts"],"names":[],"mappings":";AAYA,iBAAe,4BAA4B,kBA4D1C;AAUD,OAAO,EAAE,4BAA4B,EAAE,CAAC"}

95
dist/scripts/rebuild-database.js vendored Normal file
View File

@@ -0,0 +1,95 @@
#!/usr/bin/env node
"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.rebuildDocumentationDatabase = rebuildDocumentationDatabase;
const dotenv = __importStar(require("dotenv"));
const node_documentation_service_1 = require("../services/node-documentation-service");
dotenv.config();
async function rebuildDocumentationDatabase() {
console.log('🔄 Starting enhanced documentation database rebuild...\n');
const startTime = Date.now();
const service = new node_documentation_service_1.NodeDocumentationService();
try {
const results = await service.rebuildDatabase();
const duration = ((Date.now() - startTime) / 1000).toFixed(2);
console.log('\n✅ Enhanced documentation database rebuild completed!\n');
console.log('📊 Results:');
console.log(` Total nodes found: ${results.total}`);
console.log(` Successfully processed: ${results.successful}`);
console.log(` Failed: ${results.failed}`);
console.log(` Duration: ${duration}s`);
if (results.errors.length > 0) {
console.log(`\n⚠️ First ${Math.min(5, results.errors.length)} errors:`);
results.errors.slice(0, 5).forEach(err => {
console.log(` - ${err}`);
});
if (results.errors.length > 5) {
console.log(` ... and ${results.errors.length - 5} more errors`);
}
}
const stats = await service.getStatistics();
console.log('\n📈 Database Statistics:');
console.log(` Total nodes: ${stats.totalNodes}`);
console.log(` Nodes with documentation: ${stats.nodesWithDocs}`);
console.log(` Nodes with examples: ${stats.nodesWithExamples}`);
console.log(` Nodes with credentials: ${stats.nodesWithCredentials}`);
console.log(` Trigger nodes: ${stats.triggerNodes}`);
console.log(` Webhook nodes: ${stats.webhookNodes}`);
console.log('\n📦 Package distribution:');
stats.packageDistribution.slice(0, 10).forEach((pkg) => {
console.log(` ${pkg.package}: ${pkg.count} nodes`);
});
await service.close();
console.log('\n✨ Enhanced documentation database is ready!');
console.log('💡 The database now includes:');
console.log(' - Complete node source code');
console.log(' - Enhanced documentation with operations and API methods');
console.log(' - Code examples and templates');
console.log(' - Related resources and required scopes');
}
catch (error) {
console.error('\n❌ Documentation database rebuild failed:', error);
service.close();
process.exit(1);
}
}
if (require.main === module) {
rebuildDocumentationDatabase().catch(error => {
console.error('Fatal error:', error);
process.exit(1);
});
}
//# sourceMappingURL=rebuild-database.js.map

1
dist/scripts/rebuild-database.js.map vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"rebuild-database.js","sourceRoot":"","sources":["../../src/scripts/rebuild-database.ts"],"names":[],"mappings":"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"}

3
dist/scripts/rebuild-optimized.d.ts vendored Normal file
View File

@@ -0,0 +1,3 @@
#!/usr/bin/env node
export {};
//# sourceMappingURL=rebuild-optimized.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"rebuild-optimized.d.ts","sourceRoot":"","sources":["../../src/scripts/rebuild-optimized.ts"],"names":[],"mappings":""}

198
dist/scripts/rebuild-optimized.js vendored Normal file
View File

@@ -0,0 +1,198 @@
#!/usr/bin/env node
"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 });
const database_adapter_1 = require("../database/database-adapter");
const node_loader_1 = require("../loaders/node-loader");
const node_parser_1 = require("../parsers/node-parser");
const docs_mapper_1 = require("../mappers/docs-mapper");
const node_repository_1 = require("../database/node-repository");
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
async function extractNodeSource(NodeClass, packageName, nodeName) {
try {
const possiblePaths = [
`${packageName}/dist/nodes/${nodeName}.node.js`,
`${packageName}/dist/nodes/${nodeName}/${nodeName}.node.js`,
`${packageName}/nodes/${nodeName}.node.js`,
`${packageName}/nodes/${nodeName}/${nodeName}.node.js`
];
let nodeFilePath = null;
let nodeSourceCode = '// Source code not found';
for (const path of possiblePaths) {
try {
nodeFilePath = require.resolve(path);
nodeSourceCode = await fs.promises.readFile(nodeFilePath, 'utf8');
break;
}
catch (e) {
}
}
if (nodeSourceCode === '// Source code not found' && NodeClass.toString) {
nodeSourceCode = `// Extracted from NodeClass\n${NodeClass.toString()}`;
nodeFilePath = 'extracted-from-class';
}
let credentialSourceCode;
try {
const credName = nodeName.replace(/Node$/, '');
const credentialPaths = [
`${packageName}/dist/credentials/${credName}.credentials.js`,
`${packageName}/dist/credentials/${credName}/${credName}.credentials.js`,
`${packageName}/credentials/${credName}.credentials.js`
];
for (const path of credentialPaths) {
try {
const credFilePath = require.resolve(path);
credentialSourceCode = await fs.promises.readFile(credFilePath, 'utf8');
break;
}
catch (e) {
}
}
}
catch (error) {
}
return {
nodeSourceCode,
credentialSourceCode,
sourceLocation: nodeFilePath || 'unknown'
};
}
catch (error) {
console.warn(`Could not extract source for ${nodeName}: ${error.message}`);
return {
nodeSourceCode: '// Source code extraction failed',
sourceLocation: 'unknown'
};
}
}
async function rebuildOptimized() {
console.log('🔄 Building optimized n8n node database with embedded source code...\n');
const dbPath = process.env.BUILD_DB_PATH || './data/nodes.db';
const db = await (0, database_adapter_1.createDatabaseAdapter)(dbPath);
const loader = new node_loader_1.N8nNodeLoader();
const parser = new node_parser_1.NodeParser();
const mapper = new docs_mapper_1.DocsMapper();
const repository = new node_repository_1.NodeRepository(db);
const schemaPath = path.join(__dirname, '../../src/database/schema-optimized.sql');
const schema = fs.readFileSync(schemaPath, 'utf8');
db.exec(schema);
db.exec('DELETE FROM nodes');
console.log('🗑️ Cleared existing data\n');
const nodes = await loader.loadAllNodes();
console.log(`📦 Loaded ${nodes.length} nodes from packages\n`);
const stats = {
successful: 0,
failed: 0,
aiTools: 0,
triggers: 0,
webhooks: 0,
withProperties: 0,
withOperations: 0,
withDocs: 0,
withSource: 0
};
for (const { packageName, nodeName, NodeClass } of nodes) {
try {
const parsed = parser.parse(NodeClass, packageName);
if (!parsed.nodeType || !parsed.displayName) {
throw new Error('Missing required fields');
}
const docs = await mapper.fetchDocumentation(parsed.nodeType);
parsed.documentation = docs || undefined;
console.log(`📄 Extracting source code for ${parsed.nodeType}...`);
const sourceInfo = await extractNodeSource(NodeClass, packageName, nodeName);
const nodeData = {
...parsed,
developmentStyle: parsed.style,
credentialsRequired: parsed.credentials || [],
nodeSourceCode: sourceInfo.nodeSourceCode,
credentialSourceCode: sourceInfo.credentialSourceCode,
sourceLocation: sourceInfo.sourceLocation,
sourceExtractedAt: new Date().toISOString()
};
const stmt = db.prepare(`
INSERT INTO nodes (
node_type, package_name, display_name, description, category,
development_style, is_ai_tool, is_trigger, is_webhook, is_versioned,
version, documentation, properties_schema, operations, credentials_required,
node_source_code, credential_source_code, source_location, source_extracted_at
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`);
stmt.run(nodeData.nodeType, nodeData.packageName, nodeData.displayName, nodeData.description, nodeData.category, nodeData.developmentStyle, nodeData.isAITool ? 1 : 0, nodeData.isTrigger ? 1 : 0, nodeData.isWebhook ? 1 : 0, nodeData.isVersioned ? 1 : 0, nodeData.version, nodeData.documentation, JSON.stringify(nodeData.properties), JSON.stringify(nodeData.operations), JSON.stringify(nodeData.credentialsRequired), nodeData.nodeSourceCode, nodeData.credentialSourceCode, nodeData.sourceLocation, nodeData.sourceExtractedAt);
stats.successful++;
if (parsed.isAITool)
stats.aiTools++;
if (parsed.isTrigger)
stats.triggers++;
if (parsed.isWebhook)
stats.webhooks++;
if (parsed.properties.length > 0)
stats.withProperties++;
if (parsed.operations.length > 0)
stats.withOperations++;
if (docs)
stats.withDocs++;
if (sourceInfo.nodeSourceCode !== '// Source code extraction failed')
stats.withSource++;
console.log(`${parsed.nodeType} [Props: ${parsed.properties.length}, Ops: ${parsed.operations.length}, Source: ${sourceInfo.nodeSourceCode.length} bytes]`);
}
catch (error) {
stats.failed++;
console.error(`❌ Failed to process ${nodeName}: ${error.message}`);
}
}
console.log('\n🔍 Building full-text search index...');
db.exec('INSERT INTO nodes_fts(nodes_fts) VALUES("rebuild")');
console.log('\n📊 Summary:');
console.log(` Total nodes: ${nodes.length}`);
console.log(` Successful: ${stats.successful}`);
console.log(` Failed: ${stats.failed}`);
console.log(` AI Tools: ${stats.aiTools}`);
console.log(` Triggers: ${stats.triggers}`);
console.log(` Webhooks: ${stats.webhooks}`);
console.log(` With Properties: ${stats.withProperties}`);
console.log(` With Operations: ${stats.withOperations}`);
console.log(` With Documentation: ${stats.withDocs}`);
console.log(` With Source Code: ${stats.withSource}`);
const dbStats = db.prepare('SELECT page_count * page_size as size FROM pragma_page_count(), pragma_page_size()').get();
console.log(`\n💾 Database size: ${(dbStats.size / 1024 / 1024).toFixed(2)} MB`);
console.log('\n✨ Optimized rebuild complete!');
db.close();
}
if (require.main === module) {
rebuildOptimized().catch(console.error);
}
//# sourceMappingURL=rebuild-optimized.js.map

1
dist/scripts/rebuild-optimized.js.map vendored Normal file

File diff suppressed because one or more lines are too long

3
dist/scripts/rebuild.d.ts vendored Normal file
View File

@@ -0,0 +1,3 @@
#!/usr/bin/env node
export {};
//# sourceMappingURL=rebuild.d.ts.map

1
dist/scripts/rebuild.d.ts.map vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"rebuild.d.ts","sourceRoot":"","sources":["../../src/scripts/rebuild.ts"],"names":[],"mappings":""}

234
dist/scripts/rebuild.js vendored Normal file
View File

@@ -0,0 +1,234 @@
#!/usr/bin/env node
"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 });
const database_adapter_1 = require("../database/database-adapter");
const node_loader_1 = require("../loaders/node-loader");
const node_parser_1 = require("../parsers/node-parser");
const docs_mapper_1 = require("../mappers/docs-mapper");
const node_repository_1 = require("../database/node-repository");
const template_sanitizer_1 = require("../utils/template-sanitizer");
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
async function rebuild() {
console.log('🔄 Rebuilding n8n node database...\n');
const dbPath = process.env.NODE_DB_PATH || './data/nodes.db';
const db = await (0, database_adapter_1.createDatabaseAdapter)(dbPath);
const loader = new node_loader_1.N8nNodeLoader();
const parser = new node_parser_1.NodeParser();
const mapper = new docs_mapper_1.DocsMapper();
const repository = new node_repository_1.NodeRepository(db);
const schema = fs.readFileSync(path.join(__dirname, '../../src/database/schema.sql'), 'utf8');
db.exec(schema);
db.exec('DELETE FROM nodes');
console.log('🗑️ Cleared existing data\n');
const nodes = await loader.loadAllNodes();
console.log(`📦 Loaded ${nodes.length} nodes from packages\n`);
const stats = {
successful: 0,
failed: 0,
aiTools: 0,
triggers: 0,
webhooks: 0,
withProperties: 0,
withOperations: 0,
withDocs: 0
};
console.log('🔄 Processing nodes...');
const processedNodes = [];
for (const { packageName, nodeName, NodeClass } of nodes) {
try {
const parsed = parser.parse(NodeClass, packageName);
if (!parsed.nodeType || !parsed.displayName) {
throw new Error(`Missing required fields - nodeType: ${parsed.nodeType}, displayName: ${parsed.displayName}, packageName: ${parsed.packageName}`);
}
if (!parsed.packageName) {
throw new Error(`Missing packageName for node ${nodeName}`);
}
const docs = await mapper.fetchDocumentation(parsed.nodeType);
parsed.documentation = docs || undefined;
processedNodes.push({ parsed, docs: docs || undefined, nodeName });
}
catch (error) {
stats.failed++;
const errorMessage = error.message;
console.error(`❌ Failed to process ${nodeName}: ${errorMessage}`);
}
}
console.log(`\n💾 Saving ${processedNodes.length} processed nodes to database...`);
let saved = 0;
for (const { parsed, docs, nodeName } of processedNodes) {
try {
repository.saveNode(parsed);
saved++;
stats.successful++;
if (parsed.isAITool)
stats.aiTools++;
if (parsed.isTrigger)
stats.triggers++;
if (parsed.isWebhook)
stats.webhooks++;
if (parsed.properties.length > 0)
stats.withProperties++;
if (parsed.operations.length > 0)
stats.withOperations++;
if (docs)
stats.withDocs++;
console.log(`${parsed.nodeType} [Props: ${parsed.properties.length}, Ops: ${parsed.operations.length}]`);
}
catch (error) {
stats.failed++;
const errorMessage = error.message;
console.error(`❌ Failed to save ${nodeName}: ${errorMessage}`);
}
}
console.log(`💾 Save completed: ${saved} nodes saved successfully`);
console.log('\n🔍 Running validation checks...');
try {
const validationResults = validateDatabase(repository);
if (!validationResults.passed) {
console.log('⚠️ Validation Issues:');
validationResults.issues.forEach(issue => console.log(` - ${issue}`));
}
else {
console.log('✅ All validation checks passed');
}
}
catch (validationError) {
console.error('❌ Validation failed:', validationError.message);
console.log('⚠️ Skipping validation due to database compatibility issues');
}
console.log('\n📊 Summary:');
console.log(` Total nodes: ${nodes.length}`);
console.log(` Successful: ${stats.successful}`);
console.log(` Failed: ${stats.failed}`);
console.log(` AI Tools: ${stats.aiTools}`);
console.log(` Triggers: ${stats.triggers}`);
console.log(` Webhooks: ${stats.webhooks}`);
console.log(` With Properties: ${stats.withProperties}`);
console.log(` With Operations: ${stats.withOperations}`);
console.log(` With Documentation: ${stats.withDocs}`);
console.log('\n🧹 Checking for templates to sanitize...');
const templateCount = db.prepare('SELECT COUNT(*) as count FROM templates').get();
if (templateCount && templateCount.count > 0) {
console.log(` Found ${templateCount.count} templates, sanitizing...`);
const sanitizer = new template_sanitizer_1.TemplateSanitizer();
let sanitizedCount = 0;
const templates = db.prepare('SELECT id, name, workflow_json FROM templates').all();
for (const template of templates) {
const originalWorkflow = JSON.parse(template.workflow_json);
const { sanitized: sanitizedWorkflow, wasModified } = sanitizer.sanitizeWorkflow(originalWorkflow);
if (wasModified) {
const stmt = db.prepare('UPDATE templates SET workflow_json = ? WHERE id = ?');
stmt.run(JSON.stringify(sanitizedWorkflow), template.id);
sanitizedCount++;
console.log(` ✅ Sanitized template ${template.id}: ${template.name}`);
}
}
console.log(` Sanitization complete: ${sanitizedCount} templates cleaned`);
}
else {
console.log(' No templates found in database');
}
console.log('\n✨ Rebuild complete!');
db.close();
}
function validateDatabase(repository) {
const issues = [];
try {
const db = repository.db;
const nodeCount = db.prepare('SELECT COUNT(*) as count FROM nodes').get();
if (nodeCount.count === 0) {
issues.push('CRITICAL: Database is empty - no nodes found! Rebuild failed or was interrupted.');
return { passed: false, issues };
}
if (nodeCount.count < 500) {
issues.push(`WARNING: Only ${nodeCount.count} nodes found - expected at least 500 (both n8n packages)`);
}
const criticalNodes = ['nodes-base.httpRequest', 'nodes-base.code', 'nodes-base.webhook', 'nodes-base.slack'];
for (const nodeType of criticalNodes) {
const node = repository.getNode(nodeType);
if (!node) {
issues.push(`Critical node ${nodeType} not found`);
continue;
}
if (node.properties.length === 0) {
issues.push(`Node ${nodeType} has no properties`);
}
}
const aiTools = repository.getAITools();
if (aiTools.length === 0) {
issues.push('No AI tools found - check detection logic');
}
const ftsTableCheck = db.prepare(`
SELECT name FROM sqlite_master
WHERE type='table' AND name='nodes_fts'
`).get();
if (!ftsTableCheck) {
issues.push('CRITICAL: FTS5 table (nodes_fts) does not exist - searches will fail or be very slow');
}
else {
const ftsCount = db.prepare('SELECT COUNT(*) as count FROM nodes_fts').get();
if (ftsCount.count === 0) {
issues.push('CRITICAL: FTS5 index is empty - searches will return zero results');
}
else if (nodeCount.count !== ftsCount.count) {
issues.push(`FTS5 index out of sync: ${nodeCount.count} nodes but ${ftsCount.count} FTS5 entries`);
}
const searchableNodes = ['webhook', 'merge', 'split'];
for (const searchTerm of searchableNodes) {
const searchResult = db.prepare(`
SELECT COUNT(*) as count FROM nodes_fts
WHERE nodes_fts MATCH ?
`).get(searchTerm);
if (searchResult.count === 0) {
issues.push(`CRITICAL: Search for "${searchTerm}" returns zero results in FTS5 index`);
}
}
}
}
catch (error) {
const errorMessage = error.message;
issues.push(`Validation error: ${errorMessage}`);
}
return {
passed: issues.length === 0,
issues
};
}
if (require.main === module) {
rebuild().catch(console.error);
}
//# sourceMappingURL=rebuild.js.map

1
dist/scripts/rebuild.js.map vendored Normal file

File diff suppressed because one or more lines are too long

3
dist/scripts/sanitize-templates.d.ts vendored Normal file
View File

@@ -0,0 +1,3 @@
#!/usr/bin/env node
export {};
//# sourceMappingURL=sanitize-templates.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"sanitize-templates.d.ts","sourceRoot":"","sources":["../../src/scripts/sanitize-templates.ts"],"names":[],"mappings":""}

88
dist/scripts/sanitize-templates.js vendored Normal file
View File

@@ -0,0 +1,88 @@
#!/usr/bin/env node
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const database_adapter_1 = require("../database/database-adapter");
const template_sanitizer_1 = require("../utils/template-sanitizer");
const zlib_1 = require("zlib");
async function sanitizeTemplates() {
console.log('🧹 Sanitizing workflow templates in database...\n');
const db = await (0, database_adapter_1.createDatabaseAdapter)('./data/nodes.db');
const sanitizer = new template_sanitizer_1.TemplateSanitizer();
try {
const templates = db.prepare('SELECT id, name, workflow_json, workflow_json_compressed FROM templates').all();
console.log(`Found ${templates.length} templates to check\n`);
let sanitizedCount = 0;
const problematicTemplates = [];
for (const template of templates) {
let originalWorkflow = null;
let useCompressed = false;
if (template.workflow_json_compressed) {
try {
const buffer = Buffer.from(template.workflow_json_compressed, 'base64');
const decompressed = (0, zlib_1.gunzipSync)(buffer).toString('utf-8');
originalWorkflow = JSON.parse(decompressed);
useCompressed = true;
}
catch (e) {
console.log(`⚠️ Failed to decompress template ${template.id}, trying uncompressed`);
}
}
if (!originalWorkflow && template.workflow_json) {
try {
originalWorkflow = JSON.parse(template.workflow_json);
}
catch (e) {
console.log(`⚠️ Skipping template ${template.id}: Invalid JSON in both formats`);
continue;
}
}
if (!originalWorkflow) {
continue;
}
const { sanitized: sanitizedWorkflow, wasModified } = sanitizer.sanitizeWorkflow(originalWorkflow);
if (wasModified) {
const detectedTokens = sanitizer.detectTokens(originalWorkflow);
if (useCompressed) {
const compressed = (0, zlib_1.gzipSync)(JSON.stringify(sanitizedWorkflow)).toString('base64');
const stmt = db.prepare('UPDATE templates SET workflow_json_compressed = ? WHERE id = ?');
stmt.run(compressed, template.id);
}
else {
const stmt = db.prepare('UPDATE templates SET workflow_json = ? WHERE id = ?');
stmt.run(JSON.stringify(sanitizedWorkflow), template.id);
}
sanitizedCount++;
problematicTemplates.push({
id: template.id,
name: template.name,
tokens: detectedTokens
});
console.log(`✅ Sanitized template ${template.id}: ${template.name}`);
detectedTokens.forEach(token => {
console.log(` - Found: ${token.substring(0, 20)}...`);
});
}
}
console.log(`\n📊 Summary:`);
console.log(` Total templates: ${templates.length}`);
console.log(` Sanitized: ${sanitizedCount}`);
if (problematicTemplates.length > 0) {
console.log(`\n⚠️ Templates that contained API tokens:`);
problematicTemplates.forEach(t => {
console.log(` - ${t.id}: ${t.name}`);
});
}
console.log('\n✨ Sanitization complete!');
}
catch (error) {
console.error('❌ Error sanitizing templates:', error);
process.exit(1);
}
finally {
db.close();
}
}
if (require.main === module) {
sanitizeTemplates().catch(console.error);
}
//# sourceMappingURL=sanitize-templates.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"sanitize-templates.js","sourceRoot":"","sources":["../../src/scripts/sanitize-templates.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,4 @@
#!/usr/bin/env node
declare function seedCanonicalExamples(): Promise<void>;
export { seedCanonicalExamples };
//# sourceMappingURL=seed-canonical-ai-examples.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"seed-canonical-ai-examples.d.ts","sourceRoot":"","sources":["../../src/scripts/seed-canonical-ai-examples.ts"],"names":[],"mappings":";AAmCA,iBAAe,qBAAqB,kBAsHnC;AAOD,OAAO,EAAE,qBAAqB,EAAE,CAAC"}

View File

@@ -0,0 +1,121 @@
#!/usr/bin/env node
"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.seedCanonicalExamples = seedCanonicalExamples;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const database_adapter_1 = require("../database/database-adapter");
const logger_1 = require("../utils/logger");
async function seedCanonicalExamples() {
try {
const examplesPath = path.join(__dirname, '../data/canonical-ai-tool-examples.json');
const examplesData = fs.readFileSync(examplesPath, 'utf-8');
const canonicalExamples = JSON.parse(examplesData);
logger_1.logger.info('Loading canonical AI tool examples', {
version: canonicalExamples.version,
tools: canonicalExamples.examples.length
});
const db = await (0, database_adapter_1.createDatabaseAdapter)('./data/nodes.db');
const templateStmt = db.prepare(`
INSERT OR IGNORE INTO templates (
id,
workflow_id,
name,
description,
views,
created_at,
updated_at
) VALUES (?, ?, ?, ?, ?, datetime('now'), datetime('now'))
`);
const canonicalTemplateId = -1000;
templateStmt.run(canonicalTemplateId, canonicalTemplateId, 'Canonical AI Tool Examples', 'Hand-crafted examples demonstrating best practices for AI tools', 99999);
const stmt = db.prepare(`
INSERT OR REPLACE INTO template_node_configs (
node_type,
template_id,
template_name,
template_views,
node_name,
parameters_json,
credentials_json,
has_credentials,
has_expressions,
complexity,
use_cases
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`);
let totalInserted = 0;
for (const toolExamples of canonicalExamples.examples) {
const { node_type, display_name, examples } = toolExamples;
logger_1.logger.info(`Seeding examples for ${display_name}`, {
nodeType: node_type,
exampleCount: examples.length
});
for (let i = 0; i < examples.length; i++) {
const example = examples[i];
const templateId = canonicalTemplateId;
const templateName = `Canonical: ${display_name} - ${example.name}`;
const paramsStr = JSON.stringify(example.parameters);
const hasExpressions = paramsStr.includes('={{') || paramsStr.includes('$json') || paramsStr.includes('$node') ? 1 : 0;
stmt.run(node_type, templateId, templateName, 99999, example.name, JSON.stringify(example.parameters), example.credentials ? JSON.stringify(example.credentials) : null, example.credentials ? 1 : 0, hasExpressions, example.complexity, example.use_case);
totalInserted++;
logger_1.logger.info(` ✓ Seeded: ${example.name}`, {
complexity: example.complexity,
hasCredentials: !!example.credentials,
hasExpressions: hasExpressions === 1
});
}
}
db.close();
logger_1.logger.info('Canonical examples seeding complete', {
totalExamples: totalInserted,
tools: canonicalExamples.examples.length
});
console.log('\n✅ Successfully seeded', totalInserted, 'canonical AI tool examples');
console.log('\nExamples are now available via:');
console.log(' • search_nodes({query: "HTTP Request Tool", includeExamples: true})');
console.log(' • get_node_essentials({nodeType: "nodes-langchain.toolCode", includeExamples: true})');
}
catch (error) {
logger_1.logger.error('Failed to seed canonical examples', { error });
console.error('❌ Error:', error);
process.exit(1);
}
}
if (require.main === module) {
seedCanonicalExamples().catch(console.error);
}
//# sourceMappingURL=seed-canonical-ai-examples.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"seed-canonical-ai-examples.js","sourceRoot":"","sources":["../../src/scripts/seed-canonical-ai-examples.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,3 @@
#!/usr/bin/env npx tsx
export {};
//# sourceMappingURL=test-autofix-documentation.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"test-autofix-documentation.d.ts","sourceRoot":"","sources":["../../src/scripts/test-autofix-documentation.ts"],"names":[],"mappings":""}

View File

@@ -0,0 +1,103 @@
#!/usr/bin/env npx tsx
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tool_docs_1 = require("../mcp/tool-docs");
const tools_documentation_1 = require("../mcp/tools-documentation");
const logger_1 = require("../utils/logger");
const logger = new logger_1.Logger({ prefix: '[AutofixDoc Test]' });
async function testAutofixDocumentation() {
logger.info('Testing n8n_autofix_workflow documentation...\n');
logger.info('Test 1: Checking documentation registry');
const hasDoc = 'n8n_autofix_workflow' in tool_docs_1.toolsDocumentation;
if (hasDoc) {
logger.info('✅ Documentation found in registry');
}
else {
logger.error('❌ Documentation NOT found in registry');
logger.info('Available tools:', Object.keys(tool_docs_1.toolsDocumentation).filter(k => k.includes('autofix')));
}
if (hasDoc) {
logger.info('\nTest 2: Checking documentation structure');
const doc = tool_docs_1.toolsDocumentation['n8n_autofix_workflow'];
const hasEssentials = doc.essentials &&
doc.essentials.description &&
doc.essentials.keyParameters &&
doc.essentials.example;
const hasFull = doc.full &&
doc.full.description &&
doc.full.parameters &&
doc.full.examples;
if (hasEssentials) {
logger.info('✅ Essentials documentation complete');
logger.info(` Description: ${doc.essentials.description.substring(0, 80)}...`);
logger.info(` Key params: ${doc.essentials.keyParameters.join(', ')}`);
}
else {
logger.error('❌ Essentials documentation incomplete');
}
if (hasFull) {
logger.info('✅ Full documentation complete');
logger.info(` Parameters: ${Object.keys(doc.full.parameters).join(', ')}`);
logger.info(` Examples: ${doc.full.examples.length} provided`);
}
else {
logger.error('❌ Full documentation incomplete');
}
}
logger.info('\nTest 3: Testing getToolDocumentation function');
try {
const essentialsDoc = (0, tools_documentation_1.getToolDocumentation)('n8n_autofix_workflow', 'essentials');
if (essentialsDoc.includes("Tool 'n8n_autofix_workflow' not found")) {
logger.error('❌ Essentials documentation retrieval failed');
}
else {
logger.info('✅ Essentials documentation retrieved');
const lines = essentialsDoc.split('\n').slice(0, 3);
lines.forEach(line => logger.info(` ${line}`));
}
}
catch (error) {
logger.error('❌ Error retrieving essentials documentation:', error);
}
try {
const fullDoc = (0, tools_documentation_1.getToolDocumentation)('n8n_autofix_workflow', 'full');
if (fullDoc.includes("Tool 'n8n_autofix_workflow' not found")) {
logger.error('❌ Full documentation retrieval failed');
}
else {
logger.info('✅ Full documentation retrieved');
const lines = fullDoc.split('\n').slice(0, 3);
lines.forEach(line => logger.info(` ${line}`));
}
}
catch (error) {
logger.error('❌ Error retrieving full documentation:', error);
}
logger.info('\nTest 4: Checking workflow management tools listing');
const workflowTools = Object.keys(tool_docs_1.toolsDocumentation).filter(k => k.startsWith('n8n_'));
const hasAutofix = workflowTools.includes('n8n_autofix_workflow');
if (hasAutofix) {
logger.info('✅ n8n_autofix_workflow is listed in workflow management tools');
logger.info(` Total workflow tools: ${workflowTools.length}`);
const relatedTools = workflowTools.filter(t => t.includes('validate') || t.includes('update') || t.includes('fix'));
logger.info(` Related tools: ${relatedTools.join(', ')}`);
}
else {
logger.error('❌ n8n_autofix_workflow NOT listed in workflow management tools');
}
logger.info('\n' + '='.repeat(60));
logger.info('Summary:');
if (hasDoc && hasAutofix) {
logger.info('✨ Documentation integration successful!');
logger.info('The n8n_autofix_workflow tool documentation is properly integrated.');
logger.info('\nTo use in MCP:');
logger.info(' - Essentials: tools_documentation({topic: "n8n_autofix_workflow"})');
logger.info(' - Full: tools_documentation({topic: "n8n_autofix_workflow", depth: "full"})');
}
else {
logger.error('⚠️ Documentation integration incomplete');
logger.info('Please check the implementation and rebuild the project.');
}
}
testAutofixDocumentation().catch(console.error);
//# sourceMappingURL=test-autofix-documentation.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"test-autofix-documentation.js","sourceRoot":"","sources":["../../src/scripts/test-autofix-documentation.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,2 @@
export {};
//# sourceMappingURL=test-autofix-workflow.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"test-autofix-workflow.d.ts","sourceRoot":"","sources":["../../src/scripts/test-autofix-workflow.ts"],"names":[],"mappings":""}

223
dist/scripts/test-autofix-workflow.js vendored Normal file
View File

@@ -0,0 +1,223 @@
"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 });
const workflow_auto_fixer_1 = require("../services/workflow-auto-fixer");
const workflow_validator_1 = require("../services/workflow-validator");
const enhanced_config_validator_1 = require("../services/enhanced-config-validator");
const expression_format_validator_1 = require("../services/expression-format-validator");
const node_repository_1 = require("../database/node-repository");
const logger_1 = require("../utils/logger");
const database_adapter_1 = require("../database/database-adapter");
const path = __importStar(require("path"));
const logger = new logger_1.Logger({ prefix: '[TestAutofix]' });
async function testAutofix() {
const dbPath = path.join(__dirname, '../../data/nodes.db');
const dbAdapter = await (0, database_adapter_1.createDatabaseAdapter)(dbPath);
const repository = new node_repository_1.NodeRepository(dbAdapter);
const testWorkflow = {
id: 'test_workflow_1',
name: 'Test Workflow for Autofix',
nodes: [
{
id: 'webhook_1',
name: 'Webhook',
type: 'n8n-nodes-base.webhook',
typeVersion: 1.1,
position: [250, 300],
parameters: {
httpMethod: 'GET',
path: 'test-webhook',
responseMode: 'onReceived',
responseData: 'firstEntryJson'
}
},
{
id: 'http_1',
name: 'HTTP Request',
type: 'n8n-nodes-base.httpRequest',
typeVersion: 5.0,
position: [450, 300],
parameters: {
method: 'GET',
url: '{{ $json.webhookUrl }}',
sendHeaders: true,
headerParameters: {
parameters: [
{
name: 'Authorization',
value: '{{ $json.token }}'
}
]
}
},
onError: 'continueErrorOutput'
},
{
id: 'set_1',
name: 'Set',
type: 'n8n-nodes-base.set',
typeVersion: 3.5,
position: [650, 300],
parameters: {
mode: 'manual',
duplicateItem: false,
values: {
values: [
{
name: 'status',
value: '{{ $json.success }}'
}
]
}
}
}
],
connections: {
'Webhook': {
main: [
[
{
node: 'HTTP Request',
type: 'main',
index: 0
}
]
]
},
'HTTP Request': {
main: [
[
{
node: 'Set',
type: 'main',
index: 0
}
]
]
}
}
};
logger.info('=== Testing Workflow Auto-Fixer ===\n');
logger.info('Step 1: Validating workflow to identify issues...');
const validator = new workflow_validator_1.WorkflowValidator(repository, enhanced_config_validator_1.EnhancedConfigValidator);
const validationResult = await validator.validateWorkflow(testWorkflow, {
validateNodes: true,
validateConnections: true,
validateExpressions: true,
profile: 'ai-friendly'
});
logger.info(`Found ${validationResult.errors.length} errors and ${validationResult.warnings.length} warnings`);
logger.info('\nStep 2: Checking for expression format issues...');
const allFormatIssues = [];
for (const node of testWorkflow.nodes) {
const formatContext = {
nodeType: node.type,
nodeName: node.name,
nodeId: node.id
};
const nodeFormatIssues = expression_format_validator_1.ExpressionFormatValidator.validateNodeParameters(node.parameters, formatContext);
const enrichedIssues = nodeFormatIssues.map(issue => ({
...issue,
nodeName: node.name,
nodeId: node.id
}));
allFormatIssues.push(...enrichedIssues);
}
logger.info(`Found ${allFormatIssues.length} expression format issues`);
if (allFormatIssues.length > 0) {
logger.info('\nExpression format issues found:');
for (const issue of allFormatIssues) {
logger.info(` - ${issue.fieldPath}: ${issue.issueType} (${issue.severity})`);
logger.info(` Current: ${JSON.stringify(issue.currentValue)}`);
logger.info(` Fixed: ${JSON.stringify(issue.correctedValue)}`);
}
}
logger.info('\nStep 3: Generating fixes (preview mode)...');
const autoFixer = new workflow_auto_fixer_1.WorkflowAutoFixer();
const previewResult = await autoFixer.generateFixes(testWorkflow, validationResult, allFormatIssues, {
applyFixes: false,
confidenceThreshold: 'medium'
});
logger.info(`\nGenerated ${previewResult.fixes.length} fixes:`);
logger.info(`Summary: ${previewResult.summary}`);
logger.info('\nFixes by type:');
for (const [type, count] of Object.entries(previewResult.stats.byType)) {
if (count > 0) {
logger.info(` - ${type}: ${count}`);
}
}
logger.info('\nFixes by confidence:');
for (const [confidence, count] of Object.entries(previewResult.stats.byConfidence)) {
if (count > 0) {
logger.info(` - ${confidence}: ${count}`);
}
}
logger.info('\nDetailed fixes:');
for (const fix of previewResult.fixes) {
logger.info(`\n[${fix.confidence.toUpperCase()}] ${fix.node}.${fix.field} (${fix.type})`);
logger.info(` Before: ${JSON.stringify(fix.before)}`);
logger.info(` After: ${JSON.stringify(fix.after)}`);
logger.info(` Description: ${fix.description}`);
}
logger.info('\n\nGenerated diff operations:');
for (const op of previewResult.operations) {
logger.info(`\nOperation: ${op.type}`);
logger.info(` Details: ${JSON.stringify(op, null, 2)}`);
}
logger.info('\n\n=== Testing Different Confidence Thresholds ===');
for (const threshold of ['high', 'medium', 'low']) {
const result = await autoFixer.generateFixes(testWorkflow, validationResult, allFormatIssues, {
applyFixes: false,
confidenceThreshold: threshold
});
logger.info(`\nThreshold "${threshold}": ${result.fixes.length} fixes`);
}
logger.info('\n\n=== Testing Specific Fix Types ===');
const fixTypes = ['expression-format', 'typeversion-correction', 'error-output-config'];
for (const fixType of fixTypes) {
const result = await autoFixer.generateFixes(testWorkflow, validationResult, allFormatIssues, {
applyFixes: false,
fixTypes: [fixType]
});
logger.info(`\nFix type "${fixType}": ${result.fixes.length} fixes`);
}
logger.info('\n\n✅ Autofix test completed successfully!');
await dbAdapter.close();
}
testAutofix().catch(error => {
logger.error('Test failed:', error);
process.exit(1);
});
//# sourceMappingURL=test-autofix-workflow.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,3 @@
#!/usr/bin/env node
export {};
//# sourceMappingURL=test-execution-filtering.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"test-execution-filtering.d.ts","sourceRoot":"","sources":["../../src/scripts/test-execution-filtering.ts"],"names":[],"mappings":""}

206
dist/scripts/test-execution-filtering.js vendored Normal file
View File

@@ -0,0 +1,206 @@
#!/usr/bin/env node
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const execution_processor_1 = require("../services/execution-processor");
const n8n_api_1 = require("../types/n8n-api");
console.log('='.repeat(80));
console.log('Execution Filtering Feature - Manual Test Suite');
console.log('='.repeat(80));
console.log('');
function createTestExecution(itemCount) {
const items = Array.from({ length: itemCount }, (_, i) => ({
json: {
id: i + 1,
name: `Item ${i + 1}`,
email: `user${i}@example.com`,
value: Math.random() * 1000,
metadata: {
createdAt: new Date().toISOString(),
tags: ['tag1', 'tag2'],
},
},
}));
return {
id: `test-exec-${Date.now()}`,
workflowId: 'workflow-test',
status: n8n_api_1.ExecutionStatus.SUCCESS,
mode: 'manual',
finished: true,
startedAt: '2024-01-01T10:00:00.000Z',
stoppedAt: '2024-01-01T10:00:05.000Z',
data: {
resultData: {
runData: {
'HTTP Request': [
{
startTime: Date.now(),
executionTime: 234,
data: {
main: [items],
},
},
],
'Filter': [
{
startTime: Date.now(),
executionTime: 45,
data: {
main: [items.slice(0, Math.floor(itemCount / 2))],
},
},
],
'Set': [
{
startTime: Date.now(),
executionTime: 12,
data: {
main: [items.slice(0, 5)],
},
},
],
},
},
},
};
}
console.log('📊 TEST 1: Preview Mode (No Data, Just Structure)');
console.log('-'.repeat(80));
const execution1 = createTestExecution(50);
const { preview, recommendation } = (0, execution_processor_1.generatePreview)(execution1);
console.log('Preview:', JSON.stringify(preview, null, 2));
console.log('\nRecommendation:', JSON.stringify(recommendation, null, 2));
console.log('\n✅ Preview mode shows structure without consuming tokens for data\n');
console.log('📝 TEST 2: Summary Mode (2 items per node)');
console.log('-'.repeat(80));
const execution2 = createTestExecution(50);
const summaryResult = (0, execution_processor_1.filterExecutionData)(execution2, { mode: 'summary' });
console.log('Summary Mode Result:');
console.log('- Mode:', summaryResult.mode);
console.log('- Summary:', JSON.stringify(summaryResult.summary, null, 2));
console.log('- HTTP Request items shown:', summaryResult.nodes?.['HTTP Request']?.data?.metadata.itemsShown);
console.log('- HTTP Request truncated:', summaryResult.nodes?.['HTTP Request']?.data?.metadata.truncated);
console.log('\n✅ Summary mode returns 2 items per node (safe default)\n');
console.log('🎯 TEST 3: Filtered Mode (Custom itemsLimit: 5)');
console.log('-'.repeat(80));
const execution3 = createTestExecution(100);
const filteredResult = (0, execution_processor_1.filterExecutionData)(execution3, {
mode: 'filtered',
itemsLimit: 5,
});
console.log('Filtered Mode Result:');
console.log('- Items shown per node:', filteredResult.nodes?.['HTTP Request']?.data?.metadata.itemsShown);
console.log('- Total items available:', filteredResult.nodes?.['HTTP Request']?.data?.metadata.totalItems);
console.log('- More data available:', filteredResult.summary?.hasMoreData);
console.log('\n✅ Filtered mode allows custom item limits\n');
console.log('🔍 TEST 4: Filter to Specific Nodes');
console.log('-'.repeat(80));
const execution4 = createTestExecution(30);
const nodeFilterResult = (0, execution_processor_1.filterExecutionData)(execution4, {
mode: 'filtered',
nodeNames: ['HTTP Request'],
itemsLimit: 3,
});
console.log('Node Filter Result:');
console.log('- Nodes in result:', Object.keys(nodeFilterResult.nodes || {}));
console.log('- Expected: ["HTTP Request"]');
console.log('- Executed nodes:', nodeFilterResult.summary?.executedNodes);
console.log('- Total nodes:', nodeFilterResult.summary?.totalNodes);
console.log('\n✅ Can filter to specific nodes only\n');
console.log('🏗️ TEST 5: Structure-Only Mode (itemsLimit: 0)');
console.log('-'.repeat(80));
const execution5 = createTestExecution(100);
const structureResult = (0, execution_processor_1.filterExecutionData)(execution5, {
mode: 'filtered',
itemsLimit: 0,
});
console.log('Structure-Only Result:');
console.log('- Items shown:', structureResult.nodes?.['HTTP Request']?.data?.metadata.itemsShown);
console.log('- First item (structure):', JSON.stringify(structureResult.nodes?.['HTTP Request']?.data?.output?.[0]?.[0], null, 2));
console.log('\n✅ Structure-only mode shows data shape without values\n');
console.log('💾 TEST 6: Full Mode (All Data)');
console.log('-'.repeat(80));
const execution6 = createTestExecution(5);
const fullResult = (0, execution_processor_1.filterExecutionData)(execution6, { mode: 'full' });
console.log('Full Mode Result:');
console.log('- Items shown:', fullResult.nodes?.['HTTP Request']?.data?.metadata.itemsShown);
console.log('- Total items:', fullResult.nodes?.['HTTP Request']?.data?.metadata.totalItems);
console.log('- Truncated:', fullResult.nodes?.['HTTP Request']?.data?.metadata.truncated);
console.log('\n✅ Full mode returns all data (use with caution)\n');
console.log('🔄 TEST 7: Backward Compatibility (No Filtering)');
console.log('-'.repeat(80));
const execution7 = createTestExecution(10);
const legacyResult = (0, execution_processor_1.processExecution)(execution7, {});
console.log('Legacy Result:');
console.log('- Returns original execution:', legacyResult === execution7);
console.log('- Type:', typeof legacyResult);
console.log('\n✅ Backward compatible - no options returns original execution\n');
console.log('🔗 TEST 8: Include Input Data');
console.log('-'.repeat(80));
const execution8 = createTestExecution(5);
const inputDataResult = (0, execution_processor_1.filterExecutionData)(execution8, {
mode: 'filtered',
itemsLimit: 2,
includeInputData: true,
});
console.log('Input Data Result:');
console.log('- Has input data:', !!inputDataResult.nodes?.['HTTP Request']?.data?.input);
console.log('- Has output data:', !!inputDataResult.nodes?.['HTTP Request']?.data?.output);
console.log('\n✅ Can include input data for debugging\n');
console.log('⚠️ TEST 9: itemsLimit Validation');
console.log('-'.repeat(80));
const execution9 = createTestExecution(50);
const negativeResult = (0, execution_processor_1.filterExecutionData)(execution9, {
mode: 'filtered',
itemsLimit: -5,
});
console.log('- Negative itemsLimit (-5) handled:', negativeResult.nodes?.['HTTP Request']?.data?.metadata.itemsShown === 2);
const largeResult = (0, execution_processor_1.filterExecutionData)(execution9, {
mode: 'filtered',
itemsLimit: 999999,
});
console.log('- Large itemsLimit (999999) capped:', (largeResult.nodes?.['HTTP Request']?.data?.metadata.itemsShown || 0) <= 1000);
const unlimitedResult = (0, execution_processor_1.filterExecutionData)(execution9, {
mode: 'filtered',
itemsLimit: -1,
});
console.log('- Unlimited itemsLimit (-1) works:', unlimitedResult.nodes?.['HTTP Request']?.data?.metadata.itemsShown === 50);
console.log('\n✅ itemsLimit validation works correctly\n');
console.log('🎯 TEST 10: Follow Recommendation Workflow');
console.log('-'.repeat(80));
const execution10 = createTestExecution(100);
const { preview: preview10, recommendation: rec10 } = (0, execution_processor_1.generatePreview)(execution10);
console.log('1. Preview shows:', {
totalItems: preview10.nodes['HTTP Request']?.itemCounts.output,
sizeKB: preview10.estimatedSizeKB,
});
console.log('\n2. Recommendation:', {
canFetchFull: rec10.canFetchFull,
suggestedMode: rec10.suggestedMode,
suggestedItemsLimit: rec10.suggestedItemsLimit,
reason: rec10.reason,
});
const options = {
mode: rec10.suggestedMode,
itemsLimit: rec10.suggestedItemsLimit,
};
const recommendedResult = (0, execution_processor_1.filterExecutionData)(execution10, options);
console.log('\n3. Following recommendation gives:', {
mode: recommendedResult.mode,
itemsShown: recommendedResult.nodes?.['HTTP Request']?.data?.metadata.itemsShown,
hasMoreData: recommendedResult.summary?.hasMoreData,
});
console.log('\n✅ Recommendation workflow helps make optimal choices\n');
console.log('='.repeat(80));
console.log('✨ All Tests Completed Successfully!');
console.log('='.repeat(80));
console.log('\n🎉 Execution Filtering Feature is Working!\n');
console.log('Key Takeaways:');
console.log('1. Always use preview mode first for unknown datasets');
console.log('2. Follow the recommendation for optimal token usage');
console.log('3. Use nodeNames to filter to relevant nodes');
console.log('4. itemsLimit: 0 shows structure without data');
console.log('5. itemsLimit: -1 returns unlimited items (use with caution)');
console.log('6. Summary mode (2 items) is a safe default');
console.log('7. Full mode should only be used for small datasets');
console.log('');
//# sourceMappingURL=test-execution-filtering.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,3 @@
#!/usr/bin/env npx tsx
export {};
//# sourceMappingURL=test-node-suggestions.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"test-node-suggestions.d.ts","sourceRoot":"","sources":["../../src/scripts/test-node-suggestions.ts"],"names":[],"mappings":""}

165
dist/scripts/test-node-suggestions.js vendored Normal file
View File

@@ -0,0 +1,165 @@
#!/usr/bin/env npx tsx
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const database_adapter_1 = require("../database/database-adapter");
const node_repository_1 = require("../database/node-repository");
const node_similarity_service_1 = require("../services/node-similarity-service");
const workflow_validator_1 = require("../services/workflow-validator");
const enhanced_config_validator_1 = require("../services/enhanced-config-validator");
const workflow_auto_fixer_1 = require("../services/workflow-auto-fixer");
const logger_1 = require("../utils/logger");
const path_1 = __importDefault(require("path"));
const logger = new logger_1.Logger({ prefix: '[NodeSuggestions Test]' });
const console = {
log: (msg) => logger.info(msg),
error: (msg, err) => logger.error(msg, err)
};
async function testNodeSimilarity() {
console.log('🔍 Testing Enhanced Node Type Suggestions\n');
const dbPath = path_1.default.join(process.cwd(), 'data/nodes.db');
const db = await (0, database_adapter_1.createDatabaseAdapter)(dbPath);
const repository = new node_repository_1.NodeRepository(db);
const similarityService = new node_similarity_service_1.NodeSimilarityService(repository);
const validator = new workflow_validator_1.WorkflowValidator(repository, enhanced_config_validator_1.EnhancedConfigValidator);
const testCases = [
{ invalid: 'HttpRequest', expected: 'nodes-base.httpRequest' },
{ invalid: 'HTTPRequest', expected: 'nodes-base.httpRequest' },
{ invalid: 'Webhook', expected: 'nodes-base.webhook' },
{ invalid: 'WebHook', expected: 'nodes-base.webhook' },
{ invalid: 'slack', expected: 'nodes-base.slack' },
{ invalid: 'googleSheets', expected: 'nodes-base.googleSheets' },
{ invalid: 'telegram', expected: 'nodes-base.telegram' },
{ invalid: 'htpRequest', expected: 'nodes-base.httpRequest' },
{ invalid: 'webook', expected: 'nodes-base.webhook' },
{ invalid: 'slak', expected: 'nodes-base.slack' },
{ invalid: 'http', expected: 'nodes-base.httpRequest' },
{ invalid: 'sheet', expected: 'nodes-base.googleSheets' },
{ invalid: 'nodes-base.openai', expected: 'nodes-langchain.openAi' },
{ invalid: 'n8n-nodes-base.httpRequest', expected: 'nodes-base.httpRequest' },
{ invalid: 'foobar', expected: null },
{ invalid: 'xyz123', expected: null },
];
console.log('Testing individual node type suggestions:');
console.log('='.repeat(60));
for (const testCase of testCases) {
const suggestions = await similarityService.findSimilarNodes(testCase.invalid, 3);
console.log(`\n❌ Invalid type: "${testCase.invalid}"`);
if (suggestions.length > 0) {
console.log('✨ Suggestions:');
for (const suggestion of suggestions) {
const confidence = Math.round(suggestion.confidence * 100);
const marker = suggestion.nodeType === testCase.expected ? '✅' : ' ';
console.log(`${marker} ${suggestion.nodeType} (${confidence}% match) - ${suggestion.reason}`);
if (suggestion.confidence >= 0.9) {
console.log(' 💡 Can be auto-fixed!');
}
}
if (testCase.expected) {
const found = suggestions.some(s => s.nodeType === testCase.expected);
if (!found) {
console.log(` ⚠️ Expected "${testCase.expected}" was not suggested!`);
}
}
}
else {
console.log(' No suggestions found');
if (testCase.expected) {
console.log(` ⚠️ Expected "${testCase.expected}" was not suggested!`);
}
}
}
console.log('\n' + '='.repeat(60));
console.log('\n📋 Testing workflow validation with unknown nodes:');
console.log('='.repeat(60));
const testWorkflow = {
id: 'test-workflow',
name: 'Test Workflow',
nodes: [
{
id: '1',
name: 'Start',
type: 'nodes-base.manualTrigger',
position: [100, 100],
parameters: {},
typeVersion: 1
},
{
id: '2',
name: 'HTTP Request',
type: 'HTTPRequest',
position: [300, 100],
parameters: {},
typeVersion: 1
},
{
id: '3',
name: 'Slack',
type: 'slack',
position: [500, 100],
parameters: {},
typeVersion: 1
},
{
id: '4',
name: 'Unknown',
type: 'foobar',
position: [700, 100],
parameters: {},
typeVersion: 1
}
],
connections: {
'Start': {
main: [[{ node: 'HTTP Request', type: 'main', index: 0 }]]
},
'HTTP Request': {
main: [[{ node: 'Slack', type: 'main', index: 0 }]]
},
'Slack': {
main: [[{ node: 'Unknown', type: 'main', index: 0 }]]
}
},
settings: {}
};
const validationResult = await validator.validateWorkflow(testWorkflow, {
validateNodes: true,
validateConnections: false,
validateExpressions: false,
profile: 'runtime'
});
console.log('\nValidation Results:');
for (const error of validationResult.errors) {
if (error.message?.includes('Unknown node type:')) {
console.log(`\n🔴 ${error.nodeName}: ${error.message}`);
}
}
console.log('\n' + '='.repeat(60));
console.log('\n🔧 Testing AutoFixer with node type corrections:');
console.log('='.repeat(60));
const autoFixer = new workflow_auto_fixer_1.WorkflowAutoFixer(repository);
const fixResult = await autoFixer.generateFixes(testWorkflow, validationResult, [], {
applyFixes: false,
fixTypes: ['node-type-correction'],
confidenceThreshold: 'high'
});
if (fixResult.fixes.length > 0) {
console.log('\n✅ Auto-fixable issues found:');
for (const fix of fixResult.fixes) {
console.log(`${fix.description}`);
}
console.log(`\nSummary: ${fixResult.summary}`);
}
else {
console.log('\n❌ No auto-fixable node type issues found (only high-confidence fixes are applied)');
}
console.log('\n' + '='.repeat(60));
console.log('\n✨ Test complete!');
}
testNodeSimilarity().catch(error => {
console.error('Test failed:', error);
process.exit(1);
});
//# sourceMappingURL=test-node-suggestions.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,3 @@
#!/usr/bin/env node
export {};
//# sourceMappingURL=test-protocol-negotiation.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"test-protocol-negotiation.d.ts","sourceRoot":"","sources":["../../src/scripts/test-protocol-negotiation.ts"],"names":[],"mappings":""}

View File

@@ -0,0 +1,154 @@
#!/usr/bin/env node
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const protocol_version_1 = require("../utils/protocol-version");
const testCases = [
{
name: 'Standard MCP client (Claude Desktop)',
clientVersion: '2025-03-26',
clientInfo: { name: 'Claude Desktop', version: '1.0.0' },
expectedVersion: '2025-03-26',
expectedIsN8nClient: false
},
{
name: 'n8n client with specific client info',
clientVersion: '2025-03-26',
clientInfo: { name: 'n8n', version: '1.0.0' },
expectedVersion: protocol_version_1.N8N_PROTOCOL_VERSION,
expectedIsN8nClient: true
},
{
name: 'LangChain client',
clientVersion: '2025-03-26',
clientInfo: { name: 'langchain-js', version: '0.1.0' },
expectedVersion: protocol_version_1.N8N_PROTOCOL_VERSION,
expectedIsN8nClient: true
},
{
name: 'n8n client via user agent',
clientVersion: '2025-03-26',
userAgent: 'n8n/1.0.0',
expectedVersion: protocol_version_1.N8N_PROTOCOL_VERSION,
expectedIsN8nClient: true
},
{
name: 'n8n mode environment variable',
clientVersion: '2025-03-26',
expectedVersion: protocol_version_1.N8N_PROTOCOL_VERSION,
expectedIsN8nClient: true
},
{
name: 'Client requesting older version',
clientVersion: '2024-06-25',
clientInfo: { name: 'Some Client', version: '1.0.0' },
expectedVersion: '2024-06-25',
expectedIsN8nClient: false
},
{
name: 'Client requesting unsupported version',
clientVersion: '2020-01-01',
clientInfo: { name: 'Old Client', version: '1.0.0' },
expectedVersion: protocol_version_1.STANDARD_PROTOCOL_VERSION,
expectedIsN8nClient: false
},
{
name: 'No client info provided',
expectedVersion: protocol_version_1.STANDARD_PROTOCOL_VERSION,
expectedIsN8nClient: false
},
{
name: 'n8n headers detection',
clientVersion: '2025-03-26',
headers: { 'x-n8n-version': '1.0.0' },
expectedVersion: protocol_version_1.N8N_PROTOCOL_VERSION,
expectedIsN8nClient: true
}
];
async function runTests() {
console.log('🧪 Testing Protocol Version Negotiation\n');
let passed = 0;
let failed = 0;
const originalN8nMode = process.env.N8N_MODE;
for (const testCase of testCases) {
try {
if (testCase.name.includes('environment variable')) {
process.env.N8N_MODE = 'true';
}
else {
delete process.env.N8N_MODE;
}
const detectedAsN8n = (0, protocol_version_1.isN8nClient)(testCase.clientInfo, testCase.userAgent, testCase.headers);
const result = (0, protocol_version_1.negotiateProtocolVersion)(testCase.clientVersion, testCase.clientInfo, testCase.userAgent, testCase.headers);
const versionCorrect = result.version === testCase.expectedVersion;
const n8nDetectionCorrect = result.isN8nClient === testCase.expectedIsN8nClient;
const isN8nFunctionCorrect = detectedAsN8n === testCase.expectedIsN8nClient;
if (versionCorrect && n8nDetectionCorrect && isN8nFunctionCorrect) {
console.log(`${testCase.name}`);
console.log(` Version: ${result.version}, n8n client: ${result.isN8nClient}`);
console.log(` Reasoning: ${result.reasoning}\n`);
passed++;
}
else {
console.log(`${testCase.name}`);
console.log(` Expected: version=${testCase.expectedVersion}, isN8n=${testCase.expectedIsN8nClient}`);
console.log(` Got: version=${result.version}, isN8n=${result.isN8nClient}`);
console.log(` isN8nClient function: ${detectedAsN8n} (expected: ${testCase.expectedIsN8nClient})`);
console.log(` Reasoning: ${result.reasoning}\n`);
failed++;
}
}
catch (error) {
console.log(`💥 ${testCase.name} - ERROR`);
console.log(` ${error instanceof Error ? error.message : String(error)}\n`);
failed++;
}
}
if (originalN8nMode) {
process.env.N8N_MODE = originalN8nMode;
}
else {
delete process.env.N8N_MODE;
}
console.log(`\n📊 Test Results:`);
console.log(` ✅ Passed: ${passed}`);
console.log(` ❌ Failed: ${failed}`);
console.log(` Total: ${passed + failed}`);
if (failed > 0) {
console.log(`\n❌ Some tests failed!`);
process.exit(1);
}
else {
console.log(`\n🎉 All tests passed!`);
}
}
async function testIntegration() {
console.log('\n🔧 Integration Test - MCP Server Protocol Negotiation\n');
const scenarios = [
{
name: 'Claude Desktop connecting',
clientInfo: { name: 'Claude Desktop', version: '1.0.0' },
clientVersion: '2025-03-26'
},
{
name: 'n8n connecting via HTTP',
headers: { 'user-agent': 'n8n/1.52.0' },
clientVersion: '2025-03-26'
}
];
for (const scenario of scenarios) {
const result = (0, protocol_version_1.negotiateProtocolVersion)(scenario.clientVersion, scenario.clientInfo, scenario.headers?.['user-agent'], scenario.headers);
console.log(`🔍 ${scenario.name}:`);
console.log(` Negotiated version: ${result.version}`);
console.log(` Is n8n client: ${result.isN8nClient}`);
console.log(` Reasoning: ${result.reasoning}\n`);
}
}
if (require.main === module) {
runTests()
.then(() => testIntegration())
.catch(error => {
console.error('Test execution failed:', error);
process.exit(1);
});
}
//# sourceMappingURL=test-protocol-negotiation.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"test-protocol-negotiation.js","sourceRoot":"","sources":["../../src/scripts/test-protocol-negotiation.ts"],"names":[],"mappings":"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"}

3
dist/scripts/test-summary.d.ts vendored Normal file
View File

@@ -0,0 +1,3 @@
#!/usr/bin/env npx tsx
export {};
//# sourceMappingURL=test-summary.d.ts.map

1
dist/scripts/test-summary.d.ts.map vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"test-summary.d.ts","sourceRoot":"","sources":["../../src/scripts/test-summary.ts"],"names":[],"mappings":""}

77
dist/scripts/test-summary.js vendored Normal file
View File

@@ -0,0 +1,77 @@
#!/usr/bin/env npx tsx
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const database_adapter_1 = require("../database/database-adapter");
const node_repository_1 = require("../database/node-repository");
const node_similarity_service_1 = require("../services/node-similarity-service");
const path_1 = __importDefault(require("path"));
async function testSummary() {
const dbPath = path_1.default.join(process.cwd(), 'data/nodes.db');
const db = await (0, database_adapter_1.createDatabaseAdapter)(dbPath);
const repository = new node_repository_1.NodeRepository(db);
const similarityService = new node_similarity_service_1.NodeSimilarityService(repository);
const testCases = [
{ invalid: 'HttpRequest', expected: 'nodes-base.httpRequest' },
{ invalid: 'HTTPRequest', expected: 'nodes-base.httpRequest' },
{ invalid: 'Webhook', expected: 'nodes-base.webhook' },
{ invalid: 'WebHook', expected: 'nodes-base.webhook' },
{ invalid: 'slack', expected: 'nodes-base.slack' },
{ invalid: 'googleSheets', expected: 'nodes-base.googleSheets' },
{ invalid: 'telegram', expected: 'nodes-base.telegram' },
{ invalid: 'htpRequest', expected: 'nodes-base.httpRequest' },
{ invalid: 'webook', expected: 'nodes-base.webhook' },
{ invalid: 'slak', expected: 'nodes-base.slack' },
{ invalid: 'http', expected: 'nodes-base.httpRequest' },
{ invalid: 'sheet', expected: 'nodes-base.googleSheets' },
{ invalid: 'nodes-base.openai', expected: 'nodes-langchain.openAi' },
{ invalid: 'n8n-nodes-base.httpRequest', expected: 'nodes-base.httpRequest' },
{ invalid: 'foobar', expected: null },
{ invalid: 'xyz123', expected: null },
];
let passed = 0;
let failed = 0;
console.log('Test Results Summary:');
console.log('='.repeat(60));
for (const testCase of testCases) {
const suggestions = await similarityService.findSimilarNodes(testCase.invalid, 3);
let result = '❌';
let status = 'FAILED';
if (testCase.expected === null) {
if (suggestions.length === 0) {
result = '✅';
status = 'PASSED';
passed++;
}
else {
failed++;
}
}
else {
const found = suggestions.some(s => s.nodeType === testCase.expected);
if (found) {
const suggestion = suggestions.find(s => s.nodeType === testCase.expected);
const isAutoFixable = suggestion && suggestion.confidence >= 0.9;
result = '✅';
status = isAutoFixable ? 'PASSED (auto-fixable)' : 'PASSED';
passed++;
}
else {
failed++;
}
}
console.log(`${result} "${testCase.invalid}" → ${testCase.expected || 'no suggestions'}: ${status}`);
}
console.log('='.repeat(60));
console.log(`\nTotal: ${passed}/${testCases.length} tests passed`);
if (failed === 0) {
console.log('🎉 All tests passed!');
}
else {
console.log(`⚠️ ${failed} tests failed`);
}
}
testSummary().catch(console.error);
//# sourceMappingURL=test-summary.js.map

1
dist/scripts/test-summary.js.map vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"test-summary.js","sourceRoot":"","sources":["../../src/scripts/test-summary.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,2 @@
export {};
//# sourceMappingURL=test-telemetry-mutations-verbose.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"test-telemetry-mutations-verbose.d.ts","sourceRoot":"","sources":["../../src/scripts/test-telemetry-mutations-verbose.ts"],"names":[],"mappings":""}

View File

@@ -0,0 +1,133 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const telemetry_manager_js_1 = require("../telemetry/telemetry-manager.js");
const config_manager_js_1 = require("../telemetry/config-manager.js");
async function testMutations() {
console.log('Starting verbose telemetry mutation test...\n');
const configManager = config_manager_js_1.TelemetryConfigManager.getInstance();
console.log('Telemetry config is enabled:', configManager.isEnabled());
console.log('Telemetry config file:', configManager['configPath']);
const testMutation = {
sessionId: 'test_session_' + Date.now(),
toolName: 'n8n_update_partial_workflow',
userIntent: 'Add a Merge node for data consolidation',
operations: [
{
type: 'addNode',
nodeId: 'Merge1',
node: {
id: 'Merge1',
type: 'n8n-nodes-base.merge',
name: 'Merge',
position: [600, 200],
parameters: {}
}
},
{
type: 'addConnection',
source: 'previous_node',
target: 'Merge1'
}
],
workflowBefore: {
id: 'test-workflow',
name: 'Test Workflow',
active: true,
nodes: [
{
id: 'previous_node',
type: 'n8n-nodes-base.manualTrigger',
name: 'When called',
position: [300, 200],
parameters: {}
}
],
connections: {},
nodeIds: []
},
workflowAfter: {
id: 'test-workflow',
name: 'Test Workflow',
active: true,
nodes: [
{
id: 'previous_node',
type: 'n8n-nodes-base.manualTrigger',
name: 'When called',
position: [300, 200],
parameters: {}
},
{
id: 'Merge1',
type: 'n8n-nodes-base.merge',
name: 'Merge',
position: [600, 200],
parameters: {}
}
],
connections: {
'previous_node': [
{
node: 'Merge1',
type: 'main',
index: 0,
source: 0,
destination: 0
}
]
},
nodeIds: []
},
mutationSuccess: true,
durationMs: 125
};
console.log('\nTest Mutation Data:');
console.log('==================');
console.log(JSON.stringify({
intent: testMutation.userIntent,
tool: testMutation.toolName,
operationCount: testMutation.operations.length,
sessionId: testMutation.sessionId
}, null, 2));
console.log('\n');
console.log('Calling telemetry.trackWorkflowMutation...');
try {
await telemetry_manager_js_1.telemetry.trackWorkflowMutation(testMutation);
console.log('✓ trackWorkflowMutation completed successfully\n');
}
catch (error) {
console.error('✗ trackWorkflowMutation failed:', error);
console.error('\n');
}
const metricsBeforeFlush = telemetry_manager_js_1.telemetry.getMetrics();
console.log('Metrics before flush:');
console.log('- mutationQueueSize:', metricsBeforeFlush.tracking.mutationQueueSize);
console.log('- eventsTracked:', metricsBeforeFlush.processing.eventsTracked);
console.log('- eventsFailed:', metricsBeforeFlush.processing.eventsFailed);
console.log('\n');
console.log('Flushing telemetry (waiting 10 seconds for Supabase)...');
try {
await telemetry_manager_js_1.telemetry.flush();
console.log('✓ Telemetry flush completed\n');
}
catch (error) {
console.error('✗ Flush failed:', error);
console.error('\n');
}
await new Promise(resolve => setTimeout(resolve, 2000));
const metricsAfterFlush = telemetry_manager_js_1.telemetry.getMetrics();
console.log('Metrics after flush:');
console.log('- mutationQueueSize:', metricsAfterFlush.tracking.mutationQueueSize);
console.log('- eventsTracked:', metricsAfterFlush.processing.eventsTracked);
console.log('- eventsFailed:', metricsAfterFlush.processing.eventsFailed);
console.log('- batchesSent:', metricsAfterFlush.processing.batchesSent);
console.log('- batchesFailed:', metricsAfterFlush.processing.batchesFailed);
console.log('- circuitBreakerState:', metricsAfterFlush.processing.circuitBreakerState);
console.log('\n');
console.log('Test completed. Check workflow_mutations table in Supabase.');
}
testMutations().catch(error => {
console.error('Test failed:', error);
process.exit(1);
});
//# sourceMappingURL=test-telemetry-mutations-verbose.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"test-telemetry-mutations-verbose.js","sourceRoot":"","sources":["../../src/scripts/test-telemetry-mutations-verbose.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,2 @@
export {};
//# sourceMappingURL=test-telemetry-mutations.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"test-telemetry-mutations.d.ts","sourceRoot":"","sources":["../../src/scripts/test-telemetry-mutations.ts"],"names":[],"mappings":""}

129
dist/scripts/test-telemetry-mutations.js vendored Normal file
View File

@@ -0,0 +1,129 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const telemetry_manager_js_1 = require("../telemetry/telemetry-manager.js");
const config_manager_js_1 = require("../telemetry/config-manager.js");
async function testMutations() {
console.log('Starting telemetry mutation test...\n');
const configManager = config_manager_js_1.TelemetryConfigManager.getInstance();
console.log('Telemetry Status:');
console.log('================');
console.log(configManager.getStatus());
console.log('\n');
const metricsAfterInit = telemetry_manager_js_1.telemetry.getMetrics();
console.log('Telemetry Metrics (After Init):');
console.log('================================');
console.log(JSON.stringify(metricsAfterInit, null, 2));
console.log('\n');
const testMutation = {
sessionId: 'test_session_' + Date.now(),
toolName: 'n8n_update_partial_workflow',
userIntent: 'Add a Merge node for data consolidation',
operations: [
{
type: 'addNode',
nodeId: 'Merge1',
node: {
id: 'Merge1',
type: 'n8n-nodes-base.merge',
name: 'Merge',
position: [600, 200],
parameters: {}
}
},
{
type: 'addConnection',
source: 'previous_node',
target: 'Merge1'
}
],
workflowBefore: {
id: 'test-workflow',
name: 'Test Workflow',
active: true,
nodes: [
{
id: 'previous_node',
type: 'n8n-nodes-base.manualTrigger',
name: 'When called',
position: [300, 200],
parameters: {}
}
],
connections: {},
nodeIds: []
},
workflowAfter: {
id: 'test-workflow',
name: 'Test Workflow',
active: true,
nodes: [
{
id: 'previous_node',
type: 'n8n-nodes-base.manualTrigger',
name: 'When called',
position: [300, 200],
parameters: {}
},
{
id: 'Merge1',
type: 'n8n-nodes-base.merge',
name: 'Merge',
position: [600, 200],
parameters: {}
}
],
connections: {
'previous_node': [
{
node: 'Merge1',
type: 'main',
index: 0,
source: 0,
destination: 0
}
]
},
nodeIds: []
},
mutationSuccess: true,
durationMs: 125
};
console.log('Test Mutation Data:');
console.log('==================');
console.log(JSON.stringify({
intent: testMutation.userIntent,
tool: testMutation.toolName,
operationCount: testMutation.operations.length,
sessionId: testMutation.sessionId
}, null, 2));
console.log('\n');
console.log('Calling telemetry.trackWorkflowMutation...');
try {
await telemetry_manager_js_1.telemetry.trackWorkflowMutation(testMutation);
console.log('✓ trackWorkflowMutation completed successfully\n');
}
catch (error) {
console.error('✗ trackWorkflowMutation failed:', error);
console.error('\n');
}
console.log('Flushing telemetry...');
try {
await telemetry_manager_js_1.telemetry.flush();
console.log('✓ Telemetry flushed successfully\n');
}
catch (error) {
console.error('✗ Flush failed:', error);
console.error('\n');
}
const metricsAfterFlush = telemetry_manager_js_1.telemetry.getMetrics();
console.log('Telemetry Metrics (After Flush):');
console.log('==================================');
console.log(JSON.stringify(metricsAfterFlush, null, 2));
console.log('\n');
console.log('Test completed. Check workflow_mutations table in Supabase.');
}
testMutations().catch(error => {
console.error('Test failed:', error);
process.exit(1);
});
//# sourceMappingURL=test-telemetry-mutations.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"test-telemetry-mutations.js","sourceRoot":"","sources":["../../src/scripts/test-telemetry-mutations.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,3 @@
#!/usr/bin/env node
export {};
//# sourceMappingURL=test-webhook-autofix.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"test-webhook-autofix.d.ts","sourceRoot":"","sources":["../../src/scripts/test-webhook-autofix.ts"],"names":[],"mappings":""}

117
dist/scripts/test-webhook-autofix.js vendored Normal file
View File

@@ -0,0 +1,117 @@
#!/usr/bin/env node
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const node_repository_1 = require("../database/node-repository");
const database_adapter_1 = require("../database/database-adapter");
const workflow_auto_fixer_1 = require("../services/workflow-auto-fixer");
const workflow_validator_1 = require("../services/workflow-validator");
const enhanced_config_validator_1 = require("../services/enhanced-config-validator");
const logger_1 = require("../utils/logger");
const path_1 = require("path");
const logger = new logger_1.Logger({ prefix: '[TestWebhookAutofix]' });
const testWorkflow = {
id: 'test_webhook_fix',
name: 'Test Webhook Autofix',
active: false,
nodes: [
{
id: '1',
name: 'Webhook',
type: 'n8n-nodes-base.webhook',
typeVersion: 2.1,
position: [250, 300],
parameters: {},
},
{
id: '2',
name: 'HTTP Request',
type: 'n8n-nodes-base.httpRequest',
typeVersion: 4.2,
position: [450, 300],
parameters: {
url: 'https://api.example.com/data',
method: 'GET'
}
}
],
connections: {
'Webhook': {
main: [[{
node: 'HTTP Request',
type: 'main',
index: 0
}]]
}
},
settings: {
executionOrder: 'v1'
},
staticData: undefined
};
async function testWebhookAutofix() {
logger.info('Testing webhook path autofixer...');
const dbPath = (0, path_1.join)(process.cwd(), 'data', 'nodes.db');
const adapter = await (0, database_adapter_1.createDatabaseAdapter)(dbPath);
const repository = new node_repository_1.NodeRepository(adapter);
const validator = new workflow_validator_1.WorkflowValidator(repository, enhanced_config_validator_1.EnhancedConfigValidator);
const autoFixer = new workflow_auto_fixer_1.WorkflowAutoFixer(repository);
logger.info('Step 1: Validating workflow to identify issues...');
const validationResult = await validator.validateWorkflow(testWorkflow);
console.log('\n📋 Validation Summary:');
console.log(`- Valid: ${validationResult.valid}`);
console.log(`- Errors: ${validationResult.errors.length}`);
console.log(`- Warnings: ${validationResult.warnings.length}`);
if (validationResult.errors.length > 0) {
console.log('\n❌ Errors found:');
validationResult.errors.forEach(error => {
console.log(` - [${error.nodeName || error.nodeId}] ${error.message}`);
});
}
logger.info('\nStep 2: Generating fixes in preview mode...');
const fixResult = await autoFixer.generateFixes(testWorkflow, validationResult, [], {
applyFixes: false,
fixTypes: ['webhook-missing-path']
});
console.log('\n🔧 Fix Results:');
console.log(`- Summary: ${fixResult.summary}`);
console.log(`- Total fixes: ${fixResult.stats.total}`);
console.log(`- Webhook path fixes: ${fixResult.stats.byType['webhook-missing-path']}`);
if (fixResult.fixes.length > 0) {
console.log('\n📝 Detailed Fixes:');
fixResult.fixes.forEach(fix => {
console.log(` - Node: ${fix.node}`);
console.log(` Field: ${fix.field}`);
console.log(` Type: ${fix.type}`);
console.log(` Before: ${fix.before || 'undefined'}`);
console.log(` After: ${fix.after}`);
console.log(` Confidence: ${fix.confidence}`);
console.log(` Description: ${fix.description}`);
});
}
if (fixResult.operations.length > 0) {
console.log('\n🔄 Operations to Apply:');
fixResult.operations.forEach(op => {
if (op.type === 'updateNode') {
console.log(` - Update Node: ${op.nodeId}`);
console.log(` Updates: ${JSON.stringify(op.updates, null, 2)}`);
}
});
}
if (fixResult.fixes.length > 0) {
const webhookFix = fixResult.fixes.find(f => f.type === 'webhook-missing-path');
if (webhookFix) {
const uuid = webhookFix.after;
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
const isValidUUID = uuidRegex.test(uuid);
console.log('\n✅ UUID Validation:');
console.log(` - Generated UUID: ${uuid}`);
console.log(` - Valid format: ${isValidUUID ? 'Yes' : 'No'}`);
}
}
logger.info('\n✨ Webhook autofix test completed successfully!');
}
testWebhookAutofix().catch(error => {
logger.error('Test failed:', error);
process.exit(1);
});
//# sourceMappingURL=test-webhook-autofix.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"test-webhook-autofix.js","sourceRoot":"","sources":["../../src/scripts/test-webhook-autofix.ts"],"names":[],"mappings":"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"}

3
dist/scripts/validate.d.ts vendored Normal file
View File

@@ -0,0 +1,3 @@
#!/usr/bin/env node
export {};
//# sourceMappingURL=validate.d.ts.map

1
dist/scripts/validate.d.ts.map vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/scripts/validate.ts"],"names":[],"mappings":""}

121
dist/scripts/validate.js vendored Normal file
View File

@@ -0,0 +1,121 @@
#!/usr/bin/env node
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const database_adapter_1 = require("../database/database-adapter");
async function validate() {
const db = await (0, database_adapter_1.createDatabaseAdapter)('./data/nodes.db');
console.log('🔍 Validating critical nodes...\n');
const criticalChecks = [
{
type: 'nodes-base.httpRequest',
checks: {
hasDocumentation: true,
documentationContains: 'HTTP Request',
style: 'programmatic'
}
},
{
type: 'nodes-base.code',
checks: {
hasDocumentation: true,
documentationContains: 'Code'
}
},
{
type: 'nodes-base.slack',
checks: {
hasOperations: true,
style: 'programmatic'
}
},
{
type: 'nodes-langchain.agent',
checks: {
isAITool: false,
packageName: '@n8n/n8n-nodes-langchain'
}
}
];
let passed = 0;
let failed = 0;
for (const check of criticalChecks) {
const node = db.prepare('SELECT * FROM nodes WHERE node_type = ?').get(check.type);
if (!node) {
console.log(`${check.type}: NOT FOUND`);
failed++;
continue;
}
let nodeOk = true;
const issues = [];
if (check.checks.hasDocumentation && !node.documentation) {
nodeOk = false;
issues.push('missing documentation');
}
if (check.checks.documentationContains &&
!node.documentation?.includes(check.checks.documentationContains)) {
nodeOk = false;
issues.push(`documentation doesn't contain "${check.checks.documentationContains}"`);
}
if (check.checks.style && node.development_style !== check.checks.style) {
nodeOk = false;
issues.push(`wrong style: ${node.development_style}`);
}
if (check.checks.hasOperations) {
const operations = JSON.parse(node.operations || '[]');
if (!operations.length) {
nodeOk = false;
issues.push('no operations found');
}
}
if (check.checks.isAITool !== undefined && !!node.is_ai_tool !== check.checks.isAITool) {
nodeOk = false;
issues.push(`AI tool flag mismatch: expected ${check.checks.isAITool}, got ${!!node.is_ai_tool}`);
}
if ('isVersioned' in check.checks && check.checks.isVersioned && !node.is_versioned) {
nodeOk = false;
issues.push('not marked as versioned');
}
if (check.checks.packageName && node.package_name !== check.checks.packageName) {
nodeOk = false;
issues.push(`wrong package: ${node.package_name}`);
}
if (nodeOk) {
console.log(`${check.type}`);
passed++;
}
else {
console.log(`${check.type}: ${issues.join(', ')}`);
failed++;
}
}
console.log(`\n📊 Results: ${passed} passed, ${failed} failed`);
const stats = db.prepare(`
SELECT
COUNT(*) as total,
SUM(is_ai_tool) as ai_tools,
SUM(is_trigger) as triggers,
SUM(is_versioned) as versioned,
COUNT(DISTINCT package_name) as packages
FROM nodes
`).get();
console.log('\n📈 Database Statistics:');
console.log(` Total nodes: ${stats.total}`);
console.log(` AI tools: ${stats.ai_tools}`);
console.log(` Triggers: ${stats.triggers}`);
console.log(` Versioned: ${stats.versioned}`);
console.log(` Packages: ${stats.packages}`);
const docStats = db.prepare(`
SELECT
COUNT(*) as total,
SUM(CASE WHEN documentation IS NOT NULL THEN 1 ELSE 0 END) as with_docs
FROM nodes
`).get();
console.log(`\n📚 Documentation Coverage:`);
console.log(` Nodes with docs: ${docStats.with_docs}/${docStats.total} (${Math.round(docStats.with_docs / docStats.total * 100)}%)`);
db.close();
process.exit(failed > 0 ? 1 : 0);
}
if (require.main === module) {
validate().catch(console.error);
}
//# sourceMappingURL=validate.js.map

1
dist/scripts/validate.js.map vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/scripts/validate.ts"],"names":[],"mappings":"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"}

3
dist/scripts/validation-summary.d.ts vendored Normal file
View File

@@ -0,0 +1,3 @@
#!/usr/bin/env node
export {};
//# sourceMappingURL=validation-summary.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"validation-summary.d.ts","sourceRoot":"","sources":["../../src/scripts/validation-summary.ts"],"names":[],"mappings":""}

135
dist/scripts/validation-summary.js vendored Normal file
View File

@@ -0,0 +1,135 @@
#!/usr/bin/env node
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = require("fs");
const path_1 = __importDefault(require("path"));
const node_repository_1 = require("../database/node-repository");
const database_adapter_1 = require("../database/database-adapter");
const workflow_validator_1 = require("../services/workflow-validator");
const enhanced_config_validator_1 = require("../services/enhanced-config-validator");
const template_repository_1 = require("../templates/template-repository");
const logger_1 = require("../utils/logger");
const logger = new logger_1.Logger({ prefix: '[validation-summary]' });
async function runValidationSummary() {
const dbPath = path_1.default.join(process.cwd(), 'data', 'nodes.db');
if (!(0, fs_1.existsSync)(dbPath)) {
logger.error('Database not found. Run npm run rebuild first.');
process.exit(1);
}
const db = await (0, database_adapter_1.createDatabaseAdapter)(dbPath);
const repository = new node_repository_1.NodeRepository(db);
const templateRepository = new template_repository_1.TemplateRepository(db);
const validator = new workflow_validator_1.WorkflowValidator(repository, enhanced_config_validator_1.EnhancedConfigValidator);
try {
const templates = await templateRepository.getAllTemplates(50);
const results = {
total: templates.length,
valid: 0,
invalid: 0,
noErrors: 0,
errorCategories: {
unknownNodes: 0,
missingRequired: 0,
expressionErrors: 0,
connectionErrors: 0,
cycles: 0,
other: 0
},
commonUnknownNodes: new Map(),
stickyNoteIssues: 0
};
for (const template of templates) {
try {
const workflow = JSON.parse(template.workflow_json || '{}');
const validationResult = await validator.validateWorkflow(workflow, {
profile: 'minimal'
});
if (validationResult.valid) {
results.valid++;
}
else {
results.invalid++;
}
if (validationResult.errors.length === 0) {
results.noErrors++;
}
validationResult.errors.forEach((error) => {
const errorMsg = typeof error.message === 'string' ? error.message : JSON.stringify(error.message);
if (errorMsg.includes('Unknown node type')) {
results.errorCategories.unknownNodes++;
const match = errorMsg.match(/Unknown node type: (.+)/);
if (match) {
const nodeType = match[1];
results.commonUnknownNodes.set(nodeType, (results.commonUnknownNodes.get(nodeType) || 0) + 1);
}
}
else if (errorMsg.includes('missing_required')) {
results.errorCategories.missingRequired++;
if (error.nodeName?.includes('Sticky Note')) {
results.stickyNoteIssues++;
}
}
else if (errorMsg.includes('Expression error')) {
results.errorCategories.expressionErrors++;
}
else if (errorMsg.includes('connection') || errorMsg.includes('Connection')) {
results.errorCategories.connectionErrors++;
}
else if (errorMsg.includes('cycle')) {
results.errorCategories.cycles++;
}
else {
results.errorCategories.other++;
}
});
}
catch (error) {
results.invalid++;
}
}
console.log('\n' + '='.repeat(80));
console.log('WORKFLOW VALIDATION SUMMARY');
console.log('='.repeat(80));
console.log(`\nTemplates analyzed: ${results.total}`);
console.log(`Valid workflows: ${results.valid} (${((results.valid / results.total) * 100).toFixed(1)}%)`);
console.log(`Workflows without errors: ${results.noErrors} (${((results.noErrors / results.total) * 100).toFixed(1)}%)`);
console.log('\nError Categories:');
console.log(` - Unknown nodes: ${results.errorCategories.unknownNodes}`);
console.log(` - Missing required properties: ${results.errorCategories.missingRequired}`);
console.log(` (Sticky note issues: ${results.stickyNoteIssues})`);
console.log(` - Expression errors: ${results.errorCategories.expressionErrors}`);
console.log(` - Connection errors: ${results.errorCategories.connectionErrors}`);
console.log(` - Workflow cycles: ${results.errorCategories.cycles}`);
console.log(` - Other errors: ${results.errorCategories.other}`);
if (results.commonUnknownNodes.size > 0) {
console.log('\nTop Unknown Node Types:');
const sortedNodes = Array.from(results.commonUnknownNodes.entries())
.sort((a, b) => b[1] - a[1])
.slice(0, 10);
sortedNodes.forEach(([nodeType, count]) => {
console.log(` - ${nodeType} (${count} occurrences)`);
});
}
console.log('\nKey Insights:');
const stickyNotePercent = ((results.stickyNoteIssues / results.errorCategories.missingRequired) * 100).toFixed(1);
console.log(` - ${stickyNotePercent}% of missing required property errors are from Sticky Notes`);
console.log(` - Most workflows have some validation warnings (best practices)`);
console.log(` - Expression validation is working well`);
console.log(` - Node type normalization is handling most cases correctly`);
}
catch (error) {
logger.error('Failed to run validation summary:', error);
process.exit(1);
}
finally {
db.close();
}
}
runValidationSummary().catch(error => {
logger.error('Summary failed:', error);
process.exit(1);
});
//# sourceMappingURL=validation-summary.js.map

File diff suppressed because one or more lines are too long