@sanoma-ai/workflows 0.0.0-stage → 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/LICENSE +105 -0
- package/README.md +544 -2
- 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/approvals.d.ts +46 -0
- package/dist/approvals.js +111 -0
- package/dist/approvals.js.map +1 -0
- package/dist/ast.d.ts +57 -0
- package/dist/ast.js +81 -0
- package/dist/ast.js.map +1 -0
- package/dist/call.d.ts +37 -0
- package/dist/call.js +417 -0
- package/dist/call.js.map +1 -0
- package/dist/client.d.ts +203 -0
- package/dist/client.js +457 -0
- package/dist/client.js.map +1 -0
- package/dist/config.d.ts +126 -0
- package/dist/config.js +264 -0
- package/dist/config.js.map +1 -0
- package/dist/credentials.d.ts +55 -0
- package/dist/credentials.js +261 -0
- package/dist/credentials.js.map +1 -0
- package/dist/cucumber.d.ts +64 -0
- package/dist/cucumber.js +158 -0
- package/dist/cucumber.js.map +1 -0
- package/dist/datafile.d.ts +71 -0
- package/dist/datafile.js +380 -0
- package/dist/datafile.js.map +1 -0
- package/dist/db.d.ts +58 -0
- package/dist/db.js +179 -0
- package/dist/db.js.map +1 -0
- package/dist/define.d.ts +205 -0
- package/dist/define.js +103 -0
- package/dist/define.js.map +1 -0
- package/dist/describe.d.ts +141 -0
- package/dist/describe.js +135 -0
- package/dist/describe.js.map +1 -0
- package/dist/drift.d.ts +127 -0
- package/dist/drift.js +167 -0
- package/dist/drift.js.map +1 -0
- package/dist/env.d.ts +49 -0
- package/dist/env.js +83 -0
- package/dist/env.js.map +1 -0
- package/dist/errors.d.ts +88 -0
- package/dist/errors.js +148 -0
- package/dist/errors.js.map +1 -0
- package/dist/expectations.d.ts +26 -0
- package/dist/expectations.js +162 -0
- package/dist/expectations.js.map +1 -0
- package/dist/fake.d.ts +55 -0
- package/dist/fake.js +87 -0
- package/dist/fake.js.map +1 -0
- package/dist/fill.d.ts +9 -0
- package/dist/fill.js +17 -0
- package/dist/fill.js.map +1 -0
- 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 +23 -0
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -0
- package/dist/ledger.d.ts +217 -0
- package/dist/ledger.js +251 -0
- package/dist/ledger.js.map +1 -0
- package/dist/lint.d.ts +32 -0
- package/dist/lint.js +168 -0
- package/dist/lint.js.map +1 -0
- package/dist/lockfile.d.ts +36 -0
- package/dist/lockfile.js +69 -0
- package/dist/lockfile.js.map +1 -0
- package/dist/log.d.ts +24 -0
- package/dist/log.js +83 -0
- package/dist/log.js.map +1 -0
- package/dist/op.d.ts +260 -0
- package/dist/op.js +188 -0
- package/dist/op.js.map +1 -0
- package/dist/outline.d.ts +179 -0
- package/dist/outline.js +506 -0
- package/dist/outline.js.map +1 -0
- package/dist/paths.d.ts +11 -0
- package/dist/paths.js +30 -0
- package/dist/paths.js.map +1 -0
- package/dist/plugin.d.ts +28 -0
- package/dist/plugin.js +25 -0
- package/dist/plugin.js.map +1 -0
- package/dist/policy.d.ts +114 -0
- package/dist/policy.js +60 -0
- package/dist/policy.js.map +1 -0
- package/dist/resource.d.ts +378 -0
- package/dist/resource.js +430 -0
- package/dist/resource.js.map +1 -0
- package/dist/resources.d.ts +77 -0
- package/dist/resources.js +244 -0
- package/dist/resources.js.map +1 -0
- package/dist/run.d.ts +101 -0
- package/dist/run.js +7 -0
- package/dist/run.js.map +1 -0
- package/dist/sandbox.d.ts +33 -0
- package/dist/sandbox.js +127 -0
- package/dist/sandbox.js.map +1 -0
- package/dist/scenario.d.ts +221 -0
- package/dist/scenario.js +1104 -0
- package/dist/scenario.js.map +1 -0
- package/dist/scenarios.d.ts +55 -0
- package/dist/scenarios.js +71 -0
- package/dist/scenarios.js.map +1 -0
- 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 +69 -0
- package/dist/shared.js +84 -0
- package/dist/shared.js.map +1 -0
- package/dist/source.d.ts +58 -0
- package/dist/source.js +54 -0
- package/dist/source.js.map +1 -0
- package/dist/steps.d.ts +76 -0
- package/dist/steps.js +23 -0
- package/dist/steps.js.map +1 -0
- package/dist/version.d.ts +29 -0
- package/dist/version.js +76 -0
- package/dist/version.js.map +1 -0
- package/dist/worker.d.ts +37 -0
- package/dist/worker.js +228 -0
- package/dist/worker.js.map +1 -0
- package/dist/writer.d.ts +35 -0
- package/dist/writer.js +201 -0
- package/dist/writer.js.map +1 -0
- package/oxlint.json +128 -0
- package/package.json +96 -3
- package/src/apply-steps.ts +110 -0
- package/src/apply.ts +626 -0
- package/src/approvals.ts +157 -0
- package/src/ast.ts +115 -0
- package/src/call.ts +483 -0
- package/src/client.ts +604 -0
- package/src/config.ts +404 -0
- package/src/credentials.ts +296 -0
- package/src/cucumber.ts +230 -0
- package/src/datafile.ts +481 -0
- package/src/db.ts +197 -0
- package/src/define.ts +285 -0
- package/src/describe.ts +282 -0
- package/src/drift.ts +259 -0
- package/src/env.ts +122 -0
- package/src/errors.ts +202 -0
- package/src/expectations.ts +191 -0
- package/src/fake.ts +156 -0
- package/src/fill.ts +24 -0
- package/src/host.ts +96 -0
- package/src/index.ts +143 -0
- package/src/ledger.ts +419 -0
- package/src/lint.ts +208 -0
- package/src/lockfile.ts +95 -0
- package/src/log.ts +82 -0
- package/src/op.ts +402 -0
- package/src/outline.ts +620 -0
- package/src/paths.ts +32 -0
- package/src/plugin.ts +37 -0
- package/src/policy.ts +139 -0
- package/src/resource.ts +670 -0
- package/src/resources.ts +311 -0
- package/src/run.ts +106 -0
- package/src/sandbox.ts +161 -0
- package/src/scenario.ts +1365 -0
- package/src/scenarios.ts +111 -0
- package/src/secret.ts +92 -0
- package/src/shared.ts +126 -0
- package/src/source.ts +82 -0
- package/src/steps.ts +90 -0
- package/src/version.ts +86 -0
- package/src/worker.ts +264 -0
- package/src/writer.ts +225 -0
package/dist/resource.js
ADDED
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { checkHost } from "./host.js";
|
|
3
|
+
import { RESOURCE, VENDOR } from "./op.js";
|
|
4
|
+
import { isSanomaSecret, isSecret } from "./secret.js";
|
|
5
|
+
/**
|
|
6
|
+
* Where a declared resource keeps its brand, its type's `<vendor>.<type>`: a symbol, so a field
|
|
7
|
+
* holding a resource is told from data; a registered one (`Symbol.for`), so a copy of this
|
|
8
|
+
* package reads what another copy declared, as `VENDOR`.
|
|
9
|
+
*/
|
|
10
|
+
export const DECLARED = Symbol.for("sanoma.declared");
|
|
11
|
+
const importId = z.string().min(1);
|
|
12
|
+
/** What a driver keeps beside a state (an OpenTofu provider's private data and state version), passed back unchanged. */
|
|
13
|
+
const handle = z.string().optional().describe("The driver's data for the object, opaque: pass it back unchanged");
|
|
14
|
+
const record = z.record(z.string(), z.unknown());
|
|
15
|
+
/** What a plan of a change says will happen, as `PlanResponse.Action` names it. */
|
|
16
|
+
export const PLAN_ACTIONS = ["none", "create", "update", "replace", "delete"];
|
|
17
|
+
/** The operations of a writable type that change its objects: only the apply workflow calls them (`isChangeOp`). */
|
|
18
|
+
export const CHANGE_OPS = ["create", "update", "delete"];
|
|
19
|
+
const opsOf = (schema) => {
|
|
20
|
+
// Both answer `{ gone: true }` when the vendor has no such object, and its state when it has.
|
|
21
|
+
const output = z.object({ id: importId, gone: z.boolean(), state: schema.optional(), handle });
|
|
22
|
+
const known = { id: importId, state: record.optional(), handle };
|
|
23
|
+
// The declared fields, a secret marker (`{ $secret }`) at a write-only one: the driver resolves it.
|
|
24
|
+
const desired = record.describe("The declared fields; a write-only one may hold a secret marker");
|
|
25
|
+
const changed = z.object({ id: importId, state: schema, handle });
|
|
26
|
+
const action = z.enum(PLAN_ACTIONS);
|
|
27
|
+
/** Fields as dotted paths, a list item's with its index. */
|
|
28
|
+
const paths = z.array(z.string());
|
|
29
|
+
return {
|
|
30
|
+
import: { input: z.object({ id: importId }), output },
|
|
31
|
+
read: { input: z.object(known), output },
|
|
32
|
+
plan: {
|
|
33
|
+
input: z.object({ ...known, id: importId.optional(), desired: desired.optional() }),
|
|
34
|
+
output: z.object({
|
|
35
|
+
action,
|
|
36
|
+
// The new state, without write-only fields; a value known only after apply is `null`, its path in `unknown`.
|
|
37
|
+
planned: record.optional(),
|
|
38
|
+
unknown: paths,
|
|
39
|
+
replace: paths.describe("The fields whose change replaces the object: not empty exactly when `replace`"),
|
|
40
|
+
}),
|
|
41
|
+
},
|
|
42
|
+
create: { input: z.object({ desired }), output: changed },
|
|
43
|
+
update: {
|
|
44
|
+
input: z.object({ ...known, desired, expect: z.object({ action, replace: paths }).optional() }),
|
|
45
|
+
output: changed,
|
|
46
|
+
},
|
|
47
|
+
delete: { input: z.object(known), output: z.object({ id: importId, gone: z.literal(true) }) },
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
/** What the ledger keeps of a resource operation's `handle`: its name, never its bytes. */
|
|
51
|
+
const opaque = ["handle"];
|
|
52
|
+
/** The policy's `target` for a resource's operations: the id, an identity or a binding id. */
|
|
53
|
+
const target = ({ id }) => id;
|
|
54
|
+
/**
|
|
55
|
+
* True for an operation that changes a writable type's objects (`CHANGE_OPS`), which only the
|
|
56
|
+
* apply workflow may call: by its vendor, resource and name, so a copy of a connector is told too.
|
|
57
|
+
*/
|
|
58
|
+
export function isChangeOp(op, types) {
|
|
59
|
+
return (CHANGE_OPS.includes(op.name) && types.get(`${op.vendor}.${op.resource}`)?.writable === true);
|
|
60
|
+
}
|
|
61
|
+
/** True for a plain object: not null, not a list. */
|
|
62
|
+
export const isObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
63
|
+
/** `path.name`, or `name` at the top: a field's dotted path. */
|
|
64
|
+
export const joinPath = (path, name) => (path ? `${path}.${name}` : name);
|
|
65
|
+
const isDeclared = (v) => isObject(v) && typeof v[DECLARED] === "string";
|
|
66
|
+
/** One order for a list compared as a multiset: by each item's JSON. */
|
|
67
|
+
const canonical = (items) => items
|
|
68
|
+
.map((item) => [JSON.stringify(item) ?? "", item])
|
|
69
|
+
.toSorted(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
|
|
70
|
+
.map(([, item]) => item);
|
|
71
|
+
const comparers = new WeakMap();
|
|
72
|
+
/** The type's comparer, made once per `fields`. */
|
|
73
|
+
function comparerOf(fields) {
|
|
74
|
+
let compare = comparers.get(fields);
|
|
75
|
+
if (!compare) {
|
|
76
|
+
compare = comparer(fields);
|
|
77
|
+
comparers.set(fields, compare);
|
|
78
|
+
}
|
|
79
|
+
return compare;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* The fields of `state` that `desired` declares, minus vendor-owned and write-only ones: only
|
|
83
|
+
* declared fields are compared, as CloudFormation does. An object is picked field by field, a
|
|
84
|
+
* list item by item against the declared item at its index, and an `unordered` list (a set)
|
|
85
|
+
* item by item against what its declared items declare, then sorted, so its order never
|
|
86
|
+
* drifts. Anything else is kept whole.
|
|
87
|
+
*
|
|
88
|
+
* So a field the data file leaves out is never drift, whatever the vendor holds. That covers
|
|
89
|
+
* attributes the provider marks `computed` and `optional`: they are the user's to set, not
|
|
90
|
+
* vendor-owned, but the vendor fills them when nobody does (GitHub's `etag`, `topics`,
|
|
91
|
+
* `visibility`), so they are compared only when declared.
|
|
92
|
+
*/
|
|
93
|
+
export function compareDeclared(fields, state, desired) {
|
|
94
|
+
return comparerOf(fields).pick(state, desired);
|
|
95
|
+
}
|
|
96
|
+
function comparer(fields) {
|
|
97
|
+
const skip = new Set([...fields.vendorOwned, ...fields.writeOnly]);
|
|
98
|
+
const unordered = new Set(fields.unordered);
|
|
99
|
+
const pick = (actual, declared, path) => {
|
|
100
|
+
if (Array.isArray(declared) && Array.isArray(actual)) {
|
|
101
|
+
if (unordered.has(path)) {
|
|
102
|
+
// What any declared item declares: a set's items have no declared counterpart by index.
|
|
103
|
+
const objects = declared.filter(isObject);
|
|
104
|
+
const like = objects.length ? Object.assign({}, ...objects) : undefined;
|
|
105
|
+
return canonical(like ? actual.map((item) => pick(item, like, path)) : actual);
|
|
106
|
+
}
|
|
107
|
+
return actual.map((item, i) => (i < declared.length ? pick(item, declared[i], path) : item));
|
|
108
|
+
}
|
|
109
|
+
if (!isObject(declared) || !isObject(actual))
|
|
110
|
+
return actual ?? null;
|
|
111
|
+
const out = {};
|
|
112
|
+
for (const [name, value] of Object.entries(declared)) {
|
|
113
|
+
const at = joinPath(path, name);
|
|
114
|
+
if (value === undefined || skip.has(at))
|
|
115
|
+
continue;
|
|
116
|
+
out[name] = pick(actual[name], value, at);
|
|
117
|
+
}
|
|
118
|
+
return out;
|
|
119
|
+
};
|
|
120
|
+
return { pick: (state, desired) => pick(state, desired, ""), unordered };
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Where `state` differs from what `desired` declares: the type's `normalize` of each (by default
|
|
124
|
+
* `compareDeclared`: declared fields only, never vendor-owned or write-only ones, `unordered`
|
|
125
|
+
* lists as sets), then leaf by leaf: objects field by field, lists of one length item by item,
|
|
126
|
+
* and anything else (a list whose length changed, an `unordered` one) whole.
|
|
127
|
+
*
|
|
128
|
+
* `accept` is, by a reference's path as `refs` has it (`repository_id`, `teams.0`), the values
|
|
129
|
+
* the vendor may hold there for the resource it names (its `node_id`, say: see
|
|
130
|
+
* `FieldReference.by`): any of them counts as the declared value.
|
|
131
|
+
*/
|
|
132
|
+
export function diffDeclared(
|
|
133
|
+
// `any`: a type's `normalize` takes its own declared fields.
|
|
134
|
+
resource, state, desired, accept = {}) {
|
|
135
|
+
const actual = withAccepted(state, desired, accept);
|
|
136
|
+
const { unordered } = comparerOf(resource.fields);
|
|
137
|
+
return changes(resource.normalize(desired, desired), resource.normalize(actual, desired), unordered);
|
|
138
|
+
}
|
|
139
|
+
/** `state`, with each value `accept` takes at its path replaced by the declared one there. */
|
|
140
|
+
function withAccepted(state, desired, accept) {
|
|
141
|
+
const paths = Object.entries(accept).filter(([, values]) => values.length);
|
|
142
|
+
if (!paths.length)
|
|
143
|
+
return state;
|
|
144
|
+
const out = structuredClone(state);
|
|
145
|
+
for (const [path, values] of paths) {
|
|
146
|
+
const at = holderOf(out, path);
|
|
147
|
+
if (at && values.includes(at.holder[at.key]))
|
|
148
|
+
at.holder[at.key] = valueAt(desired, path);
|
|
149
|
+
}
|
|
150
|
+
return out;
|
|
151
|
+
}
|
|
152
|
+
/** The object or list holding the value at a dotted path (a list item's by its index), and its key there. */
|
|
153
|
+
export function holderOf(value, path) {
|
|
154
|
+
const keys = path.split(".");
|
|
155
|
+
const key = keys.pop();
|
|
156
|
+
const holder = keys.reduce((v, k) => (isObject(v) || Array.isArray(v) ? v[k] : undefined), value);
|
|
157
|
+
return isObject(holder) || Array.isArray(holder) ? { holder: holder, key } : undefined;
|
|
158
|
+
}
|
|
159
|
+
/** A field's dotted path as `fields` names it, without a list item's index: `teams.0` is `teams`. */
|
|
160
|
+
export const fieldPathOf = (at) => at.replaceAll(/\.\d+(?=\.|$)/g, "");
|
|
161
|
+
/** The value at a dotted path, a list item's by its index. */
|
|
162
|
+
export const valueAt = (value, path) => path.split(".").reduce((v, key) => (isObject(v) || Array.isArray(v) ? v[key] : undefined), value);
|
|
163
|
+
/** True when the two are the same JSON, where a missing value is `null`. */
|
|
164
|
+
function same(a, b) {
|
|
165
|
+
if (a === b || (a == null && b == null))
|
|
166
|
+
return true;
|
|
167
|
+
if (Array.isArray(a) && Array.isArray(b))
|
|
168
|
+
return a.length === b.length && a.every((item, i) => same(item, b[i]));
|
|
169
|
+
if (isObject(a) && isObject(b))
|
|
170
|
+
return Object.keys({ ...a, ...b }).every((key) => same(a[key], b[key]));
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Where `actual` differs from `desired`, leaf by leaf. `path` names the field as `fields` does,
|
|
175
|
+
* without indexes; `at` as a report does, with them.
|
|
176
|
+
*/
|
|
177
|
+
function changes(desired, actual, unordered, path = "", at = "") {
|
|
178
|
+
if (isObject(desired) && isObject(actual)) {
|
|
179
|
+
return Object.keys({ ...desired, ...actual }).flatMap((key) => changes(desired[key], actual[key], unordered, joinPath(path, key), joinPath(at, key)));
|
|
180
|
+
}
|
|
181
|
+
if (Array.isArray(desired) && Array.isArray(actual) && desired.length === actual.length && !unordered.has(path)) {
|
|
182
|
+
return desired.flatMap((item, i) => changes(item, actual[i], unordered, path, joinPath(at, String(i))));
|
|
183
|
+
}
|
|
184
|
+
return same(desired, actual) ? [] : [{ path: at, desired: desired ?? null, actual: actual ?? null }];
|
|
185
|
+
}
|
|
186
|
+
/** The secret markers in a write-only value, in its place: the value itself, or a map of them (none: `[]`). */
|
|
187
|
+
function markers(value) {
|
|
188
|
+
if (isSecret(value))
|
|
189
|
+
return [value];
|
|
190
|
+
if (!isObject(value))
|
|
191
|
+
return [];
|
|
192
|
+
const kept = Object.entries(value).flatMap(([name, v]) => markers(v).map((m) => [name, m]));
|
|
193
|
+
return kept.length ? [Object.fromEntries(kept)] : [];
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* `desired` without the values at the fields the type marks write-only (a webhook's `secret`):
|
|
197
|
+
* what a run may record of a declaration. A list's items lose them too. A secret marker
|
|
198
|
+
* (`secret("NAME")`) stays, there or inside a write-only map (a host's `secrets`): it names a
|
|
199
|
+
* stored secret and holds none, and the driver resolves it.
|
|
200
|
+
*/
|
|
201
|
+
export function withoutWriteOnly(fields, desired) {
|
|
202
|
+
if (!fields.writeOnly.length)
|
|
203
|
+
return desired;
|
|
204
|
+
const drop = new Set(fields.writeOnly);
|
|
205
|
+
const strip = (value, path) => {
|
|
206
|
+
if (Array.isArray(value))
|
|
207
|
+
return value.map((item) => strip(item, path));
|
|
208
|
+
if (!isObject(value))
|
|
209
|
+
return value;
|
|
210
|
+
return Object.fromEntries(Object.entries(value).flatMap(([name, v]) => {
|
|
211
|
+
const at = joinPath(path, name);
|
|
212
|
+
return drop.has(at) ? markers(v).map((m) => [name, m]) : [[name, strip(v, at)]];
|
|
213
|
+
}));
|
|
214
|
+
};
|
|
215
|
+
return strip(desired, "");
|
|
216
|
+
}
|
|
217
|
+
/** True when `path` is one of `paths`, or a field inside one: a secret's map (`secrets.KEY`) is as write-only as the map. */
|
|
218
|
+
const underAny = (path, paths) => path.split(".").some((_, i, keys) => paths.has(keys.slice(0, i + 1).join(".")));
|
|
219
|
+
/** The dotted paths in `value` that `paths` holds, looking into objects and lists' items. */
|
|
220
|
+
function pathsIn(value, paths, prefix = "") {
|
|
221
|
+
if (Array.isArray(value))
|
|
222
|
+
return [...new Set(value.flatMap((item) => pathsIn(item, paths, prefix)))];
|
|
223
|
+
if (!isObject(value))
|
|
224
|
+
return [];
|
|
225
|
+
return Object.entries(value).flatMap(([name, v]) => {
|
|
226
|
+
const path = joinPath(prefix, name);
|
|
227
|
+
if (v === undefined)
|
|
228
|
+
return [];
|
|
229
|
+
return paths.has(path) ? [path] : pathsIn(v, paths, path);
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Declares a resource type: its schema, flagged fields, identity and how it is compared, and
|
|
234
|
+
* derives its operations, `<vendor>.<type>.read` and `<vendor>.<type>.import`, both effect
|
|
235
|
+
* `read` and idempotent, with the import id as the policy's `target`:
|
|
236
|
+
*
|
|
237
|
+
* - `import` takes `{ id }`, an identity (what `find` makes) or a binding id (what `bindingId`
|
|
238
|
+
* makes), and returns `{ gone: false, state }`, the object's
|
|
239
|
+
* state (with the driver's opaque `handle` when it keeps one), or `{ gone: true }` when the
|
|
240
|
+
* vendor has no such object.
|
|
241
|
+
* - `read` takes `{ id, state?, handle? }`, a state from an earlier `import` or `read`, and
|
|
242
|
+
* returns the same: `{ gone: true }` when the object no longer exists, else its fresh
|
|
243
|
+
* `state`. A driver may import first when it is given no state.
|
|
244
|
+
*
|
|
245
|
+
* A `writable` type has the change operations too, which only the apply workflow may call
|
|
246
|
+
* (`isChangeOp`): `create`, `update` and `delete` effect `write` (`delete` idempotent), and `plan`:
|
|
247
|
+
*
|
|
248
|
+
* - `plan` (`read`, idempotent) takes `{ id?, state?, handle?, desired? }`, no `desired` for a
|
|
249
|
+
* delete and no `id` for a create, and returns `{ action, planned?, unknown, replace }`:
|
|
250
|
+
* what apply would do, the new state without write-only fields, the paths known only after
|
|
251
|
+
* apply, and those whose change replaces the object.
|
|
252
|
+
* - `create` (`target` `new:<vendor>.<type>`) takes `{ desired }` and returns `{ id, state,
|
|
253
|
+
* handle? }`, `id` its binding id.
|
|
254
|
+
* - `update` takes `{ id, state?, handle?, desired, expect? }` and returns the same; given
|
|
255
|
+
* `expect` (a plan's `action` and `replace`), it refuses a fresh plan that differs
|
|
256
|
+
* (`DriverError`, `vendorCode` `plan_changed`).
|
|
257
|
+
* - `delete` takes `{ id, state?, handle? }` and returns `{ id, gone: true }`.
|
|
258
|
+
*
|
|
259
|
+
* `desired` may hold secret markers at write-only fields, which the driver resolves; no output
|
|
260
|
+
* holds a write-only value.
|
|
261
|
+
*
|
|
262
|
+
* The ledger records a `handle` as `"<handle>"`, never its bytes (the operations' `opaque`).
|
|
263
|
+
*
|
|
264
|
+
* Calling the result declares one resource, for a data file: `repository({ name: "sanoma" })`
|
|
265
|
+
* is a `Declared`, `{ vendor, type, name: "sanoma", desired, refs: {} }`. It refuses fields the
|
|
266
|
+
* schema does not have, fields the vendor owns (unless the identity names them), values the
|
|
267
|
+
* schema rejects, and an empty identity. Where `fields.references` allows it, a field may name
|
|
268
|
+
* another declared resource of that type (`repository_id: site`): `desired` holds, and the
|
|
269
|
+
* schema and `find` read, that resource's `name`, and `refs` says where it was named. A type
|
|
270
|
+
* without `find` declares resources without a `name`, found only by their bindings.
|
|
271
|
+
*/
|
|
272
|
+
export function defineResource(spec) {
|
|
273
|
+
const { vendor, type, schema, fields, find, identity, host } = spec;
|
|
274
|
+
const writable = (spec.writable ?? false);
|
|
275
|
+
const what = `${vendor}.${type}`;
|
|
276
|
+
if (host)
|
|
277
|
+
checkHost(what, host, spec);
|
|
278
|
+
const title = spec.title.toLowerCase();
|
|
279
|
+
const io = opsOf(schema);
|
|
280
|
+
// The policy's `target` for a create: the type, as no object has an id yet.
|
|
281
|
+
const created = `new:${what}`;
|
|
282
|
+
const changeOps = {
|
|
283
|
+
plan: {
|
|
284
|
+
effect: "read",
|
|
285
|
+
idempotent: true,
|
|
286
|
+
description: `Plan how apply would make a ${title} match its declaration (or delete it, given none); nothing changes`,
|
|
287
|
+
...io.plan,
|
|
288
|
+
target: ({ id }) => id ?? created,
|
|
289
|
+
opaque,
|
|
290
|
+
},
|
|
291
|
+
create: {
|
|
292
|
+
effect: "write",
|
|
293
|
+
description: `Create a ${title} as declared`,
|
|
294
|
+
...io.create,
|
|
295
|
+
target: () => created,
|
|
296
|
+
opaque,
|
|
297
|
+
},
|
|
298
|
+
update: {
|
|
299
|
+
effect: "write",
|
|
300
|
+
description: `Change a ${title} to match its declaration, replacing it where a field cannot change in place`,
|
|
301
|
+
...io.update,
|
|
302
|
+
target,
|
|
303
|
+
opaque,
|
|
304
|
+
},
|
|
305
|
+
delete: {
|
|
306
|
+
effect: "write",
|
|
307
|
+
// A retry reads first, and finds the object gone.
|
|
308
|
+
idempotent: true,
|
|
309
|
+
description: `Delete a ${title}; done already when it is gone`,
|
|
310
|
+
...io.delete,
|
|
311
|
+
target,
|
|
312
|
+
opaque,
|
|
313
|
+
},
|
|
314
|
+
};
|
|
315
|
+
const base = {
|
|
316
|
+
import: {
|
|
317
|
+
effect: "read",
|
|
318
|
+
idempotent: true,
|
|
319
|
+
description: `Find a ${title} by its ${identity ? `${identity} or its ` : ""}binding id and read it; gone when there is none`,
|
|
320
|
+
...io.import,
|
|
321
|
+
target,
|
|
322
|
+
opaque,
|
|
323
|
+
},
|
|
324
|
+
read: {
|
|
325
|
+
effect: "read",
|
|
326
|
+
idempotent: true,
|
|
327
|
+
description: `Read a ${title} as it is now; gone when it no longer exists`,
|
|
328
|
+
...io.read,
|
|
329
|
+
target,
|
|
330
|
+
opaque,
|
|
331
|
+
},
|
|
332
|
+
};
|
|
333
|
+
const ops = (writable ? { ...base, ...changeOps } : base);
|
|
334
|
+
const named = new Set(identity?.match(/[A-Za-z_][\w.]*/g));
|
|
335
|
+
const owned = new Set(fields.vendorOwned.filter((path) => !named.has(path)));
|
|
336
|
+
const references = fields.references ?? {};
|
|
337
|
+
const writeOnly = new Set(fields.writeOnly);
|
|
338
|
+
const declare = (given) => {
|
|
339
|
+
const refs = {};
|
|
340
|
+
// Where a secret is given, with list items' indexes: the schema does not judge its marker.
|
|
341
|
+
const secrets = new Set();
|
|
342
|
+
// Each resource `given` names, where `references` allows one of its type, replaced by its name.
|
|
343
|
+
// `path` is the field's, as `references` names it; `at` has list items' indexes too.
|
|
344
|
+
const resolve = (value, path, at) => {
|
|
345
|
+
if (isSecret(value)) {
|
|
346
|
+
if (!underAny(path, writeOnly)) {
|
|
347
|
+
throw new Error(`${what}: ${at} is not write-only, so it takes a value, not a secret (${value.$secret})`);
|
|
348
|
+
}
|
|
349
|
+
if (isSanomaSecret(value.$secret) && !(host && underAny(path, new Set([host.inputs.secrets])))) {
|
|
350
|
+
throw new Error(`${what}: ${at} names ${value.$secret}, one of sanoma's own: only a host's secrets may`);
|
|
351
|
+
}
|
|
352
|
+
secrets.add(at);
|
|
353
|
+
return value;
|
|
354
|
+
}
|
|
355
|
+
if (isDeclared(value)) {
|
|
356
|
+
const id = value[DECLARED];
|
|
357
|
+
const wants = references[path];
|
|
358
|
+
if (wants === undefined)
|
|
359
|
+
throw new Error(`${what}: ${at} takes a value, not a resource (${id} ${value.name})`);
|
|
360
|
+
if (wants.type !== id)
|
|
361
|
+
throw new Error(`${what}: ${at} names a resource of type ${wants.type}, not ${id} (${value.name})`);
|
|
362
|
+
if (value.name === undefined)
|
|
363
|
+
throw new Error(`${what}: ${at} names a ${id}, which has no identity to name it by`);
|
|
364
|
+
refs[at] = `${id}:${value.name}`;
|
|
365
|
+
return value.name;
|
|
366
|
+
}
|
|
367
|
+
if (Array.isArray(value))
|
|
368
|
+
return value.map((item, i) => resolve(item, path, `${at}.${i}`));
|
|
369
|
+
if (!isObject(value))
|
|
370
|
+
return value;
|
|
371
|
+
return Object.fromEntries(Object.entries(value).map(([field, v]) => [field, resolve(v, joinPath(path, field), joinPath(at, field))]));
|
|
372
|
+
};
|
|
373
|
+
const desired = resolve(given, "", "");
|
|
374
|
+
const unknown = Object.keys(desired ?? {}).filter((name) => !Object.hasOwn(schema.shape, name));
|
|
375
|
+
if (unknown.length)
|
|
376
|
+
throw new Error(`${what}: no field ${unknown.join(", ")}`);
|
|
377
|
+
// Apply fills a host's revision from its ref: the file names a branch, never a commit.
|
|
378
|
+
if (host && pathsIn(desired, new Set([host.revision])).length) {
|
|
379
|
+
throw new Error(`${what}: leave out ${host.revision}: apply sets it from ${host.inputs.ref}`);
|
|
380
|
+
}
|
|
381
|
+
const vendors = pathsIn(desired, owned);
|
|
382
|
+
if (vendors.length) {
|
|
383
|
+
throw new Error(`${what}: leave out ${vendors.join(", ")}: the vendor sets ${vendors.length > 1 ? "them" : "it"}`);
|
|
384
|
+
}
|
|
385
|
+
const parsed = schema.safeParse(desired);
|
|
386
|
+
const issues = parsed.error?.issues.filter((issue) => !secrets.has(issue.path.join(".")));
|
|
387
|
+
if (issues?.length)
|
|
388
|
+
throw new Error(`${what}: ${z.prettifyError(new z.ZodError(issues))}`);
|
|
389
|
+
const name = find?.(desired);
|
|
390
|
+
if (find && (typeof name !== "string" || name === ""))
|
|
391
|
+
throw new Error(`${what}: its ${identity} is missing`);
|
|
392
|
+
return Object.freeze({
|
|
393
|
+
[DECLARED]: what,
|
|
394
|
+
vendor,
|
|
395
|
+
type,
|
|
396
|
+
...(name !== undefined && { name }),
|
|
397
|
+
desired,
|
|
398
|
+
refs: Object.freeze(refs),
|
|
399
|
+
});
|
|
400
|
+
};
|
|
401
|
+
const resource = Object.assign(declare, {
|
|
402
|
+
vendor,
|
|
403
|
+
type,
|
|
404
|
+
title: spec.title,
|
|
405
|
+
identity,
|
|
406
|
+
schema,
|
|
407
|
+
fields,
|
|
408
|
+
find,
|
|
409
|
+
bindingId: spec.bindingId ?? ((state) => String(state.id)),
|
|
410
|
+
normalize: spec.normalize ?? ((state, desired) => compareDeclared(fields, state, desired)),
|
|
411
|
+
writable,
|
|
412
|
+
...(host && { host }),
|
|
413
|
+
stateless: spec.stateless ?? host !== undefined,
|
|
414
|
+
...(spec.afterCreate && { afterCreate: spec.afterCreate }),
|
|
415
|
+
ops,
|
|
416
|
+
// A symbol, so `defineConnector` tells a resource type from a group of operations.
|
|
417
|
+
[RESOURCE]: true,
|
|
418
|
+
});
|
|
419
|
+
return Object.freeze(resource);
|
|
420
|
+
}
|
|
421
|
+
/** Every resource type the connectors declare, by `<vendor>.<type>`. */
|
|
422
|
+
export function resourceTypesOf(connectors) {
|
|
423
|
+
const types = new Map();
|
|
424
|
+
for (const connector of connectors) {
|
|
425
|
+
for (const r of connector[VENDOR].resources)
|
|
426
|
+
types.set(`${r.vendor}.${r.type}`, r);
|
|
427
|
+
}
|
|
428
|
+
return types;
|
|
429
|
+
}
|
|
430
|
+
//# sourceMappingURL=resource.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource.js","sourceRoot":"","sources":["../src/resource.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { type SanomaConfig } from "./config.ts";
|
|
2
|
+
import { type Binding, type Bindings } from "./lockfile.ts";
|
|
3
|
+
import { type Connector } from "./op.ts";
|
|
4
|
+
import type { Span } from "./outline.ts";
|
|
5
|
+
import { type Resource } from "./resource.ts";
|
|
6
|
+
/** A resource a data file declares, as read from the file without running it. */
|
|
7
|
+
export interface DeclaredResource {
|
|
8
|
+
/** `<file>#<export>`, the file relative to the config's root, with `/`: `resources/identity/github.ts#website`. */
|
|
9
|
+
id: string;
|
|
10
|
+
/** The data file it is declared in, as `id` names it: `resources/identity/github.ts`. */
|
|
11
|
+
file: string;
|
|
12
|
+
vendor: string;
|
|
13
|
+
type: string;
|
|
14
|
+
/** What people call it: its identity, else its export's name. */
|
|
15
|
+
name: string;
|
|
16
|
+
/** The import id that finds it unbound: what its type's `find` makes of its fields; absent when the type has none. */
|
|
17
|
+
identity?: string;
|
|
18
|
+
/** The vendor's id of the object the lockfile binds it to (`LOCKFILE`); absent when unbound. */
|
|
19
|
+
binding?: string;
|
|
20
|
+
/** Its `export const` statement, as UTF-16 offsets into the file's text. */
|
|
21
|
+
span: Span;
|
|
22
|
+
/** Its fields, as its type checked them: each resource it names as that resource's `name`. */
|
|
23
|
+
desired: Record<string, unknown>;
|
|
24
|
+
/**
|
|
25
|
+
* Where it names another declared resource: the field's dotted path (a list item's with its
|
|
26
|
+
* index, `teams.0`) to that resource's id.
|
|
27
|
+
*/
|
|
28
|
+
refs: Record<string, string>;
|
|
29
|
+
}
|
|
30
|
+
/** Something wrong in the data files, or in finding them. */
|
|
31
|
+
export interface ResourceProblem {
|
|
32
|
+
/**
|
|
33
|
+
* The data file, relative to the config's root, with `/`: `resources/identity/github.ts`.
|
|
34
|
+
* Absent, with `line` and `column`, when the problem is the config's: it has no root.
|
|
35
|
+
*/
|
|
36
|
+
file?: string;
|
|
37
|
+
/** From 1. */
|
|
38
|
+
line?: number;
|
|
39
|
+
/** From 1, in UTF-16 code units. */
|
|
40
|
+
column?: number;
|
|
41
|
+
message: string;
|
|
42
|
+
}
|
|
43
|
+
/** What the data files declare: each resource read without problems, the lockfile's bindings, and the problems. */
|
|
44
|
+
export interface DataFiles {
|
|
45
|
+
/** By file and then in file order, less any with a problem, and any that names one. */
|
|
46
|
+
resources: DeclaredResource[];
|
|
47
|
+
/** The lockfile's bindings, by key (`<file>#<export>`), as read: none when it is missing or has a problem. */
|
|
48
|
+
bindings: Bindings;
|
|
49
|
+
/** Each binding whose key no data file declares, by key. */
|
|
50
|
+
orphans: (Binding & {
|
|
51
|
+
key: string;
|
|
52
|
+
})[];
|
|
53
|
+
/** By file, line and column. */
|
|
54
|
+
problems: ResourceProblem[];
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* The resources the config's data files declare, read without importing or running them; throws
|
|
58
|
+
* one error listing every problem, each at `file:line:column`, for a test or CI to fail on.
|
|
59
|
+
* `describeConfig` lists the same, with the problems beside them instead.
|
|
60
|
+
*/
|
|
61
|
+
export declare function readResources(config: SanomaConfig): DeclaredResource[];
|
|
62
|
+
/**
|
|
63
|
+
* Reads `resources/` under `root`, the config's directory: each `.ts` file in it but
|
|
64
|
+
* `*.test.ts`, `*.d.ts` and `node_modules`, parsed with oxc and held to the data-file subset
|
|
65
|
+
* (`readDataFile`). A constructor import (`@sanoma-ai/connector-github/resources`) is matched to the
|
|
66
|
+
* connector whose `info.package` it names, never imported; each resource is checked by calling
|
|
67
|
+
* its type, as running the file would, with each resource it names given as that resource.
|
|
68
|
+
*
|
|
69
|
+
* Problems: anything outside the subset, a constructor or data file the config does not know, a
|
|
70
|
+
* type the connector does not declare, a value the type refuses (a reference where its type
|
|
71
|
+
* takes none among them), a reference cycle, and two resources of one type with one identity.
|
|
72
|
+
*
|
|
73
|
+
* Each declaration is joined to its binding in the lockfile (`readLockfile`) by its key,
|
|
74
|
+
* `<file>#<export>`; a binding no export declares is an orphan. Problems: the lockfile's, a
|
|
75
|
+
* binding of another type than its declaration's, and two declarations bound to one object.
|
|
76
|
+
*/
|
|
77
|
+
export declare function readDataFiles(root: string | undefined, connectors: readonly Connector<any, any>[], types?: ReadonlyMap<string, Resource>): DataFiles;
|