n8n-mcp
Version:
Integration between n8n workflow automation and Model Context Protocol (MCP)
192 lines • 7.55 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.NodeRepository = void 0;
class NodeRepository {
constructor(dbOrService) {
if ('db' in dbOrService) {
this.db = dbOrService.db;
}
else {
this.db = dbOrService;
}
}
saveNode(node) {
const stmt = this.db.prepare(`
INSERT OR REPLACE 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,
outputs, output_names
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`);
stmt.run(node.nodeType, node.packageName, node.displayName, node.description, node.category, node.style, node.isAITool ? 1 : 0, node.isTrigger ? 1 : 0, node.isWebhook ? 1 : 0, node.isVersioned ? 1 : 0, node.version, node.documentation || null, JSON.stringify(node.properties, null, 2), JSON.stringify(node.operations, null, 2), JSON.stringify(node.credentials, null, 2), node.outputs ? JSON.stringify(node.outputs, null, 2) : null, node.outputNames ? JSON.stringify(node.outputNames, null, 2) : null);
}
getNode(nodeType) {
const row = this.db.prepare(`
SELECT * FROM nodes WHERE node_type = ?
`).get(nodeType);
if (!row)
return null;
return {
nodeType: row.node_type,
displayName: row.display_name,
description: row.description,
category: row.category,
developmentStyle: row.development_style,
package: row.package_name,
isAITool: Number(row.is_ai_tool) === 1,
isTrigger: Number(row.is_trigger) === 1,
isWebhook: Number(row.is_webhook) === 1,
isVersioned: Number(row.is_versioned) === 1,
version: row.version,
properties: this.safeJsonParse(row.properties_schema, []),
operations: this.safeJsonParse(row.operations, []),
credentials: this.safeJsonParse(row.credentials_required, []),
hasDocumentation: !!row.documentation,
outputs: row.outputs ? this.safeJsonParse(row.outputs, null) : null,
outputNames: row.output_names ? this.safeJsonParse(row.output_names, null) : null
};
}
getAITools() {
const rows = this.db.prepare(`
SELECT node_type, display_name, description, package_name
FROM nodes
WHERE is_ai_tool = 1
ORDER BY display_name
`).all();
return rows.map(row => ({
nodeType: row.node_type,
displayName: row.display_name,
description: row.description,
package: row.package_name
}));
}
safeJsonParse(json, defaultValue) {
try {
return JSON.parse(json);
}
catch {
return defaultValue;
}
}
upsertNode(node) {
this.saveNode(node);
}
getNodeByType(nodeType) {
return this.getNode(nodeType);
}
getNodesByCategory(category) {
const rows = this.db.prepare(`
SELECT * FROM nodes WHERE category = ?
ORDER BY display_name
`).all(category);
return rows.map(row => this.parseNodeRow(row));
}
searchNodes(query, mode = 'OR', limit = 20) {
let sql = '';
const params = [];
if (mode === 'FUZZY') {
sql = `
SELECT * FROM nodes
WHERE node_type LIKE ? OR display_name LIKE ? OR description LIKE ?
ORDER BY display_name
LIMIT ?
`;
const fuzzyQuery = `%${query}%`;
params.push(fuzzyQuery, fuzzyQuery, fuzzyQuery, limit);
}
else {
const words = query.split(/\s+/).filter(w => w.length > 0);
const conditions = words.map(() => '(node_type LIKE ? OR display_name LIKE ? OR description LIKE ?)');
const operator = mode === 'AND' ? ' AND ' : ' OR ';
sql = `
SELECT * FROM nodes
WHERE ${conditions.join(operator)}
ORDER BY display_name
LIMIT ?
`;
for (const word of words) {
const searchTerm = `%${word}%`;
params.push(searchTerm, searchTerm, searchTerm);
}
params.push(limit);
}
const rows = this.db.prepare(sql).all(...params);
return rows.map(row => this.parseNodeRow(row));
}
getAllNodes(limit) {
let sql = 'SELECT * FROM nodes ORDER BY display_name';
if (limit) {
sql += ` LIMIT ${limit}`;
}
const rows = this.db.prepare(sql).all();
return rows.map(row => this.parseNodeRow(row));
}
getNodeCount() {
const result = this.db.prepare('SELECT COUNT(*) as count FROM nodes').get();
return result.count;
}
getAIToolNodes() {
return this.getAITools();
}
getNodesByPackage(packageName) {
const rows = this.db.prepare(`
SELECT * FROM nodes WHERE package_name = ?
ORDER BY display_name
`).all(packageName);
return rows.map(row => this.parseNodeRow(row));
}
searchNodeProperties(nodeType, query, maxResults = 20) {
const node = this.getNode(nodeType);
if (!node || !node.properties)
return [];
const results = [];
const searchLower = query.toLowerCase();
function searchProperties(properties, path = []) {
for (const prop of properties) {
if (results.length >= maxResults)
break;
const currentPath = [...path, prop.name || prop.displayName];
const pathString = currentPath.join('.');
if (prop.name?.toLowerCase().includes(searchLower) ||
prop.displayName?.toLowerCase().includes(searchLower) ||
prop.description?.toLowerCase().includes(searchLower)) {
results.push({
path: pathString,
property: prop,
description: prop.description
});
}
if (prop.options) {
searchProperties(prop.options, currentPath);
}
}
}
searchProperties(node.properties);
return results;
}
parseNodeRow(row) {
return {
nodeType: row.node_type,
displayName: row.display_name,
description: row.description,
category: row.category,
developmentStyle: row.development_style,
package: row.package_name,
isAITool: Number(row.is_ai_tool) === 1,
isTrigger: Number(row.is_trigger) === 1,
isWebhook: Number(row.is_webhook) === 1,
isVersioned: Number(row.is_versioned) === 1,
version: row.version,
properties: this.safeJsonParse(row.properties_schema, []),
operations: this.safeJsonParse(row.operations, []),
credentials: this.safeJsonParse(row.credentials_required, []),
hasDocumentation: !!row.documentation,
outputs: row.outputs ? this.safeJsonParse(row.outputs, null) : null,
outputNames: row.output_names ? this.safeJsonParse(row.output_names, null) : null
};
}
}
exports.NodeRepository = NodeRepository;
//# sourceMappingURL=node-repository.js.map