n8n
Version:
n8n Workflow Automation Tool
187 lines • 11 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.ImportOrchestrator = void 0;
const backend_common_1 = require("@n8n/backend-common");
const di_1 = require("@n8n/di");
const node_types_1 = require("../../../node-types");
const credential_importer_1 = require("../entities/credential/credential-importer");
const credential_missing_mode_1 = require("../entities/credential/credential-missing-mode");
const data_table_importer_1 = require("../entities/data-table/data-table-importer");
const folder_importer_1 = require("../entities/folder/folder-importer");
const tag_importer_1 = require("../entities/tag/tag-importer");
const tag_types_1 = require("../entities/tag/tag.types");
const variable_importer_1 = require("../entities/variable/variable-importer");
const variable_types_1 = require("../entities/variable/variable.types");
const missing_node_type_mode_1 = require("../entities/workflow/missing-node-type-mode");
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_blocked_error_1 = require("./import-blocked.error");
const import_gates_1 = require("./import-gates");
let ImportOrchestrator = class ImportOrchestrator {
constructor(credentialImporter, dataTableImporter, variableImporter, tagImporter, folderImporter, workflowImporter, workflowPublisher, nodeTypes, licenseState) {
this.credentialImporter = credentialImporter;
this.dataTableImporter = dataTableImporter;
this.variableImporter = variableImporter;
this.tagImporter = tagImporter;
this.folderImporter = folderImporter;
this.workflowImporter = workflowImporter;
this.workflowPublisher = workflowPublisher;
this.nodeTypes = nodeTypes;
this.licenseState = licenseState;
}
async assertNotBlocked(plans, options) {
const creations = plans.flatMap((plan) => plan.variablePlan.creations);
const overwrites = plans.flatMap((plan) => plan.variablePlan.overwrites);
(0, import_gates_1.assertVariableWritesAllowed)({
licenseState: this.licenseState,
apiKeyScopes: options.apiKeyScopes,
hasCreations: creations.length > 0,
hasOverwrites: overwrites.length > 0,
});
for (const { input, variablePlan } of plans) {
if (variablePlan.creations.length > 0) {
await this.variableImporter.assertCanCreate(input.context, variablePlan.creations, input.projectPendingCreation ?? false);
}
if (variablePlan.overwrites.length > 0) {
await this.variableImporter.assertCanUpdate(input.context, variablePlan.overwrites);
}
}
const issues = plans.flatMap((plan) => plan.blockingIssues);
issues.push(...(0, tag_types_1.contestedReconcileTargetFailures)(plans.map((plan) => ({
tagPlan: plan.tagPlan,
workflows: plan.workflowPlan.items.filter((item) => item.action !== 'skip'),
}))).map((failure) => ({ type: 'tag-unresolved', ...failure })));
for (const conflict of (0, variable_types_1.divergentOverwrites)(overwrites)) {
issues.push({ type: 'variable-conflict', ...conflict });
}
const quotaFailure = await this.variableImporter.quotaFailure(creations);
if (quotaFailure)
issues.push({ type: 'variable-limit-exceeded', ...quotaFailure });
if (issues.length > 0)
throw (0, import_blocked_error_1.toImportBlockedError)(issues);
}
async plan(input) {
const { context, folders, workflows, credentialRequest, dataTableRequest, variableRequest, tagRequest, options, } = input;
await this.workflowPublisher.assertCanPublish(context.user, context.projectId, options.workflowPublishingPolicy, input.projectPendingCreation);
const credentialPlan = await this.credentialImporter.plan(context, credentialRequest);
const dataTablePlan = await this.dataTableImporter.plan(context, dataTableRequest);
const variablePlan = await this.variableImporter.plan(context, variableRequest);
const workflowPlan = await this.workflowImporter.plan(context, workflows, options);
const tagPlan = await this.tagImporter.plan(context, tagRequest, workflowPlan.items.filter((item) => item.action !== 'skip'));
const folderContext = { ...context, folderConflictPolicy: options.folderConflictPolicy };
const folderPlan = await this.folderImporter.plan(folderContext, folders);
const missingNodeTypes = (0, missing_node_type_mode_1.collectMissingNodeTypes)(workflowPlan.items.filter((item) => item.action !== 'skip'), (nodeType) => this.nodeTypes.getSupportedVersions(nodeType));
const blockingIssues = this.collectBlockingIssues({
workflowPlan,
credentialPlan,
credentialRequest,
folderPlan,
dataTablePlan,
variableRequest,
variablePlan,
tagPlan,
missingNodeTypes,
missingNodeTypeMode: options.missingNodeTypeMode,
});
return {
input,
folderContext,
credentialPlan,
workflowPlan,
folderPlan,
dataTablePlan,
variablePlan,
tagPlan,
missingNodeTypes,
blockingIssues,
};
}
async apply(plan, seedWorkflowBindings) {
const { input, folderContext, credentialPlan, workflowPlan, folderPlan, dataTablePlan, variablePlan, tagPlan, } = plan;
const { context, credentialRequest } = input;
await this.tagImporter.apply(context, tagPlan);
const folderSummaries = await this.folderImporter.apply(folderContext, folderPlan);
const credentialResult = await this.credentialImporter.apply(context, credentialRequest, credentialPlan);
await this.dataTableImporter.apply(context, dataTablePlan);
const blockedFromPublish = new Map();
for (const sourceWorkflowId of (0, credential_missing_mode_1.workflowsBlockedFromPublish)(credentialRequest.requirements, new Set(credentialResult.stubbed))) {
blockedFromPublish.set(sourceWorkflowId, 'stub-credential');
}
for (const sourceWorkflowId of (0, missing_node_type_mode_1.workflowsWithMissingNodeTypes)(plan.missingNodeTypes)) {
blockedFromPublish.set(sourceWorkflowId, 'missing-node-type');
}
const { outcomes, bindings } = await this.workflowImporter.apply({ ...context, droppedTagIds: (0, tag_types_1.droppedTagIds)(tagPlan) }, workflowPlan, (0, n8n_packages_types_1.createBindings)({
credentials: credentialResult.bindings,
...(seedWorkflowBindings ? { workflows: seedWorkflowBindings } : {}),
}));
const variableResult = await this.variableImporter.apply(context, variablePlan);
return {
workflowOutcomes: outcomes.map((outcome) => withBlockedFromPublish(outcome, blockedFromPublish.get(outcome.sourceWorkflowId))),
folderSummaries,
bindings,
credentialResult,
dataTablePlan,
variablePlan,
variableResult,
tagPlan,
};
}
collectBlockingIssues({ workflowPlan, credentialPlan, credentialRequest, folderPlan, dataTablePlan, variableRequest, variablePlan, tagPlan, missingNodeTypes, missingNodeTypeMode, }) {
return [
...workflowPlan.conflicts.map((conflict) => ({ type: 'workflow-conflict', ...conflict })),
...workflowPlan.idConflicts.map((conflict) => ({ type: 'workflow-id-conflict', ...conflict })),
...workflowPlan.folderConflicts.map((conflict) => ({ type: 'workflow-folder-conflict', ...conflict })),
...folderPlan.conflicts.map((conflict) => ({ type: 'folder-conflict', ...conflict })),
...dataTablePlan.failures.map((failure) => ({ type: 'data-table-unresolved', ...failure })),
...tagPlan.failures.map((failure) => ({ type: 'tag-unresolved', ...failure })),
...this.credentialImporter
.blockingFailures(credentialRequest, credentialPlan)
.map(toCredentialBlockingIssue),
...this.variableImporter
.blockingFailures(variableRequest, variablePlan)
.map((failure) => ({ type: 'variable-unresolved', ...failure })),
...this.variableImporter
.blockingConflicts(variableRequest, variablePlan)
.map((conflict) => ({ type: 'variable-conflict', ...conflict })),
...(0, missing_node_type_mode_1.missingNodeTypeBlockingFailures)(missingNodeTypeMode, missingNodeTypes).map(({ type, typeVersion, usedByWorkflows }) => ({
type: 'missing-node-type',
nodeType: type,
typeVersion,
usedByWorkflows,
})),
];
}
};
exports.ImportOrchestrator = ImportOrchestrator;
exports.ImportOrchestrator = ImportOrchestrator = __decorate([
(0, di_1.Service)(),
__metadata("design:paramtypes", [credential_importer_1.CredentialImporter, data_table_importer_1.DataTableImporter, variable_importer_1.VariableImporter, tag_importer_1.TagImporter, folder_importer_1.FolderImporter, workflow_importer_1.WorkflowImporter, workflow_publisher_1.WorkflowPublisher, node_types_1.NodeTypes, backend_common_1.LicenseState])
], ImportOrchestrator);
function withBlockedFromPublish(outcome, blockedFromPublish) {
if (outcome.status === 'skipped' || !blockedFromPublish)
return outcome;
return { ...outcome, blockedFromPublish };
}
function toCredentialBlockingIssue(failure) {
const { kind, sourceId, targetId, expectedType, actualType, usedByWorkflows } = failure;
return {
type: 'credential-unresolved',
kind,
sourceId,
...(targetId ? { targetId } : {}),
...(expectedType ? { expectedType } : {}),
...(actualType ? { actualType } : {}),
usedByWorkflows,
};
}
//# sourceMappingURL=import-orchestrator.js.map