mirror of
https://github.com/czlonkowski/n8n-mcp.git
synced 2026-03-23 10:53:07 +00:00
chore: add pre-built dist folder for npx usage
This commit is contained in:
committed by
Romuald Członkowski
parent
a70d96a373
commit
5057481e70
33
dist/database/database-adapter.d.ts
vendored
Normal file
33
dist/database/database-adapter.d.ts
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
export interface DatabaseAdapter {
|
||||
prepare(sql: string): PreparedStatement;
|
||||
exec(sql: string): void;
|
||||
close(): void;
|
||||
pragma(key: string, value?: any): any;
|
||||
readonly inTransaction: boolean;
|
||||
transaction<T>(fn: () => T): T;
|
||||
checkFTS5Support(): boolean;
|
||||
}
|
||||
export interface PreparedStatement {
|
||||
run(...params: any[]): RunResult;
|
||||
get(...params: any[]): any;
|
||||
all(...params: any[]): any[];
|
||||
iterate(...params: any[]): IterableIterator<any>;
|
||||
pluck(toggle?: boolean): this;
|
||||
expand(toggle?: boolean): this;
|
||||
raw(toggle?: boolean): this;
|
||||
columns(): ColumnDefinition[];
|
||||
bind(...params: any[]): this;
|
||||
}
|
||||
export interface RunResult {
|
||||
changes: number;
|
||||
lastInsertRowid: number | bigint;
|
||||
}
|
||||
export interface ColumnDefinition {
|
||||
name: string;
|
||||
column: string | null;
|
||||
table: string | null;
|
||||
database: string | null;
|
||||
type: string | null;
|
||||
}
|
||||
export declare function createDatabaseAdapter(dbPath: string): Promise<DatabaseAdapter>;
|
||||
//# sourceMappingURL=database-adapter.d.ts.map
|
||||
1
dist/database/database-adapter.d.ts.map
vendored
Normal file
1
dist/database/database-adapter.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"database-adapter.d.ts","sourceRoot":"","sources":["../../src/database/database-adapter.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,iBAAiB,CAAC;IACxC,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,IAAI,IAAI,CAAC;IACd,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,GAAG,GAAG,GAAG,CAAC;IACtC,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;IAC/B,gBAAgB,IAAI,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,iBAAiB;IAChC,GAAG,CAAC,GAAG,MAAM,EAAE,GAAG,EAAE,GAAG,SAAS,CAAC;IACjC,GAAG,CAAC,GAAG,MAAM,EAAE,GAAG,EAAE,GAAG,GAAG,CAAC;IAC3B,GAAG,CAAC,GAAG,MAAM,EAAE,GAAG,EAAE,GAAG,GAAG,EAAE,CAAC;IAC7B,OAAO,CAAC,GAAG,MAAM,EAAE,GAAG,EAAE,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;IACjD,KAAK,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC9B,MAAM,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC/B,GAAG,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC5B,OAAO,IAAI,gBAAgB,EAAE,CAAC;IAC9B,IAAI,CAAC,GAAG,MAAM,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,GAAG,MAAM,CAAC;CAClC;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB;AAMD,wBAAsB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAoDpF"}
|
||||
420
dist/database/database-adapter.js
vendored
Normal file
420
dist/database/database-adapter.js
vendored
Normal file
@@ -0,0 +1,420 @@
|
||||
"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;
|
||||
};
|
||||
})();
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createDatabaseAdapter = createDatabaseAdapter;
|
||||
const fs_1 = require("fs");
|
||||
const fsSync = __importStar(require("fs"));
|
||||
const path_1 = __importDefault(require("path"));
|
||||
const logger_1 = require("../utils/logger");
|
||||
async function createDatabaseAdapter(dbPath) {
|
||||
if (process.env.MCP_MODE !== 'stdio') {
|
||||
logger_1.logger.info(`Node.js version: ${process.version}`);
|
||||
}
|
||||
if (process.env.MCP_MODE !== 'stdio') {
|
||||
logger_1.logger.info(`Platform: ${process.platform} ${process.arch}`);
|
||||
}
|
||||
try {
|
||||
if (process.env.MCP_MODE !== 'stdio') {
|
||||
logger_1.logger.info('Attempting to use better-sqlite3...');
|
||||
}
|
||||
const adapter = await createBetterSQLiteAdapter(dbPath);
|
||||
if (process.env.MCP_MODE !== 'stdio') {
|
||||
logger_1.logger.info('Successfully initialized better-sqlite3 adapter');
|
||||
}
|
||||
return adapter;
|
||||
}
|
||||
catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : String(error);
|
||||
if (errorMessage.includes('NODE_MODULE_VERSION') || errorMessage.includes('was compiled against a different Node.js version')) {
|
||||
if (process.env.MCP_MODE !== 'stdio') {
|
||||
logger_1.logger.warn(`Node.js version mismatch detected. Better-sqlite3 was compiled for a different Node.js version.`);
|
||||
}
|
||||
if (process.env.MCP_MODE !== 'stdio') {
|
||||
logger_1.logger.warn(`Current Node.js version: ${process.version}`);
|
||||
}
|
||||
}
|
||||
if (process.env.MCP_MODE !== 'stdio') {
|
||||
logger_1.logger.warn('Failed to initialize better-sqlite3, falling back to sql.js', error);
|
||||
}
|
||||
try {
|
||||
const adapter = await createSQLJSAdapter(dbPath);
|
||||
if (process.env.MCP_MODE !== 'stdio') {
|
||||
logger_1.logger.info('Successfully initialized sql.js adapter (pure JavaScript, no native dependencies)');
|
||||
}
|
||||
return adapter;
|
||||
}
|
||||
catch (sqlJsError) {
|
||||
if (process.env.MCP_MODE !== 'stdio') {
|
||||
logger_1.logger.error('Failed to initialize sql.js adapter', sqlJsError);
|
||||
}
|
||||
throw new Error('Failed to initialize any database adapter');
|
||||
}
|
||||
}
|
||||
}
|
||||
async function createBetterSQLiteAdapter(dbPath) {
|
||||
try {
|
||||
const Database = require('better-sqlite3');
|
||||
const db = new Database(dbPath);
|
||||
return new BetterSQLiteAdapter(db);
|
||||
}
|
||||
catch (error) {
|
||||
throw new Error(`Failed to create better-sqlite3 adapter: ${error}`);
|
||||
}
|
||||
}
|
||||
async function createSQLJSAdapter(dbPath) {
|
||||
let initSqlJs;
|
||||
try {
|
||||
initSqlJs = require('sql.js');
|
||||
}
|
||||
catch (error) {
|
||||
logger_1.logger.error('Failed to load sql.js module:', error);
|
||||
throw new Error('sql.js module not found. This might be an issue with npm package installation.');
|
||||
}
|
||||
const SQL = await initSqlJs({
|
||||
locateFile: (file) => {
|
||||
if (file.endsWith('.wasm')) {
|
||||
const possiblePaths = [
|
||||
path_1.default.join(__dirname, '../../node_modules/sql.js/dist/', file),
|
||||
path_1.default.join(__dirname, '../../../sql.js/dist/', file),
|
||||
path_1.default.join(process.cwd(), 'node_modules/sql.js/dist/', file),
|
||||
path_1.default.join(path_1.default.dirname(require.resolve('sql.js')), '../dist/', file)
|
||||
];
|
||||
for (const tryPath of possiblePaths) {
|
||||
if (fsSync.existsSync(tryPath)) {
|
||||
if (process.env.MCP_MODE !== 'stdio') {
|
||||
logger_1.logger.debug(`Found WASM file at: ${tryPath}`);
|
||||
}
|
||||
return tryPath;
|
||||
}
|
||||
}
|
||||
try {
|
||||
const wasmPath = require.resolve('sql.js/dist/sql-wasm.wasm');
|
||||
if (process.env.MCP_MODE !== 'stdio') {
|
||||
logger_1.logger.debug(`Found WASM file via require.resolve: ${wasmPath}`);
|
||||
}
|
||||
return wasmPath;
|
||||
}
|
||||
catch (e) {
|
||||
logger_1.logger.warn(`Could not find WASM file, using default path: ${file}`);
|
||||
return file;
|
||||
}
|
||||
}
|
||||
return file;
|
||||
}
|
||||
});
|
||||
let db;
|
||||
try {
|
||||
const data = await fs_1.promises.readFile(dbPath);
|
||||
db = new SQL.Database(new Uint8Array(data));
|
||||
logger_1.logger.info(`Loaded existing database from ${dbPath}`);
|
||||
}
|
||||
catch (error) {
|
||||
db = new SQL.Database();
|
||||
logger_1.logger.info(`Created new database at ${dbPath}`);
|
||||
}
|
||||
return new SQLJSAdapter(db, dbPath);
|
||||
}
|
||||
class BetterSQLiteAdapter {
|
||||
constructor(db) {
|
||||
this.db = db;
|
||||
}
|
||||
prepare(sql) {
|
||||
const stmt = this.db.prepare(sql);
|
||||
return new BetterSQLiteStatement(stmt);
|
||||
}
|
||||
exec(sql) {
|
||||
this.db.exec(sql);
|
||||
}
|
||||
close() {
|
||||
this.db.close();
|
||||
}
|
||||
pragma(key, value) {
|
||||
return this.db.pragma(key, value);
|
||||
}
|
||||
get inTransaction() {
|
||||
return this.db.inTransaction;
|
||||
}
|
||||
transaction(fn) {
|
||||
return this.db.transaction(fn)();
|
||||
}
|
||||
checkFTS5Support() {
|
||||
try {
|
||||
this.exec("CREATE VIRTUAL TABLE IF NOT EXISTS test_fts5 USING fts5(content);");
|
||||
this.exec("DROP TABLE IF EXISTS test_fts5;");
|
||||
return true;
|
||||
}
|
||||
catch (error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
class SQLJSAdapter {
|
||||
constructor(db, dbPath) {
|
||||
this.db = db;
|
||||
this.dbPath = dbPath;
|
||||
this.saveTimer = null;
|
||||
this.closed = false;
|
||||
const envInterval = process.env.SQLJS_SAVE_INTERVAL_MS;
|
||||
this.saveIntervalMs = envInterval ? parseInt(envInterval, 10) : SQLJSAdapter.DEFAULT_SAVE_INTERVAL_MS;
|
||||
if (isNaN(this.saveIntervalMs) || this.saveIntervalMs < 100 || this.saveIntervalMs > 60000) {
|
||||
logger_1.logger.warn(`Invalid SQLJS_SAVE_INTERVAL_MS value: ${envInterval} (must be 100-60000ms), ` +
|
||||
`using default ${SQLJSAdapter.DEFAULT_SAVE_INTERVAL_MS}ms`);
|
||||
this.saveIntervalMs = SQLJSAdapter.DEFAULT_SAVE_INTERVAL_MS;
|
||||
}
|
||||
logger_1.logger.debug(`SQLJSAdapter initialized with save interval: ${this.saveIntervalMs}ms`);
|
||||
}
|
||||
prepare(sql) {
|
||||
const stmt = this.db.prepare(sql);
|
||||
return new SQLJSStatement(stmt, () => this.scheduleSave());
|
||||
}
|
||||
exec(sql) {
|
||||
this.db.exec(sql);
|
||||
this.scheduleSave();
|
||||
}
|
||||
close() {
|
||||
if (this.closed) {
|
||||
logger_1.logger.debug('SQLJSAdapter already closed, skipping');
|
||||
return;
|
||||
}
|
||||
this.saveToFile();
|
||||
if (this.saveTimer) {
|
||||
clearTimeout(this.saveTimer);
|
||||
this.saveTimer = null;
|
||||
}
|
||||
this.db.close();
|
||||
this.closed = true;
|
||||
}
|
||||
pragma(key, value) {
|
||||
if (key === 'journal_mode' && value === 'WAL') {
|
||||
return 'memory';
|
||||
}
|
||||
return null;
|
||||
}
|
||||
get inTransaction() {
|
||||
return false;
|
||||
}
|
||||
transaction(fn) {
|
||||
try {
|
||||
this.exec('BEGIN');
|
||||
const result = fn();
|
||||
this.exec('COMMIT');
|
||||
return result;
|
||||
}
|
||||
catch (error) {
|
||||
this.exec('ROLLBACK');
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
checkFTS5Support() {
|
||||
try {
|
||||
this.exec("CREATE VIRTUAL TABLE IF NOT EXISTS test_fts5 USING fts5(content);");
|
||||
this.exec("DROP TABLE IF EXISTS test_fts5;");
|
||||
return true;
|
||||
}
|
||||
catch (error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
scheduleSave() {
|
||||
if (this.saveTimer) {
|
||||
clearTimeout(this.saveTimer);
|
||||
}
|
||||
this.saveTimer = setTimeout(() => {
|
||||
this.saveToFile();
|
||||
}, this.saveIntervalMs);
|
||||
}
|
||||
saveToFile() {
|
||||
try {
|
||||
const data = this.db.export();
|
||||
fsSync.writeFileSync(this.dbPath, data);
|
||||
logger_1.logger.debug(`Database saved to ${this.dbPath}`);
|
||||
}
|
||||
catch (error) {
|
||||
logger_1.logger.error('Failed to save database', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
SQLJSAdapter.DEFAULT_SAVE_INTERVAL_MS = 5000;
|
||||
class BetterSQLiteStatement {
|
||||
constructor(stmt) {
|
||||
this.stmt = stmt;
|
||||
}
|
||||
run(...params) {
|
||||
return this.stmt.run(...params);
|
||||
}
|
||||
get(...params) {
|
||||
return this.stmt.get(...params);
|
||||
}
|
||||
all(...params) {
|
||||
return this.stmt.all(...params);
|
||||
}
|
||||
iterate(...params) {
|
||||
return this.stmt.iterate(...params);
|
||||
}
|
||||
pluck(toggle) {
|
||||
this.stmt.pluck(toggle);
|
||||
return this;
|
||||
}
|
||||
expand(toggle) {
|
||||
this.stmt.expand(toggle);
|
||||
return this;
|
||||
}
|
||||
raw(toggle) {
|
||||
this.stmt.raw(toggle);
|
||||
return this;
|
||||
}
|
||||
columns() {
|
||||
return this.stmt.columns();
|
||||
}
|
||||
bind(...params) {
|
||||
this.stmt.bind(...params);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
class SQLJSStatement {
|
||||
constructor(stmt, onModify) {
|
||||
this.stmt = stmt;
|
||||
this.onModify = onModify;
|
||||
this.boundParams = null;
|
||||
}
|
||||
run(...params) {
|
||||
try {
|
||||
if (params.length > 0) {
|
||||
this.bindParams(params);
|
||||
if (this.boundParams) {
|
||||
this.stmt.bind(this.boundParams);
|
||||
}
|
||||
}
|
||||
this.stmt.run();
|
||||
this.onModify();
|
||||
return {
|
||||
changes: 1,
|
||||
lastInsertRowid: 0
|
||||
};
|
||||
}
|
||||
catch (error) {
|
||||
this.stmt.reset();
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
get(...params) {
|
||||
try {
|
||||
if (params.length > 0) {
|
||||
this.bindParams(params);
|
||||
if (this.boundParams) {
|
||||
this.stmt.bind(this.boundParams);
|
||||
}
|
||||
}
|
||||
if (this.stmt.step()) {
|
||||
const result = this.stmt.getAsObject();
|
||||
this.stmt.reset();
|
||||
return this.convertIntegerColumns(result);
|
||||
}
|
||||
this.stmt.reset();
|
||||
return undefined;
|
||||
}
|
||||
catch (error) {
|
||||
this.stmt.reset();
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
all(...params) {
|
||||
try {
|
||||
if (params.length > 0) {
|
||||
this.bindParams(params);
|
||||
if (this.boundParams) {
|
||||
this.stmt.bind(this.boundParams);
|
||||
}
|
||||
}
|
||||
const results = [];
|
||||
while (this.stmt.step()) {
|
||||
results.push(this.convertIntegerColumns(this.stmt.getAsObject()));
|
||||
}
|
||||
this.stmt.reset();
|
||||
return results;
|
||||
}
|
||||
catch (error) {
|
||||
this.stmt.reset();
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
iterate(...params) {
|
||||
return this.all(...params)[Symbol.iterator]();
|
||||
}
|
||||
pluck(toggle) {
|
||||
return this;
|
||||
}
|
||||
expand(toggle) {
|
||||
return this;
|
||||
}
|
||||
raw(toggle) {
|
||||
return this;
|
||||
}
|
||||
columns() {
|
||||
return [];
|
||||
}
|
||||
bind(...params) {
|
||||
this.bindParams(params);
|
||||
return this;
|
||||
}
|
||||
bindParams(params) {
|
||||
if (params.length === 0) {
|
||||
this.boundParams = null;
|
||||
return;
|
||||
}
|
||||
if (params.length === 1 && typeof params[0] === 'object' && !Array.isArray(params[0]) && params[0] !== null) {
|
||||
this.boundParams = params[0];
|
||||
}
|
||||
else {
|
||||
this.boundParams = params.map(p => p === undefined ? null : p);
|
||||
}
|
||||
}
|
||||
convertIntegerColumns(row) {
|
||||
if (!row)
|
||||
return row;
|
||||
const integerColumns = ['is_ai_tool', 'is_trigger', 'is_webhook', 'is_versioned'];
|
||||
const converted = { ...row };
|
||||
for (const col of integerColumns) {
|
||||
if (col in converted && typeof converted[col] === 'string') {
|
||||
converted[col] = parseInt(converted[col], 10);
|
||||
}
|
||||
}
|
||||
return converted;
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=database-adapter.js.map
|
||||
1
dist/database/database-adapter.js.map
vendored
Normal file
1
dist/database/database-adapter.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
91
dist/database/node-repository.d.ts
vendored
Normal file
91
dist/database/node-repository.d.ts
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
import { DatabaseAdapter } from './database-adapter';
|
||||
import { ParsedNode } from '../parsers/node-parser';
|
||||
import { SQLiteStorageService } from '../services/sqlite-storage-service';
|
||||
export declare class NodeRepository {
|
||||
private db;
|
||||
constructor(dbOrService: DatabaseAdapter | SQLiteStorageService);
|
||||
saveNode(node: ParsedNode): void;
|
||||
getNode(nodeType: string): any;
|
||||
getAITools(): any[];
|
||||
private safeJsonParse;
|
||||
upsertNode(node: ParsedNode): void;
|
||||
getNodeByType(nodeType: string): any;
|
||||
getNodesByCategory(category: string): any[];
|
||||
searchNodes(query: string, mode?: 'OR' | 'AND' | 'FUZZY', limit?: number): any[];
|
||||
getAllNodes(limit?: number): any[];
|
||||
getNodeCount(): number;
|
||||
getAIToolNodes(): any[];
|
||||
getNodesByPackage(packageName: string): any[];
|
||||
searchNodeProperties(nodeType: string, query: string, maxResults?: number): any[];
|
||||
private parseNodeRow;
|
||||
getNodeOperations(nodeType: string, resource?: string): any[];
|
||||
getNodeResources(nodeType: string): any[];
|
||||
getOperationsForResource(nodeType: string, resource: string): any[];
|
||||
getAllOperations(): Map<string, any[]>;
|
||||
getAllResources(): Map<string, any[]>;
|
||||
getNodePropertyDefaults(nodeType: string): Record<string, any>;
|
||||
getDefaultOperationForResource(nodeType: string, resource?: string): string | undefined;
|
||||
saveNodeVersion(versionData: {
|
||||
nodeType: string;
|
||||
version: string;
|
||||
packageName: string;
|
||||
displayName: string;
|
||||
description?: string;
|
||||
category?: string;
|
||||
isCurrentMax?: boolean;
|
||||
propertiesSchema?: any;
|
||||
operations?: any;
|
||||
credentialsRequired?: any;
|
||||
outputs?: any;
|
||||
minimumN8nVersion?: string;
|
||||
breakingChanges?: any[];
|
||||
deprecatedProperties?: string[];
|
||||
addedProperties?: string[];
|
||||
releasedAt?: Date;
|
||||
}): void;
|
||||
getNodeVersions(nodeType: string): any[];
|
||||
getLatestNodeVersion(nodeType: string): any | null;
|
||||
getNodeVersion(nodeType: string, version: string): any | null;
|
||||
savePropertyChange(changeData: {
|
||||
nodeType: string;
|
||||
fromVersion: string;
|
||||
toVersion: string;
|
||||
propertyName: string;
|
||||
changeType: 'added' | 'removed' | 'renamed' | 'type_changed' | 'requirement_changed' | 'default_changed';
|
||||
isBreaking?: boolean;
|
||||
oldValue?: string;
|
||||
newValue?: string;
|
||||
migrationHint?: string;
|
||||
autoMigratable?: boolean;
|
||||
migrationStrategy?: any;
|
||||
severity?: 'LOW' | 'MEDIUM' | 'HIGH';
|
||||
}): void;
|
||||
getPropertyChanges(nodeType: string, fromVersion: string, toVersion: string): any[];
|
||||
getBreakingChanges(nodeType: string, fromVersion: string, toVersion?: string): any[];
|
||||
getAutoMigratableChanges(nodeType: string, fromVersion: string, toVersion: string): any[];
|
||||
hasVersionUpgradePath(nodeType: string, fromVersion: string, toVersion: string): boolean;
|
||||
getVersionedNodesCount(): number;
|
||||
private parseNodeVersionRow;
|
||||
private parsePropertyChangeRow;
|
||||
createWorkflowVersion(data: {
|
||||
workflowId: string;
|
||||
versionNumber: number;
|
||||
workflowName: string;
|
||||
workflowSnapshot: any;
|
||||
trigger: 'partial_update' | 'full_update' | 'autofix';
|
||||
operations?: any[];
|
||||
fixTypes?: string[];
|
||||
metadata?: any;
|
||||
}): number;
|
||||
getWorkflowVersions(workflowId: string, limit?: number): any[];
|
||||
getWorkflowVersion(versionId: number): any | null;
|
||||
getLatestWorkflowVersion(workflowId: string): any | null;
|
||||
deleteWorkflowVersion(versionId: number): void;
|
||||
deleteWorkflowVersionsByWorkflowId(workflowId: string): number;
|
||||
pruneWorkflowVersions(workflowId: string, keepCount: number): number;
|
||||
truncateWorkflowVersions(): number;
|
||||
getWorkflowVersionCount(workflowId: string): number;
|
||||
getVersionStorageStats(): any;
|
||||
private parseWorkflowVersionRow;
|
||||
}
|
||||
//# sourceMappingURL=node-repository.d.ts.map
|
||||
1
dist/database/node-repository.d.ts.map
vendored
Normal file
1
dist/database/node-repository.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"node-repository.d.ts","sourceRoot":"","sources":["../../src/database/node-repository.ts"],"names":[],"mappings":"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"}
|
||||
603
dist/database/node-repository.js
vendored
Normal file
603
dist/database/node-repository.js
vendored
Normal file
@@ -0,0 +1,603 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.NodeRepository = void 0;
|
||||
const sqlite_storage_service_1 = require("../services/sqlite-storage-service");
|
||||
const node_type_normalizer_1 = require("../utils/node-type-normalizer");
|
||||
class NodeRepository {
|
||||
constructor(dbOrService) {
|
||||
if (dbOrService instanceof sqlite_storage_service_1.SQLiteStorageService) {
|
||||
this.db = dbOrService.db;
|
||||
return;
|
||||
}
|
||||
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 normalizedType = node_type_normalizer_1.NodeTypeNormalizer.normalizeToFullForm(nodeType);
|
||||
const row = this.db.prepare(`
|
||||
SELECT * FROM nodes WHERE node_type = ?
|
||||
`).get(normalizedType);
|
||||
if (!row && normalizedType !== nodeType) {
|
||||
const originalRow = this.db.prepare(`
|
||||
SELECT * FROM nodes WHERE node_type = ?
|
||||
`).get(nodeType);
|
||||
if (originalRow) {
|
||||
return this.parseNodeRow(originalRow);
|
||||
}
|
||||
}
|
||||
if (!row)
|
||||
return null;
|
||||
return this.parseNodeRow(row);
|
||||
}
|
||||
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
|
||||
};
|
||||
}
|
||||
getNodeOperations(nodeType, resource) {
|
||||
const node = this.getNode(nodeType);
|
||||
if (!node)
|
||||
return [];
|
||||
const operations = [];
|
||||
if (node.operations) {
|
||||
if (Array.isArray(node.operations)) {
|
||||
operations.push(...node.operations);
|
||||
}
|
||||
else if (typeof node.operations === 'object') {
|
||||
if (resource && node.operations[resource]) {
|
||||
return node.operations[resource];
|
||||
}
|
||||
else {
|
||||
Object.values(node.operations).forEach(ops => {
|
||||
if (Array.isArray(ops)) {
|
||||
operations.push(...ops);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
if (node.properties && Array.isArray(node.properties)) {
|
||||
for (const prop of node.properties) {
|
||||
if (prop.name === 'operation' && prop.options) {
|
||||
if (resource && prop.displayOptions?.show?.resource) {
|
||||
const allowedResources = Array.isArray(prop.displayOptions.show.resource)
|
||||
? prop.displayOptions.show.resource
|
||||
: [prop.displayOptions.show.resource];
|
||||
if (!allowedResources.includes(resource)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
operations.push(...prop.options);
|
||||
}
|
||||
}
|
||||
}
|
||||
return operations;
|
||||
}
|
||||
getNodeResources(nodeType) {
|
||||
const node = this.getNode(nodeType);
|
||||
if (!node || !node.properties)
|
||||
return [];
|
||||
const resources = [];
|
||||
for (const prop of node.properties) {
|
||||
if (prop.name === 'resource' && prop.options) {
|
||||
resources.push(...prop.options);
|
||||
}
|
||||
}
|
||||
return resources;
|
||||
}
|
||||
getOperationsForResource(nodeType, resource) {
|
||||
const node = this.getNode(nodeType);
|
||||
if (!node || !node.properties)
|
||||
return [];
|
||||
const operations = [];
|
||||
for (const prop of node.properties) {
|
||||
if (prop.name === 'operation' && prop.displayOptions?.show?.resource) {
|
||||
const allowedResources = Array.isArray(prop.displayOptions.show.resource)
|
||||
? prop.displayOptions.show.resource
|
||||
: [prop.displayOptions.show.resource];
|
||||
if (allowedResources.includes(resource) && prop.options) {
|
||||
operations.push(...prop.options);
|
||||
}
|
||||
}
|
||||
}
|
||||
return operations;
|
||||
}
|
||||
getAllOperations() {
|
||||
const allOperations = new Map();
|
||||
const nodes = this.getAllNodes();
|
||||
for (const node of nodes) {
|
||||
const operations = this.getNodeOperations(node.nodeType);
|
||||
if (operations.length > 0) {
|
||||
allOperations.set(node.nodeType, operations);
|
||||
}
|
||||
}
|
||||
return allOperations;
|
||||
}
|
||||
getAllResources() {
|
||||
const allResources = new Map();
|
||||
const nodes = this.getAllNodes();
|
||||
for (const node of nodes) {
|
||||
const resources = this.getNodeResources(node.nodeType);
|
||||
if (resources.length > 0) {
|
||||
allResources.set(node.nodeType, resources);
|
||||
}
|
||||
}
|
||||
return allResources;
|
||||
}
|
||||
getNodePropertyDefaults(nodeType) {
|
||||
try {
|
||||
const node = this.getNode(nodeType);
|
||||
if (!node || !node.properties)
|
||||
return {};
|
||||
const defaults = {};
|
||||
for (const prop of node.properties) {
|
||||
if (prop.name && prop.default !== undefined) {
|
||||
defaults[prop.name] = prop.default;
|
||||
}
|
||||
}
|
||||
return defaults;
|
||||
}
|
||||
catch (error) {
|
||||
console.error(`Error getting property defaults for ${nodeType}:`, error);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
getDefaultOperationForResource(nodeType, resource) {
|
||||
try {
|
||||
const node = this.getNode(nodeType);
|
||||
if (!node || !node.properties)
|
||||
return undefined;
|
||||
for (const prop of node.properties) {
|
||||
if (prop.name === 'operation') {
|
||||
if (resource && prop.displayOptions?.show?.resource) {
|
||||
const resourceDep = prop.displayOptions.show.resource;
|
||||
if (!Array.isArray(resourceDep) && typeof resourceDep !== 'string') {
|
||||
continue;
|
||||
}
|
||||
const allowedResources = Array.isArray(resourceDep)
|
||||
? resourceDep
|
||||
: [resourceDep];
|
||||
if (!allowedResources.includes(resource)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (prop.default !== undefined) {
|
||||
return prop.default;
|
||||
}
|
||||
if (prop.options && Array.isArray(prop.options) && prop.options.length > 0) {
|
||||
const firstOption = prop.options[0];
|
||||
return typeof firstOption === 'string' ? firstOption : firstOption.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.error(`Error getting default operation for ${nodeType}:`, error);
|
||||
return undefined;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
saveNodeVersion(versionData) {
|
||||
const stmt = this.db.prepare(`
|
||||
INSERT OR REPLACE INTO node_versions (
|
||||
node_type, version, package_name, display_name, description,
|
||||
category, is_current_max, properties_schema, operations,
|
||||
credentials_required, outputs, minimum_n8n_version,
|
||||
breaking_changes, deprecated_properties, added_properties,
|
||||
released_at
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`);
|
||||
stmt.run(versionData.nodeType, versionData.version, versionData.packageName, versionData.displayName, versionData.description || null, versionData.category || null, versionData.isCurrentMax ? 1 : 0, versionData.propertiesSchema ? JSON.stringify(versionData.propertiesSchema) : null, versionData.operations ? JSON.stringify(versionData.operations) : null, versionData.credentialsRequired ? JSON.stringify(versionData.credentialsRequired) : null, versionData.outputs ? JSON.stringify(versionData.outputs) : null, versionData.minimumN8nVersion || null, versionData.breakingChanges ? JSON.stringify(versionData.breakingChanges) : null, versionData.deprecatedProperties ? JSON.stringify(versionData.deprecatedProperties) : null, versionData.addedProperties ? JSON.stringify(versionData.addedProperties) : null, versionData.releasedAt || null);
|
||||
}
|
||||
getNodeVersions(nodeType) {
|
||||
const normalizedType = node_type_normalizer_1.NodeTypeNormalizer.normalizeToFullForm(nodeType);
|
||||
const rows = this.db.prepare(`
|
||||
SELECT * FROM node_versions
|
||||
WHERE node_type = ?
|
||||
ORDER BY version DESC
|
||||
`).all(normalizedType);
|
||||
return rows.map(row => this.parseNodeVersionRow(row));
|
||||
}
|
||||
getLatestNodeVersion(nodeType) {
|
||||
const normalizedType = node_type_normalizer_1.NodeTypeNormalizer.normalizeToFullForm(nodeType);
|
||||
const row = this.db.prepare(`
|
||||
SELECT * FROM node_versions
|
||||
WHERE node_type = ? AND is_current_max = 1
|
||||
LIMIT 1
|
||||
`).get(normalizedType);
|
||||
if (!row)
|
||||
return null;
|
||||
return this.parseNodeVersionRow(row);
|
||||
}
|
||||
getNodeVersion(nodeType, version) {
|
||||
const normalizedType = node_type_normalizer_1.NodeTypeNormalizer.normalizeToFullForm(nodeType);
|
||||
const row = this.db.prepare(`
|
||||
SELECT * FROM node_versions
|
||||
WHERE node_type = ? AND version = ?
|
||||
`).get(normalizedType, version);
|
||||
if (!row)
|
||||
return null;
|
||||
return this.parseNodeVersionRow(row);
|
||||
}
|
||||
savePropertyChange(changeData) {
|
||||
const stmt = this.db.prepare(`
|
||||
INSERT INTO version_property_changes (
|
||||
node_type, from_version, to_version, property_name, change_type,
|
||||
is_breaking, old_value, new_value, migration_hint, auto_migratable,
|
||||
migration_strategy, severity
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`);
|
||||
stmt.run(changeData.nodeType, changeData.fromVersion, changeData.toVersion, changeData.propertyName, changeData.changeType, changeData.isBreaking ? 1 : 0, changeData.oldValue || null, changeData.newValue || null, changeData.migrationHint || null, changeData.autoMigratable ? 1 : 0, changeData.migrationStrategy ? JSON.stringify(changeData.migrationStrategy) : null, changeData.severity || 'MEDIUM');
|
||||
}
|
||||
getPropertyChanges(nodeType, fromVersion, toVersion) {
|
||||
const normalizedType = node_type_normalizer_1.NodeTypeNormalizer.normalizeToFullForm(nodeType);
|
||||
const rows = this.db.prepare(`
|
||||
SELECT * FROM version_property_changes
|
||||
WHERE node_type = ? AND from_version = ? AND to_version = ?
|
||||
ORDER BY severity DESC, property_name
|
||||
`).all(normalizedType, fromVersion, toVersion);
|
||||
return rows.map(row => this.parsePropertyChangeRow(row));
|
||||
}
|
||||
getBreakingChanges(nodeType, fromVersion, toVersion) {
|
||||
const normalizedType = node_type_normalizer_1.NodeTypeNormalizer.normalizeToFullForm(nodeType);
|
||||
let sql = `
|
||||
SELECT * FROM version_property_changes
|
||||
WHERE node_type = ? AND is_breaking = 1
|
||||
`;
|
||||
const params = [normalizedType];
|
||||
if (toVersion) {
|
||||
sql += ` AND from_version >= ? AND to_version <= ?`;
|
||||
params.push(fromVersion, toVersion);
|
||||
}
|
||||
else {
|
||||
sql += ` AND from_version >= ?`;
|
||||
params.push(fromVersion);
|
||||
}
|
||||
sql += ` ORDER BY from_version, to_version, severity DESC`;
|
||||
const rows = this.db.prepare(sql).all(...params);
|
||||
return rows.map(row => this.parsePropertyChangeRow(row));
|
||||
}
|
||||
getAutoMigratableChanges(nodeType, fromVersion, toVersion) {
|
||||
const normalizedType = node_type_normalizer_1.NodeTypeNormalizer.normalizeToFullForm(nodeType);
|
||||
const rows = this.db.prepare(`
|
||||
SELECT * FROM version_property_changes
|
||||
WHERE node_type = ?
|
||||
AND from_version = ?
|
||||
AND to_version = ?
|
||||
AND auto_migratable = 1
|
||||
ORDER BY severity DESC
|
||||
`).all(normalizedType, fromVersion, toVersion);
|
||||
return rows.map(row => this.parsePropertyChangeRow(row));
|
||||
}
|
||||
hasVersionUpgradePath(nodeType, fromVersion, toVersion) {
|
||||
const versions = this.getNodeVersions(nodeType);
|
||||
if (versions.length === 0)
|
||||
return false;
|
||||
const fromExists = versions.some(v => v.version === fromVersion);
|
||||
const toExists = versions.some(v => v.version === toVersion);
|
||||
return fromExists && toExists;
|
||||
}
|
||||
getVersionedNodesCount() {
|
||||
const result = this.db.prepare(`
|
||||
SELECT COUNT(DISTINCT node_type) as count
|
||||
FROM node_versions
|
||||
`).get();
|
||||
return result.count;
|
||||
}
|
||||
parseNodeVersionRow(row) {
|
||||
return {
|
||||
id: row.id,
|
||||
nodeType: row.node_type,
|
||||
version: row.version,
|
||||
packageName: row.package_name,
|
||||
displayName: row.display_name,
|
||||
description: row.description,
|
||||
category: row.category,
|
||||
isCurrentMax: Number(row.is_current_max) === 1,
|
||||
propertiesSchema: row.properties_schema ? this.safeJsonParse(row.properties_schema, []) : null,
|
||||
operations: row.operations ? this.safeJsonParse(row.operations, []) : null,
|
||||
credentialsRequired: row.credentials_required ? this.safeJsonParse(row.credentials_required, []) : null,
|
||||
outputs: row.outputs ? this.safeJsonParse(row.outputs, null) : null,
|
||||
minimumN8nVersion: row.minimum_n8n_version,
|
||||
breakingChanges: row.breaking_changes ? this.safeJsonParse(row.breaking_changes, []) : [],
|
||||
deprecatedProperties: row.deprecated_properties ? this.safeJsonParse(row.deprecated_properties, []) : [],
|
||||
addedProperties: row.added_properties ? this.safeJsonParse(row.added_properties, []) : [],
|
||||
releasedAt: row.released_at,
|
||||
createdAt: row.created_at
|
||||
};
|
||||
}
|
||||
parsePropertyChangeRow(row) {
|
||||
return {
|
||||
id: row.id,
|
||||
nodeType: row.node_type,
|
||||
fromVersion: row.from_version,
|
||||
toVersion: row.to_version,
|
||||
propertyName: row.property_name,
|
||||
changeType: row.change_type,
|
||||
isBreaking: Number(row.is_breaking) === 1,
|
||||
oldValue: row.old_value,
|
||||
newValue: row.new_value,
|
||||
migrationHint: row.migration_hint,
|
||||
autoMigratable: Number(row.auto_migratable) === 1,
|
||||
migrationStrategy: row.migration_strategy ? this.safeJsonParse(row.migration_strategy, null) : null,
|
||||
severity: row.severity,
|
||||
createdAt: row.created_at
|
||||
};
|
||||
}
|
||||
createWorkflowVersion(data) {
|
||||
const stmt = this.db.prepare(`
|
||||
INSERT INTO workflow_versions (
|
||||
workflow_id, version_number, workflow_name, workflow_snapshot,
|
||||
trigger, operations, fix_types, metadata
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`);
|
||||
const result = stmt.run(data.workflowId, data.versionNumber, data.workflowName, JSON.stringify(data.workflowSnapshot), data.trigger, data.operations ? JSON.stringify(data.operations) : null, data.fixTypes ? JSON.stringify(data.fixTypes) : null, data.metadata ? JSON.stringify(data.metadata) : null);
|
||||
return result.lastInsertRowid;
|
||||
}
|
||||
getWorkflowVersions(workflowId, limit) {
|
||||
let sql = `
|
||||
SELECT * FROM workflow_versions
|
||||
WHERE workflow_id = ?
|
||||
ORDER BY version_number DESC
|
||||
`;
|
||||
if (limit) {
|
||||
sql += ` LIMIT ?`;
|
||||
const rows = this.db.prepare(sql).all(workflowId, limit);
|
||||
return rows.map(row => this.parseWorkflowVersionRow(row));
|
||||
}
|
||||
const rows = this.db.prepare(sql).all(workflowId);
|
||||
return rows.map(row => this.parseWorkflowVersionRow(row));
|
||||
}
|
||||
getWorkflowVersion(versionId) {
|
||||
const row = this.db.prepare(`
|
||||
SELECT * FROM workflow_versions WHERE id = ?
|
||||
`).get(versionId);
|
||||
if (!row)
|
||||
return null;
|
||||
return this.parseWorkflowVersionRow(row);
|
||||
}
|
||||
getLatestWorkflowVersion(workflowId) {
|
||||
const row = this.db.prepare(`
|
||||
SELECT * FROM workflow_versions
|
||||
WHERE workflow_id = ?
|
||||
ORDER BY version_number DESC
|
||||
LIMIT 1
|
||||
`).get(workflowId);
|
||||
if (!row)
|
||||
return null;
|
||||
return this.parseWorkflowVersionRow(row);
|
||||
}
|
||||
deleteWorkflowVersion(versionId) {
|
||||
this.db.prepare(`
|
||||
DELETE FROM workflow_versions WHERE id = ?
|
||||
`).run(versionId);
|
||||
}
|
||||
deleteWorkflowVersionsByWorkflowId(workflowId) {
|
||||
const result = this.db.prepare(`
|
||||
DELETE FROM workflow_versions WHERE workflow_id = ?
|
||||
`).run(workflowId);
|
||||
return result.changes;
|
||||
}
|
||||
pruneWorkflowVersions(workflowId, keepCount) {
|
||||
const versions = this.db.prepare(`
|
||||
SELECT id FROM workflow_versions
|
||||
WHERE workflow_id = ?
|
||||
ORDER BY version_number DESC
|
||||
`).all(workflowId);
|
||||
if (versions.length <= keepCount) {
|
||||
return 0;
|
||||
}
|
||||
const idsToDelete = versions.slice(keepCount).map(v => v.id);
|
||||
if (idsToDelete.length === 0) {
|
||||
return 0;
|
||||
}
|
||||
const placeholders = idsToDelete.map(() => '?').join(',');
|
||||
const result = this.db.prepare(`
|
||||
DELETE FROM workflow_versions WHERE id IN (${placeholders})
|
||||
`).run(...idsToDelete);
|
||||
return result.changes;
|
||||
}
|
||||
truncateWorkflowVersions() {
|
||||
const result = this.db.prepare(`
|
||||
DELETE FROM workflow_versions
|
||||
`).run();
|
||||
return result.changes;
|
||||
}
|
||||
getWorkflowVersionCount(workflowId) {
|
||||
const result = this.db.prepare(`
|
||||
SELECT COUNT(*) as count FROM workflow_versions WHERE workflow_id = ?
|
||||
`).get(workflowId);
|
||||
return result.count;
|
||||
}
|
||||
getVersionStorageStats() {
|
||||
const totalResult = this.db.prepare(`
|
||||
SELECT COUNT(*) as count FROM workflow_versions
|
||||
`).get();
|
||||
const sizeResult = this.db.prepare(`
|
||||
SELECT SUM(LENGTH(workflow_snapshot)) as total_size FROM workflow_versions
|
||||
`).get();
|
||||
const byWorkflow = this.db.prepare(`
|
||||
SELECT
|
||||
workflow_id,
|
||||
workflow_name,
|
||||
COUNT(*) as version_count,
|
||||
SUM(LENGTH(workflow_snapshot)) as total_size,
|
||||
MAX(created_at) as last_backup
|
||||
FROM workflow_versions
|
||||
GROUP BY workflow_id
|
||||
ORDER BY version_count DESC
|
||||
`).all();
|
||||
return {
|
||||
totalVersions: totalResult.count,
|
||||
totalSize: sizeResult.total_size || 0,
|
||||
byWorkflow: byWorkflow.map(row => ({
|
||||
workflowId: row.workflow_id,
|
||||
workflowName: row.workflow_name,
|
||||
versionCount: row.version_count,
|
||||
totalSize: row.total_size,
|
||||
lastBackup: row.last_backup
|
||||
}))
|
||||
};
|
||||
}
|
||||
parseWorkflowVersionRow(row) {
|
||||
return {
|
||||
id: row.id,
|
||||
workflowId: row.workflow_id,
|
||||
versionNumber: row.version_number,
|
||||
workflowName: row.workflow_name,
|
||||
workflowSnapshot: this.safeJsonParse(row.workflow_snapshot, null),
|
||||
trigger: row.trigger,
|
||||
operations: row.operations ? this.safeJsonParse(row.operations, null) : null,
|
||||
fixTypes: row.fix_types ? this.safeJsonParse(row.fix_types, null) : null,
|
||||
metadata: row.metadata ? this.safeJsonParse(row.metadata, null) : null,
|
||||
createdAt: row.created_at
|
||||
};
|
||||
}
|
||||
}
|
||||
exports.NodeRepository = NodeRepository;
|
||||
//# sourceMappingURL=node-repository.js.map
|
||||
1
dist/database/node-repository.js.map
vendored
Normal file
1
dist/database/node-repository.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user