@openfn/project 0.5.1 → 0.6.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/dist/index.d.ts +2 -1
- package/dist/index.js +74 -3
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -32,6 +32,7 @@ declare class Workflow {
|
|
|
32
32
|
getUUID(id: any): string;
|
|
33
33
|
toJSON(): JSON.Object;
|
|
34
34
|
getUUIDMap(): Record<string, string>;
|
|
35
|
+
getVersionHash(): string;
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
type FromFsConfig = {
|
|
@@ -95,7 +96,7 @@ declare class Project {
|
|
|
95
96
|
constructor(data: l.Project, repoConfig?: RepoOptions);
|
|
96
97
|
serialize(type?: 'json' | 'yaml' | 'fs' | 'state', options?: any): any;
|
|
97
98
|
getVersionHash(): void;
|
|
98
|
-
getWorkflow(
|
|
99
|
+
getWorkflow(idOrName: string): Workflow | undefined;
|
|
99
100
|
getIdentifier(): string;
|
|
100
101
|
compare(proj: Project): void;
|
|
101
102
|
getUUID(workflow: string | Workflow, stepId: string, otherStep?: string): any;
|
package/dist/index.js
CHANGED
|
@@ -9,6 +9,74 @@ function slugify(text) {
|
|
|
9
9
|
return text?.replace(/\W/g, " ").trim().replace(/\s+/g, "-").toLowerCase();
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
// src/util/version.ts
|
|
13
|
+
import crypto from "node:crypto";
|
|
14
|
+
var SHORT_HASH_LENGTH = 12;
|
|
15
|
+
function isDefined(v) {
|
|
16
|
+
return v !== void 0 && v !== null;
|
|
17
|
+
}
|
|
18
|
+
var generateHash = (workflow, source = "cli") => {
|
|
19
|
+
const parts = [];
|
|
20
|
+
const wfKeys = ["name", "credentials"].sort();
|
|
21
|
+
const stepKeys = [
|
|
22
|
+
"name",
|
|
23
|
+
"adaptors",
|
|
24
|
+
"adaptor",
|
|
25
|
+
// there's ao adaptor & adaptors key in steps somehow.
|
|
26
|
+
"expression",
|
|
27
|
+
"configuration",
|
|
28
|
+
// assumes a string credential id
|
|
29
|
+
"expression"
|
|
30
|
+
// TODO need to model trigger types in this, which I think are currently ignored
|
|
31
|
+
].sort();
|
|
32
|
+
const edgeKeys = [
|
|
33
|
+
"condition",
|
|
34
|
+
"label",
|
|
35
|
+
"disabled"
|
|
36
|
+
// This feels more like an option - should be excluded?
|
|
37
|
+
].sort();
|
|
38
|
+
wfKeys.forEach((key) => {
|
|
39
|
+
if (isDefined(workflow[key])) {
|
|
40
|
+
parts.push(key, serializeValue(workflow[key]));
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
const steps = (workflow.steps || []).slice().sort((a, b) => {
|
|
44
|
+
const aName = a.name ?? "";
|
|
45
|
+
const bName = b.name ?? "";
|
|
46
|
+
return aName.localeCompare(bName);
|
|
47
|
+
});
|
|
48
|
+
for (const step of steps) {
|
|
49
|
+
stepKeys.forEach((key) => {
|
|
50
|
+
if (isDefined(step[key])) {
|
|
51
|
+
parts.push(key, serializeValue(step[key]));
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
if (step.next && Array.isArray(step.next)) {
|
|
55
|
+
const edges = step.next.slice().sort((a, b) => {
|
|
56
|
+
const aLabel = a.label || "";
|
|
57
|
+
const bLabel = b.label || "";
|
|
58
|
+
return aLabel.localeCompare(bLabel);
|
|
59
|
+
});
|
|
60
|
+
for (const edge of edges) {
|
|
61
|
+
edgeKeys.forEach((key) => {
|
|
62
|
+
if (isDefined(edge[key])) {
|
|
63
|
+
parts.push(key, serializeValue(edge[key]));
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const str = parts.join("");
|
|
70
|
+
const hash = crypto.createHash("sha256").update(str).digest("hex");
|
|
71
|
+
return `${source}:${hash.substring(0, SHORT_HASH_LENGTH)}`;
|
|
72
|
+
};
|
|
73
|
+
function serializeValue(val) {
|
|
74
|
+
if (typeof val === "object") {
|
|
75
|
+
return JSON.stringify(val);
|
|
76
|
+
}
|
|
77
|
+
return String(val);
|
|
78
|
+
}
|
|
79
|
+
|
|
12
80
|
// src/Workflow.ts
|
|
13
81
|
var clone = (obj) => JSON.parse(JSON.stringify(obj));
|
|
14
82
|
var Workflow = class {
|
|
@@ -138,6 +206,9 @@ var Workflow = class {
|
|
|
138
206
|
getUUIDMap() {
|
|
139
207
|
return this.index.uuid;
|
|
140
208
|
}
|
|
209
|
+
getVersionHash() {
|
|
210
|
+
return generateHash(this);
|
|
211
|
+
}
|
|
141
212
|
};
|
|
142
213
|
var Workflow_default = Workflow;
|
|
143
214
|
|
|
@@ -1031,7 +1102,7 @@ var Project = class {
|
|
|
1031
1102
|
// collections for the project
|
|
1032
1103
|
// TODO to be well typed
|
|
1033
1104
|
collections;
|
|
1034
|
-
static from(type, data, options) {
|
|
1105
|
+
static from(type, data, options = {}) {
|
|
1035
1106
|
if (type === "state") {
|
|
1036
1107
|
return from_app_state_default(data, options);
|
|
1037
1108
|
} else if (type === "fs") {
|
|
@@ -1079,8 +1150,8 @@ var Project = class {
|
|
|
1079
1150
|
// what else might we need?
|
|
1080
1151
|
// get workflow by name or id
|
|
1081
1152
|
// this is fuzzy, but is that wrong?
|
|
1082
|
-
getWorkflow(
|
|
1083
|
-
return this.workflows.find((wf) => wf.id ==
|
|
1153
|
+
getWorkflow(idOrName) {
|
|
1154
|
+
return this.workflows.find((wf) => wf.id == idOrName) || this.workflows.find((wf) => wf.name === idOrName);
|
|
1084
1155
|
}
|
|
1085
1156
|
// it's the name of the project.yaml file
|
|
1086
1157
|
// qualified name? Remote name? App name?
|