@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
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { DBOS } from "@dbos-inc/dbos-sdk";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { notApprover, Principal } from "./define.js";
|
|
4
|
+
import { RejectedError } from "./errors.js";
|
|
5
|
+
import { entry, write } from "./ledger.js";
|
|
6
|
+
import { warn } from "./log.js";
|
|
7
|
+
import { approverLabel, mayDecide } from "./shared.js";
|
|
8
|
+
// The wire contract between a run waiting on approvals and whoever decides them. The client
|
|
9
|
+
// imports this file and never the worker's.
|
|
10
|
+
/** The DBOS event a run publishes its approvals on, as `ApprovalState[]`. */
|
|
11
|
+
export const APPROVALS_EVENT = "approvals";
|
|
12
|
+
/** The `recv` topic a decision on an approval is sent to. */
|
|
13
|
+
export const topicOf = (approvalId) => approvalId;
|
|
14
|
+
/** The DBOS event an approval's decision is published on, as its decided `ApprovalState`, once made. */
|
|
15
|
+
export const decisionEventOf = (approvalId) => `approval:${approvalId}`;
|
|
16
|
+
/**
|
|
17
|
+
* The idempotency key a decision message is sent with, so a retried send queues it once. DBOS
|
|
18
|
+
* scopes the key per run, not per topic, so it names the approval too: one message id reused
|
|
19
|
+
* for two approvals of a run would otherwise drop the second send.
|
|
20
|
+
*/
|
|
21
|
+
export const messageKeyOf = (approvalId, messageId) => `${approvalId}:${messageId}`;
|
|
22
|
+
/**
|
|
23
|
+
* A decision, as sent to a run. `id` names the message, so whoever sent it can tell whether
|
|
24
|
+
* the run decided with it or with another; `SanomaClient.decide` sets one.
|
|
25
|
+
*/
|
|
26
|
+
export const ApprovalMessage = z.object({
|
|
27
|
+
id: z.string().optional(),
|
|
28
|
+
decision: z.enum(["approve", "reject"]),
|
|
29
|
+
by: Principal,
|
|
30
|
+
note: z.string().optional(),
|
|
31
|
+
});
|
|
32
|
+
const statusOf = (decision) => (decision === "approve" ? "approved" : "rejected");
|
|
33
|
+
/** The sender's id, from a message that may not be a valid decision. */
|
|
34
|
+
function senderOf(raw) {
|
|
35
|
+
const by = typeof raw === "object" && raw !== null ? raw.by : undefined;
|
|
36
|
+
const id = typeof by === "object" && by !== null ? by.id : undefined;
|
|
37
|
+
return typeof id === "string" && id ? id : undefined;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Waits, durably, for a decision from someone who may make it. Throws `RejectedError` on a
|
|
41
|
+
* rejection. Without `held`, the workflow asked (`ctx.approval`); with it, the policy did, and
|
|
42
|
+
* `place` is the held call's outline node and name.
|
|
43
|
+
*/
|
|
44
|
+
export async function awaitApproval(run, title, req, place, held) {
|
|
45
|
+
const { covers } = req;
|
|
46
|
+
const all = run.approvals;
|
|
47
|
+
const state = {
|
|
48
|
+
id: `approval-${all.length + 1}`,
|
|
49
|
+
title,
|
|
50
|
+
approver: req.approver,
|
|
51
|
+
...(req.links === undefined ? {} : { links: req.links }),
|
|
52
|
+
...(req.details === undefined ? {} : { details: req.details }),
|
|
53
|
+
requestedBy: held ? "policy" : "workflow",
|
|
54
|
+
covers,
|
|
55
|
+
...(held ? { op: held.op, opSeq: held.seq, input: held.input } : {}),
|
|
56
|
+
status: "pending",
|
|
57
|
+
requestedAt: 0,
|
|
58
|
+
refused: [],
|
|
59
|
+
};
|
|
60
|
+
all.push(state);
|
|
61
|
+
state.requestedAt = await DBOS.now();
|
|
62
|
+
await DBOS.setEvent(APPROVALS_EVENT, all);
|
|
63
|
+
await write(run, entry(run, {
|
|
64
|
+
type: "approval.requested",
|
|
65
|
+
approval: state.id,
|
|
66
|
+
...place,
|
|
67
|
+
title,
|
|
68
|
+
approver: state.approver,
|
|
69
|
+
requestedBy: state.requestedBy,
|
|
70
|
+
covers,
|
|
71
|
+
...(held ? { op: held.op, opSeq: held.seq } : {}),
|
|
72
|
+
}, { key: state.id, at: state.requestedAt }));
|
|
73
|
+
for (;;) {
|
|
74
|
+
const raw = await DBOS.recv(topicOf(state.id), { timeoutSeconds: 24 * 60 * 60 });
|
|
75
|
+
if (raw === null || raw === undefined) {
|
|
76
|
+
warn(`run ${run.id}: approval ${state.id} ("${title}") is still waiting for ${approverLabel(state.approver)}`);
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
const at = await DBOS.now();
|
|
80
|
+
const parsed = ApprovalMessage.safeParse(raw);
|
|
81
|
+
const msg = parsed.success ? parsed.data : undefined;
|
|
82
|
+
if (!msg || !mayDecide(state, msg.by)) {
|
|
83
|
+
const by = msg?.by.id ?? senderOf(raw);
|
|
84
|
+
const reason = msg ? notApprover(state, msg.by) : "not a valid decision message";
|
|
85
|
+
state.refused.push({
|
|
86
|
+
...(by === undefined ? {} : { by }),
|
|
87
|
+
...(msg?.id === undefined ? {} : { id: msg.id }),
|
|
88
|
+
at,
|
|
89
|
+
reason,
|
|
90
|
+
});
|
|
91
|
+
await DBOS.setEvent(APPROVALS_EVENT, all);
|
|
92
|
+
await write(run, entry(run, { type: "approval.refused", approval: state.id, ...(by === undefined ? {} : { by }), reason }, { key: `${state.id}:refused:${state.refused.length}`, at }));
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
Object.assign(state, {
|
|
96
|
+
status: statusOf(msg.decision),
|
|
97
|
+
decidedBy: msg.by.id,
|
|
98
|
+
decidedAt: at,
|
|
99
|
+
note: msg.note,
|
|
100
|
+
decidedWith: msg.id,
|
|
101
|
+
});
|
|
102
|
+
// The list first, then the ledger, then the decision event: whoever sees the event sees both.
|
|
103
|
+
await DBOS.setEvent(APPROVALS_EVENT, all);
|
|
104
|
+
await write(run, entry(run, { type: "approval.decided", approval: state.id, decision: msg.decision, by: msg.by.id, note: msg.note }, { key: state.id, at }));
|
|
105
|
+
await DBOS.setEvent(decisionEventOf(state.id), state);
|
|
106
|
+
if (msg.decision === "reject")
|
|
107
|
+
throw new RejectedError(title, msg.by, msg.note, state.id);
|
|
108
|
+
return { approvedBy: msg.by.id, at, note: msg.note };
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=approvals.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approvals.js","sourceRoot":"","sources":["../src/approvals.ts"],"names":[],"mappings":"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"}
|
package/dist/ast.d.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/** oxc-parser's ESTree nodes, read by shape. */
|
|
2
|
+
export type Node = any;
|
|
3
|
+
/** Parses TypeScript, which covers the JavaScript a built package holds, as a module; a `.tsx` or `.jsx` file with its JSX. */
|
|
4
|
+
export declare const parse: (filename: string, source: string) => import("oxc-parser").ParseResult;
|
|
5
|
+
/** A node's children in source order, by oxc-parser's `visitorKeys`, without its types. A hole in a list is `null`. */
|
|
6
|
+
export declare const childrenOf: (node: Node) => Node[];
|
|
7
|
+
/**
|
|
8
|
+
* The offset each line of `source` starts at, from line 1, and one past the end of the text as
|
|
9
|
+
* the start of the line after the last: where each line ends is the next start, less its `\n`.
|
|
10
|
+
*/
|
|
11
|
+
export declare const lineStartsOf: (source: string) => number[];
|
|
12
|
+
/** Where an offset into `source` is, as a line and a column, both from 1. */
|
|
13
|
+
export declare function locator(source: string): (offset: number) => {
|
|
14
|
+
line: number;
|
|
15
|
+
column: number;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* The offset into a text of a line and column, both from 1, as a stack frame gives them, from
|
|
19
|
+
* the text's `lineStartsOf`; or undefined when the text has no such line, or the line no such
|
|
20
|
+
* column (a frame mapped wrong must not land in the next line). The column is taken as a UTF-16
|
|
21
|
+
* unit index, as V8 counts it.
|
|
22
|
+
*/
|
|
23
|
+
export declare function offsetOf(lineStarts: readonly number[], line: number, column: number): number | undefined;
|
|
24
|
+
/** Something wrong in a file, at a line and column from 1. */
|
|
25
|
+
export interface LintProblem {
|
|
26
|
+
line: number;
|
|
27
|
+
column: number;
|
|
28
|
+
message: string;
|
|
29
|
+
}
|
|
30
|
+
/** A file parsed, its syntax errors as problems, and offsets as lines and columns from 1. */
|
|
31
|
+
export declare function parsed(source: string, filename: string): {
|
|
32
|
+
program: Node;
|
|
33
|
+
problems: LintProblem[];
|
|
34
|
+
at: (offset: number) => {
|
|
35
|
+
line: number;
|
|
36
|
+
column: number;
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* A file read and parsed once, for the outline and the lint alike: its text with `\n` line
|
|
41
|
+
* endings (CodeMirror counts a line break as one unit, oxc counts `\r\n` as two, and spans need
|
|
42
|
+
* `\n` alone), its program, offsets as lines and columns, and its syntax problems.
|
|
43
|
+
*/
|
|
44
|
+
export interface SourceFile {
|
|
45
|
+
file: string;
|
|
46
|
+
source: string;
|
|
47
|
+
program: Node;
|
|
48
|
+
at: (offset: number) => {
|
|
49
|
+
line: number;
|
|
50
|
+
column: number;
|
|
51
|
+
};
|
|
52
|
+
problems: LintProblem[];
|
|
53
|
+
}
|
|
54
|
+
/** Reads and parses `file`; or why it could not be read, as a message naming it. */
|
|
55
|
+
export declare function readSource(file: string): SourceFile | string;
|
|
56
|
+
/** Problems in the order of their place in the file. */
|
|
57
|
+
export declare const byPosition: <P extends Omit<LintProblem, "message">>(problems: P[]) => P[];
|
package/dist/ast.js
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { parseSync, visitorKeys } from "oxc-parser";
|
|
3
|
+
import { errorMessage } from "./shared.js";
|
|
4
|
+
/** Parses TypeScript, which covers the JavaScript a built package holds, as a module; a `.tsx` or `.jsx` file with its JSX. */
|
|
5
|
+
export const parse = (filename, source) => parseSync(filename, source, {
|
|
6
|
+
lang: /\.[jt]sx$/.test(filename) ? "tsx" : "ts",
|
|
7
|
+
sourceType: "module",
|
|
8
|
+
preserveParens: false,
|
|
9
|
+
});
|
|
10
|
+
// The keys that hold types, not code: nothing the lint or the outline looks for is in them.
|
|
11
|
+
const TYPE_KEYS = new Set([
|
|
12
|
+
"typeAnnotation",
|
|
13
|
+
"typeParameters",
|
|
14
|
+
"returnType",
|
|
15
|
+
"typeArguments",
|
|
16
|
+
"superTypeArguments",
|
|
17
|
+
"implements",
|
|
18
|
+
]);
|
|
19
|
+
const CODE_KEYS = new Map(Object.entries(visitorKeys).map(([type, keys]) => [type, keys.filter((key) => !TYPE_KEYS.has(key))]));
|
|
20
|
+
/** A node's children in source order, by oxc-parser's `visitorKeys`, without its types. A hole in a list is `null`. */
|
|
21
|
+
export const childrenOf = (node) => (CODE_KEYS.get(node.type) ?? []).flatMap((key) => node[key] ?? []);
|
|
22
|
+
/**
|
|
23
|
+
* The offset each line of `source` starts at, from line 1, and one past the end of the text as
|
|
24
|
+
* the start of the line after the last: where each line ends is the next start, less its `\n`.
|
|
25
|
+
*/
|
|
26
|
+
export const lineStartsOf = (source) => {
|
|
27
|
+
const lineStarts = [0];
|
|
28
|
+
for (let i = 0; i < source.length; i++)
|
|
29
|
+
if (source[i] === "\n")
|
|
30
|
+
lineStarts.push(i + 1);
|
|
31
|
+
lineStarts.push(source.length + 1);
|
|
32
|
+
return lineStarts;
|
|
33
|
+
};
|
|
34
|
+
/** Where an offset into `source` is, as a line and a column, both from 1. */
|
|
35
|
+
export function locator(source) {
|
|
36
|
+
const lineStarts = lineStartsOf(source);
|
|
37
|
+
return (offset) => {
|
|
38
|
+
let line = 0;
|
|
39
|
+
while (line + 1 < lineStarts.length && lineStarts[line + 1] <= offset)
|
|
40
|
+
line++;
|
|
41
|
+
return { line: line + 1, column: offset - lineStarts[line] + 1 };
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The offset into a text of a line and column, both from 1, as a stack frame gives them, from
|
|
46
|
+
* the text's `lineStartsOf`; or undefined when the text has no such line, or the line no such
|
|
47
|
+
* column (a frame mapped wrong must not land in the next line). The column is taken as a UTF-16
|
|
48
|
+
* unit index, as V8 counts it.
|
|
49
|
+
*/
|
|
50
|
+
export function offsetOf(lineStarts, line, column) {
|
|
51
|
+
const start = lineStarts[line - 1];
|
|
52
|
+
const next = lineStarts[line];
|
|
53
|
+
if (line < 1 || column < 1 || start === undefined || next === undefined)
|
|
54
|
+
return undefined;
|
|
55
|
+
const offset = start + column - 1;
|
|
56
|
+
return offset < next - 1 ? offset : undefined;
|
|
57
|
+
}
|
|
58
|
+
/** A file parsed, its syntax errors as problems, and offsets as lines and columns from 1. */
|
|
59
|
+
export function parsed(source, filename) {
|
|
60
|
+
const { program, errors } = parse(filename, source);
|
|
61
|
+
const at = locator(source);
|
|
62
|
+
const problems = errors.map((e) => ({
|
|
63
|
+
...at(e.labels?.[0]?.start ?? 0),
|
|
64
|
+
message: `syntax: ${e.message}`,
|
|
65
|
+
}));
|
|
66
|
+
return { program: program, problems, at };
|
|
67
|
+
}
|
|
68
|
+
/** Reads and parses `file`; or why it could not be read, as a message naming it. */
|
|
69
|
+
export function readSource(file) {
|
|
70
|
+
let source;
|
|
71
|
+
try {
|
|
72
|
+
source = readFileSync(file, "utf8").replaceAll("\r\n", "\n");
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
return `${file} could not be read: ${errorMessage(err)}`;
|
|
76
|
+
}
|
|
77
|
+
return { file, source, ...parsed(source, file) };
|
|
78
|
+
}
|
|
79
|
+
/** Problems in the order of their place in the file. */
|
|
80
|
+
export const byPosition = (problems) => problems.toSorted((a, b) => a.line - b.line || a.column - b.column);
|
|
81
|
+
//# sourceMappingURL=ast.js.map
|
package/dist/ast.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ast.js","sourceRoot":"","sources":["../src/ast.ts"],"names":[],"mappings":"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"}
|
package/dist/call.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { type WorkflowDefinition } from "./define.ts";
|
|
2
|
+
import { type Op } from "./op.ts";
|
|
3
|
+
import { type RecordedDecision } from "./policy.ts";
|
|
4
|
+
import type { Run, WorkerState } from "./run.ts";
|
|
5
|
+
/**
|
|
6
|
+
* True for a failure that is not the run's outcome, so the ledger does not record it: DBOS
|
|
7
|
+
* cancelled the run or another process took it over, or the run's worker is stopping and the
|
|
8
|
+
* error has none of our codes. `stop()` marks the worker stopped before DBOS shuts down, so from
|
|
9
|
+
* then on whatever fails without a code (DBOS's "system database has been shut down", pg's
|
|
10
|
+
* closed pool) is the shutdown, and the run recovered on the next worker records how it ends.
|
|
11
|
+
* A coded failure then (a driver's final answer, a denial, a rejection) is still the outcome:
|
|
12
|
+
* DBOS records the run's error and never runs it again, so the ledger records it too. Narrower
|
|
13
|
+
* than `isRunControlError`: DBOS's other errors (a run that is not deterministic) end the run
|
|
14
|
+
* for good, and are recorded.
|
|
15
|
+
*/
|
|
16
|
+
export declare function isInfrastructureError(err: unknown, state: Pick<WorkerState, "stopped">): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Where a call is, as its records say: its outline node's `path`, and the step's name, as the
|
|
19
|
+
* outline resolved it (`OutlineNode`'s `name`), or for a call the outline could not name, the
|
|
20
|
+
* operation a computed id called, or an approval's title that is no literal.
|
|
21
|
+
*/
|
|
22
|
+
export interface Placed {
|
|
23
|
+
node: string;
|
|
24
|
+
name: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* The run's `ctx`: the operations and built-ins its workflow `uses`, and nothing else. Every
|
|
28
|
+
* member that writes a record is placed in the outline where the workflow calls it (`placeCall`)
|
|
29
|
+
* and goes through the run's queue (`serial`), its records carrying the node and the step's
|
|
30
|
+
* name; `ctx.now()` only reads the clock, queued, and `ctx.runId` is a value. `ctx.all` alone
|
|
31
|
+
* skips the queue: it makes no DBOS call or record itself, it only calls its members, whose ctx
|
|
32
|
+
* calls are queued. Queued, it would hold the queue until its members settled, and their calls,
|
|
33
|
+
* queued behind it, would never start.
|
|
34
|
+
*/
|
|
35
|
+
export declare function buildCtx(wf: WorkflowDefinition<any, any>, run: Run): any;
|
|
36
|
+
/** Asks the policy about one call, and checks its answer. Runs inside a step, so it must have no side effects of its own. */
|
|
37
|
+
export declare function decide(run: Run, op: Op, input: unknown): Promise<RecordedDecision>;
|