UNPKG

n8n

Version:

n8n Workflow Automation Tool

160 lines 7.1 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.EvalThreadRestoreService = void 0; const db_1 = require("@n8n/db"); const di_1 = require("@n8n/di"); const n8n_workflow_1 = require("n8n-workflow"); const node_crypto_1 = require("node:crypto"); const bad_request_error_1 = require("../../../errors/response-errors/bad-request.error"); const data_table_service_1 = require("../../../modules/data-table/data-table.service"); function isRecord(value) { return typeof value === 'object' && value !== null && !Array.isArray(value); } function isWorkflowNode(value) { if (!isRecord(value)) return false; return (typeof value.id === 'string' && typeof value.name === 'string' && typeof value.type === 'string' && typeof value.typeVersion === 'number' && Array.isArray(value.position) && value.position.length === 2 && value.position.every((coordinate) => typeof coordinate === 'number') && isRecord(value.parameters)); } function isConnections(value) { return isRecord(value); } let EvalThreadRestoreService = class EvalThreadRestoreService { constructor(workflowRepo, sharedWorkflowRepo, dataTableService) { this.workflowRepo = workflowRepo; this.sharedWorkflowRepo = sharedWorkflowRepo; this.dataTableService = dataTableService; } async restoreDataTables(dataTables, projectId, options = {}) { const uniquifyNames = options.uniquifyNames ?? true; const idMap = new Map(); try { for (const table of dataTables) { if (table.id.length < 8) { throw new bad_request_error_1.BadRequestError(`Seed data table id "${table.id}" is too short to remap safely (need ≥8 chars)`); } let name = table.name; if (uniquifyNames) { const suffix = ` [seed ${(0, node_crypto_1.randomUUID)().slice(0, 8)}]`; name = `${table.name.slice(0, 128 - suffix.length)}${suffix}`; } const created = await this.dataTableService.createDataTable(projectId, { name, columns: table.columns, }); idMap.set(table.id, created.id); if (table.rows && table.rows.length > 0) { await this.dataTableService.insertRows(created.id, projectId, table.rows); } } } catch (error) { await this.deleteDataTables([...idMap.values()], projectId); throw error; } return idMap; } async reseedDataTableRows(tableId, projectId, rows) { await this.dataTableService.clearRows(tableId, projectId); if (rows.length > 0) { await this.dataTableService.insertRows(tableId, projectId, rows); } } async deleteDataTables(dataTableIds, projectId) { for (const id of dataTableIds) { try { await this.dataTableService.deleteDataTable(id, projectId); } catch { } } } async restoreWorkflows(workflows, projectId, dataTableIdMap = new Map()) { const created = []; try { for (const workflow of workflows) { if (await this.createWorkflowPinnedToId(workflow, projectId, dataTableIdMap)) { created.push(workflow.id); } } } catch (error) { await this.deleteWorkflows(created); throw error; } return created; } async deleteWorkflows(workflowIds) { for (const id of workflowIds) { try { await this.workflowRepo.delete({ id }); } catch { } } } async createWorkflowPinnedToId(workflow, projectId, dataTableIdMap) { const remapDataTableIds = (value) => { if (dataTableIdMap.size === 0) return value; let serialized = JSON.stringify(value); for (const [oldId, newId] of dataTableIdMap) { serialized = serialized.replaceAll(oldId, newId); } return (0, n8n_workflow_1.jsonParse)(serialized); }; const nodes = workflow.nodes.map((node, index) => { if (!isWorkflowNode(node)) { throw new bad_request_error_1.BadRequestError(`Seed workflow ${workflow.id} node at index ${index} is not a valid workflow node`); } const { credentials: _stripped, ...rest } = node; const remapped = remapDataTableIds(rest); if (!isWorkflowNode(remapped)) { throw new bad_request_error_1.BadRequestError(`Seed workflow ${workflow.id} node at index ${index} became invalid after data-table id remap`); } return remapped; }); const connections = remapDataTableIds(workflow.connections); if (!isConnections(connections)) { throw new bad_request_error_1.BadRequestError(`Seed workflow ${workflow.id} connections must be an object`); } const owningProject = await this.sharedWorkflowRepo.getWorkflowOwningProject(workflow.id); if (owningProject && owningProject.id !== projectId) { throw new bad_request_error_1.BadRequestError(`Seed workflow id ${workflow.id} already exists in another project; refusing to overwrite`); } await this.workflowRepo.save(this.workflowRepo.create({ id: workflow.id, name: workflow.name, nodes, connections, active: false, versionId: (0, node_crypto_1.randomUUID)(), })); if (!owningProject) { await this.sharedWorkflowRepo.makeOwner([workflow.id], projectId); return true; } return false; } }; exports.EvalThreadRestoreService = EvalThreadRestoreService; exports.EvalThreadRestoreService = EvalThreadRestoreService = __decorate([ (0, di_1.Service)(), __metadata("design:paramtypes", [db_1.WorkflowRepository, db_1.SharedWorkflowRepository, data_table_service_1.DataTableService]) ], EvalThreadRestoreService); //# sourceMappingURL=thread-restore.service.js.map