@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.
Files changed (176) hide show
  1. package/LICENSE +105 -0
  2. package/README.md +544 -2
  3. package/dist/apply-steps.d.ts +6 -0
  4. package/dist/apply-steps.js +93 -0
  5. package/dist/apply-steps.js.map +1 -0
  6. package/dist/apply.d.ts +197 -0
  7. package/dist/apply.js +470 -0
  8. package/dist/apply.js.map +1 -0
  9. package/dist/approvals.d.ts +46 -0
  10. package/dist/approvals.js +111 -0
  11. package/dist/approvals.js.map +1 -0
  12. package/dist/ast.d.ts +57 -0
  13. package/dist/ast.js +81 -0
  14. package/dist/ast.js.map +1 -0
  15. package/dist/call.d.ts +37 -0
  16. package/dist/call.js +417 -0
  17. package/dist/call.js.map +1 -0
  18. package/dist/client.d.ts +203 -0
  19. package/dist/client.js +457 -0
  20. package/dist/client.js.map +1 -0
  21. package/dist/config.d.ts +126 -0
  22. package/dist/config.js +264 -0
  23. package/dist/config.js.map +1 -0
  24. package/dist/credentials.d.ts +55 -0
  25. package/dist/credentials.js +261 -0
  26. package/dist/credentials.js.map +1 -0
  27. package/dist/cucumber.d.ts +64 -0
  28. package/dist/cucumber.js +158 -0
  29. package/dist/cucumber.js.map +1 -0
  30. package/dist/datafile.d.ts +71 -0
  31. package/dist/datafile.js +380 -0
  32. package/dist/datafile.js.map +1 -0
  33. package/dist/db.d.ts +58 -0
  34. package/dist/db.js +179 -0
  35. package/dist/db.js.map +1 -0
  36. package/dist/define.d.ts +205 -0
  37. package/dist/define.js +103 -0
  38. package/dist/define.js.map +1 -0
  39. package/dist/describe.d.ts +141 -0
  40. package/dist/describe.js +135 -0
  41. package/dist/describe.js.map +1 -0
  42. package/dist/drift.d.ts +127 -0
  43. package/dist/drift.js +167 -0
  44. package/dist/drift.js.map +1 -0
  45. package/dist/env.d.ts +49 -0
  46. package/dist/env.js +83 -0
  47. package/dist/env.js.map +1 -0
  48. package/dist/errors.d.ts +88 -0
  49. package/dist/errors.js +148 -0
  50. package/dist/errors.js.map +1 -0
  51. package/dist/expectations.d.ts +26 -0
  52. package/dist/expectations.js +162 -0
  53. package/dist/expectations.js.map +1 -0
  54. package/dist/fake.d.ts +55 -0
  55. package/dist/fake.js +87 -0
  56. package/dist/fake.js.map +1 -0
  57. package/dist/fill.d.ts +9 -0
  58. package/dist/fill.js +17 -0
  59. package/dist/fill.js.map +1 -0
  60. package/dist/host.d.ts +56 -0
  61. package/dist/host.js +45 -0
  62. package/dist/host.js.map +1 -0
  63. package/dist/index.d.ts +23 -0
  64. package/dist/index.js +29 -0
  65. package/dist/index.js.map +1 -0
  66. package/dist/ledger.d.ts +217 -0
  67. package/dist/ledger.js +251 -0
  68. package/dist/ledger.js.map +1 -0
  69. package/dist/lint.d.ts +32 -0
  70. package/dist/lint.js +168 -0
  71. package/dist/lint.js.map +1 -0
  72. package/dist/lockfile.d.ts +36 -0
  73. package/dist/lockfile.js +69 -0
  74. package/dist/lockfile.js.map +1 -0
  75. package/dist/log.d.ts +24 -0
  76. package/dist/log.js +83 -0
  77. package/dist/log.js.map +1 -0
  78. package/dist/op.d.ts +260 -0
  79. package/dist/op.js +188 -0
  80. package/dist/op.js.map +1 -0
  81. package/dist/outline.d.ts +179 -0
  82. package/dist/outline.js +506 -0
  83. package/dist/outline.js.map +1 -0
  84. package/dist/paths.d.ts +11 -0
  85. package/dist/paths.js +30 -0
  86. package/dist/paths.js.map +1 -0
  87. package/dist/plugin.d.ts +28 -0
  88. package/dist/plugin.js +25 -0
  89. package/dist/plugin.js.map +1 -0
  90. package/dist/policy.d.ts +114 -0
  91. package/dist/policy.js +60 -0
  92. package/dist/policy.js.map +1 -0
  93. package/dist/resource.d.ts +378 -0
  94. package/dist/resource.js +430 -0
  95. package/dist/resource.js.map +1 -0
  96. package/dist/resources.d.ts +77 -0
  97. package/dist/resources.js +244 -0
  98. package/dist/resources.js.map +1 -0
  99. package/dist/run.d.ts +101 -0
  100. package/dist/run.js +7 -0
  101. package/dist/run.js.map +1 -0
  102. package/dist/sandbox.d.ts +33 -0
  103. package/dist/sandbox.js +127 -0
  104. package/dist/sandbox.js.map +1 -0
  105. package/dist/scenario.d.ts +221 -0
  106. package/dist/scenario.js +1104 -0
  107. package/dist/scenario.js.map +1 -0
  108. package/dist/scenarios.d.ts +55 -0
  109. package/dist/scenarios.js +71 -0
  110. package/dist/scenarios.js.map +1 -0
  111. package/dist/secret.d.ts +42 -0
  112. package/dist/secret.js +58 -0
  113. package/dist/secret.js.map +1 -0
  114. package/dist/shared.d.ts +69 -0
  115. package/dist/shared.js +84 -0
  116. package/dist/shared.js.map +1 -0
  117. package/dist/source.d.ts +58 -0
  118. package/dist/source.js +54 -0
  119. package/dist/source.js.map +1 -0
  120. package/dist/steps.d.ts +76 -0
  121. package/dist/steps.js +23 -0
  122. package/dist/steps.js.map +1 -0
  123. package/dist/version.d.ts +29 -0
  124. package/dist/version.js +76 -0
  125. package/dist/version.js.map +1 -0
  126. package/dist/worker.d.ts +37 -0
  127. package/dist/worker.js +228 -0
  128. package/dist/worker.js.map +1 -0
  129. package/dist/writer.d.ts +35 -0
  130. package/dist/writer.js +201 -0
  131. package/dist/writer.js.map +1 -0
  132. package/oxlint.json +128 -0
  133. package/package.json +96 -3
  134. package/src/apply-steps.ts +110 -0
  135. package/src/apply.ts +626 -0
  136. package/src/approvals.ts +157 -0
  137. package/src/ast.ts +115 -0
  138. package/src/call.ts +483 -0
  139. package/src/client.ts +604 -0
  140. package/src/config.ts +404 -0
  141. package/src/credentials.ts +296 -0
  142. package/src/cucumber.ts +230 -0
  143. package/src/datafile.ts +481 -0
  144. package/src/db.ts +197 -0
  145. package/src/define.ts +285 -0
  146. package/src/describe.ts +282 -0
  147. package/src/drift.ts +259 -0
  148. package/src/env.ts +122 -0
  149. package/src/errors.ts +202 -0
  150. package/src/expectations.ts +191 -0
  151. package/src/fake.ts +156 -0
  152. package/src/fill.ts +24 -0
  153. package/src/host.ts +96 -0
  154. package/src/index.ts +143 -0
  155. package/src/ledger.ts +419 -0
  156. package/src/lint.ts +208 -0
  157. package/src/lockfile.ts +95 -0
  158. package/src/log.ts +82 -0
  159. package/src/op.ts +402 -0
  160. package/src/outline.ts +620 -0
  161. package/src/paths.ts +32 -0
  162. package/src/plugin.ts +37 -0
  163. package/src/policy.ts +139 -0
  164. package/src/resource.ts +670 -0
  165. package/src/resources.ts +311 -0
  166. package/src/run.ts +106 -0
  167. package/src/sandbox.ts +161 -0
  168. package/src/scenario.ts +1365 -0
  169. package/src/scenarios.ts +111 -0
  170. package/src/secret.ts +92 -0
  171. package/src/shared.ts +126 -0
  172. package/src/source.ts +82 -0
  173. package/src/steps.ts +90 -0
  174. package/src/version.ts +86 -0
  175. package/src/worker.ts +264 -0
  176. package/src/writer.ts +225 -0
