fyflow-orchestration 0.10.0 → 0.12.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/AGENTS.md +249 -53
- package/README.md +5 -5
- package/dist/browser/chunks/{chunk-NA6QQAZ2.js → chunk-4JFQX7DL.js} +164 -49
- package/dist/browser/index.js +546 -3
- package/dist/browser/scheduler/index.js +1 -1
- package/dist/node/chunks/{chunk-NA6QQAZ2.js → chunk-4JFQX7DL.js} +164 -49
- package/dist/node/index.js +546 -3
- package/dist/node/scheduler/index.js +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/src/definition/assist.d.ts +1 -1
- package/dist/types/src/definition/condition.d.ts +21 -3
- package/dist/types/src/definition/definition-schema.d.ts +23 -0
- package/dist/types/src/definition/types.d.ts +8 -5
- package/dist/types/src/definition/validate.d.ts +50 -6
- package/dist/types/src/definition/wiring.d.ts +15 -5
- package/dist/types/src/driver/driver.d.ts +17 -6
- package/dist/types/src/fold/run-state.d.ts +17 -0
- package/package.json +2 -1
package/dist/browser/index.js
CHANGED
|
@@ -9,23 +9,28 @@ import {
|
|
|
9
9
|
ConfigRefused,
|
|
10
10
|
DECLARED_POOL_KEYS,
|
|
11
11
|
DOCUMENT_KEYS,
|
|
12
|
+
DOC_KEYS_DECLARED,
|
|
12
13
|
DerivationRefused,
|
|
13
14
|
Driver,
|
|
14
15
|
DuplicateTaskId,
|
|
15
16
|
EDGE_KEYS_DECLARED,
|
|
17
|
+
EDGE_KEYS_REQUIRED,
|
|
16
18
|
GATE_TYPE_KEYS,
|
|
17
19
|
GateTypeRefused,
|
|
18
20
|
GroupConfigRefused,
|
|
19
21
|
GroupTypeMissing,
|
|
22
|
+
ID_RE_COPY,
|
|
20
23
|
INSTANCE_KEYS,
|
|
21
24
|
InvalidDefinition,
|
|
22
25
|
InvalidRunId,
|
|
23
26
|
InvalidTaskId,
|
|
24
27
|
KEY_PATH_RE,
|
|
28
|
+
KINDS_COPY,
|
|
25
29
|
MESSAGE_OPTION_KEYS,
|
|
26
30
|
MissingJoinPolicy,
|
|
27
31
|
MultipleRuns,
|
|
28
32
|
NODE_KEYS_DECLARED,
|
|
33
|
+
NODE_KEYS_REQUIRED,
|
|
29
34
|
NODE_TYPE_DECLARATION_KEYS,
|
|
30
35
|
NameCollision,
|
|
31
36
|
NameMissing,
|
|
@@ -42,6 +47,7 @@ import {
|
|
|
42
47
|
PREDICATE_ROOTS,
|
|
43
48
|
PoolTypeMissing,
|
|
44
49
|
RETRY_POLICY_KEYS,
|
|
50
|
+
ROUTABLE_STATES,
|
|
45
51
|
RegistryError,
|
|
46
52
|
ResumeRefused,
|
|
47
53
|
RunControlRefused,
|
|
@@ -145,7 +151,537 @@ import {
|
|
|
145
151
|
visibilityKey,
|
|
146
152
|
witness,
|
|
147
153
|
workersOf
|
|
148
|
-
} from "./chunks/chunk-
|
|
154
|
+
} from "./chunks/chunk-4JFQX7DL.js";
|
|
155
|
+
|
|
156
|
+
// src/definition/definition-schema.ts
|
|
157
|
+
var DRAFT_2020_12 = "https://json-schema.org/draft/2020-12/schema";
|
|
158
|
+
var ref = (name) => ({ $ref: `#/$defs/${name}` });
|
|
159
|
+
function body(re, name) {
|
|
160
|
+
const s = re.source;
|
|
161
|
+
if (!s.startsWith("^") || !s.endsWith("$") || re.flags !== "") {
|
|
162
|
+
throw new Error(`definitionSchema: ${name} is no longer an anchored, flagless expression (${String(re)}) \u2014 its body cannot be reused as a pattern`);
|
|
163
|
+
}
|
|
164
|
+
return s.slice(1, -1);
|
|
165
|
+
}
|
|
166
|
+
function keyPathSegment(id) {
|
|
167
|
+
const seg = `${id}(?:\\[(?:0|[1-9][0-9]{0,8})\\])*`;
|
|
168
|
+
const whole = body(KEY_PATH_RE, "KEY_PATH_RE");
|
|
169
|
+
if (whole !== `${seg}(?:\\.${seg})*`) {
|
|
170
|
+
throw new Error(`definitionSchema: KEY_PATH_RE (${String(KEY_PATH_RE)}) is no longer one segment pattern repeated \u2014 a comparison's path pattern cannot be derived from it`);
|
|
171
|
+
}
|
|
172
|
+
return seg;
|
|
173
|
+
}
|
|
174
|
+
function described(table, key, where) {
|
|
175
|
+
const d = Object.prototype.hasOwnProperty.call(table, key) ? table[key] : void 0;
|
|
176
|
+
if (d === void 0) throw new Error(`definitionSchema: ${where} declares the key "${key}" and no description is written for it`);
|
|
177
|
+
return d;
|
|
178
|
+
}
|
|
179
|
+
var DOC_DESCRIPTIONS = {
|
|
180
|
+
flowId: "The flow's id: 1-64 characters from [A-Za-z0-9_-] (FD-V16), the charset of spec/task-id.md \u2014 it is a segment of every task id this flow mints.",
|
|
181
|
+
version: "The definition's version, an integer >= 1 (FD-V21), managed by the author. The driver does not interpret it.",
|
|
182
|
+
entry: "The id of the node a run starts at. It must name a node of this document that is neither a join nor an end (FD-V3 \u2014 validateDefinition's, not this schema's).",
|
|
183
|
+
nodes: "One object per node, order irrelevant. Node ids are unique across the document (FD-V1 \u2014 validateDefinition's)."
|
|
184
|
+
};
|
|
185
|
+
var NODE_DESCRIPTIONS = {
|
|
186
|
+
id: "The node's id: 1-64 characters from [A-Za-z0-9_-] (FD-V16), unique in the document (FD-V1). It is a segment of the task id the node mints.",
|
|
187
|
+
kind: 'Which of the seven node kinds this is (FD-V24). There is no "decision" kind: a decision is an edge\'s `when`, and a decision with memory is a `gate`.',
|
|
188
|
+
edges: "Where the run goes from here, in order. The first eligible edge whose `when` holds is taken; an edge with no `on` routes `done` only.",
|
|
189
|
+
needs: "What this node receives instead of the previous node's output: an object whose keys name what the node receives and whose values are references (spec/flow-definition.md section 3, FD-V26). Where each reference points is validateDefinition's (FD-V27-FD-V29, FD-V49).",
|
|
190
|
+
settings: "Settings, a plain object.",
|
|
191
|
+
type: "A registered type's name."
|
|
192
|
+
};
|
|
193
|
+
var KIND_DESCRIPTIONS = {
|
|
194
|
+
task: {
|
|
195
|
+
kind: "A `task`: the one kind that is dispatched \u2014 one scheduler task, run by the worker of the node type it names.",
|
|
196
|
+
type: "The registered NODE type that runs this task (required since v0.19). Which names are registered is the registry's: FD-V32, validateDefinition's. The built-in \"Transform\" runs nothing but the node's own `transform` (FD-V46).",
|
|
197
|
+
pool: "A named pool INSTANCE of this node's type, from the registry's `pools` (FD-V38). Absent: the type's default instance, keyed by the type's name.",
|
|
198
|
+
settings: "Settings handed to the worker in its envelope, merged OVER the type's defaults. A plain object; what its worker's settingsSchema says of them is FD-V33's, validateDefinition's.",
|
|
199
|
+
transform: "An expression the node type's worker wrapper evaluates over this node's input before the worker sees it: exactly { lang, expr } (FD-V37). The language must be registered (FD-V35) and accept the expression (FD-V36) \u2014 validateDefinition's.",
|
|
200
|
+
optional: "true: the FLOW handles this task's failure \u2014 it ends `failed` and may route a `failed` edge. Absent or false: a failure out of retries waits for a person (`user_action`).",
|
|
201
|
+
retryPolicy: "How the scheduler retries a failed attempt, inside one task id: exactly { maxRetries, backoffMs } (FD-V30).",
|
|
202
|
+
workerGroups: "The resource groups the scheduler holds this task to: a non-empty list of distinct group ids (FD-V31). That each id is one the registry's `groups` declares is validateDefinition's.",
|
|
203
|
+
needs: NODE_DESCRIPTIONS.needs
|
|
204
|
+
},
|
|
205
|
+
fanout: {
|
|
206
|
+
kind: "A `fanout`: opens a region of N branches declared HERE, closed by the one `join` naming it. Dispatches nothing.",
|
|
207
|
+
branches: "The region's branch entries: at least two distinct node ids (FD-V9), each a string (FD-V21), each a task or an ask, none of them its own join (FD-V9, FD-V12 \u2014 validateDefinition's)."
|
|
208
|
+
},
|
|
209
|
+
map: {
|
|
210
|
+
kind: "A `map`: opens a region of ONE branch, opened once per item of an array at run time, closed by the one `join` naming it. Dispatches nothing.",
|
|
211
|
+
over: "The key, in the value that reaches the map, holding the array of items: 1-64 characters from [A-Za-z0-9_-] (FD-V25).",
|
|
212
|
+
branch: "The id of the one node each item's instance starts at \u2014 a task or an ask (FD-V25, validateDefinition's).",
|
|
213
|
+
needs: "What the map receives before it reads `over` (spec/flow-definition.md section 3, FD-V26)."
|
|
214
|
+
},
|
|
215
|
+
join: {
|
|
216
|
+
kind: "A `join`: closes the region its `of` opened, by the join policy the driver is given. Dispatches nothing.",
|
|
217
|
+
of: "The id of the `fanout` or `map` whose region this closes: a string (FD-V21); that it names an existing node (FD-V2) and that the node is one (FD-V6) are validateDefinition's.",
|
|
218
|
+
edges: "Exactly one edge, carrying neither `when` nor `on` (FD-V7): a join has no outcome for either to read."
|
|
219
|
+
},
|
|
220
|
+
end: {
|
|
221
|
+
kind: "An `end`: terminates one path. No edges.",
|
|
222
|
+
outcome: "A non-empty, author-defined string (FD-V8). The driver does not interpret it."
|
|
223
|
+
},
|
|
224
|
+
gate: {
|
|
225
|
+
kind: "A `gate`: routes the branch that reaches it by a registered GATE type's decision, and hands on exactly what reached it \u2014 a decision with memory. Dispatches nothing.",
|
|
226
|
+
type: `The registered GATE type that decides: a built-in (${Object.keys(BUILT_IN_GATE_TYPES).sort().map((t) => `"${t}"`).join(", ")}) or one the registry's \`gateTypes\` adds (FD-V39, validateDefinition's).`,
|
|
227
|
+
settings: "Settings the gate type reads: a plain object (FD-V40). A `key`, where present, is a key path the library resolves over what reached the gate. What the type's settingsSchema says of the rest is validateDefinition's.",
|
|
228
|
+
edges: "One edge per route of the gate's type, each carrying `to` and `route` \u2014 an edge with no `route` carries the type's DEFAULT route, which may also be named (FD-V41). That every route is wired exactly once is validateDefinition's."
|
|
229
|
+
},
|
|
230
|
+
ask: {
|
|
231
|
+
kind: `An \`ask\`: waits for a PERSON, whose answer is its output and is routed by its edges as a task's settlement is. Never dispatched. A task's ${ASK_REFUSED_KEYS.map((k) => `\`${k}\``).join(", ")} are refused on an ask (FD-V47).`,
|
|
232
|
+
settings: "Opaque settings a UI reads: a plain object (FD-V21). The library never reads them.",
|
|
233
|
+
answerSchema: "The schema a `done` answer is held to, in the library's built-in schema subset (FD-V48, ADR 0053). That an `examples` entry conforms is validateDefinition's (ADR 0056).",
|
|
234
|
+
needs: "What the person is shown as the ask's input (spec/flow-definition.md section 3, FD-V26)."
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
var EDGE_DESCRIPTIONS = {
|
|
238
|
+
to: "The id of the node this edge leads to (FD-V2, validateDefinition's).",
|
|
239
|
+
on: 'The terminal states this edge is eligible for: a non-empty list of distinct "done" / "failed" (FD-V18). Absent: ["done"]. "user_action" suspends rather than routes.',
|
|
240
|
+
when: "The decision: a registered predicate NAME { predicate }, a declared COMPARISON { path, op, value, default?, length? }, or a flat GROUP { all } or { any } of comparisons (FD-V42-FD-V45). Absent: the edge is the default for its state.",
|
|
241
|
+
needs: "What this edge's predicate sees beyond its node's outcome \u2014 `needs`' grammar minus \".\" (FD-V26).",
|
|
242
|
+
route: "On a gate's edge, which of the gate type's routes it carries; absent: the type's DEFAULT route (FD-V41). Refused on every other kind's edge."
|
|
243
|
+
};
|
|
244
|
+
var RETRY_DESCRIPTIONS = {
|
|
245
|
+
maxRetries: "How many times a failed attempt is re-dispatched: an integer >= 0.",
|
|
246
|
+
backoffMs: "Milliseconds between a failed attempt and its retry: a finite number >= 0."
|
|
247
|
+
};
|
|
248
|
+
var TRANSFORM_DESCRIPTIONS = {
|
|
249
|
+
lang: "A registered language's name (FD-V35, validateDefinition's).",
|
|
250
|
+
expr: "Text that language compiles (FD-V36, validateDefinition's): `$` is the value this node receives, `$settings` its effective settings."
|
|
251
|
+
};
|
|
252
|
+
var PREDICATE_DESCRIPTIONS = {
|
|
253
|
+
predicate: "A registered predicate's name (FD-V4, validateDefinition's).",
|
|
254
|
+
path: `A key path over the decision's context, starting at ${PREDICATE_ROOTS.map((r) => `"${r}"`).join(" or ")} and naming a key beyond it; a key past the root may be followed by array indexes [n], the root never (FD-V43).`,
|
|
255
|
+
op: `One of ${PREDICATE_OPS.join(", ")} (FD-V44). The ordering operators compare numbers and "startsWith" a string \u2014 a comparison between kinds is no match, never a coercion.`,
|
|
256
|
+
value: "The scalar compared against: null, a boolean, a number or a string (FD-V44).",
|
|
257
|
+
default: "What is compared where the path does not resolve or resolves to null: a scalar, or \u2014 with `length` \u2014 an array or a string (FD-V44).",
|
|
258
|
+
length: "Exactly true: compare the LENGTH of the array or string, against a number (FD-V44).",
|
|
259
|
+
all: "A flat group: a non-empty list of comparisons that must all hold (FD-V45).",
|
|
260
|
+
any: "A flat group: a non-empty list of comparisons of which one must hold (FD-V45)."
|
|
261
|
+
};
|
|
262
|
+
var SUBSET_DESCRIPTIONS = {
|
|
263
|
+
type: "One of the seven JSON types, or a non-empty list of distinct ones.",
|
|
264
|
+
required: "Property names an object must carry.",
|
|
265
|
+
properties: "A schema, in the subset, per property name.",
|
|
266
|
+
additionalProperties: "true or false only \u2014 never a schema.",
|
|
267
|
+
enum: "A non-empty list of the values allowed.",
|
|
268
|
+
const: "The one value allowed.",
|
|
269
|
+
minimum: "The smallest number allowed.",
|
|
270
|
+
maximum: "The largest number allowed.",
|
|
271
|
+
minLength: "The shortest string allowed: an integer >= 0.",
|
|
272
|
+
maxLength: "The longest string allowed: an integer >= 0.",
|
|
273
|
+
items: "ONE schema, in the subset, for every item \u2014 never a tuple.",
|
|
274
|
+
minItems: "The fewest items allowed: an integer >= 0.",
|
|
275
|
+
examples: "A non-empty list of values the schema accepts (that each conforms is ADR 0056's check, validateDefinition's).",
|
|
276
|
+
title: "An annotation: a string, constraining nothing (ADR 0098).",
|
|
277
|
+
description: "An annotation: a string, constraining nothing (ADR 0098).",
|
|
278
|
+
readOnly: "An annotation: true or false, constraining nothing (ADR 0098).",
|
|
279
|
+
writeOnly: "An annotation: true or false, constraining nothing (ADR 0098)."
|
|
280
|
+
};
|
|
281
|
+
var NUMERIC_OPS = ["lt", "lte", "gt", "gte"];
|
|
282
|
+
var STRING_OPS = ["startsWith"];
|
|
283
|
+
var ERROR_PART = "!error";
|
|
284
|
+
function nodeKeySchema(kind, key) {
|
|
285
|
+
switch (key) {
|
|
286
|
+
case "id":
|
|
287
|
+
return ref("id");
|
|
288
|
+
case "kind":
|
|
289
|
+
return { const: kind };
|
|
290
|
+
case "type":
|
|
291
|
+
case "pool":
|
|
292
|
+
return { type: "string" };
|
|
293
|
+
case "settings":
|
|
294
|
+
return kind === "gate" ? { type: "object", properties: { key: { type: "string", pattern: KEY_PATH_RE.source, description: "A key path: dot-separated object keys, each [A-Za-z0-9_-]{1,64} and optionally followed by array indexes [n] (n is 0 or has no leading zero, at most 999999999; never leading the path) \u2014 files[0].series; no quoted key, no wildcard, no expression (FD-V40)." } } } : { type: "object" };
|
|
295
|
+
case "transform":
|
|
296
|
+
return ref("transform");
|
|
297
|
+
case "optional":
|
|
298
|
+
return { type: "boolean" };
|
|
299
|
+
case "needs":
|
|
300
|
+
return ref("needs");
|
|
301
|
+
case "retryPolicy":
|
|
302
|
+
return ref("retryPolicy");
|
|
303
|
+
case "workerGroups":
|
|
304
|
+
return { type: "array", minItems: 1, uniqueItems: true, items: { type: "string" } };
|
|
305
|
+
// **`branches`' entries and `of` are ids, unconditionally** — v0.52, W215, Q774 resolved (P44 (d1)): `FD-V21` refuses
|
|
306
|
+
// a non-string `of` and a non-string branch entry, so the schema may too (ADR 0132 rule 2). Until then both admitted
|
|
307
|
+
// a non-string here, because the validator accepted one (W210's conformity reader, B1). A string outside the charset
|
|
308
|
+
// names no node — every node id is `FD-V16`'s — so `FD-V2` refuses it.
|
|
309
|
+
case "branches":
|
|
310
|
+
return { type: "array", minItems: 2, uniqueItems: true, items: ref("id") };
|
|
311
|
+
case "of":
|
|
312
|
+
return ref("id");
|
|
313
|
+
case "over":
|
|
314
|
+
case "branch":
|
|
315
|
+
return ref("id");
|
|
316
|
+
case "outcome":
|
|
317
|
+
return { type: "string", minLength: 1 };
|
|
318
|
+
case "answerSchema":
|
|
319
|
+
return ref("subsetSchema");
|
|
320
|
+
case "edges": {
|
|
321
|
+
if (kind === "join") return { type: "array", minItems: 1, maxItems: 1, items: ref("joinEdge") };
|
|
322
|
+
if (kind === "gate") return { type: "array", minItems: 1, items: ref("gateEdge") };
|
|
323
|
+
return { type: "array", minItems: 1, items: ref("edge") };
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
throw new Error(`definitionSchema: the "${kind}" kind declares the key "${key}" and no schema is written for it`);
|
|
327
|
+
}
|
|
328
|
+
function edgeKeySchema(key) {
|
|
329
|
+
switch (key) {
|
|
330
|
+
case "to":
|
|
331
|
+
return ref("id");
|
|
332
|
+
case "on":
|
|
333
|
+
return { type: "array", minItems: 1, uniqueItems: true, items: { enum: [...ROUTABLE_STATES] } };
|
|
334
|
+
case "when":
|
|
335
|
+
return ref("when");
|
|
336
|
+
case "needs":
|
|
337
|
+
return ref("edgeNeeds");
|
|
338
|
+
case "route":
|
|
339
|
+
return { type: "string" };
|
|
340
|
+
}
|
|
341
|
+
throw new Error(`definitionSchema: an edge declares the key "${key}" and no schema is written for it`);
|
|
342
|
+
}
|
|
343
|
+
var EDGE_KEYS_BY_SITE = {
|
|
344
|
+
edge: (k) => k !== "route",
|
|
345
|
+
joinEdge: (k) => k !== "route" && k !== "on" && k !== "when",
|
|
346
|
+
gateEdge: (k) => k === "to" || k === "route"
|
|
347
|
+
};
|
|
348
|
+
var SITE_DESCRIPTIONS = {
|
|
349
|
+
edge: "An edge of a task or an ask: { to, on?, when?, needs? }.",
|
|
350
|
+
joinEdge: "A join's one edge: { to, needs? } \u2014 neither `on` nor `when` (FD-V7).",
|
|
351
|
+
gateEdge: "A gate's edge: { to, route? } and nothing else (FD-V41)."
|
|
352
|
+
};
|
|
353
|
+
function edgeSchema(site) {
|
|
354
|
+
const keys = EDGE_KEYS_DECLARED.filter(EDGE_KEYS_BY_SITE[site]);
|
|
355
|
+
return {
|
|
356
|
+
description: SITE_DESCRIPTIONS[site],
|
|
357
|
+
type: "object",
|
|
358
|
+
required: EDGE_KEYS_REQUIRED.filter((k) => keys.includes(k)),
|
|
359
|
+
properties: Object.fromEntries(keys.map((k) => [k, { ...edgeKeySchema(k), description: described(EDGE_DESCRIPTIONS, k, "an edge") }])),
|
|
360
|
+
additionalProperties: false
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
function kindSchema(kind) {
|
|
364
|
+
const keys = NODE_KEYS_DECLARED[kind];
|
|
365
|
+
const required = NODE_KEYS_REQUIRED[kind];
|
|
366
|
+
if (keys === void 0 || required === void 0) throw new Error(`definitionSchema: the validator declares no keys for the kind "${kind}"`);
|
|
367
|
+
const own2 = KIND_DESCRIPTIONS[kind] ?? {};
|
|
368
|
+
return {
|
|
369
|
+
description: described(own2, "kind", `the "${kind}" kind`),
|
|
370
|
+
type: "object",
|
|
371
|
+
required: [...required],
|
|
372
|
+
properties: Object.fromEntries(keys.map((k) => [k, {
|
|
373
|
+
...nodeKeySchema(kind, k),
|
|
374
|
+
description: Object.prototype.hasOwnProperty.call(own2, k) ? own2[k] : described(NODE_DESCRIPTIONS, k, `the "${kind}" kind`)
|
|
375
|
+
}])),
|
|
376
|
+
additionalProperties: false
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
function subsetKeywordSchema(keyword) {
|
|
380
|
+
const nonNegInt = { type: "integer", minimum: 0 };
|
|
381
|
+
switch (keyword) {
|
|
382
|
+
case "type":
|
|
383
|
+
return { anyOf: [{ enum: [...SCHEMA_TYPES] }, { type: "array", minItems: 1, uniqueItems: true, items: { enum: [...SCHEMA_TYPES] } }] };
|
|
384
|
+
case "required":
|
|
385
|
+
return { type: "array", uniqueItems: true, items: { type: "string" } };
|
|
386
|
+
case "properties":
|
|
387
|
+
return { type: "object", additionalProperties: ref("subsetSchema") };
|
|
388
|
+
case "additionalProperties":
|
|
389
|
+
return { type: "boolean" };
|
|
390
|
+
case "enum":
|
|
391
|
+
return { type: "array", minItems: 1 };
|
|
392
|
+
case "const":
|
|
393
|
+
return {};
|
|
394
|
+
case "minimum":
|
|
395
|
+
case "maximum":
|
|
396
|
+
return { type: "number" };
|
|
397
|
+
case "minLength":
|
|
398
|
+
case "maxLength":
|
|
399
|
+
case "minItems":
|
|
400
|
+
return nonNegInt;
|
|
401
|
+
case "items":
|
|
402
|
+
return ref("subsetSchema");
|
|
403
|
+
case "examples":
|
|
404
|
+
return { type: "array", minItems: 1 };
|
|
405
|
+
case "title":
|
|
406
|
+
case "description":
|
|
407
|
+
return { type: "string" };
|
|
408
|
+
case "readOnly":
|
|
409
|
+
case "writeOnly":
|
|
410
|
+
return { type: "boolean" };
|
|
411
|
+
}
|
|
412
|
+
throw new Error(`definitionSchema: the schema subset declares the keyword "${keyword}" and no schema is written for it`);
|
|
413
|
+
}
|
|
414
|
+
function needsSchema(withSelf, description) {
|
|
415
|
+
return {
|
|
416
|
+
description,
|
|
417
|
+
type: "object",
|
|
418
|
+
minProperties: 1,
|
|
419
|
+
propertyNames: ref("id"),
|
|
420
|
+
additionalProperties: ref(withSelf ? "reference" : "edgeReference")
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
function referenceSchema(withSelf, id) {
|
|
424
|
+
const aimed = `${id}(?:${ERROR_PART})?\\??`;
|
|
425
|
+
const tokens = [...withSelf ? ["\\."] : [], "\\$payload", "\\$item", aimed];
|
|
426
|
+
return {
|
|
427
|
+
description: (withSelf ? '"." (what this node would have received), ' : "") + `"$payload" (what the run entered with), "$item" (the item of the map instance containing this node), a node id (that node's output), or a node id followed by "!error" (that node's error, null where it succeeded) \u2014 each node form with an optional "?" last (the node may not have run: absent, not refused), and as a one-element array (every output of that node visible on this node's path, in branch-path order; where each form is legal is FD-V28's) (FD-V26).`,
|
|
428
|
+
anyOf: [
|
|
429
|
+
{ type: "string", pattern: `^(?:${tokens.join("|")})$` },
|
|
430
|
+
{ type: "array", minItems: 1, maxItems: 1, items: { type: "string", pattern: `^${aimed}$` } }
|
|
431
|
+
]
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
function leafSchema(id) {
|
|
435
|
+
const path = `^(?:${PREDICATE_ROOTS.join("|")})(?:\\.${keyPathSegment(id)})+$`;
|
|
436
|
+
const scalar = () => ({ type: ["null", "boolean", "number", "string"] });
|
|
437
|
+
const keySchemas = {
|
|
438
|
+
path: { type: "string", pattern: path },
|
|
439
|
+
op: { enum: [...PREDICATE_OPS] },
|
|
440
|
+
value: scalar(),
|
|
441
|
+
default: { anyOf: [scalar(), { type: "array", items: scalar() }] },
|
|
442
|
+
length: { const: true }
|
|
443
|
+
};
|
|
444
|
+
return {
|
|
445
|
+
description: "A declared comparison over the decision's context.",
|
|
446
|
+
type: "object",
|
|
447
|
+
required: [...PREDICATE_LEAF_REQUIRED],
|
|
448
|
+
properties: Object.fromEntries(PREDICATE_LEAF_KEYS.map((k) => {
|
|
449
|
+
const s = keySchemas[k];
|
|
450
|
+
if (s === void 0) throw new Error(`definitionSchema: a comparison declares the key "${k}" and no schema is written for it`);
|
|
451
|
+
return [k, { ...s, description: described(PREDICATE_DESCRIPTIONS, k, "a comparison") }];
|
|
452
|
+
})),
|
|
453
|
+
additionalProperties: false,
|
|
454
|
+
allOf: [
|
|
455
|
+
// `length: true` compares a length — a number — and a length has no prefix; its default stands in for the value.
|
|
456
|
+
{
|
|
457
|
+
if: { required: ["length"] },
|
|
458
|
+
then: { properties: { value: { type: "number" }, op: { not: { enum: [...STRING_OPS] } }, default: { type: ["array", "string"] } } }
|
|
459
|
+
},
|
|
460
|
+
// with no `length`: an ordering operator compares a number, and a default is a scalar.
|
|
461
|
+
{
|
|
462
|
+
if: { not: { required: ["length"] } },
|
|
463
|
+
then: { properties: { default: scalar() } }
|
|
464
|
+
},
|
|
465
|
+
{
|
|
466
|
+
if: { required: ["op"], properties: { op: { enum: [...NUMERIC_OPS] } } },
|
|
467
|
+
then: { anyOf: [{ required: ["length"] }, { properties: { value: { type: "number" } } }] }
|
|
468
|
+
},
|
|
469
|
+
{
|
|
470
|
+
if: { required: ["op"], properties: { op: { enum: [...STRING_OPS] } } },
|
|
471
|
+
then: { properties: { value: { type: "string" } } }
|
|
472
|
+
}
|
|
473
|
+
]
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
function definitionSchema(registry) {
|
|
477
|
+
if (registry !== void 0) checkRegistry(registry);
|
|
478
|
+
const s = staticSchema();
|
|
479
|
+
if (registry !== void 0) specialise(s, registry);
|
|
480
|
+
return s;
|
|
481
|
+
}
|
|
482
|
+
function staticSchema() {
|
|
483
|
+
const id = body(ID_RE_COPY, "ID_RE");
|
|
484
|
+
body(KEY_PATH_RE, "KEY_PATH_RE");
|
|
485
|
+
const defs = {
|
|
486
|
+
id: { description: "A node id: 1-64 characters from [A-Za-z0-9_-] (FD-V16).", type: "string", pattern: `^${id}$` },
|
|
487
|
+
node: {
|
|
488
|
+
description: `A node: one of ${KINDS_COPY.join(", ")}, told apart by \`kind\`.`,
|
|
489
|
+
type: "object",
|
|
490
|
+
required: ["kind"],
|
|
491
|
+
properties: { kind: { enum: [...KINDS_COPY] } },
|
|
492
|
+
allOf: KINDS_COPY.map((k) => ({ if: { required: ["kind"], properties: { kind: { const: k } } }, then: ref(`${k}Node`) }))
|
|
493
|
+
},
|
|
494
|
+
...Object.fromEntries(KINDS_COPY.map((k) => [`${k}Node`, kindSchema(k)])),
|
|
495
|
+
edge: edgeSchema("edge"),
|
|
496
|
+
joinEdge: edgeSchema("joinEdge"),
|
|
497
|
+
gateEdge: edgeSchema("gateEdge"),
|
|
498
|
+
needs: needsSchema(true, "A node's `needs`: a non-empty object, each key 1-64 characters from [A-Za-z0-9_-], each value a reference (FD-V26)."),
|
|
499
|
+
edgeNeeds: needsSchema(false, "An edge's `needs`: as a node's, minus \".\" \u2014 its predicate already has the outcome (FD-V26)."),
|
|
500
|
+
reference: referenceSchema(true, id),
|
|
501
|
+
edgeReference: referenceSchema(false, id),
|
|
502
|
+
retryPolicy: {
|
|
503
|
+
description: "Exactly the scheduler's shape (FD-V30).",
|
|
504
|
+
type: "object",
|
|
505
|
+
required: [...RETRY_POLICY_KEYS],
|
|
506
|
+
properties: Object.fromEntries(RETRY_POLICY_KEYS.map((k) => [k, {
|
|
507
|
+
...k === "maxRetries" ? { type: "integer", minimum: 0 } : { type: "number", minimum: 0 },
|
|
508
|
+
description: described(RETRY_DESCRIPTIONS, k, "a retryPolicy")
|
|
509
|
+
}])),
|
|
510
|
+
additionalProperties: false
|
|
511
|
+
},
|
|
512
|
+
transform: {
|
|
513
|
+
description: "Exactly { lang, expr }, both strings (FD-V37).",
|
|
514
|
+
type: "object",
|
|
515
|
+
required: [...TRANSFORM_KEYS],
|
|
516
|
+
properties: Object.fromEntries(TRANSFORM_KEYS.map((k) => [k, { type: "string", description: described(TRANSFORM_DESCRIPTIONS, k, "a transform") }])),
|
|
517
|
+
additionalProperties: false
|
|
518
|
+
},
|
|
519
|
+
when: {
|
|
520
|
+
description: "One of three shapes, told apart by its keys (FD-V42): a registered name, a declared comparison, or a flat group.",
|
|
521
|
+
oneOf: [ref("predicateName"), ref("comparison"), ref("group")]
|
|
522
|
+
},
|
|
523
|
+
predicateName: {
|
|
524
|
+
description: "A registered predicate, by name (FD-V4's lookup is validateDefinition's).",
|
|
525
|
+
type: "object",
|
|
526
|
+
required: [...PREDICATE_NAME_KEYS],
|
|
527
|
+
properties: Object.fromEntries(PREDICATE_NAME_KEYS.map((k) => [k, { type: "string", description: described(PREDICATE_DESCRIPTIONS, k, "a predicate name") }])),
|
|
528
|
+
additionalProperties: false
|
|
529
|
+
},
|
|
530
|
+
comparison: leafSchema(id),
|
|
531
|
+
group: {
|
|
532
|
+
description: "A FLAT group \u2014 `all` or `any`, never both, never nested, its members comparisons (FD-V45).",
|
|
533
|
+
oneOf: PREDICATE_GROUP_KEYS.map((k) => ({
|
|
534
|
+
type: "object",
|
|
535
|
+
required: [k],
|
|
536
|
+
properties: { [k]: { type: "array", minItems: 1, items: ref("comparison"), description: described(PREDICATE_DESCRIPTIONS, k, "a group") } },
|
|
537
|
+
additionalProperties: false
|
|
538
|
+
}))
|
|
539
|
+
},
|
|
540
|
+
subsetSchema: {
|
|
541
|
+
description: "A schema in the library's built-in subset (ADR 0053): a plain object using only these keywords \u2014 any other is refused, never ignored (Q278).",
|
|
542
|
+
type: "object",
|
|
543
|
+
properties: Object.fromEntries(SCHEMA_KEYWORDS.map((k) => [k, { ...subsetKeywordSchema(k), description: described(SUBSET_DESCRIPTIONS, k, "the schema subset") }])),
|
|
544
|
+
additionalProperties: false
|
|
545
|
+
}
|
|
546
|
+
};
|
|
547
|
+
return {
|
|
548
|
+
$schema: DRAFT_2020_12,
|
|
549
|
+
title: "FlowDefinition",
|
|
550
|
+
description: "The STATIC SHAPE of a fyflow-orchestration flow definition (spec/flow-definition.md). It carries every rule a node, an edge or a value decides by its own shape, and none that needs another node or a registry: whether a named node exists and what kind it is, reachability, cycles, regions and joins, where a `needs` reference points, and every registered name \u2014 node types, pools, groups, languages, predicates, gate types and their routes and settings. For all of those, and for the definition as a whole, the AUTHORITY is `validateDefinition(flow, registry)` \u2014 and `runtime.check(flow)` on a runtime. A document this schema refuses, validateDefinition refuses; one it accepts may still be refused there.",
|
|
551
|
+
type: "object",
|
|
552
|
+
required: [...DOC_KEYS_DECLARED],
|
|
553
|
+
properties: Object.fromEntries(DOC_KEYS_DECLARED.map((k) => {
|
|
554
|
+
const s = k === "flowId" || k === "entry" ? ref("id") : k === "version" ? { type: "integer", minimum: 1 } : k === "nodes" ? { type: "array", minItems: 1, items: ref("node") } : (() => {
|
|
555
|
+
throw new Error(`definitionSchema: the document declares the key "${k}" and no schema is written for it`);
|
|
556
|
+
})();
|
|
557
|
+
return [k, { ...s, description: described(DOC_DESCRIPTIONS, k, "the document") }];
|
|
558
|
+
})),
|
|
559
|
+
additionalProperties: false,
|
|
560
|
+
$defs: defs
|
|
561
|
+
};
|
|
562
|
+
}
|
|
563
|
+
var REGISTRY_DESCRIPTION = "The SHAPE of a fyflow-orchestration flow definition SPECIALISED TO ONE REGISTRY (spec/flow-definition.md section 1). Beyond the static shape it carries what the registry decides of a node by itself: a task's `type`, one of the registry's node types (FD-V32), and per type its `pool` (the type's own name or one of its named instances, FD-V38), its `settings` held to the type's worker settingsSchema (FD-V33) and, for a type that only transforms, a required `transform` (FD-V46); `workerGroups` from the registry's groups (FD-V31); `transform.lang` from its languages (FD-V35); a predicate NAME from its predicates (FD-V4); a gate's `type`, one of its gate types (FD-V39), and per type its `settings` held to the type's settingsSchema (FD-V40) and, for a STATIC gate type, each edge's `route` one of its routes (FD-V41). It does NOT cleanly carry, and leaves to the authority: FD-V33 over the EFFECTIVE settings \u2014 a node's settings merged over its type's defaults \u2014 so a settingsSchema's `required` is WEAKENED by the keys the defaults supply, and a default's own value and any top-level keyword but properties, required and additionalProperties are unchecked; a `minLength` above 1 inside an embedded registry schema, relaxed to half rounded up, because the registry's schema subset counts a string's UTF-16 units and JSON Schema its code points; a DERIVED gate type's routes, which its routesFor computes from each gate's settings; FD-V41's every route wired EXACTLY ONCE; a gate type's settingsProblem and a language's compile (FD-V36), which are code; a node type's worker inputSchema, which is RUNTIME input and is carried as an ANNOTATION only, at `$defs.inputSchema` in its type's branch; and every rule that needs another node \u2014 existence, kinds, reachability, cycles, regions, joins, where a `needs` reference points. For all of those, and for the definition as a whole, the AUTHORITY is `validateDefinition(flow, registry)` against THIS registry \u2014 and `runtime.check(flow)` on a runtime. A document this schema refuses, validateDefinition refuses against this registry; one it accepts may still be refused there.";
|
|
564
|
+
function relaxed(schema) {
|
|
565
|
+
const walk = (s) => {
|
|
566
|
+
if (typeof s.minLength === "number" && s.minLength > 1) s.minLength = Math.ceil(s.minLength / 2);
|
|
567
|
+
if (isObject(s.properties)) {
|
|
568
|
+
for (const p of Object.values(s.properties)) if (isObject(p)) walk(p);
|
|
569
|
+
}
|
|
570
|
+
if (isObject(s.items)) walk(s.items);
|
|
571
|
+
return s;
|
|
572
|
+
};
|
|
573
|
+
return walk(structuredClone(schema));
|
|
574
|
+
}
|
|
575
|
+
var isObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
576
|
+
var own = (o, k) => Object.prototype.hasOwnProperty.call(o, k);
|
|
577
|
+
var quoted = (names) => [...names].map((n) => JSON.stringify(n)).join(", ");
|
|
578
|
+
function nodeTypeBranch(name, t, workers, pools) {
|
|
579
|
+
const instances = [...pools].filter(([, p]) => p.type === name).map(([k]) => k);
|
|
580
|
+
const workerName = t.worker;
|
|
581
|
+
const worker = typeof workerName === "string" ? workers.get(workerName) : void 0;
|
|
582
|
+
const properties = {
|
|
583
|
+
pool: {
|
|
584
|
+
description: `A pool of "${name}": its own name (the default instance)${instances.length ? ` or a named instance of it \u2014 ${quoted(instances)}` : ""} (FD-V38).`,
|
|
585
|
+
enum: [name, ...instances]
|
|
586
|
+
}
|
|
587
|
+
};
|
|
588
|
+
const required = [];
|
|
589
|
+
const settingsSchema = worker?.settingsSchema;
|
|
590
|
+
if (settingsSchema !== void 0) {
|
|
591
|
+
const defaults = t.settings ?? {};
|
|
592
|
+
const left = (settingsSchema.required ?? []).filter((k) => !own(defaults, k));
|
|
593
|
+
const settings = {
|
|
594
|
+
description: `Settings held to worker "${String(workerName)}"'s settingsSchema, merged OVER the type's defaults` + (Object.keys(defaults).length ? ` (${quoted(Object.keys(defaults))} supplied by them)` : "") + " (FD-V33).",
|
|
595
|
+
type: "object"
|
|
596
|
+
};
|
|
597
|
+
if (isObject(settingsSchema.properties)) {
|
|
598
|
+
settings.properties = Object.fromEntries(Object.entries(settingsSchema.properties).map(([k, p]) => [k, relaxed(p)]));
|
|
599
|
+
}
|
|
600
|
+
if (settingsSchema.additionalProperties === false) settings.additionalProperties = false;
|
|
601
|
+
if (left.length) {
|
|
602
|
+
settings.required = left;
|
|
603
|
+
required.push("settings");
|
|
604
|
+
}
|
|
605
|
+
properties.settings = settings;
|
|
606
|
+
}
|
|
607
|
+
if (onlyTransforms(t)) required.push("transform");
|
|
608
|
+
const branch = {
|
|
609
|
+
description: onlyTransforms(t) ? `A task of the built-in type "${name}": it names no worker and runs only its own \`transform\`, which it must declare (FD-V46).` : `A task of node type "${name}", run by worker "${String(workerName)}".` + (worker?.inputSchema !== void 0 ? " What that worker receives as input is described at $defs.inputSchema here \u2014 an ANNOTATION: it is runtime input, and nothing in a definition is held to it." : ""),
|
|
610
|
+
properties
|
|
611
|
+
};
|
|
612
|
+
if (required.length) branch.required = required;
|
|
613
|
+
if (worker?.inputSchema !== void 0) branch.$defs = { inputSchema: structuredClone(worker.inputSchema) };
|
|
614
|
+
return branch;
|
|
615
|
+
}
|
|
616
|
+
function gateTypeBranch(name, t) {
|
|
617
|
+
const properties = {};
|
|
618
|
+
const branch = { description: "", properties };
|
|
619
|
+
if (t.settingsSchema !== void 0) {
|
|
620
|
+
properties.settings = relaxed(t.settingsSchema);
|
|
621
|
+
if (findings(t.settingsSchema, {}).length > 0) branch.required = ["settings"];
|
|
622
|
+
}
|
|
623
|
+
if (typeof t.routesFor !== "function") {
|
|
624
|
+
const set = routesOf(t, {});
|
|
625
|
+
if ("problem" in set) throw new Error(`definitionSchema: gate type "${name}" resolves no route set: ${set.problem}`);
|
|
626
|
+
properties.edges = {
|
|
627
|
+
items: {
|
|
628
|
+
properties: {
|
|
629
|
+
route: {
|
|
630
|
+
description: `One of "${name}"'s routes \u2014 ${quoted(set.routes)}; an edge with no \`route\` carries its default, "${set.defaultRoute}" (FD-V41).`,
|
|
631
|
+
enum: [...set.routes]
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
};
|
|
636
|
+
branch.description = `A gate of the STATIC gate type "${name}": routes ${quoted(set.routes)}, the default "${set.defaultRoute}". That each is wired exactly once is validateDefinition's (FD-V41).`;
|
|
637
|
+
} else {
|
|
638
|
+
branch.description = `A gate of the DERIVED gate type "${name}": its routes are computed from each gate's settings, so which \`route\` names exist is validateDefinition's (FD-V41).`;
|
|
639
|
+
}
|
|
640
|
+
return branch;
|
|
641
|
+
}
|
|
642
|
+
var branchOn = (key, name, then) => ({ if: { required: [key], properties: { [key]: { const: name } } }, then });
|
|
643
|
+
function specialise(s, registry) {
|
|
644
|
+
const defs = s.$defs;
|
|
645
|
+
const nodeTypes = nodeTypesOf(registry.nodeTypes);
|
|
646
|
+
const workers = workersOf(registry.workers);
|
|
647
|
+
const pools = poolsOf(registry.pools);
|
|
648
|
+
const gateTypes = gateTypesOf(registry.gateTypes);
|
|
649
|
+
const groups = [...new Set(registry.groups ?? [])];
|
|
650
|
+
const predicates = [...new Set(registry.predicates)];
|
|
651
|
+
const languages = [...languagesOf(registry.languages).keys()];
|
|
652
|
+
const task = defs.taskNode;
|
|
653
|
+
task.properties.type = {
|
|
654
|
+
...task.properties.type,
|
|
655
|
+
description: `The node type that runs this task: one of the registry's \u2014 ${quoted(nodeTypes.keys())} (FD-V32). What each type adds is its branch in this node's allOf.`,
|
|
656
|
+
enum: [...nodeTypes.keys()]
|
|
657
|
+
};
|
|
658
|
+
task.properties.workerGroups = {
|
|
659
|
+
...task.properties.workerGroups,
|
|
660
|
+
description: `The resource groups the scheduler holds this task to: a non-empty list of distinct ids of the registry's groups \u2014 ${groups.length ? quoted(groups) : "it declares none"} (FD-V31).`,
|
|
661
|
+
items: { type: "string", enum: groups }
|
|
662
|
+
};
|
|
663
|
+
task.allOf = [...nodeTypes].map(([n, t]) => branchOn("type", n, nodeTypeBranch(n, t, workers, pools)));
|
|
664
|
+
const transform = defs.transform;
|
|
665
|
+
transform.properties.lang = {
|
|
666
|
+
...transform.properties.lang,
|
|
667
|
+
description: `A language the registry declares \u2014 ${languages.length ? quoted(languages) : "it declares none"} (FD-V35). That it compiles \`expr\` is validateDefinition's (FD-V36).`,
|
|
668
|
+
enum: languages
|
|
669
|
+
};
|
|
670
|
+
const predicateName = defs.predicateName;
|
|
671
|
+
predicateName.properties.predicate = {
|
|
672
|
+
...predicateName.properties.predicate,
|
|
673
|
+
description: `A predicate the registry declares \u2014 ${predicates.length ? quoted(predicates) : "it declares none"} (FD-V4).`,
|
|
674
|
+
enum: predicates
|
|
675
|
+
};
|
|
676
|
+
const gate = defs.gateNode;
|
|
677
|
+
gate.properties.type = {
|
|
678
|
+
...gate.properties.type,
|
|
679
|
+
description: `The gate type that decides: one of ${quoted(gateTypes.keys())} \u2014 the built-ins and the registry's \`gateTypes\` (FD-V39). What each adds is its branch in this node's allOf.`,
|
|
680
|
+
enum: [...gateTypes.keys()]
|
|
681
|
+
};
|
|
682
|
+
gate.allOf = [...gateTypes].map(([g, t]) => branchOn("type", g, gateTypeBranch(g, t)));
|
|
683
|
+
s.description = REGISTRY_DESCRIPTION;
|
|
684
|
+
}
|
|
149
685
|
|
|
150
686
|
// src/definition/assist.ts
|
|
151
687
|
var TYPES = ["object", "array", "string", "number", "integer", "boolean", "null"];
|
|
@@ -260,11 +796,11 @@ function object(s, indent) {
|
|
|
260
796
|
const req = new Set(s.required ?? []);
|
|
261
797
|
const named = [...props.map(([k]) => k)];
|
|
262
798
|
const all = [...props, ...[...req].filter((k) => !named.includes(k)).map((k) => [k, {}])];
|
|
263
|
-
const
|
|
799
|
+
const body2 = all.map(([k, sub]) => `${indent} ${lit(k)}${req.has(k) ? "" : "?"}: ${tsTypeOf(sub, `${indent} `)};`).join("\n");
|
|
264
800
|
const rest = closed ? "" : `
|
|
265
801
|
${indent} [k: string]: unknown;`;
|
|
266
802
|
return `{
|
|
267
|
-
${
|
|
803
|
+
${body2}${rest}
|
|
268
804
|
${indent}}`;
|
|
269
805
|
}
|
|
270
806
|
function signatureOf(name, worker) {
|
|
@@ -300,23 +836,28 @@ export {
|
|
|
300
836
|
ConfigRefused,
|
|
301
837
|
DECLARED_POOL_KEYS,
|
|
302
838
|
DOCUMENT_KEYS,
|
|
839
|
+
DOC_KEYS_DECLARED,
|
|
303
840
|
DerivationRefused,
|
|
304
841
|
Driver,
|
|
305
842
|
DuplicateTaskId,
|
|
306
843
|
EDGE_KEYS_DECLARED,
|
|
844
|
+
EDGE_KEYS_REQUIRED,
|
|
307
845
|
GATE_TYPE_KEYS,
|
|
308
846
|
GateTypeRefused,
|
|
309
847
|
GroupConfigRefused,
|
|
310
848
|
GroupTypeMissing,
|
|
849
|
+
ID_RE_COPY as ID_RE,
|
|
311
850
|
INSTANCE_KEYS,
|
|
312
851
|
InvalidDefinition,
|
|
313
852
|
InvalidRunId,
|
|
314
853
|
InvalidTaskId,
|
|
315
854
|
KEY_PATH_RE,
|
|
855
|
+
KINDS_COPY as KINDS,
|
|
316
856
|
MESSAGE_OPTION_KEYS,
|
|
317
857
|
MissingJoinPolicy,
|
|
318
858
|
MultipleRuns,
|
|
319
859
|
NODE_KEYS_DECLARED,
|
|
860
|
+
NODE_KEYS_REQUIRED,
|
|
320
861
|
NODE_TYPE_DECLARATION_KEYS,
|
|
321
862
|
NameCollision,
|
|
322
863
|
NameMissing,
|
|
@@ -334,6 +875,7 @@ export {
|
|
|
334
875
|
PREDICATE_ROOTS,
|
|
335
876
|
PoolTypeMissing,
|
|
336
877
|
RETRY_POLICY_KEYS,
|
|
878
|
+
ROUTABLE_STATES,
|
|
337
879
|
RegistryError,
|
|
338
880
|
ResumeRefused,
|
|
339
881
|
RunControlRefused,
|
|
@@ -371,6 +913,7 @@ export {
|
|
|
371
913
|
checkRegistry,
|
|
372
914
|
checkWiring,
|
|
373
915
|
compileProblem,
|
|
916
|
+
definitionSchema,
|
|
374
917
|
derivePool,
|
|
375
918
|
describeFindings,
|
|
376
919
|
describePaths,
|