UNPKG

n8n

Version:

n8n Workflow Automation Tool

167 lines • 8.53 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.VariableExporter = void 0; const db_1 = require("@n8n/db"); const di_1 = require("@n8n/di"); const n8n_workflow_1 = require("n8n-workflow"); const variables_service_ee_1 = require("../../../../environments.ee/variables/variables.service.ee"); const variable_serializer_1 = require("./variable.serializer"); const unique_filename_allocator_1 = require("../../io/unique-filename-allocator"); const package_export_errors_1 = require("../package-export.errors"); function isBundleableVariable(variable) { return variable !== undefined; } let VariableExporter = class VariableExporter { constructor(variablesService, sharedWorkflowRepository, variableSerializer) { this.variablesService = variablesService; this.sharedWorkflowRepository = sharedWorkflowRepository; this.variableSerializer = variableSerializer; } async export(request) { if (request.requirements.length === 0) { return { entries: [], requirements: [] }; } const workflowIds = [...new Set(request.requirements.map((r) => r.workflowId))]; const [allVariables, accessibleVariables, projectIdByWorkflowId] = await Promise.all([ this.variablesService.getAllCached(), this.variablesService.getAllForUser(request.user), this.resolveWorkflowProjects(workflowIds), ]); const accessibleIds = new Set(accessibleVariables.map((variable) => variable.id)); const resolvedNames = this.resolveRequirements(request.requirements, projectIdByWorkflowId, allVariables, accessibleIds); this.assertNoBundledVariableCollision(resolvedNames, request.projectTargetsById); const allocators = new Map(); const allocatorFor = (baseDir) => { const existing = allocators.get(baseDir); if (existing) return existing; const created = new unique_filename_allocator_1.UniqueFilenameAllocator(baseDir, 'variable'); allocators.set(baseDir, created); return created; }; const entries = []; const bundledVariableIds = new Set(); const requirements = []; for (const { name, usedByWorkflows, variables } of resolvedNames) { let aggregateValue; let everyWorkflowResolvedToSameValue = true; for (const variable of variables) { if (!isBundleableVariable(variable)) { everyWorkflowResolvedToSameValue = false; continue; } if (aggregateValue === undefined) { aggregateValue = variable.value; } else if (aggregateValue !== variable.value) { everyWorkflowResolvedToSameValue = false; } if (bundledVariableIds.has(variable.id)) continue; bundledVariableIds.add(variable.id); const baseDir = this.resolveBaseDir(variable, request.projectTargetsById); const target = allocatorFor(baseDir).allocate(variable.key); request.writer.writeDirectory(target); request.writer.writeFile(`${target}/variable.json`, JSON.stringify(this.variableSerializer.serialize(variable, { includeValue: request.includeVariableValues, }), null, '\t')); entries.push({ id: variable.id, name: variable.key, target }); } requirements.push({ name, ...(request.includeVariableValues && everyWorkflowResolvedToSameValue && aggregateValue !== undefined ? { value: aggregateValue } : {}), usedByWorkflows, }); } return { entries, requirements }; } resolveRequirements(requirements, projectIdByWorkflowId, allVariables, accessibleIds) { const variablesByKey = new Map(); for (const variable of allVariables) { const bucket = variablesByKey.get(variable.key); if (bucket) bucket.push(variable); else variablesByKey.set(variable.key, [variable]); } const resolveForWorkflow = (name, workflowId) => { const workflowProjectId = projectIdByWorkflowId.get(workflowId); const picked = (0, n8n_workflow_1.pickVariableForProject)(variablesByKey.get(name) ?? [], name, workflowProjectId); return picked && accessibleIds.has(picked.id) ? picked : undefined; }; return [...this.groupByName(requirements)].map(([name, usedByWorkflows]) => ({ name, usedByWorkflows, variables: usedByWorkflows.map((workflowId) => resolveForWorkflow(name, workflowId)), })); } resolveBaseDir(variable, projectTargetsById) { if (!projectTargetsById || projectTargetsById.size === 0) return 'variables'; const prefix = variable.project ? projectTargetsById.get(variable.project.id) : undefined; return prefix ? `${prefix}/variables` : 'variables'; } async resolveWorkflowProjects(workflowIds) { const owners = await this.sharedWorkflowRepository.findByWorkflowIds(workflowIds); return new Map(owners.map((owner) => [owner.workflowId, owner.project.id])); } assertNoBundledVariableCollision(resolvedNames, projectTargetsById) { const conflictingNames = resolvedNames .filter(({ variables }) => this.hasDirectoryCollision(variables, projectTargetsById)) .map(({ name }) => name); if (conflictingNames.length === 0) return; const displayedNames = conflictingNames.slice(0, 20); const omittedCount = conflictingNames.length - displayedNames.length; throw new package_export_errors_1.PackageExportBlockedError(`${conflictingNames.length} variable name(s) resolve to different variables that would collide in the package. Export aborted.`, { description: `Conflicting variable name(s): ${displayedNames.join(', ')}${omittedCount > 0 ? `, and ${omittedCount} more` : ''}. Export the projects as a project package instead.`, }); } hasDirectoryCollision(variables, projectTargetsById) { const idByDir = new Map(); for (const variable of variables) { if (!isBundleableVariable(variable)) continue; const dir = this.resolveBaseDir(variable, projectTargetsById); const previousId = idByDir.get(dir); if (previousId !== undefined && previousId !== variable.id) return true; idByDir.set(dir, variable.id); } return false; } groupByName(requirements) { const grouped = new Map(); for (const requirement of requirements) { const workflowIds = grouped.get(requirement.variableName); if (workflowIds) { if (!workflowIds.includes(requirement.workflowId)) { workflowIds.push(requirement.workflowId); } } else { grouped.set(requirement.variableName, [requirement.workflowId]); } } return grouped; } }; exports.VariableExporter = VariableExporter; exports.VariableExporter = VariableExporter = __decorate([ (0, di_1.Service)(), __metadata("design:paramtypes", [variables_service_ee_1.VariablesService, db_1.SharedWorkflowRepository, variable_serializer_1.VariableSerializer]) ], VariableExporter); //# sourceMappingURL=variable.exporter.js.map