@sanoma-ai/workflows 0.1.0 → 0.2.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/README.md +72 -21
- package/dist/apply-steps.d.ts +6 -0
- package/dist/apply-steps.js +93 -0
- package/dist/apply-steps.js.map +1 -0
- package/dist/apply.d.ts +197 -0
- package/dist/apply.js +470 -0
- package/dist/apply.js.map +1 -0
- package/dist/call.d.ts +4 -0
- package/dist/call.js +19 -4
- package/dist/call.js.map +1 -1
- package/dist/client.d.ts +38 -2
- package/dist/client.js +67 -10
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts +3 -3
- package/dist/config.js +33 -16
- package/dist/config.js.map +1 -1
- package/dist/credentials.d.ts +25 -0
- package/dist/credentials.js +73 -5
- package/dist/credentials.js.map +1 -1
- package/dist/datafile.d.ts +11 -2
- package/dist/datafile.js +56 -2
- package/dist/datafile.js.map +1 -1
- package/dist/describe.d.ts +11 -5
- package/dist/describe.js +13 -5
- package/dist/describe.js.map +1 -1
- package/dist/drift.d.ts +64 -12
- package/dist/drift.js +118 -41
- package/dist/drift.js.map +1 -1
- package/dist/expectations.d.ts +2 -2
- package/dist/expectations.js +28 -3
- package/dist/expectations.js.map +1 -1
- package/dist/host.d.ts +56 -0
- package/dist/host.js +45 -0
- package/dist/host.js.map +1 -0
- package/dist/index.d.ts +6 -2
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/lockfile.d.ts +36 -0
- package/dist/lockfile.js +69 -0
- package/dist/lockfile.js.map +1 -0
- package/dist/op.d.ts +3 -0
- package/dist/op.js.map +1 -1
- package/dist/resource.d.ts +188 -22
- package/dist/resource.js +173 -28
- package/dist/resource.js.map +1 -1
- package/dist/resources.d.ts +18 -3
- package/dist/resources.js +53 -6
- package/dist/resources.js.map +1 -1
- package/dist/run.d.ts +14 -0
- package/dist/run.js +6 -1
- package/dist/run.js.map +1 -1
- package/dist/sandbox.js +5 -1
- package/dist/sandbox.js.map +1 -1
- package/dist/scenario.d.ts +12 -3
- package/dist/scenario.js +33 -8
- package/dist/scenario.js.map +1 -1
- package/dist/secret.d.ts +42 -0
- package/dist/secret.js +58 -0
- package/dist/secret.js.map +1 -0
- package/dist/shared.d.ts +8 -0
- package/dist/shared.js +7 -0
- package/dist/shared.js.map +1 -1
- package/dist/source.d.ts +58 -0
- package/dist/source.js +54 -0
- package/dist/source.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/worker.d.ts +3 -0
- package/dist/worker.js +13 -4
- package/dist/worker.js.map +1 -1
- package/dist/writer.d.ts +35 -0
- package/dist/writer.js +201 -0
- package/dist/writer.js.map +1 -0
- package/package.json +6 -1
- package/src/apply-steps.ts +110 -0
- package/src/apply.ts +626 -0
- package/src/call.ts +19 -4
- package/src/client.ts +83 -13
- package/src/config.ts +48 -25
- package/src/credentials.ts +90 -5
- package/src/datafile.ts +76 -4
- package/src/describe.ts +36 -16
- package/src/drift.ts +155 -45
- package/src/expectations.ts +30 -4
- package/src/host.ts +96 -0
- package/src/index.ts +24 -1
- package/src/lockfile.ts +95 -0
- package/src/op.ts +3 -0
- package/src/resource.ts +270 -47
- package/src/resources.ts +63 -8
- package/src/run.ts +15 -0
- package/src/sandbox.ts +5 -1
- package/src/scenario.ts +50 -13
- package/src/secret.ts +92 -0
- package/src/shared.ts +10 -0
- package/src/source.ts +82 -0
- package/src/version.ts +1 -1
- package/src/worker.ts +16 -5
- package/src/writer.ts +225 -0
package/dist/drift.js
CHANGED
|
@@ -1,39 +1,106 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { defineWorkflow } from "./define.js";
|
|
3
3
|
import { isRunControlError } from "./errors.js";
|
|
4
|
-
import { diffDeclared } from "./resource.js";
|
|
4
|
+
import { diffDeclared, fieldPathOf, valueAt } from "./resource.js";
|
|
5
5
|
import { errorMessage } from "./shared.js";
|
|
6
|
+
import { SOURCE_RESOLVE } from "./source.js";
|
|
6
7
|
export { DRIFT_WORKFLOW } from "./shared.js";
|
|
7
8
|
/**
|
|
8
9
|
* The drift workflow's input: nothing. The run reads the data files itself, so a run says what
|
|
9
10
|
* they declared when it ran, and no caller can hand it other resources to check.
|
|
10
11
|
*/
|
|
11
12
|
export const DriftInput = z.object({}).strict();
|
|
13
|
+
/** A clone URL (a scheme's, or scp-like `user@host:path`): what a `by` field of a host's source holds, told from an id. */
|
|
14
|
+
const CLONE_URL = /^((https?|ssh|git|file):\/\/|[\w.-]+@[\w.-]+:)/;
|
|
15
|
+
// What drift and apply share. Observing a resource is one `ctx` call, which a workflow makes in
|
|
16
|
+
// its own `run` (the outline draws only those): `observeBy` says what each import is called with,
|
|
17
|
+
// `observed` reads its answer, and `compare` turns what every import found into drift's results.
|
|
18
|
+
/** The `import` ops of the types among `ops` with a driver, by type, sorted: what observing them uses. */
|
|
19
|
+
export function importsOf(types, ops, drivers) {
|
|
20
|
+
return [...types.keys()].toSorted().flatMap((type) => {
|
|
21
|
+
const op = ops.get(`${type}.import`);
|
|
22
|
+
return op && drivers.has(op.id) ? [op] : [];
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* What a declared resource is observed by: the import id (`by`, default its binding, else its
|
|
27
|
+
* identity), or without one what it is found to be: `gone` for none, `error` when its type is
|
|
28
|
+
* not the connectors' or has no import among `imports`.
|
|
29
|
+
*/
|
|
30
|
+
export function observeBy({ vendor, type, binding, identity }, types, imports, by = binding ?? identity) {
|
|
31
|
+
const key = `${vendor}.${type}`;
|
|
32
|
+
if (!types.has(key))
|
|
33
|
+
return { error: `the config's connectors declare no resource type ${key}` };
|
|
34
|
+
if (!imports.some((op) => op.id === `${key}.import`))
|
|
35
|
+
return { error: `no driver for ${key}.import` };
|
|
36
|
+
return by === undefined ? { gone: true } : { id: by };
|
|
37
|
+
}
|
|
38
|
+
/** What an import's answer found. */
|
|
39
|
+
export const observed = (out) => out.gone || !out.state ? { gone: true } : { state: out.state };
|
|
40
|
+
/**
|
|
41
|
+
* Each declared resource against what its import `found`: `error`, `absent` (unbound, with the
|
|
42
|
+
* binding id of what its identity found as `found`), `gone`, else the state and the declared
|
|
43
|
+
* fields compared by `diffDeclared`, a reference against the state of the resource it names
|
|
44
|
+
* (so GitHub's node id for a repository counts as its name). A host with a `revisions` entry
|
|
45
|
+
* also compares its revision against the commit its ref names now (or is that entry's `error`).
|
|
46
|
+
*/
|
|
47
|
+
export function compare(types, resources, found, revisions = new Map()) {
|
|
48
|
+
return resources.map(({ id, vendor, type, name, binding, desired, refs }) => {
|
|
49
|
+
const row = { id, type, vendor, name, ...(binding !== undefined && { binding }) };
|
|
50
|
+
const now = found.get(id);
|
|
51
|
+
if ("error" in now)
|
|
52
|
+
return { ...row, status: "error", fields: [], error: now.error };
|
|
53
|
+
const resource = types.get(`${vendor}.${type}`);
|
|
54
|
+
if (binding === undefined) {
|
|
55
|
+
return {
|
|
56
|
+
...row,
|
|
57
|
+
status: "absent",
|
|
58
|
+
fields: [],
|
|
59
|
+
...("state" in now && { found: resource.bindingId(now.state) }),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
if ("gone" in now)
|
|
63
|
+
return { ...row, status: "gone", fields: [] };
|
|
64
|
+
// Each reference, by where it is: the values the vendor may hold there for its resource.
|
|
65
|
+
const accept = {};
|
|
66
|
+
for (const [at, target] of Object.entries(refs)) {
|
|
67
|
+
const by = resource.fields.references?.[fieldPathOf(at)]?.by ?? [];
|
|
68
|
+
const named = found.get(target);
|
|
69
|
+
if (named && "state" in named)
|
|
70
|
+
accept[at] = by.map((field) => named.state[field]).filter((v) => v != null);
|
|
71
|
+
}
|
|
72
|
+
const fields = diffDeclared(resource, now.state, desired, accept);
|
|
73
|
+
const resolved = revisions.get(id);
|
|
74
|
+
if (resolved && "error" in resolved)
|
|
75
|
+
return { ...row, status: "error", fields: [], error: resolved.error };
|
|
76
|
+
// A host whose state does not say which commit it runs is not compared.
|
|
77
|
+
const actual = resource.host?.outputs(now.state).revision;
|
|
78
|
+
if (resolved && actual !== undefined && actual !== resolved.revision) {
|
|
79
|
+
fields.push({ path: resource.host.revision, desired: resolved.revision, actual });
|
|
80
|
+
}
|
|
81
|
+
return { ...row, status: fields.length ? "drifted" : "clean", fields };
|
|
82
|
+
});
|
|
83
|
+
}
|
|
12
84
|
/**
|
|
13
85
|
* The drift workflow for a config: it `uses` the `import` of every resource type the connectors
|
|
14
86
|
* declare (`types`) that has a driver, so its version changes with them, not with the data
|
|
15
87
|
* files. `resolveConfig` adds it to a config whose connectors declare resource types, with
|
|
16
88
|
* `declared`, the step that reads the data files.
|
|
17
89
|
*
|
|
18
|
-
* A run reads the data files (`declared`, recorded as a step, so a replay checks
|
|
19
|
-
* then imports each resource by its
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
90
|
+
* A run reads the data files and the lockfile (`declared`, recorded as a step, so a replay checks
|
|
91
|
+
* the same list), then imports each resource by its binding, else by its identity, in the files'
|
|
92
|
+
* order: one vendor call each, none for a resource with neither. A bound resource whose import
|
|
93
|
+
* says gone is `gone`; an unbound one is `absent`, with the binding id of what its identity found
|
|
94
|
+
* as `found`. Else the state and the declared fields are compared by `diffDeclared`, a reference
|
|
95
|
+
* against the state of the resource it names, read in the same run (so GitHub's node id for a
|
|
96
|
+
* repository counts as its name). A failed call is that resource's
|
|
23
97
|
* `error`, and the run goes on to the next; a failure that ends the run (`isRunControlError`)
|
|
24
98
|
* ends it.
|
|
25
99
|
*/
|
|
26
100
|
export function driftWorkflow(types, ops, drivers, declared) {
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
});
|
|
31
|
-
// Why a resource of each type cannot be read, if it cannot.
|
|
32
|
-
const unreadable = new Map();
|
|
33
|
-
for (const type of types.keys()) {
|
|
34
|
-
if (!uses.some((op) => op.id === `${type}.import`))
|
|
35
|
-
unreadable.set(type, `no driver for ${type}.import`);
|
|
36
|
-
}
|
|
101
|
+
const imports = importsOf(types, ops, drivers);
|
|
102
|
+
const resolve = ops.get(SOURCE_RESOLVE);
|
|
103
|
+
const uses = [...imports, ...(resolve ? [resolve] : [])];
|
|
37
104
|
return defineWorkflow({
|
|
38
105
|
// The literal, held to the one name: the outline finds a workflow by a string, or a const of its own file.
|
|
39
106
|
name: "drift",
|
|
@@ -46,45 +113,55 @@ export function driftWorkflow(types, ops, drivers, declared) {
|
|
|
46
113
|
const { resources, problems } = await declared();
|
|
47
114
|
// Every import first, so a reference compares against what its resource holds now.
|
|
48
115
|
const found = new Map();
|
|
49
|
-
for (const
|
|
50
|
-
const
|
|
51
|
-
const why = types.has(key) ? unreadable.get(key) : `the config's connectors declare no resource type ${key}`;
|
|
116
|
+
for (const resource of resources) {
|
|
117
|
+
const by = observeBy(resource, types, imports);
|
|
52
118
|
// An if/else, not a `continue`: the outline draws the import as the way past the error.
|
|
53
|
-
if (
|
|
54
|
-
found.set(id,
|
|
119
|
+
if (!("id" in by))
|
|
120
|
+
found.set(resource.id, by);
|
|
55
121
|
else {
|
|
56
122
|
try {
|
|
57
|
-
|
|
58
|
-
found.set(id, out.gone || !out.state ? { gone: true } : { state: out.state });
|
|
123
|
+
found.set(resource.id, observed(await ctx[resource.vendor][resource.type].import({ id: by.id })));
|
|
59
124
|
}
|
|
60
125
|
catch (err) {
|
|
61
126
|
if (isRunControlError(err))
|
|
62
127
|
throw err;
|
|
63
|
-
found.set(id, { error: errorMessage(err) });
|
|
128
|
+
found.set(resource.id, { error: errorMessage(err) });
|
|
64
129
|
}
|
|
65
130
|
}
|
|
66
131
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
if ("error" in now)
|
|
71
|
-
return { ...row, status: "error", fields: [], error: now.error };
|
|
72
|
-
if ("gone" in now)
|
|
73
|
-
return { ...row, status: "gone", fields: [] };
|
|
132
|
+
// A host's revision against the commit its ref names now: a merge is drift on the host.
|
|
133
|
+
const revisions = new Map();
|
|
134
|
+
for (const { id, vendor, type, desired, refs } of resources) {
|
|
74
135
|
const resource = types.get(`${vendor}.${type}`);
|
|
75
|
-
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
136
|
+
const host = resource?.host;
|
|
137
|
+
const source = host && sourceUrl(desired, refs[host.inputs.source], resource, found);
|
|
138
|
+
const ref = host && valueAt(desired, host.inputs.ref);
|
|
139
|
+
if (host && "state" in found.get(id) && source !== undefined && typeof ref === "string" && ref) {
|
|
140
|
+
try {
|
|
141
|
+
revisions.set(id, await ctx.sanoma.source.resolve({ url: source, ref }));
|
|
142
|
+
}
|
|
143
|
+
catch (err) {
|
|
144
|
+
if (isRunControlError(err))
|
|
145
|
+
throw err;
|
|
146
|
+
revisions.set(id, { error: errorMessage(err) });
|
|
147
|
+
}
|
|
82
148
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
});
|
|
149
|
+
}
|
|
150
|
+
const results = compare(types, resources, found, revisions);
|
|
86
151
|
return { startedAt, finishedAt: await ctx.now(), problems, resources: results };
|
|
87
152
|
},
|
|
88
153
|
});
|
|
89
154
|
}
|
|
155
|
+
/**
|
|
156
|
+
* A host's source: the clone URL its data file gives, or, when it names a declared repository
|
|
157
|
+
* (`target`), the first of the reference's `by` fields that holds one in that repository's state,
|
|
158
|
+
* read in this run.
|
|
159
|
+
*/
|
|
160
|
+
export function sourceUrl(desired, target, { host, fields }, found) {
|
|
161
|
+
const path = host.inputs.source;
|
|
162
|
+
const named = target === undefined ? undefined : found.get(target);
|
|
163
|
+
const by = fields.references?.[path]?.by ?? [];
|
|
164
|
+
const values = target === undefined ? [valueAt(desired, path)] : named && "state" in named ? by.map((f) => named.state[f]) : [];
|
|
165
|
+
return values.find((v) => typeof v === "string" && CLONE_URL.test(v));
|
|
166
|
+
}
|
|
90
167
|
//# sourceMappingURL=drift.js.map
|
package/dist/drift.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drift.js","sourceRoot":"","sources":["../src/drift.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,cAAc,EAA2B,MAAM,aAAa,CAAC;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEhD,OAAO,EAAmB,YAAY,EAAiB,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"drift.js","sourceRoot":"","sources":["../src/drift.ts"],"names":[],"mappings":"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"}
|
package/dist/expectations.d.ts
CHANGED
|
@@ -18,8 +18,8 @@ type Unstepped<T> = T extends unknown ? Omit<T, "step"> : never;
|
|
|
18
18
|
* (a policy denial, a rejected approval, a vendor's final failure) was attempted, not made. An
|
|
19
19
|
* operation `was denied` when the policy's decision on some call to it is `deny`, and `was held
|
|
20
20
|
* for` an approver when an approval for that approver holds it: one the policy asked for on its
|
|
21
|
-
* call, or one that `covers` it. A drift expectation reads the report a finished
|
|
22
|
-
* returned. A step named in the workflow's outline is read by the `name` its records carry
|
|
21
|
+
* call, or one that `covers` it. A drift or apply expectation reads the report a finished run
|
|
22
|
+
* of it returned. A step named in the workflow's outline is read by the `name` its records carry
|
|
23
23
|
* (its calls made, and `waitsOf`); a record written before steps had names has none.
|
|
24
24
|
*/
|
|
25
25
|
export declare function detailOf(e: CoreExpectation, records: readonly LedgerRecord[]): string | undefined;
|
package/dist/expectations.js
CHANGED
|
@@ -77,14 +77,37 @@ function driftDetail(e, end) {
|
|
|
77
77
|
return undefined;
|
|
78
78
|
return `${e.declared} is ${found(resource)}, not ${e.status === "drifted" ? `drifted in ${e.field}` : e.status}`;
|
|
79
79
|
}
|
|
80
|
+
/**
|
|
81
|
+
* Why an apply expectation fails against the report a finished apply run returned as its output:
|
|
82
|
+
* the resource `created` (a step that created it, done), or `bound` to an object in the lockfile it ended with.
|
|
83
|
+
*/
|
|
84
|
+
function applyDetail(e, end) {
|
|
85
|
+
const report = end.output;
|
|
86
|
+
if (!Array.isArray(report?.results) || !report.lockfile)
|
|
87
|
+
return "the run's output is not an apply report";
|
|
88
|
+
if ("bound" in e) {
|
|
89
|
+
const binding = report.lockfile.bindings[e.declared];
|
|
90
|
+
if (binding?.id === e.bound)
|
|
91
|
+
return undefined;
|
|
92
|
+
return binding ? `${e.declared} is bound to ${binding.id}, not ${e.bound}` : `${e.declared} is not bound`;
|
|
93
|
+
}
|
|
94
|
+
const result = report.results.find((r) => r.id === e.declared);
|
|
95
|
+
// A gone object recreated is bound again; one forgotten is not.
|
|
96
|
+
const created = result?.status === "done" && (result.action === "create" || (result.action === "gone" && !!result.binding));
|
|
97
|
+
if (created)
|
|
98
|
+
return undefined;
|
|
99
|
+
if (!result)
|
|
100
|
+
return `apply did nothing with ${e.declared}`;
|
|
101
|
+
return `apply's ${result.action} of ${e.declared} ${result.status === "failed" ? `failed: ${result.error}` : `was ${result.status}`}`;
|
|
102
|
+
}
|
|
80
103
|
/**
|
|
81
104
|
* Why an expectation of the generic steps does not hold against a run's ledger records, or
|
|
82
105
|
* undefined when it does. A call is an `op.called` record without an `error`; one with an error
|
|
83
106
|
* (a policy denial, a rejected approval, a vendor's final failure) was attempted, not made. An
|
|
84
107
|
* operation `was denied` when the policy's decision on some call to it is `deny`, and `was held
|
|
85
108
|
* for` an approver when an approval for that approver holds it: one the policy asked for on its
|
|
86
|
-
* call, or one that `covers` it. A drift expectation reads the report a finished
|
|
87
|
-
* returned. A step named in the workflow's outline is read by the `name` its records carry
|
|
109
|
+
* call, or one that `covers` it. A drift or apply expectation reads the report a finished run
|
|
110
|
+
* of it returned. A step named in the workflow's outline is read by the `name` its records carry
|
|
88
111
|
* (its calls made, and `waitsOf`); a record written before steps had names has none.
|
|
89
112
|
*/
|
|
90
113
|
export function detailOf(e, records) {
|
|
@@ -132,6 +155,8 @@ export function detailOf(e, records) {
|
|
|
132
155
|
// A finished run: what `the run succeeds` expects, and what a drift expectation reads its report from.
|
|
133
156
|
if (end.type === "run.failed")
|
|
134
157
|
return `the run failed: ${end.error.message}`;
|
|
135
|
-
|
|
158
|
+
if (!("declared" in e))
|
|
159
|
+
return undefined;
|
|
160
|
+
return "status" in e ? driftDetail(e, end) : applyDetail(e, end);
|
|
136
161
|
}
|
|
137
162
|
//# sourceMappingURL=expectations.js.map
|
package/dist/expectations.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expectations.js","sourceRoot":"","sources":["../src/expectations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"expectations.js","sourceRoot":"","sources":["../src/expectations.ts"],"names":[],"mappings":"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"}
|
package/dist/host.d.ts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { z } from "zod";
|
|
2
|
+
/** How a host keeps the runtime up: `long-lived`, or (later) woken on a schedule. */
|
|
3
|
+
export type HostLifetime = "long-lived" | "wake-on-schedule";
|
|
4
|
+
/** What a host can do, for choosing one. */
|
|
5
|
+
export interface HostCapabilities {
|
|
6
|
+
lifetime: HostLifetime;
|
|
7
|
+
/** Its `url` is reachable from the internet, not only from this machine. */
|
|
8
|
+
publicUrl: boolean;
|
|
9
|
+
/** It builds the repository from git itself, at the revision apply gives it. */
|
|
10
|
+
buildsFromGit: boolean;
|
|
11
|
+
/** Its outbound connections come from fixed addresses, for a vendor's allow-list. */
|
|
12
|
+
staticEgress: boolean;
|
|
13
|
+
}
|
|
14
|
+
/** What a host's state says of it: where the app answers, which commit it runs, and whether it is up. */
|
|
15
|
+
export interface HostOutputs {
|
|
16
|
+
url: string;
|
|
17
|
+
/** The commit it runs, when its state says. */
|
|
18
|
+
revision?: string;
|
|
19
|
+
healthy: boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* A resource type's `host`: the fields it takes the runtime's inputs in, by dotted path into its
|
|
23
|
+
* declared fields, and how its state reads as `HostOutputs`. A host is drifted when
|
|
24
|
+
* `outputs(state).revision` differs from what `sanoma.source.resolve` says `ref` is now.
|
|
25
|
+
*/
|
|
26
|
+
export interface HostSpec {
|
|
27
|
+
capabilities: HostCapabilities;
|
|
28
|
+
inputs: {
|
|
29
|
+
/** The repository's clone URL, or a reference to a declared repository whose state holds one (a `by` field). */
|
|
30
|
+
source: string;
|
|
31
|
+
/** The branch (or tag) it runs: `main`, never a commit. */
|
|
32
|
+
ref: string;
|
|
33
|
+
/** The secrets it passes the runtime (`SANOMA_DATABASE_URL`, `SANOMA_SECRETS_KEY`): a write-only field. */
|
|
34
|
+
secrets: string;
|
|
35
|
+
/** The port the app listens on. */
|
|
36
|
+
port: string;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* The field apply fills with the commit `ref` resolves to, before it plans: hidden, as a data
|
|
40
|
+
* file may not declare it, so a merge to `ref` is a change to the host.
|
|
41
|
+
*/
|
|
42
|
+
revision: string;
|
|
43
|
+
outputs: (state: Record<string, unknown>) => HostOutputs;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Throws what is wrong with a resource type's `host`: an input or `revision` that names no field,
|
|
47
|
+
* `secrets` that is not write-only, a `revision` that is, an unknown lifetime, a type apply cannot
|
|
48
|
+
* change (not `writable`).
|
|
49
|
+
*/
|
|
50
|
+
export declare function checkHost(what: string, host: HostSpec, type: {
|
|
51
|
+
schema: z.ZodObject;
|
|
52
|
+
fields: {
|
|
53
|
+
writeOnly: readonly string[];
|
|
54
|
+
};
|
|
55
|
+
writable?: boolean;
|
|
56
|
+
}): void;
|
package/dist/host.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const LIFETIMES = ["long-lived", "wake-on-schedule"];
|
|
2
|
+
/** True when `schema` has a field at the dotted `path`, looking through optional, nullable and default wrappers. */
|
|
3
|
+
function hasPath(schema, path) {
|
|
4
|
+
let at = schema;
|
|
5
|
+
for (const key of path.split(".")) {
|
|
6
|
+
at = unwrap(at);
|
|
7
|
+
const shape = at.shape;
|
|
8
|
+
at = shape?.[key];
|
|
9
|
+
if (!at)
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
function unwrap(schema) {
|
|
15
|
+
let at = schema;
|
|
16
|
+
while ("unwrap" in at && typeof at.unwrap === "function")
|
|
17
|
+
at = at.unwrap();
|
|
18
|
+
return at;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Throws what is wrong with a resource type's `host`: an input or `revision` that names no field,
|
|
22
|
+
* `secrets` that is not write-only, a `revision` that is, an unknown lifetime, a type apply cannot
|
|
23
|
+
* change (not `writable`).
|
|
24
|
+
*/
|
|
25
|
+
export function checkHost(what, host, type) {
|
|
26
|
+
const problems = [];
|
|
27
|
+
if (!type.writable)
|
|
28
|
+
problems.push("it must be writable, so apply can create and update it");
|
|
29
|
+
if (!LIFETIMES.includes(host.capabilities?.lifetime)) {
|
|
30
|
+
problems.push(`capabilities.lifetime is one of ${LIFETIMES.join(", ")}`);
|
|
31
|
+
}
|
|
32
|
+
for (const [input, path] of [...Object.entries(host.inputs ?? {}), ["revision", host.revision]]) {
|
|
33
|
+
if (typeof path !== "string" || !hasPath(type.schema, path))
|
|
34
|
+
problems.push(`${input} names no field (${path})`);
|
|
35
|
+
}
|
|
36
|
+
if (!type.fields.writeOnly.includes(host.inputs?.secrets))
|
|
37
|
+
problems.push("inputs.secrets must be a write-only field");
|
|
38
|
+
if (type.fields.writeOnly.includes(host.revision))
|
|
39
|
+
problems.push("revision must not be write-only: drift reads it");
|
|
40
|
+
if (typeof host.outputs !== "function")
|
|
41
|
+
problems.push("outputs must be a function of the state");
|
|
42
|
+
if (problems.length)
|
|
43
|
+
throw new Error(`${what}: its host: ${problems.join("; ")}`);
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=host.js.map
|
package/dist/host.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host.js","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"AAqDA,MAAM,SAAS,GAA4B,CAAC,YAAY,EAAE,kBAAkB,CAAC,CAAC;AAE9E,oHAAoH;AACpH,SAAS,OAAO,CAAC,MAAiB,EAAE,IAAY;IAC9C,IAAI,EAAE,GAA0B,MAAM,CAAC;IACvC,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QAClC,EAAE,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC;QAChB,MAAM,KAAK,GAAI,EAA2B,CAAC,KAAK,CAAC;QACjD,EAAE,GAAG,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC;QAClB,IAAI,CAAC,EAAE;YAAE,OAAO,KAAK,CAAC;IACxB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,MAAM,CAAC,MAAiB;IAC/B,IAAI,EAAE,GAAG,MAAM,CAAC;IAChB,OAAO,QAAQ,IAAI,EAAE,IAAI,OAAO,EAAE,CAAC,MAAM,KAAK,UAAU;QAAE,EAAE,GAAG,EAAE,CAAC,MAAM,EAAe,CAAC;IACxF,OAAO,EAAE,CAAC;AACZ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS,CACvB,IAAY,EACZ,IAAc,EACd,IAA2F;IAE3F,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,IAAI,CAAC,IAAI,CAAC,QAAQ;QAAE,QAAQ,CAAC,IAAI,CAAC,wDAAwD,CAAC,CAAC;IAC5F,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,EAAE,CAAC;QACrD,QAAQ,CAAC,IAAI,CAAC,mCAAmC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC3E,CAAC;IACD,KAAK,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,CAAC,UAAU,EAAE,IAAI,CAAC,QAAQ,CAAU,CAAC,EAAE,CAAC;QACzG,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;YAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,oBAAoB,IAAI,GAAG,CAAC,CAAC;IAClH,CAAC;IACD,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC;QAAE,QAAQ,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAC;IACtH,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC;QAAE,QAAQ,CAAC,IAAI,CAAC,iDAAiD,CAAC,CAAC;IACpH,IAAI,OAAO,IAAI,CAAC,OAAO,KAAK,UAAU;QAAE,QAAQ,CAAC,IAAI,CAAC,yCAAyC,CAAC,CAAC;IACjG,IAAI,QAAQ,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,eAAe,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACpF,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
export { type CallContext, type Connector, type ConnectorSetup, type ConnectorVendor, type Driver, type DriverEnv, type DriverFn, defineConnector, DriverError, type Effect, isOp, type Op, type OpSpec, type ResourceGroup, retryableStatus, type VendorInfo, withSetup, } from "./op.ts";
|
|
2
2
|
export { defineWorkflow, Principal, type ApprovalRequest, type ApprovalResult, type ApprovalState, type Approver, type Builtin, type Ctx, type SleepRequest, type StepOptions, type Use, type WorkflowDefinition, } from "./define.ts";
|
|
3
|
-
export { compareDeclared, type Declared, type Declaring, defineResource, diffDeclared, type FieldReference, type References, type Resource, type ResourceFields, type ResourceOps, type ResourceSpec, } from "./resource.ts";
|
|
3
|
+
export { compareDeclared, type Declared, type Declaring, defineResource, diffDeclared, type FieldReference, type PlanAction, type References, type Resource, type ResourceFields, type ResourceOps, type ResourceSpec, withoutWriteOnly, } from "./resource.ts";
|
|
4
4
|
export { defineConfig, resolveConfig, resolveDatabaseUrl, type ResolvedConfig, type SanomaConfig } from "./config.ts";
|
|
5
5
|
export { type CredentialStatus, credentialsOf } from "./env.ts";
|
|
6
|
+
export { APPLY_WORKFLOW, ApplyInput, type ApplyPlan, type ApplyReport, type ApplyResult, type PlanAnswer, type PlanStep, } from "./apply.ts";
|
|
6
7
|
export { DRIFT_WORKFLOW, type DriftDeclared, type DriftField, type DriftReport, type DriftResult, type DriftStatus, } from "./drift.ts";
|
|
7
8
|
export type { DeclaredResource, ResourceProblem } from "./resources.ts";
|
|
8
9
|
export { allow, allowAll, approve, approvedFor, type Decision, definePolicy, deny, type Policy, type PolicyCall, type PolicyOp, policyOpOf, type RecordedDecision, } from "./policy.ts";
|
|
@@ -12,7 +13,10 @@ export { ApprovalMessage, APPROVALS_EVENT, decisionEventOf } from "./approvals.t
|
|
|
12
13
|
export { RUNTIME_VERSION } from "./version.ts";
|
|
13
14
|
export type { RunArgs } from "./run.ts";
|
|
14
15
|
export { startWorker, type Worker, type WorkerOptions } from "./worker.ts";
|
|
15
|
-
export {
|
|
16
|
+
export { generateSecret, isSecret, memorySecrets, type Resolved, resolveSecrets, type Secret, type Secrets, } from "./secret.ts";
|
|
17
|
+
export { resolveRevision, SOURCE_RESOLVE, type Source } from "./source.ts";
|
|
18
|
+
export type { HostCapabilities, HostLifetime, HostOutputs, HostSpec } from "./host.ts";
|
|
19
|
+
export { SanomaClient, type RunsFilter, type RunSummary, type StartOptions, type StoredSecret } from "./client.ts";
|
|
16
20
|
export { dbosClient } from "./db.ts";
|
|
17
21
|
export { approverLabel, credentialReady, DEFAULT_SLEEP_NAME, ENDED_STATUSES, errorMessage, isEnded, isLoopback, mayDecide, problemAt, problemLine, RUN_STATUSES, type RunStatus, } from "./shared.ts";
|
|
18
22
|
export { defineDriver, type DriverImpl, type OpIdOf } from "./op.ts";
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
export { defineConnector, DriverError, isOp, retryableStatus, withSetup, } from "./op.js";
|
|
2
2
|
export { defineWorkflow, Principal, } from "./define.js";
|
|
3
|
-
export { compareDeclared, defineResource, diffDeclared, } from "./resource.js";
|
|
3
|
+
export { compareDeclared, defineResource, diffDeclared, withoutWriteOnly, } from "./resource.js";
|
|
4
4
|
export { defineConfig, resolveConfig, resolveDatabaseUrl } from "./config.js";
|
|
5
5
|
export { credentialsOf } from "./env.js";
|
|
6
|
+
export { APPLY_WORKFLOW, ApplyInput, } from "./apply.js";
|
|
6
7
|
export { DRIFT_WORKFLOW, } from "./drift.js";
|
|
7
8
|
export { allow, allowAll, approve, approvedFor, definePolicy, deny, policyOpOf, } from "./policy.js";
|
|
8
9
|
export { errorCode, invalidInput, PolicyDeniedError, RejectedError, SanomaError, } from "./errors.js";
|
|
@@ -10,6 +11,9 @@ export { jsonlLedger, memoryLedger, postgresLedger, } from "./ledger.js";
|
|
|
10
11
|
export { ApprovalMessage, APPROVALS_EVENT, decisionEventOf } from "./approvals.js";
|
|
11
12
|
export { RUNTIME_VERSION } from "./version.js";
|
|
12
13
|
export { startWorker } from "./worker.js";
|
|
14
|
+
// `secret` itself is at `@sanoma-ai/workflows/resources`, for data files; this is the drivers' side.
|
|
15
|
+
export { generateSecret, isSecret, memorySecrets, resolveSecrets, } from "./secret.js";
|
|
16
|
+
export { resolveRevision, SOURCE_RESOLVE } from "./source.js";
|
|
13
17
|
export { SanomaClient } from "./client.js";
|
|
14
18
|
// A raw DBOS client on the runtime's database, for tests and tools that read DBOS directly.
|
|
15
19
|
export { dbosClient } from "./db.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAQL,eAAe,EACf,WAAW,EAEX,IAAI,EAIJ,eAAe,EAEf,SAAS,GACV,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,cAAc,EACd,SAAS,GAWV,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,eAAe,EAGf,cAAc,EACd,YAAY,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAQL,eAAe,EACf,WAAW,EAEX,IAAI,EAIJ,eAAe,EAEf,SAAS,GACV,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,cAAc,EACd,SAAS,GAWV,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,eAAe,EAGf,cAAc,EACd,YAAY,EAQZ,gBAAgB,GACjB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,kBAAkB,EAA0C,MAAM,aAAa,CAAC;AACtH,OAAO,EAAyB,aAAa,EAAE,MAAM,UAAU,CAAC;AAChE,OAAO,EACL,cAAc,EACd,UAAU,GAMX,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,cAAc,GAMf,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,KAAK,EACL,QAAQ,EACR,OAAO,EACP,WAAW,EAEX,YAAY,EACZ,IAAI,EAIJ,UAAU,GAEX,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,SAAS,EAIT,YAAY,EACZ,iBAAiB,EACjB,aAAa,EACb,WAAW,GACZ,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,WAAW,EACX,YAAY,EACZ,cAAc,GAKf,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACnF,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,OAAO,EAAE,WAAW,EAAmC,MAAM,aAAa,CAAC;AAC3E,qGAAqG;AACrG,OAAO,EACL,cAAc,EACd,QAAQ,EACR,aAAa,EAEb,cAAc,GAGf,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,eAAe,EAAE,cAAc,EAAe,MAAM,aAAa,CAAC;AAE3E,OAAO,EAAE,YAAY,EAA0E,MAAM,aAAa,CAAC;AACnH,4FAA4F;AAC5F,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,4EAA4E;AAC5E,OAAO,EACL,aAAa,EACb,eAAe,EACf,kBAAkB,EAClB,cAAc,EACd,YAAY,EACZ,OAAO,EACP,UAAU,EACV,SAAS,EACT,SAAS,EACT,WAAW,EACX,YAAY,GAEb,MAAM,aAAa,CAAC;AACrB,kFAAkF;AAClF,kGAAkG;AAClG,uDAAuD;AACvD,OAAO,EAAE,YAAY,EAAgC,MAAM,SAAS,CAAC;AACrE,6FAA6F;AAC7F,OAAO,EAAE,WAAW,EAAoD,MAAM,YAAY,CAAC;AAC3F,8EAA8E"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { ResourceProblem } from "./resources.ts";
|
|
2
|
+
/** Where the lockfile is, relative to the config's root. */
|
|
3
|
+
export declare const LOCKFILE = "resources/sanoma.lock.json";
|
|
4
|
+
/** Which vendor object a declaration means: its `<vendor>.<type>` and the vendor's stable id for it. */
|
|
5
|
+
export interface Binding {
|
|
6
|
+
type: string;
|
|
7
|
+
id: string;
|
|
8
|
+
}
|
|
9
|
+
/** The lockfile's content: by declaration key, `<file>#<export>` (the file relative to the config's root, with `/`). */
|
|
10
|
+
export type Bindings = Record<string, Binding>;
|
|
11
|
+
/**
|
|
12
|
+
* The lockfile under `root`: no bindings when there is none, and no bindings with a problem when
|
|
13
|
+
* it is not JSON or not a map of `<file>#<export>` to `{ type, id }`.
|
|
14
|
+
*/
|
|
15
|
+
export declare function readLockfile(root: string): {
|
|
16
|
+
bindings: Bindings;
|
|
17
|
+
problems: ResourceProblem[];
|
|
18
|
+
};
|
|
19
|
+
/** The lockfile's text for `bindings`: keys sorted, two-space JSON, a trailing newline, so a diff shows only what changed. */
|
|
20
|
+
export declare function serializeLockfile(bindings: Bindings): string;
|
|
21
|
+
/** Writes the lockfile under `root` whole or not at all: to a file beside it, then renamed over it. Apply only. */
|
|
22
|
+
export declare function writeLockfile(root: string, bindings: Bindings): void;
|
|
23
|
+
/**
|
|
24
|
+
* One change to the lockfile: a declaration bound for the first time (`bind`, `to`), pointed at
|
|
25
|
+
* another object (`rebind`, `from` and `to`), or no longer bound (`unbind`, `from`). `type` is
|
|
26
|
+
* the binding's `<vendor>.<type>`, the new one's for a rebind.
|
|
27
|
+
*/
|
|
28
|
+
export interface Rebind {
|
|
29
|
+
key: string;
|
|
30
|
+
type: string;
|
|
31
|
+
kind: "bind" | "rebind" | "unbind";
|
|
32
|
+
from?: string;
|
|
33
|
+
to?: string;
|
|
34
|
+
}
|
|
35
|
+
/** What changed from `before` to `after`, by key, sorted. */
|
|
36
|
+
export declare function diffLockfiles(before: Bindings, after: Bindings): Rebind[];
|
package/dist/lockfile.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { existsSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
// The lockfile: which vendor object each declaration means, kept apart from the data files (which
|
|
5
|
+
// hold intent only), as `package-lock.json` is from `package.json`. Only apply writes it.
|
|
6
|
+
/** Where the lockfile is, relative to the config's root. */
|
|
7
|
+
export const LOCKFILE = "resources/sanoma.lock.json";
|
|
8
|
+
const lockfile = z.record(z.string().regex(/^resources\/[^#]+#[^#]+$/), z.strictObject({ type: z.string().regex(/^[^.\s]+\.[^.\s]+$/), id: z.string().min(1) }));
|
|
9
|
+
/**
|
|
10
|
+
* The lockfile under `root`: no bindings when there is none, and no bindings with a problem when
|
|
11
|
+
* it is not JSON or not a map of `<file>#<export>` to `{ type, id }`.
|
|
12
|
+
*/
|
|
13
|
+
export function readLockfile(root) {
|
|
14
|
+
const path = join(root, LOCKFILE);
|
|
15
|
+
if (!existsSync(path))
|
|
16
|
+
return { bindings: {}, problems: [] };
|
|
17
|
+
let json;
|
|
18
|
+
try {
|
|
19
|
+
json = JSON.parse(readFileSync(path, "utf8"));
|
|
20
|
+
}
|
|
21
|
+
catch (e) {
|
|
22
|
+
return { bindings: {}, problems: [{ file: LOCKFILE, message: `not JSON: ${e.message}` }] };
|
|
23
|
+
}
|
|
24
|
+
const parsed = lockfile.safeParse(json);
|
|
25
|
+
if (!parsed.success) {
|
|
26
|
+
// One line: zod's own spans lines.
|
|
27
|
+
return {
|
|
28
|
+
bindings: {},
|
|
29
|
+
problems: [{ file: LOCKFILE, message: z.prettifyError(parsed.error).replaceAll(/\s*\n\s*/g, " ") }],
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
return { bindings: parsed.data, problems: [] };
|
|
33
|
+
}
|
|
34
|
+
/** The lockfile's text for `bindings`: keys sorted, two-space JSON, a trailing newline, so a diff shows only what changed. */
|
|
35
|
+
export function serializeLockfile(bindings) {
|
|
36
|
+
const sorted = Object.entries(bindings)
|
|
37
|
+
.toSorted(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
|
|
38
|
+
.map(([key, { type, id }]) => [key, { type, id }]);
|
|
39
|
+
return `${JSON.stringify(Object.fromEntries(sorted), null, 2)}\n`;
|
|
40
|
+
}
|
|
41
|
+
/** Writes the lockfile under `root` whole or not at all: to a file beside it, then renamed over it. Apply only. */
|
|
42
|
+
export function writeLockfile(root, bindings) {
|
|
43
|
+
const path = join(root, LOCKFILE);
|
|
44
|
+
const temporary = `${path}.${process.pid}.tmp`;
|
|
45
|
+
try {
|
|
46
|
+
writeFileSync(temporary, serializeLockfile(bindings));
|
|
47
|
+
renameSync(temporary, path);
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
rmSync(temporary, { force: true });
|
|
51
|
+
throw err;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/** What changed from `before` to `after`, by key, sorted. */
|
|
55
|
+
export function diffLockfiles(before, after) {
|
|
56
|
+
const keys = [...new Set([...Object.keys(before), ...Object.keys(after)])].toSorted();
|
|
57
|
+
return keys.flatMap((key) => {
|
|
58
|
+
const was = before[key];
|
|
59
|
+
const now = after[key];
|
|
60
|
+
if (!now)
|
|
61
|
+
return was ? [{ key, type: was.type, kind: "unbind", from: was.id }] : [];
|
|
62
|
+
if (!was)
|
|
63
|
+
return [{ key, type: now.type, kind: "bind", to: now.id }];
|
|
64
|
+
if (was.id === now.id && was.type === now.type)
|
|
65
|
+
return [];
|
|
66
|
+
return [{ key, type: now.type, kind: "rebind", from: was.id, to: now.id }];
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=lockfile.js.map
|