@sanoma-ai/workflows 0.9.1 → 0.10.1

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.
Files changed (207) hide show
  1. package/README.md +193 -50
  2. package/SECRET-SUPPORT.md +33 -0
  3. package/dist/apply-steps.js +5 -2
  4. package/dist/apply-steps.js.map +1 -1
  5. package/dist/apply.d.ts +3 -0
  6. package/dist/apply.js +27 -13
  7. package/dist/apply.js.map +1 -1
  8. package/dist/approvals.d.ts +1 -0
  9. package/dist/approvals.js +6 -1
  10. package/dist/approvals.js.map +1 -1
  11. package/dist/apps.d.ts +13 -24
  12. package/dist/apps.js +69 -68
  13. package/dist/apps.js.map +1 -1
  14. package/dist/ast.d.ts +9 -7
  15. package/dist/ast.js +2 -0
  16. package/dist/ast.js.map +1 -1
  17. package/dist/authentication.d.ts +54 -0
  18. package/dist/authentication.js +138 -0
  19. package/dist/authentication.js.map +1 -0
  20. package/dist/call-workflow.d.ts +5 -0
  21. package/dist/call-workflow.js +4 -3
  22. package/dist/call-workflow.js.map +1 -1
  23. package/dist/call.d.ts +3 -2
  24. package/dist/call.js +36 -7
  25. package/dist/call.js.map +1 -1
  26. package/dist/cedar.js +14 -1
  27. package/dist/cedar.js.map +1 -1
  28. package/dist/change-steps.js +7 -5
  29. package/dist/change-steps.js.map +1 -1
  30. package/dist/change.d.ts +7 -0
  31. package/dist/change.js +7 -0
  32. package/dist/change.js.map +1 -1
  33. package/dist/client.d.ts +62 -10
  34. package/dist/client.js +272 -47
  35. package/dist/client.js.map +1 -1
  36. package/dist/collection.d.ts +7 -0
  37. package/dist/collection.js +5 -2
  38. package/dist/collection.js.map +1 -1
  39. package/dist/config.d.ts +16 -4
  40. package/dist/config.js +89 -21
  41. package/dist/config.js.map +1 -1
  42. package/dist/connection.d.ts +389 -0
  43. package/dist/connection.js +657 -0
  44. package/dist/connection.js.map +1 -0
  45. package/dist/credentials.d.ts +7 -53
  46. package/dist/credentials.js +84 -247
  47. package/dist/credentials.js.map +1 -1
  48. package/dist/db.js +34 -2
  49. package/dist/db.js.map +1 -1
  50. package/dist/define.d.ts +9 -2
  51. package/dist/define.js.map +1 -1
  52. package/dist/definitions.d.ts +20 -0
  53. package/dist/definitions.js +16 -0
  54. package/dist/definitions.js.map +1 -0
  55. package/dist/deployment-key.d.ts +2 -0
  56. package/dist/deployment-key.js +22 -0
  57. package/dist/deployment-key.js.map +1 -0
  58. package/dist/describe.d.ts +15 -175
  59. package/dist/describe.js +122 -35
  60. package/dist/describe.js.map +1 -1
  61. package/dist/description.d.ts +532 -0
  62. package/dist/description.js +381 -0
  63. package/dist/description.js.map +1 -0
  64. package/dist/direct.js +7 -0
  65. package/dist/direct.js.map +1 -1
  66. package/dist/drift.d.ts +1 -1
  67. package/dist/drift.js +1 -1
  68. package/dist/drift.js.map +1 -1
  69. package/dist/env.d.ts +2 -0
  70. package/dist/env.js +2 -2
  71. package/dist/env.js.map +1 -1
  72. package/dist/fake.d.ts +13 -1
  73. package/dist/fake.js +70 -0
  74. package/dist/fake.js.map +1 -1
  75. package/dist/index.d.ts +11 -3
  76. package/dist/index.js +10 -2
  77. package/dist/index.js.map +1 -1
  78. package/dist/ledger.d.ts +2 -0
  79. package/dist/ledger.js +1 -1
  80. package/dist/ledger.js.map +1 -1
  81. package/dist/lint.d.ts +0 -9
  82. package/dist/lint.js +2 -17
  83. package/dist/lint.js.map +1 -1
  84. package/dist/load.d.ts +85 -0
  85. package/dist/load.js +391 -0
  86. package/dist/load.js.map +1 -0
  87. package/dist/lockfile.d.ts +2 -0
  88. package/dist/lockfile.js +8 -3
  89. package/dist/lockfile.js.map +1 -1
  90. package/dist/op.d.ts +22 -5
  91. package/dist/op.js +20 -2
  92. package/dist/op.js.map +1 -1
  93. package/dist/outline.d.ts +5 -0
  94. package/dist/outline.js +46 -5
  95. package/dist/outline.js.map +1 -1
  96. package/dist/paths.d.ts +18 -2
  97. package/dist/paths.js +19 -7
  98. package/dist/paths.js.map +1 -1
  99. package/dist/plugin.d.ts +0 -11
  100. package/dist/plugin.js +3 -18
  101. package/dist/plugin.js.map +1 -1
  102. package/dist/policy.d.ts +2 -0
  103. package/dist/policy.js.map +1 -1
  104. package/dist/resource.d.ts +10 -4
  105. package/dist/resource.js +11 -4
  106. package/dist/resource.js.map +1 -1
  107. package/dist/resources.d.ts +33 -76
  108. package/dist/resources.js +219 -227
  109. package/dist/resources.js.map +1 -1
  110. package/dist/run.d.ts +4 -0
  111. package/dist/run.js.map +1 -1
  112. package/dist/sandbox.d.ts +5 -2
  113. package/dist/sandbox.js +56 -7
  114. package/dist/sandbox.js.map +1 -1
  115. package/dist/scenario.d.ts +5 -0
  116. package/dist/scenario.js +3 -2
  117. package/dist/scenario.js.map +1 -1
  118. package/dist/scenarios.js +7 -1
  119. package/dist/scenarios.js.map +1 -1
  120. package/dist/schema.js +8 -0
  121. package/dist/schema.js.map +1 -1
  122. package/dist/secret-store-check.d.ts +11 -0
  123. package/dist/secret-store-check.js +76 -0
  124. package/dist/secret-store-check.js.map +1 -0
  125. package/dist/secret-store.d.ts +106 -0
  126. package/dist/secret-store.js +228 -0
  127. package/dist/secret-store.js.map +1 -0
  128. package/dist/secret.d.ts +2 -0
  129. package/dist/secret.js +32 -0
  130. package/dist/secret.js.map +1 -1
  131. package/dist/shared.d.ts +21 -11
  132. package/dist/shared.js +41 -7
  133. package/dist/shared.js.map +1 -1
  134. package/dist/sites.d.ts +4 -93
  135. package/dist/sites.js +76 -84
  136. package/dist/sites.js.map +1 -1
  137. package/dist/steps.d.ts +3 -0
  138. package/dist/steps.js.map +1 -1
  139. package/dist/version.d.ts +2 -1
  140. package/dist/version.js +2 -1
  141. package/dist/version.js.map +1 -1
  142. package/dist/wakeup-driver.js +15 -6
  143. package/dist/wakeup-driver.js.map +1 -1
  144. package/dist/worker.js +12 -8
  145. package/dist/worker.js.map +1 -1
  146. package/dist/writer.d.ts +53 -14
  147. package/dist/writer.js +113 -43
  148. package/dist/writer.js.map +1 -1
  149. package/oxlint.json +1 -5
  150. package/package.json +6 -1
  151. package/src/apply-steps.ts +5 -2
  152. package/src/apply.ts +54 -21
  153. package/src/approvals.ts +7 -1
  154. package/src/apps.ts +71 -86
  155. package/src/ast.ts +6 -6
  156. package/src/authentication.ts +191 -0
  157. package/src/call-workflow.ts +5 -4
  158. package/src/call.ts +52 -9
  159. package/src/cedar.ts +14 -1
  160. package/src/change-steps.ts +7 -4
  161. package/src/change.ts +10 -0
  162. package/src/client.ts +346 -45
  163. package/src/collection.ts +10 -2
  164. package/src/config.ts +107 -19
  165. package/src/connection.ts +912 -0
  166. package/src/credentials.ts +94 -281
  167. package/src/db.ts +34 -2
  168. package/src/define.ts +7 -2
  169. package/src/definitions.ts +31 -0
  170. package/src/deployment-key.ts +23 -0
  171. package/src/describe.ts +150 -227
  172. package/src/description.ts +426 -0
  173. package/src/direct.ts +7 -0
  174. package/src/drift.ts +10 -2
  175. package/src/env.ts +4 -2
  176. package/src/fake.ts +71 -0
  177. package/src/index.ts +53 -1
  178. package/src/ledger.ts +3 -1
  179. package/src/lint.ts +2 -17
  180. package/src/load.ts +466 -0
  181. package/src/lockfile.ts +10 -3
  182. package/src/op.ts +41 -7
  183. package/src/outline.ts +53 -7
  184. package/src/paths.ts +21 -6
  185. package/src/plugin.ts +3 -24
  186. package/src/policy.ts +2 -0
  187. package/src/resource.ts +24 -6
  188. package/src/resources.ts +246 -301
  189. package/src/run.ts +4 -0
  190. package/src/sandbox.ts +61 -7
  191. package/src/scenario.ts +24 -6
  192. package/src/scenarios.ts +7 -1
  193. package/src/schema.ts +10 -0
  194. package/src/secret-store-check.ts +93 -0
  195. package/src/secret-store.ts +314 -0
  196. package/src/secret.ts +29 -0
  197. package/src/shared.ts +44 -10
  198. package/src/sites.ts +85 -179
  199. package/src/steps.ts +3 -2
  200. package/src/version.ts +2 -1
  201. package/src/wakeup-driver.ts +22 -6
  202. package/src/worker.ts +12 -8
  203. package/src/writer.ts +145 -56
  204. package/dist/datafile.d.ts +0 -97
  205. package/dist/datafile.js +0 -479
  206. package/dist/datafile.js.map +0 -1
  207. package/src/datafile.ts +0 -601
