mirror of
https://github.com/czlonkowski/n8n-mcp.git
synced 2026-01-30 06:22:04 +00:00
chore: add pre-built dist folder for npx usage
This commit is contained in:
committed by
Romuald Członkowski
parent
a70d96a373
commit
5057481e70
3
dist/scripts/debug-http-search.d.ts
vendored
Normal file
3
dist/scripts/debug-http-search.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env npx tsx
|
||||
export {};
|
||||
//# sourceMappingURL=debug-http-search.d.ts.map
|
||||
1
dist/scripts/debug-http-search.d.ts.map
vendored
Normal file
1
dist/scripts/debug-http-search.d.ts.map
vendored
Normal 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
57
dist/scripts/debug-http-search.js
vendored
Normal 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
1
dist/scripts/debug-http-search.js.map
vendored
Normal 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
3
dist/scripts/extract-from-docker.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env node
|
||||
export {};
|
||||
//# sourceMappingURL=extract-from-docker.d.ts.map
|
||||
1
dist/scripts/extract-from-docker.d.ts.map
vendored
Normal file
1
dist/scripts/extract-from-docker.d.ts.map
vendored
Normal 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
210
dist/scripts/extract-from-docker.js
vendored
Normal 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
|
||||
1
dist/scripts/extract-from-docker.js.map
vendored
Normal file
1
dist/scripts/extract-from-docker.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
4
dist/scripts/fetch-templates-robust.d.ts
vendored
Normal file
4
dist/scripts/fetch-templates-robust.d.ts
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env node
|
||||
declare function fetchTemplatesRobust(): Promise<void>;
|
||||
export { fetchTemplatesRobust };
|
||||
//# sourceMappingURL=fetch-templates-robust.d.ts.map
|
||||
1
dist/scripts/fetch-templates-robust.d.ts.map
vendored
Normal file
1
dist/scripts/fetch-templates-robust.d.ts.map
vendored
Normal 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
132
dist/scripts/fetch-templates-robust.js
vendored
Normal 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
|
||||
1
dist/scripts/fetch-templates-robust.js.map
vendored
Normal file
1
dist/scripts/fetch-templates-robust.js.map
vendored
Normal 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
4
dist/scripts/fetch-templates.d.ts
vendored
Normal 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
1
dist/scripts/fetch-templates.d.ts.map
vendored
Normal 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
411
dist/scripts/fetch-templates.js
vendored
Normal 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
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
4
dist/scripts/rebuild-database.d.ts
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env node
|
||||
declare function rebuildDocumentationDatabase(): Promise<void>;
|
||||
export { rebuildDocumentationDatabase };
|
||||
//# sourceMappingURL=rebuild-database.d.ts.map
|
||||
1
dist/scripts/rebuild-database.d.ts.map
vendored
Normal file
1
dist/scripts/rebuild-database.d.ts.map
vendored
Normal 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
95
dist/scripts/rebuild-database.js
vendored
Normal 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
1
dist/scripts/rebuild-database.js.map
vendored
Normal 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
3
dist/scripts/rebuild-optimized.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env node
|
||||
export {};
|
||||
//# sourceMappingURL=rebuild-optimized.d.ts.map
|
||||
1
dist/scripts/rebuild-optimized.d.ts.map
vendored
Normal file
1
dist/scripts/rebuild-optimized.d.ts.map
vendored
Normal 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
198
dist/scripts/rebuild-optimized.js
vendored
Normal 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
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
3
dist/scripts/rebuild.d.ts
vendored
Normal 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
1
dist/scripts/rebuild.d.ts.map
vendored
Normal 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
234
dist/scripts/rebuild.js
vendored
Normal 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
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
3
dist/scripts/sanitize-templates.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env node
|
||||
export {};
|
||||
//# sourceMappingURL=sanitize-templates.d.ts.map
|
||||
1
dist/scripts/sanitize-templates.d.ts.map
vendored
Normal file
1
dist/scripts/sanitize-templates.d.ts.map
vendored
Normal 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
88
dist/scripts/sanitize-templates.js
vendored
Normal 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
|
||||
1
dist/scripts/sanitize-templates.js.map
vendored
Normal file
1
dist/scripts/sanitize-templates.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"sanitize-templates.js","sourceRoot":"","sources":["../../src/scripts/sanitize-templates.ts"],"names":[],"mappings":"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"}
|
||||
4
dist/scripts/seed-canonical-ai-examples.d.ts
vendored
Normal file
4
dist/scripts/seed-canonical-ai-examples.d.ts
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env node
|
||||
declare function seedCanonicalExamples(): Promise<void>;
|
||||
export { seedCanonicalExamples };
|
||||
//# sourceMappingURL=seed-canonical-ai-examples.d.ts.map
|
||||
1
dist/scripts/seed-canonical-ai-examples.d.ts.map
vendored
Normal file
1
dist/scripts/seed-canonical-ai-examples.d.ts.map
vendored
Normal 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"}
|
||||
121
dist/scripts/seed-canonical-ai-examples.js
vendored
Normal file
121
dist/scripts/seed-canonical-ai-examples.js
vendored
Normal 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
|
||||
1
dist/scripts/seed-canonical-ai-examples.js.map
vendored
Normal file
1
dist/scripts/seed-canonical-ai-examples.js.map
vendored
Normal 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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"}
|
||||
3
dist/scripts/test-autofix-documentation.d.ts
vendored
Normal file
3
dist/scripts/test-autofix-documentation.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env npx tsx
|
||||
export {};
|
||||
//# sourceMappingURL=test-autofix-documentation.d.ts.map
|
||||
1
dist/scripts/test-autofix-documentation.d.ts.map
vendored
Normal file
1
dist/scripts/test-autofix-documentation.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"test-autofix-documentation.d.ts","sourceRoot":"","sources":["../../src/scripts/test-autofix-documentation.ts"],"names":[],"mappings":""}
|
||||
103
dist/scripts/test-autofix-documentation.js
vendored
Normal file
103
dist/scripts/test-autofix-documentation.js
vendored
Normal 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
|
||||
1
dist/scripts/test-autofix-documentation.js.map
vendored
Normal file
1
dist/scripts/test-autofix-documentation.js.map
vendored
Normal 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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"}
|
||||
2
dist/scripts/test-autofix-workflow.d.ts
vendored
Normal file
2
dist/scripts/test-autofix-workflow.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export {};
|
||||
//# sourceMappingURL=test-autofix-workflow.d.ts.map
|
||||
1
dist/scripts/test-autofix-workflow.d.ts.map
vendored
Normal file
1
dist/scripts/test-autofix-workflow.d.ts.map
vendored
Normal 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
223
dist/scripts/test-autofix-workflow.js
vendored
Normal 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
|
||||
1
dist/scripts/test-autofix-workflow.js.map
vendored
Normal file
1
dist/scripts/test-autofix-workflow.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
3
dist/scripts/test-execution-filtering.d.ts
vendored
Normal file
3
dist/scripts/test-execution-filtering.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env node
|
||||
export {};
|
||||
//# sourceMappingURL=test-execution-filtering.d.ts.map
|
||||
1
dist/scripts/test-execution-filtering.d.ts.map
vendored
Normal file
1
dist/scripts/test-execution-filtering.d.ts.map
vendored
Normal 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
206
dist/scripts/test-execution-filtering.js
vendored
Normal 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
|
||||
1
dist/scripts/test-execution-filtering.js.map
vendored
Normal file
1
dist/scripts/test-execution-filtering.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
3
dist/scripts/test-node-suggestions.d.ts
vendored
Normal file
3
dist/scripts/test-node-suggestions.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env npx tsx
|
||||
export {};
|
||||
//# sourceMappingURL=test-node-suggestions.d.ts.map
|
||||
1
dist/scripts/test-node-suggestions.d.ts.map
vendored
Normal file
1
dist/scripts/test-node-suggestions.d.ts.map
vendored
Normal 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
165
dist/scripts/test-node-suggestions.js
vendored
Normal 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
|
||||
1
dist/scripts/test-node-suggestions.js.map
vendored
Normal file
1
dist/scripts/test-node-suggestions.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
3
dist/scripts/test-protocol-negotiation.d.ts
vendored
Normal file
3
dist/scripts/test-protocol-negotiation.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env node
|
||||
export {};
|
||||
//# sourceMappingURL=test-protocol-negotiation.d.ts.map
|
||||
1
dist/scripts/test-protocol-negotiation.d.ts.map
vendored
Normal file
1
dist/scripts/test-protocol-negotiation.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"test-protocol-negotiation.d.ts","sourceRoot":"","sources":["../../src/scripts/test-protocol-negotiation.ts"],"names":[],"mappings":""}
|
||||
154
dist/scripts/test-protocol-negotiation.js
vendored
Normal file
154
dist/scripts/test-protocol-negotiation.js
vendored
Normal 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
|
||||
1
dist/scripts/test-protocol-negotiation.js.map
vendored
Normal file
1
dist/scripts/test-protocol-negotiation.js.map
vendored
Normal 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
3
dist/scripts/test-summary.d.ts
vendored
Normal 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
1
dist/scripts/test-summary.d.ts.map
vendored
Normal 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
77
dist/scripts/test-summary.js
vendored
Normal 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
1
dist/scripts/test-summary.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"test-summary.js","sourceRoot":"","sources":["../../src/scripts/test-summary.ts"],"names":[],"mappings":"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"}
|
||||
2
dist/scripts/test-telemetry-mutations-verbose.d.ts
vendored
Normal file
2
dist/scripts/test-telemetry-mutations-verbose.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export {};
|
||||
//# sourceMappingURL=test-telemetry-mutations-verbose.d.ts.map
|
||||
1
dist/scripts/test-telemetry-mutations-verbose.d.ts.map
vendored
Normal file
1
dist/scripts/test-telemetry-mutations-verbose.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"test-telemetry-mutations-verbose.d.ts","sourceRoot":"","sources":["../../src/scripts/test-telemetry-mutations-verbose.ts"],"names":[],"mappings":""}
|
||||
133
dist/scripts/test-telemetry-mutations-verbose.js
vendored
Normal file
133
dist/scripts/test-telemetry-mutations-verbose.js
vendored
Normal 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
|
||||
1
dist/scripts/test-telemetry-mutations-verbose.js.map
vendored
Normal file
1
dist/scripts/test-telemetry-mutations-verbose.js.map
vendored
Normal 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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"}
|
||||
2
dist/scripts/test-telemetry-mutations.d.ts
vendored
Normal file
2
dist/scripts/test-telemetry-mutations.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export {};
|
||||
//# sourceMappingURL=test-telemetry-mutations.d.ts.map
|
||||
1
dist/scripts/test-telemetry-mutations.d.ts.map
vendored
Normal file
1
dist/scripts/test-telemetry-mutations.d.ts.map
vendored
Normal 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
129
dist/scripts/test-telemetry-mutations.js
vendored
Normal 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
|
||||
1
dist/scripts/test-telemetry-mutations.js.map
vendored
Normal file
1
dist/scripts/test-telemetry-mutations.js.map
vendored
Normal 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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"}
|
||||
3
dist/scripts/test-webhook-autofix.d.ts
vendored
Normal file
3
dist/scripts/test-webhook-autofix.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env node
|
||||
export {};
|
||||
//# sourceMappingURL=test-webhook-autofix.d.ts.map
|
||||
1
dist/scripts/test-webhook-autofix.d.ts.map
vendored
Normal file
1
dist/scripts/test-webhook-autofix.d.ts.map
vendored
Normal 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
117
dist/scripts/test-webhook-autofix.js
vendored
Normal 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
|
||||
1
dist/scripts/test-webhook-autofix.js.map
vendored
Normal file
1
dist/scripts/test-webhook-autofix.js.map
vendored
Normal 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
3
dist/scripts/validate.d.ts
vendored
Normal 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
1
dist/scripts/validate.d.ts.map
vendored
Normal 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
121
dist/scripts/validate.js
vendored
Normal 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
1
dist/scripts/validate.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/scripts/validate.ts"],"names":[],"mappings":";;;AAKA,mEAAqE;AAqBrE,KAAK,UAAU,QAAQ;IACrB,MAAM,EAAE,GAAG,MAAM,IAAA,wCAAqB,EAAC,iBAAiB,CAAC,CAAC;IAE1D,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;IAEjD,MAAM,cAAc,GAAG;QACrB;YACE,IAAI,EAAE,wBAAwB;YAC9B,MAAM,EAAE;gBACN,gBAAgB,EAAE,IAAI;gBACtB,qBAAqB,EAAE,cAAc;gBACrC,KAAK,EAAE,cAAc;aACtB;SACF;QACD;YACE,IAAI,EAAE,iBAAiB;YACvB,MAAM,EAAE;gBACN,gBAAgB,EAAE,IAAI;gBACtB,qBAAqB,EAAE,MAAM;aAC9B;SACF;QACD;YACE,IAAI,EAAE,kBAAkB;YACxB,MAAM,EAAE;gBACN,aAAa,EAAE,IAAI;gBACnB,KAAK,EAAE,cAAc;aACtB;SACF;QACD;YACE,IAAI,EAAE,uBAAuB;YAC7B,MAAM,EAAE;gBACN,QAAQ,EAAE,KAAK;gBACf,WAAW,EAAE,0BAA0B;aACxC;SACF;KACF,CAAC;IAEF,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,IAAI,MAAM,GAAG,CAAC,CAAC;IAEf,KAAK,MAAM,KAAK,IAAI,cAAc,EAAE,CAAC;QACnC,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC,yCAAyC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAwB,CAAC;QAE1G,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,IAAI,aAAa,CAAC,CAAC;YAC1C,MAAM,EAAE,CAAC;YACT,SAAS;QACX,CAAC;QAED,IAAI,MAAM,GAAG,IAAI,CAAC;QAClB,MAAM,MAAM,GAAa,EAAE,CAAC;QAG5B,IAAI,KAAK,CAAC,MAAM,CAAC,gBAAgB,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;YACzD,MAAM,GAAG,KAAK,CAAC;YACf,MAAM,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;QACvC,CAAC;QAED,IAAI,KAAK,CAAC,MAAM,CAAC,qBAAqB;YAClC,CAAC,IAAI,CAAC,aAAa,EAAE,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,qBAAqB,CAAC,EAAE,CAAC;YACtE,MAAM,GAAG,KAAK,CAAC;YACf,MAAM,CAAC,IAAI,CAAC,kCAAkC,KAAK,CAAC,MAAM,CAAC,qBAAqB,GAAG,CAAC,CAAC;QACvF,CAAC;QAED,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,IAAI,IAAI,CAAC,iBAAiB,KAAK,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YACxE,MAAM,GAAG,KAAK,CAAC;YACf,MAAM,CAAC,IAAI,CAAC,gBAAgB,IAAI,CAAC,iBAAiB,EAAE,CAAC,CAAC;QACxD,CAAC;QAED,IAAI,KAAK,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;YAC/B,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,CAAC;YACvD,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC;gBACvB,MAAM,GAAG,KAAK,CAAC;gBACf,MAAM,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;YACrC,CAAC;QACH,CAAC;QAED,IAAI,KAAK,CAAC,MAAM,CAAC,QAAQ,KAAK,SAAS,IAAI,CAAC,CAAC,IAAI,CAAC,UAAU,KAAK,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;YACvF,MAAM,GAAG,KAAK,CAAC;YACf,MAAM,CAAC,IAAI,CAAC,mCAAmC,KAAK,CAAC,MAAM,CAAC,QAAQ,SAAS,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;QACpG,CAAC;QAED,IAAI,aAAa,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,WAAW,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;YACpF,MAAM,GAAG,KAAK,CAAC;YACf,MAAM,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;QACzC,CAAC;QAED,IAAI,KAAK,CAAC,MAAM,CAAC,WAAW,IAAI,IAAI,CAAC,YAAY,KAAK,KAAK,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;YAC/E,MAAM,GAAG,KAAK,CAAC;YACf,MAAM,CAAC,IAAI,CAAC,kBAAkB,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;QACrD,CAAC;QAED,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;YAC/B,MAAM,EAAE,CAAC;QACX,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACrD,MAAM,EAAE,CAAC;QACX,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,iBAAiB,MAAM,YAAY,MAAM,SAAS,CAAC,CAAC;IAGhE,MAAM,KAAK,GAAG,EAAE,CAAC,OAAO,CAAC;;;;;;;;GAQxB,CAAC,CAAC,GAAG,EAAS,CAAC;IAEhB,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;IACzC,OAAO,CAAC,GAAG,CAAC,mBAAmB,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;IAC9C,OAAO,CAAC,GAAG,CAAC,gBAAgB,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC9C,OAAO,CAAC,GAAG,CAAC,gBAAgB,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC9C,OAAO,CAAC,GAAG,CAAC,iBAAiB,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC;IAChD,OAAO,CAAC,GAAG,CAAC,gBAAgB,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;IAG9C,MAAM,QAAQ,GAAG,EAAE,CAAC,OAAO,CAAC;;;;;GAK3B,CAAC,CAAC,GAAG,EAAS,CAAC;IAEhB,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;IAC5C,OAAO,CAAC,GAAG,CAAC,uBAAuB,QAAQ,CAAC,SAAS,IAAI,QAAQ,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,GAAG,QAAQ,CAAC,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC;IAEvI,EAAE,CAAC,KAAK,EAAE,CAAC;IACX,OAAO,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACnC,CAAC;AAED,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;IAC5B,QAAQ,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAClC,CAAC"}
|
||||
3
dist/scripts/validation-summary.d.ts
vendored
Normal file
3
dist/scripts/validation-summary.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env node
|
||||
export {};
|
||||
//# sourceMappingURL=validation-summary.d.ts.map
|
||||
1
dist/scripts/validation-summary.d.ts.map
vendored
Normal file
1
dist/scripts/validation-summary.d.ts.map
vendored
Normal 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
135
dist/scripts/validation-summary.js
vendored
Normal 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
|
||||
1
dist/scripts/validation-summary.js.map
vendored
Normal file
1
dist/scripts/validation-summary.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user