n8n
Version:
n8n Workflow Automation Tool
195 lines • 10.9 kB
JavaScript
;
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.ProjectPackageImporter = void 0;
const backend_common_1 = require("@n8n/backend-common");
const di_1 = require("@n8n/di");
const forbidden_error_1 = require("../../../errors/response-errors/forbidden.error");
const event_service_1 = require("../../../events/event.service");
const project_importer_1 = require("../entities/project/project-importer");
const workflow_importer_1 = require("../entities/workflow/workflow-importer");
const workflow_publisher_1 = require("../entities/workflow/workflow-publisher");
const n8n_packages_types_1 = require("../n8n-packages.types");
const import_gates_1 = require("./import-gates");
const import_blocked_error_1 = require("./import-blocked.error");
const package_layout_1 = require("./package-layout");
const import_orchestrator_1 = require("./import-orchestrator");
const import_result_1 = require("./import-result");
const import_telemetry_1 = require("./import-telemetry");
const n8n_package_parser_1 = require("./n8n-package-parser");
let ProjectPackageImporter = class ProjectPackageImporter {
constructor(packageParser, projectImporter, importOrchestrator, workflowPublisher, eventService, licenseState) {
this.packageParser = packageParser;
this.projectImporter = projectImporter;
this.importOrchestrator = importOrchestrator;
this.workflowPublisher = workflowPublisher;
this.eventService = eventService;
this.licenseState = licenseState;
}
async import(request, reader, manifest) {
this.assertAdequatePermissions(request, manifest);
const projects = await this.packageParser.getProjects(reader);
const projectPlan = await this.projectImporter.plan(request.user, projects, request.projectConflictPolicy);
if (projectPlan.conflicts.length > 0) {
throw (0, import_blocked_error_1.toImportBlockedError)(projectPlan.conflicts.map((conflict) => ({ type: 'project-conflict', ...conflict })));
}
const bundledVariables = (0, package_layout_1.needsBundledVariableValues)(request, (manifest.requirements?.variables?.length ?? 0) > 0)
? await this.packageParser.getVariables(reader)
: undefined;
const pendingCreateIds = new Set(projectPlan.items
.filter((item) => item.action === 'create')
.map((item) => item.sourceProjectId));
const planned = [];
for (const project of manifest.projects ?? []) {
const input = await this.buildImportContextForProject(request, reader, manifest, project, pendingCreateIds.has(project.id), bundledVariables);
const plan = await this.importOrchestrator.plan(input);
planned.push({ project, plan });
}
(0, import_gates_1.assertTagWritesAllowed)(request.apiKeyScopes, planned.map(({ plan }) => plan.tagPlan));
await this.importOrchestrator.assertNotBlocked(planned.map(({ plan }) => plan), { apiKeyScopes: request.apiKeyScopes });
const projectSummaries = await this.projectImporter.apply(request.user, projectPlan.items);
const packageWorkflowBindings = new Map(planned.flatMap(({ plan }) => [...(0, workflow_importer_1.collectPlannedWorkflowBindings)(plan.workflowPlan.items)]));
const applied = [];
for (const { project, plan } of planned) {
applied.push({
project,
plan,
content: await this.importOrchestrator.apply(plan, packageWorkflowBindings),
});
}
const published = await this.workflowPublisher.applyToPackage({
user: request.user,
persisted: applied.flatMap(({ content }) => content.workflowOutcomes),
policy: request.workflowPublishingPolicy,
subWorkflowRequirements: manifest.requirements?.workflows,
});
const workflows = [];
const folders = [];
const scopedBindings = [];
const matched = [];
const stubbed = [];
const variablesMatched = [];
const variablesMissing = [];
const variablesCreated = [];
const variablesStubbed = [];
const variablesSkipped = [];
const variablesUpdated = [];
const tagSummaries = [];
const scopes = [];
for (const { project, plan, content } of applied) {
workflows.push(...(0, import_result_1.toImportedWorkflowSummaries)(content.workflowOutcomes, project.id, published));
folders.push(...content.folderSummaries);
scopedBindings.push(content.bindings);
matched.push(...content.credentialResult.matched);
stubbed.push(...content.credentialResult.stubbed);
variablesMatched.push(...content.variablePlan.matched);
variablesMissing.push(...content.variablePlan.missing.map(({ name }) => name));
variablesCreated.push(...content.variableResult.created);
variablesStubbed.push(...content.variableResult.stubbed);
variablesSkipped.push(...content.variableResult.skippedExisting);
variablesUpdated.push(...content.variableResult.updated);
tagSummaries.push((0, import_result_1.toTagSummary)(content.tagPlan));
scopes.push({
context: plan.input.context,
imported: content,
credentialRequest: plan.input.credentialRequest,
dataTableRequest: plan.input.dataTableRequest,
variableRequest: plan.input.variableRequest,
tagRequest: plan.input.tagRequest,
});
}
(0, import_telemetry_1.emitPackageImportedEvent)(this.eventService, { request, manifest, scopes });
return (0, import_result_1.buildImportResult)({
package: (0, import_result_1.toPackageSummary)(manifest),
workflows,
folders,
projects: projectSummaries,
bindings: (0, n8n_packages_types_1.mergeBindings)(...scopedBindings),
credentials: { matched, stubbed },
variables: (0, import_result_1.reconcileVariableSummary)({
matched: variablesMatched,
missing: variablesMissing,
created: variablesCreated,
stubbed: variablesStubbed,
skipped: variablesSkipped,
updated: variablesUpdated,
}),
tags: (0, import_result_1.unionTagSummaries)(tagSummaries),
});
}
async buildImportContextForProject(request, reader, manifest, project, projectPendingCreation, bundledVariables) {
const basePrefix = `${project.target}/`;
const folders = await this.packageParser.getFolders(reader, basePrefix);
const workflows = await this.packageParser.getWorkflows(reader, basePrefix);
const requirements = (0, import_result_1.identifyRequirements)(manifest.requirements?.credentials, workflows);
const credentialRequest = {
requirements,
matchingMode: request.credentialMatchingMode,
missingMode: request.credentialMissingMode,
credentialBindings: (0, import_result_1.scopeCredentialBindingsToRequirements)(request.bindings?.credentials, requirements),
};
const dataTableRequest = {
requirements: (0, import_result_1.identifyRequirements)(manifest.requirements?.dataTables, workflows),
packageDataTables: await this.packageParser.getDataTables(reader),
matchingMode: request.dataTableMatchingMode,
missingMode: request.dataTableMissingMode,
schemaConflictPolicy: request.dataTableSchemaConflictPolicy,
};
const variableRequest = {
requirements: (0, package_layout_1.placeByLayout)({
requirements: (0, import_result_1.identifyRequirements)(manifest.requirements?.variables, workflows),
manifestVariables: manifest.variables,
scopePrefix: basePrefix,
bundledVariables,
}),
missingMode: request.variableMissingMode,
conflictPolicy: request.variableConflictPolicy,
};
const tagRequest = {
requirements: manifest.requirements?.tags,
missingMode: request.tagMissingMode,
conflictPolicy: request.tagConflictPolicy,
};
return {
context: {
user: request.user,
projectId: project.id,
folderId: null,
},
folders,
workflows,
credentialRequest,
dataTableRequest,
variableRequest,
tagRequest,
options: request,
projectPendingCreation,
};
}
assertAdequatePermissions(request, manifest) {
(0, import_gates_1.assertPackageImportApiKeyScopes)(request.apiKeyScopes, ['project:create', 'project:update']);
if ((manifest.folders?.length ?? 0) > 0) {
if (!this.licenseState.isLicensed('feat:folders')) {
throw new forbidden_error_1.ForbiddenError('Your license does not allow folders. Importing a package with folders requires a license that supports folders.');
}
(0, import_gates_1.assertPackageImportApiKeyScopes)(request.apiKeyScopes, ['folder:create', 'folder:update']);
}
if ((manifest.workflows?.length ?? 0) > 0) {
(0, import_gates_1.assertPackageImportApiKeyScopes)(request.apiKeyScopes, ['workflow:import']);
}
}
};
exports.ProjectPackageImporter = ProjectPackageImporter;
exports.ProjectPackageImporter = ProjectPackageImporter = __decorate([
(0, di_1.Service)(),
__metadata("design:paramtypes", [n8n_package_parser_1.N8nPackageParser, project_importer_1.ProjectImporter, import_orchestrator_1.ImportOrchestrator, workflow_publisher_1.WorkflowPublisher, event_service_1.EventService, backend_common_1.LicenseState])
], ProjectPackageImporter);
//# sourceMappingURL=project-package-importer.js.map