package/dist/load.js ADDED
@@ -0,0 +1,391 @@
1
+ import { existsSync, readFileSync, realpathSync, statSync } from "node:fs";
2
+ import { createRequire, registerHooks } from "node:module";
3
+ import { dirname, isAbsolute, join, relative, sep } from "node:path";
4
+ import { fileURLToPath, pathToFileURL } from "node:url";
5
+ import { collectionIn } from "./collection.js";
6
+ import { callerFile } from "./define.js";
7
+ import { defineApp, defineSite } from "./definitions.js";
8
+ import { VENDOR } from "./op.js";
9
+ import { APPS_DIR, appOfPath, DATA_ENTRIES, inside, relPath, SECRET_ENTRIES, SITE_ENTRIES } from "./paths.js";
10
+ import { isDeclared, isObject, joinPath, resourceTypesOf } from "./resource.js";
11
+ import { secret } from "./secret.js";
12
+ import { errorMessage } from "./shared.js";
13
+ // A company's files, loaded: synchronously (`require` of an ES module, Node's type stripping and
14
+ // `module.registerHooks`), since what reads them is (`describeConfig`, `readPeople`). Each load
15
+ // is a *generation*: its files are modules of their own (`file:…?sanoma-load=<id>`), so an edit
16
+ // is read once a new generation starts, and what they import from the runtime (constructors,
17
+ // `collection`, `defineSite`, `defineApp`) is served from the loader's own objects, which record
18
+ // where each value was made. A superseded generation's modules stay in Node's cache: each edit
19
+ // costs one copy of the files it read.
20
+ /** The scheme of the loader's own modules: an entry, `sanoma-load:<id>/<file URL>`, and a runtime module, `sanoma-load:<id>/<specifier>`. */
21
+ const SCHEME = "sanoma-load:";
22
+ /** The query that tags a company file with its generation: `file:///…/github.ts?sanoma-load=<id>`. */
23
+ const QUERY = "sanoma-load";
24
+ const registry = (globalThis[Symbol.for("sanoma.load")] ??= {
25
+ generations: new Map(),
26
+ seq: 0,
27
+ ids: new WeakMap(),
28
+ made: new WeakMap(),
29
+ });
30
+ const require = createRequire(import.meta.url);
31
+ /** Where `value` was made, when a company file made it with a constructor the loader served. */
32
+ export const madeOf = (value) => typeof value === "object" && value !== null ? registry.made.get(value) : undefined;
33
+ /** Where `defineApp` comes from, served only to an app's `app.ts`. */
34
+ const APP_ENTRIES = new Set(["sanoma", "@sanoma-ai/workflows"]);
35
+ /**
36
+ * Loads `paths` (absolute, under `root`) as the generation of `root` and the constructors of
37
+ * `connectors` (`types`, by default theirs) has them, and says what each gave, by its path
38
+ * relative to the root with `/`, sorted. The same generation, and the same answer for the same
39
+ * paths, while no file it read, nor any file's directory, changed (by size and modification time:
40
+ * one `stat` each); else a new one, so a caller may key what it makes of the answer by it (and
41
+ * never changes it). `only` loads only the files whose text it passes; the answer is kept by its
42
+ * identity, so pass one function, not a new one per call.
43
+ *
44
+ * Served to the files, by specifier: `sanoma/resources` and `@sanoma-ai/workflows/resources`
45
+ * (`sanoma`, the constructors of the vendor `sanoma`, and `secret`); each connector's
46
+ * `<info.package>/resources` (its vendor's constructors, under its id); `sanoma/data` and
47
+ * `@sanoma-ai/workflows/data` (`collection`); `sanoma/site` and `@sanoma-ai/app/site`
48
+ * (`defineSite`); and to an app's `apps/<app>/app.ts` alone, `sanoma` and `@sanoma-ai/workflows`
49
+ * (`defineApp`). Anything else is resolved as Node does.
50
+ */
51
+ export function loadModules(root, paths, connectors, { only, types = resourceTypesOf(connectors), } = {}) {
52
+ // Nothing to load, and a root that may not be there yet (a company not made): nothing to resolve.
53
+ if (!paths.length)
54
+ return new Map();
55
+ hook();
56
+ const real = realpathSync(root);
57
+ const gen = generationOf(real, connectors, types);
58
+ const files = paths.map((path) => join(real, relative(root, path)));
59
+ const byPaths = gen.answers.get(only ?? gen) ?? new Map();
60
+ gen.answers.set(only ?? gen, byPaths);
61
+ const key = files.join("\0");
62
+ const answered = byPaths.get(key);
63
+ if (answered)
64
+ return answered;
65
+ const answer = new Map();
66
+ for (const file of files) {
67
+ touch(gen, file);
68
+ if (only && !only(readFileSync(file, "utf8")))
69
+ continue;
70
+ const rel = relPath(gen.root, file);
71
+ const loaded = loadOne(gen, file, rel);
72
+ answer.set(rel, loaded);
73
+ if ("failedIn" in loaded)
74
+ answer.set(loaded.failedIn, gen.loaded.get(loaded.failedIn));
75
+ }
76
+ const result = new Map([...answer].toSorted(([a], [b]) => byOrder(a, b)));
77
+ // A value made in one file and exported by another is listed at the file that made it.
78
+ const owner = new Map();
79
+ for (const [rel, l] of result) {
80
+ if (!("exports" in l))
81
+ continue;
82
+ for (const [, value] of l.exports)
83
+ if (madeOf(value)?.file === rel)
84
+ owner.set(value, rel);
85
+ }
86
+ for (const [rel, l] of result) {
87
+ if (!("exports" in l))
88
+ continue;
89
+ const exports = l.exports
90
+ .filter(([, value]) => (owner.get(value) ?? rel) === rel)
91
+ .toSorted(([, a], [, b]) => byOrder(madeOf(a)?.seq ?? Infinity, madeOf(b)?.seq ?? Infinity));
92
+ result.set(rel, { exports });
93
+ }
94
+ byPaths.set(key, result);
95
+ answerGenerations.set(result, gen);
96
+ return result;
97
+ }
98
+ /**
99
+ * What `answer` (a `loadModules` answer) gave for `file`: its exports, or the error it threw (or a
100
+ * helper it imports threw) as a problem on one line, at the file that threw it; undefined when the
101
+ * answer does not have the file.
102
+ */
103
+ export function exportsOf(answer, file) {
104
+ const loaded = answer.get(file);
105
+ if (loaded === undefined)
106
+ return undefined;
107
+ if ("failedIn" in loaded)
108
+ return exportsOf(answer, loaded.failedIn);
109
+ if ("exports" in loaded)
110
+ return loaded;
111
+ const { error, line, column } = loaded;
112
+ const message = errorMessage(error).replaceAll(/\s*\n\s*/g, " ");
113
+ return { problem: { file, ...(line !== undefined && { line, column: column ?? 1 }), message } };
114
+ }
115
+ /** The generation each answer is of. */
116
+ const answerGenerations = new WeakMap();
117
+ /** Every value the files of `answer` (a `loadModules` answer) made, exported or not, in the order made. */
118
+ export const madeWith = (answer) => (answerGenerations.get(answer)?.made ?? []).filter((value) => answer.has(madeOf(value).file));
119
+ /**
120
+ * The company files `answer` (a `loadModules` answer) was read from, by path relative to the root:
121
+ * its files and every company file they import, directly or not (or that another answer of its
122
+ * generation imported: never fewer).
123
+ */
124
+ export const filesRead = (answer) => new Set([...answer.keys(), ...(answerGenerations.get(answer)?.imported ?? [])]);
125
+ /** One file of a generation, required once; an error placed at its own file, and reported there once. */
126
+ function loadOne(gen, file, rel) {
127
+ const done = gen.loaded.get(rel);
128
+ if (done)
129
+ return done;
130
+ let loaded;
131
+ try {
132
+ const { ns } = require(`${SCHEME}${gen.id}/${pathToFileURL(file).href}`);
133
+ loaded = { exports: Object.entries(ns) };
134
+ }
135
+ catch (error) {
136
+ // A file that imports one that threw throws the same object: reported once, where it was thrown.
137
+ const at = typeof error === "object" ? gen.reported.get(error) : undefined;
138
+ if (at !== undefined)
139
+ loaded = { failedIn: at };
140
+ else {
141
+ const placed = placeOf(gen, error);
142
+ // Never over a file that loaded (a stack cut short at `Error.stackTraceLimit`): then it is this file's.
143
+ const there = placed && gen.loaded.get(placed.file);
144
+ const { file: own = rel, line, column } = there && "exports" in there ? {} : (placed ?? {});
145
+ if (typeof error === "object")
146
+ gen.reported.set(error, own);
147
+ const report = { error, ...(line !== undefined && { line }), ...(column !== undefined && { column }) };
148
+ gen.loaded.set(own, report);
149
+ loaded = own === rel ? report : { failedIn: own };
150
+ }
151
+ }
152
+ gen.loaded.set(rel, loaded);
153
+ return loaded;
154
+ }
155
+ /** A frame of a generation's company file in a stack: its URL, without the query, then the tag, line and column. */
156
+ const TAGGED_FRAME = new RegExp(`(file://[^\\s()?]*)\\?${QUERY}=([\\w-]+):(\\d+):(\\d+)`, "g");
157
+ /**
158
+ * Where an error belongs: the last (outermost) frame of its stack in one of the generation's
159
+ * files, the top level of the file that was running, not a helper it called in another file; for
160
+ * a syntax error, the file and line its stack starts with (the caret's column); none for an error
161
+ * thrown before any file ran (top-level `await`, an import Node cannot find).
162
+ */
163
+ function placeOf(gen, error) {
164
+ const stack = isObject(error) && typeof error.stack === "string" ? error.stack : undefined;
165
+ if (stack === undefined)
166
+ return undefined;
167
+ const frame = [...stack.matchAll(TAGGED_FRAME)].findLast(([, , tag]) => tag === gen.id);
168
+ if (frame) {
169
+ const [, url, , line, column] = frame;
170
+ return { file: relPath(gen.root, fileURLToPath(url)), line: Number(line), column: Number(column) };
171
+ }
172
+ // A syntax error's stack starts `<path or URL>:<line>`, then the source and a caret under the column.
173
+ const [first = "", ...lines] = stack.split("\n");
174
+ const syntax = /^(.+):(\d+)$/.exec(first);
175
+ const path = syntax && (syntax[1].startsWith("file:") ? fileURLToPath(syntax[1]) : syntax[1]);
176
+ if (syntax && path && isAbsolute(path) && inside(gen.root, path)) {
177
+ const caret = lines.slice(0, lines.indexOf("")).findLast((line) => /^\s*\^+\s*$/.test(line));
178
+ return { file: relPath(gen.root, path), line: Number(syntax[2]), ...(caret && { column: caret.indexOf("^") + 1 }) };
179
+ }
180
+ return undefined;
181
+ }
182
+ /**
183
+ * Each company file under `root` a load has read, and each one's folder, with its stamp
184
+ * (`stampOf`) as it was before the file was read: the latest generation's for a file several
185
+ * read. Taken after a load, it still says what the load read, so a file changed while it read is
186
+ * found changed after.
187
+ */
188
+ export function stampsOf(root) {
189
+ const stamps = new Map();
190
+ if (!existsSync(root))
191
+ return stamps;
192
+ const real = realpathSync(root);
193
+ // In the order made: a later generation's stamp is the newer.
194
+ for (const gen of registry.generations.values()) {
195
+ if (gen.root === real)
196
+ for (const [path, stamp] of gen.stamps)
197
+ stamps.set(path, stamp);
198
+ }
199
+ return stamps;
200
+ }
201
+ const byOrder = (a, b) => (a < b ? -1 : a > b ? 1 : 0);
202
+ /** A file's size and modification time, or that it is gone: what a generation keeps of each file it read. */
203
+ export function stampOf(path) {
204
+ const stat = statSync(path, { bigint: true, throwIfNoEntry: false });
205
+ return stat ? `${stat.size} ${stat.mtimeNs}` : "gone";
206
+ }
207
+ /** True while each path's stamp (`stampOf`) is still the one kept. */
208
+ export function fresh(stamps) {
209
+ for (const [path, stamp] of stamps)
210
+ if (stampOf(path) !== stamp)
211
+ return false;
212
+ return true;
213
+ }
214
+ /** Records a file of the generation, and its directory, as they are now: before it is read, so an edit after is seen. */
215
+ function touch(gen, file) {
216
+ for (const path of [file, dirname(file)])
217
+ if (!gen.stamps.has(path))
218
+ gen.stamps.set(path, stampOf(path));
219
+ }
220
+ /**
221
+ * The generation of `root` and these constructors: the current one while nothing it stamped
222
+ * changed, else a new one. A generation of `root` whose files changed goes, whatever its
223
+ * constructors, so `stampsOf` never keeps the stamps of one no load will make again.
224
+ */
225
+ function generationOf(root, connectors, types) {
226
+ const packages = connectors.flatMap((c) => {
227
+ const { id, info } = c[VENDOR];
228
+ return info?.package ? [`${info.package}/resources`, id] : [];
229
+ });
230
+ const typesKey = [...packages, ...[...types.values()].map(idOf)].join(" ");
231
+ let current;
232
+ for (const gen of registry.generations.values()) {
233
+ if (gen.root !== root)
234
+ continue;
235
+ if (!fresh(gen.stamps))
236
+ registry.generations.delete(gen.id);
237
+ else if (gen.typesKey === typesKey)
238
+ current = gen;
239
+ }
240
+ if (current !== undefined)
241
+ return current;
242
+ const gen = {
243
+ id: String(++registry.seq),
244
+ root,
245
+ typesKey,
246
+ virtual: new Map(),
247
+ stamps: new Map(),
248
+ made: [],
249
+ imported: new Set(),
250
+ loaded: new Map(),
251
+ reported: new Map(),
252
+ answers: new WeakMap(),
253
+ };
254
+ gen.virtual = runtimeModules(gen, connectors, types);
255
+ registry.generations.set(gen.id, gen);
256
+ return gen;
257
+ }
258
+ function idOf(object) {
259
+ let id = registry.ids.get(object);
260
+ if (id === undefined)
261
+ registry.ids.set(object, (id = ++registry.seq));
262
+ return id;
263
+ }
264
+ /** The runtime's modules a generation serves its files, by specifier: each constructor wrapped to record where it was called. */
265
+ function runtimeModules(gen, connectors, types) {
266
+ const byVendor = new Map();
267
+ for (const resource of types.values()) {
268
+ const constructors = byVendor.get(resource.vendor) ?? {};
269
+ // Frame 2 of `callerFile` is the wrapper's caller: the company file.
270
+ constructors[resource.type] = (fields, options) => record(gen, callerFile(), resource(fields, options), refersIn(fields));
271
+ byVendor.set(resource.vendor, constructors);
272
+ }
273
+ // A type the vendor does not declare is refused where it is called for, as `<vendor>.<type>`;
274
+ // an object's own names (`toString`, `toJSON`) are not types, so printing the vendor still works.
275
+ const constructorsOf = (vendor) => new Proxy(byVendor.get(vendor) ?? {}, {
276
+ get(target, key) {
277
+ if (typeof key !== "string" || key in target || key === "toJSON")
278
+ return Reflect.get(target, key);
279
+ const known = Object.keys(target);
280
+ throw new TypeError(`${vendor} has no resource type ${key}: its types are ${known.join(", ") || "none"}`);
281
+ },
282
+ });
283
+ const modules = new Map();
284
+ for (const connector of connectors) {
285
+ const { id, info } = connector[VENDOR];
286
+ if (info?.package)
287
+ modules.set(`${info.package}/resources`, { [id]: constructorsOf(id) });
288
+ }
289
+ for (const entry of SECRET_ENTRIES)
290
+ modules.set(entry, { sanoma: constructorsOf("sanoma"), secret });
291
+ const collection = (declaration) => {
292
+ const file = callerFile();
293
+ return record(gen, file, collectionIn(file === undefined ? undefined : appOfPath(relPath(gen.root, file)), declaration));
294
+ };
295
+ for (const entry of DATA_ENTRIES)
296
+ modules.set(entry, { collection });
297
+ const site = (definition) => record(gen, callerFile(), defineSite(definition));
298
+ for (const entry of SITE_ENTRIES)
299
+ modules.set(entry, { defineSite: site });
300
+ const app = (definition) => record(gen, callerFile(), defineApp(definition));
301
+ for (const entry of APP_ENTRIES)
302
+ modules.set(entry, { defineApp: app });
303
+ return modules;
304
+ }
305
+ /** Records where `value` was made, and returns it. */
306
+ function record(gen, file, value, refers = {}) {
307
+ gen.made.push(value);
308
+ registry.made.set(value, { file: file === undefined ? "" : relPath(gen.root, file), seq: gen.made.length, refers });
309
+ return value;
310
+ }
311
+ /** Each declared resource in a constructor's fields, by its dotted path, as the constructor walks them. */
312
+ function refersIn(value, at = "", into = {}) {
313
+ if (isDeclared(value))
314
+ into[at] = value;
315
+ else if (Array.isArray(value))
316
+ value.forEach((item, i) => refersIn(item, joinPath(at, String(i)), into));
317
+ else if (isObject(value))
318
+ for (const [field, item] of Object.entries(value))
319
+ refersIn(item, joinPath(at, field), into);
320
+ return into;
321
+ }
322
+ /** True for an app's `apps/<app>/app.ts`, by URL. */
323
+ const isAppFile = (gen, url) => {
324
+ const [top, app, file, ...rest] = relPath(gen.root, fileURLToPath(url)).split("/");
325
+ return top === APPS_DIR && app !== undefined && file === "app.ts" && !rest.length;
326
+ };
327
+ /** The generation a module URL belongs to: the query on a company file's, the first segment of the loader's own. */
328
+ function tagOf(url) {
329
+ if (url?.startsWith("file:"))
330
+ return new URL(url).searchParams.get(QUERY);
331
+ if (url?.startsWith(SCHEME))
332
+ return url.slice(SCHEME.length, url.indexOf("/"));
333
+ return null;
334
+ }
335
+ /**
336
+ * Registers the loader's hooks, once per process (the registry's flag, for two copies of the
337
+ * package). A file of a generation resolves the runtime's modules to the generation's, and each
338
+ * company file (under the root, outside `node_modules`) to itself tagged with the generation,
339
+ * recorded and stamped; an entry is a module exporting the tagged file's namespace as `ns`, since
340
+ * `require` of a `file:` URL drops its query (the CommonJS loader keys by file name).
341
+ */
342
+ function hook() {
343
+ if (registry.hooked)
344
+ return;
345
+ registry.hooked = true;
346
+ registerHooks({
347
+ resolve(specifier, context, next) {
348
+ if (specifier.startsWith(SCHEME))
349
+ return { url: specifier, shortCircuit: true };
350
+ const tag = tagOf(context.parentURL);
351
+ const gen = tag === null ? undefined : registry.generations.get(tag);
352
+ if (gen === undefined)
353
+ return next(specifier, context);
354
+ if (gen.virtual.has(specifier) &&
355
+ (!APP_ENTRIES.has(specifier) || (context.parentURL.startsWith("file:") && isAppFile(gen, context.parentURL)))) {
356
+ return { url: `${SCHEME}${gen.id}/${specifier}`, shortCircuit: true };
357
+ }
358
+ const resolved = next(specifier, context);
359
+ if (!resolved.url.startsWith("file:"))
360
+ return resolved;
361
+ const url = new URL(resolved.url);
362
+ const file = fileURLToPath(url);
363
+ if (!inside(gen.root, file) || file.split(sep).includes("node_modules"))
364
+ return resolved;
365
+ touch(gen, file);
366
+ gen.imported.add(relPath(gen.root, file));
367
+ url.searchParams.set(QUERY, gen.id);
368
+ return { ...resolved, url: url.href };
369
+ },
370
+ load(url, context, next) {
371
+ if (!url.startsWith(SCHEME))
372
+ return next(url, context);
373
+ const tag = tagOf(url);
374
+ const rest = url.slice(url.indexOf("/") + 1);
375
+ if (rest.startsWith("file:")) {
376
+ const target = new URL(rest);
377
+ target.searchParams.set(QUERY, tag);
378
+ return { format: "module", source: `export * as ns from ${JSON.stringify(target.href)};`, shortCircuit: true };
379
+ }
380
+ // Read from the registry by the module itself, so a company file gets the generation's own objects.
381
+ const from = `globalThis[Symbol.for("sanoma.load")].generations.get(${JSON.stringify(tag)}).virtual.get(${JSON.stringify(rest)})`;
382
+ const names = Object.keys(registry.generations.get(tag)?.virtual.get(rest) ?? {});
383
+ const source = [
384
+ `const m = ${from};`,
385
+ ...names.map((name, i) => `const e${i} = m[${JSON.stringify(name)}];\nexport { e${i} as ${JSON.stringify(name)} };`),
386
+ ].join("\n");
387
+ return { format: "module", source, shortCircuit: true };
388
+ },
389
+ });
390
+ }
391
+ //# sourceMappingURL=load.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load.js","sourceRoot":"","sources":["../src/load.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { type ConnectionRef } from "./connection.ts";
1
2
  import type { ResourceProblem } from "./resources.ts";