@@ -0,0 +1,6 @@
1
+ import type { ApplyDeclared, ApplySteps } from "./apply.ts";
2
+ /**
3
+ * The apply workflow's steps for a config: `read`, the data files and the lockfile as drift reads
4
+ * them, under `root`; `appName` scopes the search for the lockfile apply last wrote.
5
+ */
6
+ export declare function applySteps(appName: string, root: string | undefined, read: () => Promise<Omit<ApplyDeclared, "rebinds">>): ApplySteps;
@@ -0,0 +1,93 @@
1
+ import { join, relative, sep } from "node:path";
2
+ import { DBOS } from "@dbos-inc/dbos-sdk";
3
+ import { decide } from "./call.js";
4
+ import { diffLockfiles, LOCKFILE, readLockfile, writeLockfile } from "./lockfile.js";
5
+ import { currentRun } from "./run.js";
6
+ import { APPLY_WORKFLOW } from "./shared.js";
7
+ // The apply workflow's steps that call no vendor: reading the data files, asking the policy
8
+ // ahead, and writing the lockfile. Here, not in apply.ts, which is held to the workflow lint and
9
+ // imports no DBOS; each reads its run from `currentRun`.
10
+ /** The name of the step that writes the lockfile and commits it: its output has the bindings it wrote. */
11
+ const WRITE_STEP = "apply:lockfile";
12
+ /** How many of the latest apply runs are searched for the lockfile one last wrote. */
13
+ const RUNS_SEARCHED = 100;
14
+ const runNow = () => {
15
+ const run = currentRun.getStore();
16
+ if (!run)
17
+ throw new Error("An apply step ran outside its run");
18
+ return run;
19
+ };
20
+ /**
21
+ * The bindings the latest apply run that wrote the lockfile wrote last, from its steps; undefined
22
+ * when none of the latest `RUNS_SEARCHED` did. A sandbox run writes none.
23
+ */
24
+ async function lastWritten(appName) {
25
+ const runs = await DBOS.listWorkflows({
26
+ workflowName: APPLY_WORKFLOW,
27
+ applicationName: appName,
28
+ sortDesc: true,
29
+ limit: RUNS_SEARCHED,
30
+ loadInput: false,
31
+ loadOutput: false,
32
+ });
33
+ for (const { workflowID } of runs) {
34
+ const steps = await DBOS.listWorkflowSteps(workflowID);
35
+ const last = steps?.findLast((step) => step.name === WRITE_STEP && !step.error);
36
+ if (last)
37
+ return last.output.bindings;
38
+ }
39
+ return undefined;
40
+ }
41
+ /**
42
+ * The apply workflow's steps for a config: `read`, the data files and the lockfile as drift reads
43
+ * them, under `root`; `appName` scopes the search for the lockfile apply last wrote.
44
+ */
45
+ export function applySteps(appName, root, read) {
46
+ return {
47
+ // The data files, and the lockfile against the one apply last wrote: a change someone else made.
48
+ declared: () => DBOS.runStep(async () => {
49
+ const declared = await read();
50
+ const before = await lastWritten(appName);
51
+ return { ...declared, rebinds: before ? diffLockfiles(before, declared.bindings) : [] };
52
+ }, { name: "apply:data-files" }),
53
+ // The policy asked as each call would ask it, now, so one approval can cover them all.
54
+ holds: (calls) => DBOS.runStep(async () => {
55
+ const run = runNow();
56
+ for (const { op: id, input } of calls) {
57
+ const op = run.state.ops.get(id);
58
+ // Parsed as the call will be, so the policy sees the same input with its defaults.
59
+ const parsed = op.input.safeParse(input);
60
+ const decision = await decide(run, op, parsed.success ? parsed.data : input);
61
+ if (decision.kind === "approve")
62
+ return decision.approver;
63
+ }
64
+ return undefined;
65
+ }, { name: "apply:policy" }),
66
+ // The one binding changed on the lockfile as it is now, written whole, then committed, in one
67
+ // step whose output is what it wrote. A sandbox run keeps its lockfile in memory: the run's
68
+ // report has it.
69
+ write: async (key, binding, message) => {
70
+ const run = runNow();
71
+ if (run.sandbox !== undefined || root === undefined)
72
+ return { written: false };
73
+ const { source } = run.state;
74
+ const { revision } = await DBOS.runStep(async () => {
75
+ const now = readLockfile(root);
76
+ if (now.problems.length)
77
+ throw new Error(`${LOCKFILE} cannot be updated: ${now.problems[0].message}`);
78
+ const { [key]: _, ...others } = now.bindings;
79
+ const bindings = binding ? { ...others, [key]: binding } : others;
80
+ writeLockfile(root, bindings);
81
+ const paths = [
82
+ relative(source?.root ?? root, join(root, LOCKFILE))
83
+ .split(sep)
84
+ .join("/"),
85
+ ];
86
+ const committed = await source?.commit({ paths, message, author: run.actor.id });
87
+ return { bindings, ...(committed && { revision: committed.revision }) };
88
+ }, { name: WRITE_STEP });
89
+ return { written: true, ...(revision !== undefined && { revision }) };
90
+ },
91
+ };
92
+ }
93
+ //# sourceMappingURL=apply-steps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apply-steps.js","sourceRoot":"","sources":["../src/apply-steps.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,197 @@
1
+ import { z } from "zod";
2
+ import { type Approver, type WorkflowDefinition } from "./define.ts";
3
+ import { type DriftDeclared, type DriftField, type ResolveOp } from "./drift.ts";
4
+ import type { HostOutputs } from "./host.ts";
5
+ import type { Binding, Bindings, Rebind } from "./lockfile.ts";
6
+ import type { Op } from "./op.ts";
7
+ import { type PlanAction, type Resource } from "./resource.ts";
8
+ import type { ResourceProblem } from "./resources.ts";
9
+ export { APPLY_WORKFLOW } from "./shared.ts";
10
+ /** What a person answers for a bound object the vendor no longer has (`gone`), or a binding no declaration has (`orphan`). */
11
+ export declare const PLAN_ANSWERS: readonly ["recreate", "forget", "delete"];
12
+ export type PlanAnswer = (typeof PLAN_ANSWERS)[number];
13
+ /**
14
+ * The apply workflow's input: `only` the declared ids (`<file>#<export>`) or orphaned lockfile
15
+ * keys to plan, else all; `bind`, a declared id to the vendor's id of the object to bind it to;
16
+ * `answers`, by declared id or orphaned key: `recreate` or `forget` a gone object, `forget` or
17
+ * `delete` an orphaned binding's.
18
+ */
19
+ export declare const ApplyInput: z.ZodObject<{
20
+ only: z.ZodOptional<z.ZodArray<z.ZodString>>;
21
+ bind: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
22
+ answers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodEnum<{
23
+ delete: "delete";
24
+ forget: "forget";
25
+ recreate: "recreate";
26
+ }>>>;
27
+ }, z.core.$strict>;
28
+ export type ApplyInput = z.infer<typeof ApplyInput>;
29
+ /**
30
+ * One declared resource, or orphaned binding, by what apply does with it: `create` it (as the
31
+ * vendor plans: `planned`, the paths `unknown` until it exists), `update` or `replace` its bound
32
+ * object (the declared `fields` that differ, the paths that force the replace), `bind` it to an
33
+ * object its identity `found` or the input `given`, ask about a `gone` object or an `orphan`ed
34
+ * binding (unless `answer`ed), or `none`.
35
+ */
36
+ export type PlanStep = {
37
+ id: string;
38
+ vendor: string;
39
+ type: string;
40
+ } & ({
41
+ action: "create";
42
+ planned: Record<string, unknown>;
43
+ unknown: string[];
44
+ } | {
45
+ action: "update" | "replace";
46
+ binding: string;
47
+ fields: DriftField[];
48
+ replace: string[];
49
+ } | {
50
+ action: "bind";
51
+ binding: string;
52
+ source: "found" | "given";
53
+ } | {
54
+ action: "gone";
55
+ binding: string;
56
+ answer?: PlanAnswer;
57
+ } | {
58
+ action: "orphan";
59
+ key: string;
60
+ binding: string;
61
+ answer?: PlanAnswer;
62
+ } | {
63
+ action: "none";
64
+ binding: string;
65
+ });
66
+ /** What apply would change: the problems, the lockfile's changes it did not make, and each step in dependency order. */
67
+ export interface ApplyPlan {
68
+ problems: ResourceProblem[];
69
+ /** The committed lockfile against the one apply last wrote: changes someone else made. */
70
+ rebinds: Rebind[];
71
+ steps: PlanStep[];
72
+ }
73
+ /** What became of one step: `done` (a `none` too), `skipped` (a question unanswered), or `failed`, with why. */
74
+ export interface ApplyResult {
75
+ id: string;
76
+ action: PlanStep["action"];
77
+ status: "done" | "skipped" | "failed";
78
+ /** Its binding after the step, when it has one. */
79
+ binding?: string;
80
+ /** For a host it created or updated: where it answers, as its state says. */
81
+ host?: HostOutputs;
82
+ error?: string;
83
+ }
84
+ /** The apply workflow's output. */
85
+ export interface ApplyReport {
86
+ plan: ApplyPlan;
87
+ results: ApplyResult[];
88
+ /**
89
+ * Whether the run wrote the lockfile (a sandbox run keeps its copy in memory), the revision of
90
+ * its last commit, and the bindings it ended with.
91
+ */
92
+ lockfile: {
93
+ written: boolean;
94
+ revision?: string;
95
+ bindings: Bindings;
96
+ };
97
+ }
98
+ /** What an apply run reads first: the data files and the lockfile, as drift does, and the lockfile's rebinds. */
99
+ export interface ApplyDeclared extends DriftDeclared {
100
+ bindings: Bindings;
101
+ orphans: (Binding & {
102
+ key: string;
103
+ })[];
104
+ rebinds: Rebind[];
105
+ }
106
+ /** One change call apply plans to make, as the policy would see it. */
107
+ export interface PlannedCall {
108
+ op: string;
109
+ input: unknown;
110
+ }
111
+ /** What apply does that is no vendor call, each a step of its own (`apply-steps.ts`). */
112
+ export interface ApplySteps {
113
+ declared(): Promise<ApplyDeclared>;
114
+ /** Who the policy would hold any of these calls for, the first it holds; undefined when it holds none. */
115
+ holds(calls: PlannedCall[]): Promise<Approver | undefined>;
116
+ /**
117
+ * Binds `key` to `binding` (unbinds it when undefined) in the lockfile as it is now, so a change
118
+ * another run made since this one read it stays, and commits it with `message`; a sandbox run
119
+ * writes nothing.
120
+ */
121
+ write(key: string, binding: Binding | undefined, message: string): Promise<{
122
+ written: boolean;
123
+ revision?: string;
124
+ }>;
125
+ }
126
+ type State = Record<string, unknown>;
127
+ type Expect = {
128
+ action: PlanAction;
129
+ replace: string[];
130
+ };
131
+ type ImportOp = Op<string, string, "import", {
132
+ id: string;
133
+ }, {
134
+ id: string;
135
+ gone: boolean;
136
+ state?: State;
137
+ }>;
138
+ type PlanOp = Op<string, string, "plan", {
139
+ id?: string;
140
+ desired?: State;
141
+ }, {
142
+ action: PlanAction;
143
+ planned?: State;
144
+ unknown: string[];
145
+ replace: string[];
146
+ }>;
147
+ type CreateOp = Op<string, string, "create", {
148
+ desired: State;
149
+ }, {
150
+ id: string;
151
+ state: State;
152
+ }>;
153
+ type UpdateOp = Op<string, string, "update", {
154
+ id: string;
155
+ desired: State;
156
+ expect?: Expect;
157
+ }, {
158
+ id: string;
159
+ state: State;
160
+ }>;
161
+ type DeleteOp = Op<string, string, "delete", {
162
+ id: string;
163
+ }, {
164
+ id: string;
165
+ gone: true;
166
+ }>;
167
+ type ApplyUse = ImportOp | PlanOp | CreateOp | UpdateOp | DeleteOp | ResolveOp | "approval" | "sleep";
168
+ /**
169
+ * The apply workflow for a config: it `uses` the `import` of every resource type the connectors
170
+ * declare that has a driver, and the change operations (`plan`, `create`, `update`, `delete`) of
171
+ * each writable one, and `approval`. `resolveConfig` adds it beside drift, with `steps`, the
172
+ * steps that read the data files, ask the policy and write the lockfile.
173
+ *
174
+ * A run reads the data files, the lockfile and its rebinds (`steps.declared`), and observes each
175
+ * declared resource as drift does: one import each, by the binding the input gives, else the
176
+ * lockfile's, else its identity. Then, for each resource the input wants (`only`), each after the
177
+ * ones it names, it plans:
178
+ *
179
+ * - `bind` when the input gives an object (`bind`) or, unbound, its identity finds one;
180
+ * - `create` when unbound and nothing is found, as its type's `plan` says (a gone object of a
181
+ * `stateless` type too, unless answered);
182
+ * - `gone` when its bound object is no longer there: skipped unless `answers` says `recreate`
183
+ * (created again) or `forget` (unbound);
184
+ * - `update`, `replace` or `none`, as its type's `plan` says for its bound object;
185
+ * - `orphan` for a binding no declaration has: skipped unless `answers` says `forget` (unbound) or
186
+ * `delete` (deleted at the vendor, then unbound).
187
+ *
188
+ * What cannot be planned is a problem, and has no step. When the policy would hold any of the
189
+ * change calls the plan makes (`steps.holds`), one approval asks for them all, covering each
190
+ * change operation, with the plan as its details. Then each step runs in order: a change call,
191
+ * and right after one that changes a binding, the lockfile written and committed
192
+ * (`steps.write`), so an object made is never left unbound. An update is given the plan's action
193
+ * and replace (`expect`), and refuses (`plan_changed`) when the vendor now plans otherwise; a
194
+ * reference to a resource made in this run is given its new binding. A failed step is reported
195
+ * and the run goes on; a failure that ends the run (`isRunControlError`) ends it.
196
+ */
197
+ export declare function applyWorkflow(types: ReadonlyMap<string, Resource>, ops: ReadonlyMap<string, Op>, drivers: ReadonlyMap<string, unknown>, steps: ApplySteps): WorkflowDefinition<readonly ApplyUse[], typeof ApplyInput>;