@flat8n/cli 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +155 -0
- package/dist/src/cli/api.d.ts +10 -0
- package/dist/src/cli/api.js +57 -0
- package/dist/src/cli/api.js.map +1 -0
- package/dist/src/cli/build.d.ts +2 -0
- package/dist/src/cli/build.js +162 -0
- package/dist/src/cli/build.js.map +1 -0
- package/dist/src/cli/compile.d.ts +2 -0
- package/dist/src/cli/compile.js +149 -0
- package/dist/src/cli/compile.js.map +1 -0
- package/dist/src/cli/deploy.d.ts +4 -0
- package/dist/src/cli/deploy.js +47 -0
- package/dist/src/cli/deploy.js.map +1 -0
- package/dist/src/cli/dev.d.ts +2 -0
- package/dist/src/cli/dev.js +54 -0
- package/dist/src/cli/dev.js.map +1 -0
- package/dist/src/cli/init.d.ts +1 -0
- package/dist/src/cli/init.js +237 -0
- package/dist/src/cli/init.js.map +1 -0
- package/dist/src/cli/main.d.ts +2 -0
- package/dist/src/cli/main.js +249 -0
- package/dist/src/cli/main.js.map +1 -0
- package/dist/src/cli/run.d.ts +2 -0
- package/dist/src/cli/run.js +84 -0
- package/dist/src/cli/run.js.map +1 -0
- package/dist/src/cli/server.d.ts +2 -0
- package/dist/src/cli/server.js +62 -0
- package/dist/src/cli/server.js.map +1 -0
- package/dist/src/cli/setup.d.ts +1 -0
- package/dist/src/cli/setup.js +62 -0
- package/dist/src/cli/setup.js.map +1 -0
- package/dist/src/cli/sync.d.ts +4 -0
- package/dist/src/cli/sync.js +45 -0
- package/dist/src/cli/sync.js.map +1 -0
- package/dist/src/cli/ui.d.ts +5 -0
- package/dist/src/cli/ui.js +66 -0
- package/dist/src/cli/ui.js.map +1 -0
- package/dist/src/compiler/analyze.d.ts +15 -0
- package/dist/src/compiler/analyze.js +26 -0
- package/dist/src/compiler/analyze.js.map +1 -0
- package/dist/src/compiler/diagnostics.d.ts +28 -0
- package/dist/src/compiler/diagnostics.js +26 -0
- package/dist/src/compiler/diagnostics.js.map +1 -0
- package/dist/src/compiler/inputs.d.ts +30 -0
- package/dist/src/compiler/inputs.js +2 -0
- package/dist/src/compiler/inputs.js.map +1 -0
- package/dist/src/compiler/json.d.ts +15 -0
- package/dist/src/compiler/json.js +83 -0
- package/dist/src/compiler/json.js.map +1 -0
- package/dist/src/compiler/link.d.ts +18 -0
- package/dist/src/compiler/link.js +84 -0
- package/dist/src/compiler/link.js.map +1 -0
- package/dist/src/compiler/stable-json.d.ts +3 -0
- package/dist/src/compiler/stable-json.js +18 -0
- package/dist/src/compiler/stable-json.js.map +1 -0
- package/dist/src/compiler/validate.d.ts +9 -0
- package/dist/src/compiler/validate.js +25 -0
- package/dist/src/compiler/validate.js.map +1 -0
- package/dist/src/compiler/watch.d.ts +19 -0
- package/dist/src/compiler/watch.js +67 -0
- package/dist/src/compiler/watch.js.map +1 -0
- package/dist/src/compiler/workflow-file.d.ts +2 -0
- package/dist/src/compiler/workflow-file.js +27 -0
- package/dist/src/compiler/workflow-file.js.map +1 -0
- package/dist/src/generator/n8n-generator.d.ts +3 -0
- package/dist/src/generator/n8n-generator.js +129 -0
- package/dist/src/generator/n8n-generator.js.map +1 -0
- package/dist/src/graph/graph.d.ts +11 -0
- package/dist/src/graph/graph.js +76 -0
- package/dist/src/graph/graph.js.map +1 -0
- package/dist/src/index.d.ts +7 -0
- package/dist/src/index.js +5 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/ir/model.d.ts +58 -0
- package/dist/src/ir/model.js +29 -0
- package/dist/src/ir/model.js.map +1 -0
- package/dist/src/parser/n8n-parser.d.ts +8 -0
- package/dist/src/parser/n8n-parser.js +119 -0
- package/dist/src/parser/n8n-parser.js.map +1 -0
- package/dist/src/parser/n8n-schema.d.ts +60 -0
- package/dist/src/parser/n8n-schema.js +35 -0
- package/dist/src/parser/n8n-schema.js.map +1 -0
- package/dist/src/passes/auto-layout.d.ts +6 -0
- package/dist/src/passes/auto-layout.js +52 -0
- package/dist/src/passes/auto-layout.js.map +1 -0
- package/dist/src/passes/credential-isolation.d.ts +10 -0
- package/dist/src/passes/credential-isolation.js +56 -0
- package/dist/src/passes/credential-isolation.js.map +1 -0
- package/dist/src/passes/deterministic-ids.d.ts +7 -0
- package/dist/src/passes/deterministic-ids.js +40 -0
- package/dist/src/passes/deterministic-ids.js.map +1 -0
- package/dist/src/passes/expression-rewriter.d.ts +7 -0
- package/dist/src/passes/expression-rewriter.js +294 -0
- package/dist/src/passes/expression-rewriter.js.map +1 -0
- package/dist/src/passes/inline-subworkflows.d.ts +11 -0
- package/dist/src/passes/inline-subworkflows.js +437 -0
- package/dist/src/passes/inline-subworkflows.js.map +1 -0
- package/dist/src/passes/pass.d.ts +10 -0
- package/dist/src/passes/pass.js +2 -0
- package/dist/src/passes/pass.js.map +1 -0
- package/dist/src/validation/graph-integrity.d.ts +9 -0
- package/dist/src/validation/graph-integrity.js +104 -0
- package/dist/src/validation/graph-integrity.js.map +1 -0
- package/package.json +60 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { ZodError } from "zod";
|
|
2
|
+
import { diagnostic } from "../compiler/diagnostics.js";
|
|
3
|
+
import { N8nWorkflowSchema } from "./n8n-schema.js";
|
|
4
|
+
const NODE_FIELDS = new Set([
|
|
5
|
+
"id",
|
|
6
|
+
"name",
|
|
7
|
+
"type",
|
|
8
|
+
"typeVersion",
|
|
9
|
+
"position",
|
|
10
|
+
"parameters",
|
|
11
|
+
"credentials"
|
|
12
|
+
]);
|
|
13
|
+
const WORKFLOW_FIELDS = new Set(["id", "name", "nodes", "connections", "settings"]);
|
|
14
|
+
export function parseN8nWorkflow(source) {
|
|
15
|
+
const diagnostics = [];
|
|
16
|
+
const result = N8nWorkflowSchema.safeParse(source.workflow);
|
|
17
|
+
if (!result.success) {
|
|
18
|
+
diagnostics.push(...mapZodError(source, result.error));
|
|
19
|
+
return { diagnostics };
|
|
20
|
+
}
|
|
21
|
+
const parsed = result.data;
|
|
22
|
+
const name = typeof parsed.name === "string" && parsed.name.length > 0 ? parsed.name : source.id;
|
|
23
|
+
const nodes = parsed.nodes.map((node, index) => {
|
|
24
|
+
return {
|
|
25
|
+
...(node.id !== undefined ? { id: node.id } : {}),
|
|
26
|
+
name: node.name,
|
|
27
|
+
originalName: node.name,
|
|
28
|
+
type: node.type,
|
|
29
|
+
typeVersion: node.typeVersion,
|
|
30
|
+
position: node.position,
|
|
31
|
+
parameters: node.parameters,
|
|
32
|
+
credentials: parseCredentials(node.credentials),
|
|
33
|
+
properties: copyExcept(node, NODE_FIELDS),
|
|
34
|
+
source: sourcePointer(source, `/nodes/${index}`)
|
|
35
|
+
};
|
|
36
|
+
});
|
|
37
|
+
const settings = {
|
|
38
|
+
vars: parsed.settings.vars,
|
|
39
|
+
properties: copyExcept(parsed.settings, new Set(["vars"]))
|
|
40
|
+
};
|
|
41
|
+
const edges = [];
|
|
42
|
+
for (const [sourceNode, outputs] of Object.entries(parsed.connections)) {
|
|
43
|
+
for (const [outputType, outputGroups] of Object.entries(outputs)) {
|
|
44
|
+
outputGroups.forEach((targets, outputIndex) => {
|
|
45
|
+
targets.forEach((target, targetListIndex) => {
|
|
46
|
+
edges.push({
|
|
47
|
+
source: sourceNode,
|
|
48
|
+
outputType,
|
|
49
|
+
outputIndex,
|
|
50
|
+
target: target.node,
|
|
51
|
+
inputType: target.type,
|
|
52
|
+
inputIndex: target.index,
|
|
53
|
+
sourcePointer: sourcePointer(source, `/connections/${escapePointer(sourceNode)}/${escapePointer(outputType)}/${outputIndex}/${targetListIndex}`)
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
const properties = copyExcept(parsed, WORKFLOW_FIELDS);
|
|
60
|
+
return {
|
|
61
|
+
workflow: {
|
|
62
|
+
id: source.id,
|
|
63
|
+
name,
|
|
64
|
+
path: source.path,
|
|
65
|
+
nodes,
|
|
66
|
+
edges,
|
|
67
|
+
settings,
|
|
68
|
+
properties
|
|
69
|
+
},
|
|
70
|
+
diagnostics
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
function parseCredentials(credentials) {
|
|
74
|
+
const output = {};
|
|
75
|
+
for (const [type, cred] of Object.entries(credentials)) {
|
|
76
|
+
const id = cred.id;
|
|
77
|
+
const name = cred.name;
|
|
78
|
+
output[type] = {
|
|
79
|
+
properties: copyExcept(cred, new Set(["id", "name"])),
|
|
80
|
+
...(id !== undefined ? { id: String(id) } : {}),
|
|
81
|
+
...(name !== undefined ? { name } : {})
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
return output;
|
|
85
|
+
}
|
|
86
|
+
function mapZodError(source, error) {
|
|
87
|
+
return error.issues.map((err) => {
|
|
88
|
+
const pathArray = err.path;
|
|
89
|
+
const pointer = "/" + pathArray.map(escapePointer).join("/");
|
|
90
|
+
return diagnostic({
|
|
91
|
+
pass: "parse",
|
|
92
|
+
workflow: source.id,
|
|
93
|
+
location: sourcePointer(source, pointer),
|
|
94
|
+
cause: err.message,
|
|
95
|
+
invariant: "n8n JSON must strictly match native schema",
|
|
96
|
+
suggestion: "Export a valid workflow from n8n or correct the JSON structure"
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
function copyExcept(object, excluded) {
|
|
101
|
+
const output = {};
|
|
102
|
+
for (const [key, value] of Object.entries(object)) {
|
|
103
|
+
if (!excluded.has(key)) {
|
|
104
|
+
output[key] = value;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return output;
|
|
108
|
+
}
|
|
109
|
+
function sourcePointer(source, pointer) {
|
|
110
|
+
return {
|
|
111
|
+
workflowId: source.id,
|
|
112
|
+
path: source.path,
|
|
113
|
+
pointer
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
function escapePointer(value) {
|
|
117
|
+
return String(value).replaceAll("~", "~0").replaceAll("/", "~1");
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=n8n-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"n8n-parser.js","sourceRoot":"","sources":["../../../src/parser/n8n-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const PositionSchema: z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>;
|
|
3
|
+
export declare const CredentialReferenceSchema: z.ZodObject<{
|
|
4
|
+
id: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
|
|
5
|
+
name: z.ZodOptional<z.ZodString>;
|
|
6
|
+
}, z.core.$catchall<z.ZodUnknown>>;
|
|
7
|
+
export declare const NodeSchema: z.ZodObject<{
|
|
8
|
+
id: z.ZodOptional<z.ZodString>;
|
|
9
|
+
name: z.ZodString;
|
|
10
|
+
type: z.ZodString;
|
|
11
|
+
typeVersion: z.ZodNumber;
|
|
12
|
+
position: z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>;
|
|
13
|
+
parameters: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
14
|
+
credentials: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
15
|
+
id: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
|
|
16
|
+
name: z.ZodOptional<z.ZodString>;
|
|
17
|
+
}, z.core.$catchall<z.ZodUnknown>>>>;
|
|
18
|
+
}, z.core.$catchall<z.ZodUnknown>>;
|
|
19
|
+
export declare const ConnectionTargetSchema: z.ZodObject<{
|
|
20
|
+
node: z.ZodString;
|
|
21
|
+
type: z.ZodString;
|
|
22
|
+
index: z.ZodNumber;
|
|
23
|
+
}, z.core.$catchall<z.ZodUnknown>>;
|
|
24
|
+
export declare const ConnectionsSchema: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodArray<z.ZodArray<z.ZodObject<{
|
|
25
|
+
node: z.ZodString;
|
|
26
|
+
type: z.ZodString;
|
|
27
|
+
index: z.ZodNumber;
|
|
28
|
+
}, z.core.$catchall<z.ZodUnknown>>>>>>>;
|
|
29
|
+
export declare const WorkflowSettingsSchema: z.ZodDefault<z.ZodObject<{
|
|
30
|
+
vars: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
31
|
+
}, z.core.$catchall<z.ZodUnknown>>>;
|
|
32
|
+
export declare const N8nWorkflowSchema: z.ZodObject<{
|
|
33
|
+
id: z.ZodOptional<z.ZodString>;
|
|
34
|
+
name: z.ZodOptional<z.ZodString>;
|
|
35
|
+
nodes: z.ZodArray<z.ZodObject<{
|
|
36
|
+
id: z.ZodOptional<z.ZodString>;
|
|
37
|
+
name: z.ZodString;
|
|
38
|
+
type: z.ZodString;
|
|
39
|
+
typeVersion: z.ZodNumber;
|
|
40
|
+
position: z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>;
|
|
41
|
+
parameters: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
42
|
+
credentials: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
43
|
+
id: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
|
|
44
|
+
name: z.ZodOptional<z.ZodString>;
|
|
45
|
+
}, z.core.$catchall<z.ZodUnknown>>>>;
|
|
46
|
+
}, z.core.$catchall<z.ZodUnknown>>>;
|
|
47
|
+
connections: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodArray<z.ZodArray<z.ZodObject<{
|
|
48
|
+
node: z.ZodString;
|
|
49
|
+
type: z.ZodString;
|
|
50
|
+
index: z.ZodNumber;
|
|
51
|
+
}, z.core.$catchall<z.ZodUnknown>>>>>>>;
|
|
52
|
+
settings: z.ZodDefault<z.ZodObject<{
|
|
53
|
+
vars: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
54
|
+
}, z.core.$catchall<z.ZodUnknown>>>;
|
|
55
|
+
}, z.core.$catchall<z.ZodUnknown>>;
|
|
56
|
+
export type N8nNode = z.infer<typeof NodeSchema>;
|
|
57
|
+
export type N8nConnectionTarget = z.infer<typeof ConnectionTargetSchema>;
|
|
58
|
+
export type N8nConnections = z.infer<typeof ConnectionsSchema>;
|
|
59
|
+
export type N8nWorkflowSettings = z.infer<typeof WorkflowSettingsSchema>;
|
|
60
|
+
export type N8nWorkflow = z.infer<typeof N8nWorkflowSchema>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export const PositionSchema = z.tuple([z.number().finite(), z.number().finite()]);
|
|
3
|
+
export const CredentialReferenceSchema = z.object({
|
|
4
|
+
id: z.union([z.string(), z.number()]).optional(),
|
|
5
|
+
name: z.string().optional()
|
|
6
|
+
}).catchall(z.unknown());
|
|
7
|
+
export const NodeSchema = z.object({
|
|
8
|
+
id: z.string().min(1).optional(),
|
|
9
|
+
name: z.string().min(1),
|
|
10
|
+
type: z.string().min(1),
|
|
11
|
+
typeVersion: z.number().finite(),
|
|
12
|
+
position: PositionSchema,
|
|
13
|
+
parameters: z.record(z.string(), z.unknown()).default({}),
|
|
14
|
+
credentials: z.record(z.string(), CredentialReferenceSchema).default({})
|
|
15
|
+
}).catchall(z.unknown());
|
|
16
|
+
export const ConnectionTargetSchema = z.object({
|
|
17
|
+
node: z.string().min(1),
|
|
18
|
+
type: z.string().min(1),
|
|
19
|
+
index: z.number().int().nonnegative()
|
|
20
|
+
}).catchall(z.unknown());
|
|
21
|
+
export const ConnectionsSchema = z.record(z.string(), // source node name
|
|
22
|
+
z.record(z.string(), // output type
|
|
23
|
+
z.array(z.array(ConnectionTargetSchema) // array of output indices, each containing an array of targets
|
|
24
|
+
))).default({});
|
|
25
|
+
export const WorkflowSettingsSchema = z.object({
|
|
26
|
+
vars: z.record(z.string(), z.unknown()).default({})
|
|
27
|
+
}).catchall(z.unknown()).default({ vars: {} });
|
|
28
|
+
export const N8nWorkflowSchema = z.object({
|
|
29
|
+
id: z.string().optional(),
|
|
30
|
+
name: z.string().optional(),
|
|
31
|
+
nodes: z.array(NodeSchema),
|
|
32
|
+
connections: ConnectionsSchema,
|
|
33
|
+
settings: WorkflowSettingsSchema
|
|
34
|
+
}).catchall(z.unknown());
|
|
35
|
+
//# sourceMappingURL=n8n-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"n8n-schema.js","sourceRoot":"","sources":["../../../src/parser/n8n-schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import dagre from "@dagrejs/dagre";
|
|
2
|
+
const GRID_SIZE = 20;
|
|
3
|
+
const NODE_X_SPACING = GRID_SIZE * 8;
|
|
4
|
+
const NODE_Y_SPACING = GRID_SIZE * 6;
|
|
5
|
+
const DEFAULT_NODE_WIDTH = 200;
|
|
6
|
+
const DEFAULT_NODE_HEIGHT = 100;
|
|
7
|
+
export class AutoLayoutPass {
|
|
8
|
+
name = "auto-layout";
|
|
9
|
+
run(workflow) {
|
|
10
|
+
const graph = new dagre.graphlib.Graph();
|
|
11
|
+
// Pixel-perfect alignment matching n8n's internal Tidy logic
|
|
12
|
+
graph.setGraph({
|
|
13
|
+
rankdir: "LR",
|
|
14
|
+
edgesep: NODE_Y_SPACING,
|
|
15
|
+
nodesep: NODE_Y_SPACING,
|
|
16
|
+
ranksep: NODE_X_SPACING,
|
|
17
|
+
});
|
|
18
|
+
graph.setDefaultEdgeLabel(() => ({}));
|
|
19
|
+
for (const node of workflow.nodes) {
|
|
20
|
+
graph.setNode(node.name, { width: DEFAULT_NODE_WIDTH, height: DEFAULT_NODE_HEIGHT });
|
|
21
|
+
}
|
|
22
|
+
for (const edge of workflow.edges) {
|
|
23
|
+
if (graph.hasNode(edge.source) && graph.hasNode(edge.target)) {
|
|
24
|
+
graph.setEdge(edge.source, edge.target);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
// @ts-ignore - n8n passes this undocumented flag
|
|
28
|
+
dagre.layout(graph, { disableOptimalOrderHeuristic: true });
|
|
29
|
+
const snapToGrid = (value) => Math.round(value / GRID_SIZE) * GRID_SIZE;
|
|
30
|
+
const nodes = workflow.nodes.map((node) => {
|
|
31
|
+
const gNode = graph.node(node.name);
|
|
32
|
+
if (gNode === undefined) {
|
|
33
|
+
return node;
|
|
34
|
+
}
|
|
35
|
+
// n8n translates Dagre's center coordinates to top-left bounding box coordinates
|
|
36
|
+
const x = snapToGrid(gNode.x - gNode.width / 2);
|
|
37
|
+
const y = snapToGrid(gNode.y - gNode.height / 2);
|
|
38
|
+
return {
|
|
39
|
+
...node,
|
|
40
|
+
position: [x, y],
|
|
41
|
+
};
|
|
42
|
+
});
|
|
43
|
+
return {
|
|
44
|
+
workflow: {
|
|
45
|
+
...workflow,
|
|
46
|
+
nodes,
|
|
47
|
+
},
|
|
48
|
+
diagnostics: [],
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=auto-layout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-layout.js","sourceRoot":"","sources":["../../../src/passes/auto-layout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,gBAAgB,CAAC;AAInC,MAAM,SAAS,GAAG,EAAE,CAAC;AACrB,MAAM,cAAc,GAAG,SAAS,GAAG,CAAC,CAAC;AACrC,MAAM,cAAc,GAAG,SAAS,GAAG,CAAC,CAAC;AACrC,MAAM,kBAAkB,GAAG,GAAG,CAAC;AAC/B,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAEhC,MAAM,OAAO,cAAc;IAChB,IAAI,GAAG,aAAa,CAAC;IAE9B,GAAG,CAAC,QAAoB;QACtB,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;QAEzC,6DAA6D;QAC7D,KAAK,CAAC,QAAQ,CAAC;YACb,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,cAAc;YACvB,OAAO,EAAE,cAAc;YACvB,OAAO,EAAE,cAAc;SACxB,CAAC,CAAC;QAEH,KAAK,CAAC,mBAAmB,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAEtC,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;YAClC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,kBAAkB,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC,CAAC;QACvF,CAAC;QAED,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;YAClC,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC7D,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;YAC1C,CAAC;QACH,CAAC;QAED,iDAAiD;QACjD,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,4BAA4B,EAAE,IAAI,EAAE,CAAC,CAAC;QAE5D,MAAM,UAAU,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC;QAEhF,MAAM,KAAK,GAAa,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YAClD,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACpC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,OAAO,IAAI,CAAC;YACd,CAAC;YAED,iFAAiF;YACjF,MAAM,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;YAChD,MAAM,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAEjD,OAAO;gBACL,GAAG,IAAI;gBACP,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;aACjB,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,OAAO;YACL,QAAQ,EAAE;gBACR,GAAG,QAAQ;gBACX,KAAK;aACN;YACD,WAAW,EAAE,EAAE;SAChB,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { LinkOptions } from "../compiler/inputs.js";
|
|
2
|
+
import type { CredentialMapIR, WorkflowIR } from "../ir/model.js";
|
|
3
|
+
import type { LinkPass, PassResult } from "./pass.js";
|
|
4
|
+
export declare class CredentialIsolationPass implements LinkPass {
|
|
5
|
+
readonly name = "credential-isolation";
|
|
6
|
+
private readonly options;
|
|
7
|
+
constructor(options: LinkOptions);
|
|
8
|
+
run(workflow: WorkflowIR): PassResult;
|
|
9
|
+
}
|
|
10
|
+
export declare function hasCredentials(credentials: CredentialMapIR): boolean;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
export class CredentialIsolationPass {
|
|
2
|
+
name = "credential-isolation";
|
|
3
|
+
options;
|
|
4
|
+
constructor(options) {
|
|
5
|
+
this.options = options;
|
|
6
|
+
}
|
|
7
|
+
run(workflow) {
|
|
8
|
+
return {
|
|
9
|
+
workflow: {
|
|
10
|
+
...workflow,
|
|
11
|
+
nodes: workflow.nodes.map((node) => isolateNodeCredentials(node, this.options))
|
|
12
|
+
},
|
|
13
|
+
diagnostics: []
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function isolateNodeCredentials(node, options) {
|
|
18
|
+
const entries = Object.entries(node.credentials);
|
|
19
|
+
if (entries.length === 0) {
|
|
20
|
+
return node;
|
|
21
|
+
}
|
|
22
|
+
const credentials = {};
|
|
23
|
+
for (const [credentialType, credential] of entries) {
|
|
24
|
+
credentials[credentialType] = isolateCredential(node, credentialType, credential, options);
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
...node,
|
|
28
|
+
credentials
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function isolateCredential(node, credentialType, credential, options) {
|
|
32
|
+
const override = findCredentialOverride(node, credentialType, credential, options.credentialIdOverrides ?? {});
|
|
33
|
+
const base = {
|
|
34
|
+
properties: credential.properties,
|
|
35
|
+
...(credential.name === undefined ? {} : { name: credential.name })
|
|
36
|
+
};
|
|
37
|
+
if (override !== undefined) {
|
|
38
|
+
return {
|
|
39
|
+
...base,
|
|
40
|
+
id: override
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
if (options.credentialPolicy === "preserveIds") {
|
|
44
|
+
return credential;
|
|
45
|
+
}
|
|
46
|
+
return base;
|
|
47
|
+
}
|
|
48
|
+
function findCredentialOverride(node, credentialType, credential, overrides) {
|
|
49
|
+
return (overrides[`${node.name}.${credentialType}`] ??
|
|
50
|
+
overrides[credentialType] ??
|
|
51
|
+
(credential.name === undefined ? undefined : overrides[credential.name]));
|
|
52
|
+
}
|
|
53
|
+
export function hasCredentials(credentials) {
|
|
54
|
+
return Object.keys(credentials).length > 0;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=credential-isolation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credential-isolation.js","sourceRoot":"","sources":["../../../src/passes/credential-isolation.ts"],"names":[],"mappings":"AAIA,MAAM,OAAO,uBAAuB;IACzB,IAAI,GAAG,sBAAsB,CAAC;IACtB,OAAO,CAAc;IAEtC,YAAY,OAAoB;QAC9B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED,GAAG,CAAC,QAAoB;QACtB,OAAO;YACL,QAAQ,EAAE;gBACR,GAAG,QAAQ;gBACX,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,sBAAsB,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;aAChF;YACD,WAAW,EAAE,EAAE;SAChB,CAAC;IACJ,CAAC;CACF;AAED,SAAS,sBAAsB,CAAC,IAAY,EAAE,OAAoB;IAChE,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACjD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,WAAW,GAA0C,EAAE,CAAC;IAC9D,KAAK,MAAM,CAAC,cAAc,EAAE,UAAU,CAAC,IAAI,OAAO,EAAE,CAAC;QACnD,WAAW,CAAC,cAAc,CAAC,GAAG,iBAAiB,CAAC,IAAI,EAAE,cAAc,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;IAC7F,CAAC;IAED,OAAO;QACL,GAAG,IAAI;QACP,WAAW;KACZ,CAAC;AACJ,CAAC;AAED,SAAS,iBAAiB,CACxB,IAAY,EACZ,cAAsB,EACtB,UAAiC,EACjC,OAAoB;IAEpB,MAAM,QAAQ,GAAG,sBAAsB,CAAC,IAAI,EAAE,cAAc,EAAE,UAAU,EAAE,OAAO,CAAC,qBAAqB,IAAI,EAAE,CAAC,CAAC;IAC/G,MAAM,IAAI,GAAG;QACX,UAAU,EAAE,UAAU,CAAC,UAAU;QACjC,GAAG,CAAC,UAAU,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE,CAAC;KACpE,CAAC;IAEF,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO;YACL,GAAG,IAAI;YACP,EAAE,EAAE,QAAQ;SACb,CAAC;IACJ,CAAC;IAED,IAAI,OAAO,CAAC,gBAAgB,KAAK,aAAa,EAAE,CAAC;QAC/C,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,sBAAsB,CAC7B,IAAY,EACZ,cAAsB,EACtB,UAAiC,EACjC,SAA2C;IAE3C,OAAO,CACL,SAAS,CAAC,GAAG,IAAI,CAAC,IAAI,IAAI,cAAc,EAAE,CAAC;QAC3C,SAAS,CAAC,cAAc,CAAC;QACzB,CAAC,UAAU,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CACzE,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,WAA4B;IACzD,OAAO,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;AAC7C,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { LinkPass, PassResult } from "./pass.js";
|
|
2
|
+
import type { NodeIR, WorkflowIR } from "../ir/model.js";
|
|
3
|
+
export declare class DeterministicIdsPass implements LinkPass {
|
|
4
|
+
readonly name = "deterministic-ids";
|
|
5
|
+
run(workflow: WorkflowIR): PassResult;
|
|
6
|
+
}
|
|
7
|
+
export declare function deterministicNodeId(workflow: WorkflowIR, node: NodeIR): string;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
export class DeterministicIdsPass {
|
|
3
|
+
name = "deterministic-ids";
|
|
4
|
+
run(workflow) {
|
|
5
|
+
return {
|
|
6
|
+
workflow: {
|
|
7
|
+
...workflow,
|
|
8
|
+
nodes: workflow.nodes.map((node) => withDeterministicId(workflow, node))
|
|
9
|
+
},
|
|
10
|
+
diagnostics: []
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
function withDeterministicId(workflow, node) {
|
|
15
|
+
return {
|
|
16
|
+
...node,
|
|
17
|
+
id: deterministicNodeId(workflow, node)
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export function deterministicNodeId(workflow, node) {
|
|
21
|
+
const source = [
|
|
22
|
+
"flat8n-node",
|
|
23
|
+
workflow.id,
|
|
24
|
+
workflow.path,
|
|
25
|
+
node.name,
|
|
26
|
+
node.type,
|
|
27
|
+
String(node.typeVersion)
|
|
28
|
+
].join("\u001f");
|
|
29
|
+
const hex = createHash("sha256").update(source).digest("hex");
|
|
30
|
+
return formatUuid(hex);
|
|
31
|
+
}
|
|
32
|
+
function formatUuid(hex) {
|
|
33
|
+
const chars = hex.slice(0, 32).split("");
|
|
34
|
+
chars[12] = "5";
|
|
35
|
+
const variant = Number.parseInt(chars[16] ?? "0", 16);
|
|
36
|
+
chars[16] = ((variant & 0x3) | 0x8).toString(16);
|
|
37
|
+
const value = chars.join("");
|
|
38
|
+
return `${value.slice(0, 8)}-${value.slice(8, 12)}-${value.slice(12, 16)}-${value.slice(16, 20)}-${value.slice(20, 32)}`;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=deterministic-ids.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deterministic-ids.js","sourceRoot":"","sources":["../../../src/passes/deterministic-ids.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAIzC,MAAM,OAAO,oBAAoB;IACtB,IAAI,GAAG,mBAAmB,CAAC;IAEpC,GAAG,CAAC,QAAoB;QACtB,OAAO;YACL,QAAQ,EAAE;gBACR,GAAG,QAAQ;gBACX,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,mBAAmB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;aACzE;YACD,WAAW,EAAE,EAAE;SAChB,CAAC;IACJ,CAAC;CACF;AAED,SAAS,mBAAmB,CAAC,QAAoB,EAAE,IAAY;IAC7D,OAAO;QACL,GAAG,IAAI;QACP,EAAE,EAAE,mBAAmB,CAAC,QAAQ,EAAE,IAAI,CAAC;KACxC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,QAAoB,EAAE,IAAY;IACpE,MAAM,MAAM,GAAG;QACb,aAAa;QACb,QAAQ,CAAC,EAAE;QACX,QAAQ,CAAC,IAAI;QACb,IAAI,CAAC,IAAI;QACT,IAAI,CAAC,IAAI;QACT,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC;KACzB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACjB,MAAM,GAAG,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC9D,OAAO,UAAU,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC;AAED,SAAS,UAAU,CAAC,GAAW;IAC7B,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACzC,KAAK,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC;IAChB,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,GAAG,EAAE,EAAE,CAAC,CAAC;IACtD,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,OAAO,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IACjD,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC7B,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC;AAC3H,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { JsonValue } from "../compiler/json.js";
|
|
2
|
+
export interface ReferenceRewriteMap {
|
|
3
|
+
readonly nodeNames: Readonly<Record<string, string>>;
|
|
4
|
+
readonly variableNames: Readonly<Record<string, string>>;
|
|
5
|
+
}
|
|
6
|
+
export declare function rewriteJsonReferences(value: JsonValue, references: ReferenceRewriteMap): JsonValue;
|
|
7
|
+
export declare function rewriteReferenceString(input: string, references: ReferenceRewriteMap): string;
|