2
3
  /** Where the lockfile is, relative to the config's root. */
3
4
  export declare const LOCKFILE = "resources/sanoma.lock.json";
@@ -5,6 +6,7 @@ export declare const LOCKFILE = "resources/sanoma.lock.json";
5
6
  export interface Binding {
6
7
  type: string;
7
8
  id: string;
9
+ connection?: ConnectionRef;
8
10
  }
9
11
  /** The lockfile's content: by declaration key, `<file>#<export>` (the file relative to the config's root, with `/`). */
10
12
  export type Bindings = Record<string, Binding>;
package/dist/lockfile.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { connectionRefSchema } from "./connection.js";
1
2
  import { existsSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
2
3
  import { join } from "node:path";
3
4
  import { z } from "zod";
@@ -5,7 +6,11 @@ import { z } from "zod";
5
6
  // hold intent only), as `package-lock.json` is from `package.json`. Only apply writes it.
6
7
  /** Where the lockfile is, relative to the config's root. */
7
8
  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
+ const lockfile = z.record(z.string().regex(/^resources\/[^#]+#[^#]+$/), z.strictObject({
10
+ type: z.string().regex(/^[^.\s]+\.[^.\s]+$/),
11
+ id: z.string().min(1),
12
+ connection: connectionRefSchema.optional(),
13
+ }));
9
14
  /**
10
15
  * The lockfile under `root`: no bindings when there is none, and no bindings with a problem when
11
16
  * it is not JSON or not a map of `<file>#<export>` to `{ type, id }`.
@@ -35,7 +40,7 @@ export function readLockfile(root) {
35
40
  export function serializeLockfile(bindings) {
36
41
  const sorted = Object.entries(bindings)
37
42
  .toSorted(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
38
- .map(([key, { type, id }]) => [key, { type, id }]);
43
+ .map(([key, { type, id, connection }]) => [key, { type, id, ...(connection && { connection }) }]);
39
44
  return `${JSON.stringify(Object.fromEntries(sorted), null, 2)}\n`;
40
45
  }
41
46
  /** Writes the lockfile under `root` whole or not at all: to a file beside it, then renamed over it. Apply only. */
@@ -61,7 +66,7 @@ export function diffLockfiles(before, after) {
61
66
  return was ? [{ key, type: was.type, kind: "unbind", from: was.id }] : [];
62
67
  if (!was)
63
68
  return [{ key, type: now.type, kind: "bind", to: now.id }];
64
- if (was.id === now.id && was.type === now.type)
69
+ if (was.id === now.id && was.type === now.type && JSON.stringify(was.connection) === JSON.stringify(now.connection))
65
70
  return [];
66
71
  return [{ key, type: now.type, kind: "rebind", from: was.id, to: now.id }];
67
72
  });
@@ -1 +1 @@
1
- {"version":3,"file":"lockfile.js","sourceRoot":"","sources":["../src/lockfile.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"lockfile.js","sourceRoot":"","sources":["../src/lockfile.ts"],"names":[],"mappings":"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"}
package/dist/op.d.ts CHANGED
@@ -1,3 +1,6 @@
1
+ import type { Principal } from "./define.ts";
2
+ import type { Authentication, CallAuthentication } from "./authentication.ts";
3
+ import type { ConnectionSnapshot } from "./connection.ts";
1
4
  import type { ProviderV4 } from "@ai-sdk/provider";
2
5
  import type { z } from "zod";
3
6
  import type { Fake } from "./fake.ts";
@@ -39,6 +42,8 @@ export interface OpSpec<I extends z.ZodType = z.ZodType, O extends z.ZodType = z
39
42
  * (a resource type's `handle`): the ledger records each as `"<name>"`, never its value.
40
43
  */
41
44
  opaque?: readonly string[];
45
+ /** Logical destinations this operation may create with Secrets.ensure, derived from its authorized input. */
46
+ createsSecrets?: (input: any) => readonly string[];
42
47
  }
43
48
  /** One vendor operation, such as `ghost.post.publish`. Declares the contract only; drivers implement it. */
44
49
  export interface Op<V extends string = string, R extends string = string, N extends string = string, I = any, O = any> {
@@ -59,6 +64,7 @@ export interface Op<V extends string = string, R extends string = string, N exte
59
64
  };
60
65
  /** From the spec: fields the ledger records by name only. */
61
66
  readonly opaque?: readonly string[];
67
+ readonly createsSecrets?: (input: any) => readonly string[];
62
68
  readonly input: z.ZodType<any, I>;
63
69
  readonly output: z.ZodType<O>;
64
70
  }
@@ -100,7 +106,7 @@ export type Connector<V extends string, S extends Specs> = {
100
106
  * and `resolveConfig` reads only a record of its own shape (`checkConnector`): change it with
101
107
  * the record, so a build refuses a connector another build made in another shape.
102
108
  */
103
- export declare const CONNECTOR_FORMAT = 1;
109
+ export declare const CONNECTOR_FORMAT = 3;
104
110
  /**
105
111
  * A connector's vendor: its id, who it is (`defineConnector`'s third argument, for a UI), its
106
112
  * resource types, and the driver and fake its package attaches (`withSetup`).
@@ -152,6 +158,12 @@ export declare function defineConnector<const V extends string, const S extends
152
158
  * not repeat the side effect.
153
159
  */
154
160
  export interface CallContext {
161
+ /** Authenticated initiating principal; never supplied by operation input. */
162
+ principal?: Principal;
163
+ /** Authorized account metadata. Credential material stays inside the driver boundary. */
164
+ connection?: ConnectionSnapshot;
165
+ /** Resolved after policy, for this call alone. Never return it from a driver. */
166
+ authentication?: CallAuthentication;
155
167
  idempotencyKey: string;
156
168
  runId: string;
157
169
  opId: string;
@@ -202,13 +214,15 @@ export declare function retryableStatus(status: number): boolean;
202
214
  */
203
215
  export type DriverEnv = z.ZodObject<Record<string, z.ZodType<string | undefined, string | undefined>>>;
204
216
  /**
205
- * Implements a vendor's operations, keyed `"resource.name"`. A driver reads its credentials
206
- * from the environment when it is called, never from the config file; `env` declares them.
217
+ * Implements a vendor's operations, keyed `"resource.name"`. Named authentication is supplied
218
+ * in the call context. `env` describes a driver that has not added named-account support.
207
219
  */
208
220
  export interface Driver {
209
221
  readonly vendor: string;
210
222
  readonly ops: Readonly<Record<string, DriverFn>>;
211
223
  readonly env?: DriverEnv;
224
+ /** Methods this driver consumes from CallContext.authentication. Others fail closed. */
225
+ readonly authentication?: readonly string[];
212
226
  }
213
227
  /**
214
228
  * What a connector package attaches to its connector (`withSetup`), for the config's resolver
@@ -219,7 +233,9 @@ export interface Driver {
219
233
  * no repository a change is reviewed on.
220
234
  */
221
235
  export interface ConnectorSetup {
222
- /** Makes the live driver, which reads its credentials from the environment when called: once per resolved config. */
236
+ /** Auth methods available to named connections; login identity is separate. */
237
+ authentication?: Readonly<Record<string, Authentication>>;
238
+ /** Makes the live driver once per resolved config; credentials belong to each invocation. */
223
239
  driver?: () => Driver;
224
240
  /** Makes a fake of the vendor (`defineFake`): once per sandbox run, its own. */
225
241
  fake?: () => Fake<any, any>;
@@ -333,7 +349,8 @@ export type OpIdOf<V extends string, S extends Specs> = {
333
349
  * connector doesn't declare, is refused here rather than when a run calls it. `options.env`
334
350
  * declares the environment variables it reads (see `DriverEnv`).
335
351
  */
336
- export declare function defineDriver<V extends string, S extends Specs>(connector: Connector<V, S>, impl: DriverImpl<S>, options?: {
352
+ export declare function defineDriver<V extends string, S extends Specs>(connector: Connector<V, S>, impl: DriverImpl<S> | ((call: CallContext) => DriverImpl<S>), options?: {
337
353
  env?: DriverEnv;
354
+ authentication?: readonly string[];
338
355
  }): Driver;
339
356
  export {};
package/dist/op.js CHANGED
@@ -16,7 +16,7 @@ export const VENDOR = Symbol.for("sanoma.vendor");
16
16
  * and `resolveConfig` reads only a record of its own shape (`checkConnector`): change it with
17
17
  * the record, so a build refuses a connector another build made in another shape.
18
18
  */
19
- export const CONNECTOR_FORMAT = 1;
19
+ export const CONNECTOR_FORMAT = 3;
20
20
  /** One `<svg>` element, with nothing but whitespace around it: what a logo must be. */
21
21
  const SVG_ELEMENT = /^\s*<svg[\s>][\s\S]*<\/svg>\s*$/;
22
22
  /** Whether `svg` is a logo as `VendorInfo` takes it: one `<svg>…</svg>` element. */
@@ -74,6 +74,7 @@ export function defineConnector(vendor, specs, info) {
74
74
  target: spec.target,
75
75
  phrases: spec.phrases,
76
76
  ...(spec.opaque?.length ? { opaque: spec.opaque } : {}),
77
+ ...(spec.createsSecrets && { createsSecrets: spec.createsSecrets }),
77
78
  input: spec.input,
78
79
  output: spec.output,
79
80
  });
@@ -174,6 +175,18 @@ export function defineDriver(connector, impl, options = {}) {
174
175
  }
175
176
  const vendor = connector[VENDOR].id;
176
177
  const ops = {};
178
+ if (typeof impl === "function") {
179
+ // Build clients only once the runtime has authorized and authenticated this invocation.
180
+ for (const key of declared.keys()) {
181
+ ops[key] = async (input, call) => defineDriver(connector, impl(call), options).ops[key](input, call);
182
+ }
183
+ return Object.freeze({
184
+ vendor,
185
+ ops: Object.freeze(ops),
186
+ ...(options.env && { env: options.env }),
187
+ ...(options.authentication && { authentication: Object.freeze([...options.authentication]) }),
188
+ });
189
+ }
177
190
  const extra = [];
178
191
  for (const [resource, fns] of Object.entries(impl)) {
179
192
  for (const [name, fn] of Object.entries(fns ?? {})) {
@@ -191,6 +204,11 @@ export function defineDriver(connector, impl, options = {}) {
191
204
  ];
192
205
  if (problems.length)
193
206
  throw new Error(`defineDriver("${vendor}"): ${problems.join("; ")}`);
194
- return Object.freeze({ vendor, ops: Object.freeze(ops), ...(options.env && { env: options.env }) });
207
+ return Object.freeze({
208
+ vendor,
209
+ ops: Object.freeze(ops),
210
+ ...(options.env && { env: options.env }),
211
+ ...(options.authentication && { authentication: Object.freeze([...options.authentication]) }),
212
+ });
195
213
  }
196
214
  //# sourceMappingURL=op.js.map