@sanity/workflow-engine 0.12.0 → 0.14.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/README.md +30 -0
- package/dist/_chunks-cjs/schema.cjs +809 -119
- package/dist/_chunks-cjs/schema.cjs.map +1 -1
- package/dist/_chunks-es/schema.js +810 -120
- package/dist/_chunks-es/schema.js.map +1 -1
- package/dist/define.cjs +384 -140
- package/dist/define.cjs.map +1 -1
- package/dist/define.d.cts +1996 -11940
- package/dist/define.d.ts +1996 -11940
- package/dist/define.js +385 -140
- package/dist/define.js.map +1 -1
- package/dist/index.cjs +2724 -2064
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4759 -18067
- package/dist/index.d.ts +4759 -18067
- package/dist/index.js +2766 -2106
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/define.cjs
CHANGED
|
@@ -36,28 +36,28 @@ function desugarWorkflow(authoring) {
|
|
|
36
36
|
claimFields: /* @__PURE__ */ new Map(),
|
|
37
37
|
claimedFields: /* @__PURE__ */ new Set(),
|
|
38
38
|
roleAliases
|
|
39
|
-
}, workflowFields = desugarFieldEntries(authoring.fields, ["fields"], ctx), workflowLayer = layerOf(workflowFields), stages = authoring.stages.map((stage, i) => {
|
|
40
|
-
const path = ["stages", i], stageFields = desugarFieldEntries(stage.fields, [...path, "fields"], ctx), stageEnv = {
|
|
39
|
+
}, workflowFields = desugarFieldEntries({ entries: authoring.fields, path: ["fields"], ctx }), workflowLayer = layerOf(workflowFields), stages = authoring.stages.map((stage, i) => {
|
|
40
|
+
const path = ["stages", i], stageFields = desugarFieldEntries({ entries: stage.fields, path: [...path, "fields"], ctx }), stageEnv = {
|
|
41
41
|
layers: [
|
|
42
42
|
{ scope: "stage", entries: layerOf(stageFields) },
|
|
43
43
|
{ scope: "workflow", entries: workflowLayer }
|
|
44
44
|
]
|
|
45
45
|
}, activities = (stage.activities ?? []).map(
|
|
46
|
-
(activity, j) => desugarActivity(activity, [...path, "activities", j], stageEnv, ctx)
|
|
46
|
+
(activity, j) => desugarActivity({ activity, path: [...path, "activities", j], stageEnv, ctx })
|
|
47
47
|
), transitions = (stage.transitions ?? []).map(
|
|
48
|
-
(transition, k) => desugarTransition(transition, [...path, "transitions", k], stageEnv, ctx)
|
|
49
|
-
), editable = desugarStageEditable(
|
|
50
|
-
stage.editable,
|
|
51
|
-
|
|
52
|
-
[...path, "editable"],
|
|
48
|
+
(transition, k) => desugarTransition({ transition, path: [...path, "transitions", k], stageEnv, ctx })
|
|
49
|
+
), editable = desugarStageEditable({
|
|
50
|
+
overrides: stage.editable,
|
|
51
|
+
inScope: editableFieldNames({ workflowFields, stageFields, activities }),
|
|
52
|
+
path: [...path, "editable"],
|
|
53
53
|
ctx
|
|
54
|
-
);
|
|
54
|
+
});
|
|
55
55
|
return {
|
|
56
56
|
...stripUndefined({
|
|
57
57
|
name: stage.name,
|
|
58
58
|
title: stage.title,
|
|
59
59
|
description: stage.description,
|
|
60
|
-
guards: stage.guards
|
|
60
|
+
guards: stage.guards?.map(desugarGuard)
|
|
61
61
|
}),
|
|
62
62
|
...stageFields ? { fields: stageFields } : {},
|
|
63
63
|
...activities.length > 0 ? { activities } : {},
|
|
@@ -70,7 +70,7 @@ function desugarWorkflow(authoring) {
|
|
|
70
70
|
name: authoring.name,
|
|
71
71
|
title: authoring.title,
|
|
72
72
|
description: authoring.description,
|
|
73
|
-
|
|
73
|
+
lifecycle: authoring.lifecycle,
|
|
74
74
|
initialStage: authoring.initialStage,
|
|
75
75
|
predicates: authoring.predicates,
|
|
76
76
|
roleAliases
|
|
@@ -96,13 +96,22 @@ const TODOLIST_OF = [
|
|
|
96
96
|
{ type: "actor", name: "actor", title: "Actor" },
|
|
97
97
|
{ type: "datetime", name: "at", title: "At" }
|
|
98
98
|
];
|
|
99
|
-
function desugarFieldEntries(
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
99
|
+
function desugarFieldEntries({
|
|
100
|
+
entries,
|
|
101
|
+
path,
|
|
102
|
+
ctx
|
|
103
|
+
}) {
|
|
104
|
+
return !entries || entries.length === 0 ? entries === void 0 ? void 0 : [] : entries.map((entry, i) => desugarFieldEntry({ entry, path: [...path, i], ctx }));
|
|
105
|
+
}
|
|
106
|
+
function desugarFieldEntry({
|
|
107
|
+
entry,
|
|
108
|
+
path,
|
|
109
|
+
ctx
|
|
110
|
+
}) {
|
|
111
|
+
if (entry.type === "claim") return desugarClaimField({ entry, path, ctx });
|
|
112
|
+
if (entry.type === "todoList" || entry.type === "notes")
|
|
113
|
+
return desugarListField({ entry, path, ctx });
|
|
114
|
+
const editable = normalizeEditable({ editable: entry.editable, path: [...path, "editable"], ctx });
|
|
106
115
|
return {
|
|
107
116
|
...stripUndefined({
|
|
108
117
|
type: entry.type,
|
|
@@ -117,15 +126,23 @@ function desugarFieldEntry(entry, path, ctx) {
|
|
|
117
126
|
})
|
|
118
127
|
};
|
|
119
128
|
}
|
|
120
|
-
function desugarClaimField(
|
|
129
|
+
function desugarClaimField({
|
|
130
|
+
entry,
|
|
131
|
+
path,
|
|
132
|
+
ctx
|
|
133
|
+
}) {
|
|
121
134
|
const desugared = {
|
|
122
135
|
...stripUndefined({ name: entry.name, title: entry.title, description: entry.description }),
|
|
123
136
|
type: "actor"
|
|
124
137
|
};
|
|
125
138
|
return ctx.claimFields.set(desugared, { name: entry.name, path }), desugared;
|
|
126
139
|
}
|
|
127
|
-
function desugarListField(
|
|
128
|
-
|
|
140
|
+
function desugarListField({
|
|
141
|
+
entry,
|
|
142
|
+
path,
|
|
143
|
+
ctx
|
|
144
|
+
}) {
|
|
145
|
+
const editable = normalizeEditable({ editable: entry.editable, path: [...path, "editable"], ctx });
|
|
129
146
|
return {
|
|
130
147
|
...stripUndefined({
|
|
131
148
|
name: entry.name,
|
|
@@ -139,14 +156,18 @@ function desugarListField(entry, path, ctx) {
|
|
|
139
156
|
of: entry.type === "todoList" ? TODOLIST_OF : NOTES_OF
|
|
140
157
|
};
|
|
141
158
|
}
|
|
142
|
-
function normalizeEditable(
|
|
159
|
+
function normalizeEditable({
|
|
160
|
+
editable,
|
|
161
|
+
path,
|
|
162
|
+
ctx
|
|
163
|
+
}) {
|
|
143
164
|
if (editable === void 0 || editable === !0) return editable;
|
|
144
165
|
if (Array.isArray(editable)) {
|
|
145
166
|
const condition = rolesCondition(editable, ctx.roleAliases);
|
|
146
167
|
if (condition === void 0) {
|
|
147
168
|
ctx.issues.push({
|
|
148
169
|
path,
|
|
149
|
-
message: "editable: [] names no roles \u2014 use `true` to open the
|
|
170
|
+
message: "editable: [] names no roles \u2014 use `true` to open the field to anyone in its scope, or list at least one role"
|
|
150
171
|
});
|
|
151
172
|
return;
|
|
152
173
|
}
|
|
@@ -154,7 +175,11 @@ function normalizeEditable(editable, path, ctx) {
|
|
|
154
175
|
}
|
|
155
176
|
return editable;
|
|
156
177
|
}
|
|
157
|
-
function
|
|
178
|
+
function editableFieldNames({
|
|
179
|
+
workflowFields,
|
|
180
|
+
stageFields,
|
|
181
|
+
activities
|
|
182
|
+
}) {
|
|
158
183
|
const names = /* @__PURE__ */ new Set(), collect = (entries) => {
|
|
159
184
|
for (const entry of entries ?? []) entry.editable !== void 0 && names.add(entry.name);
|
|
160
185
|
};
|
|
@@ -162,18 +187,23 @@ function editableSlotNames(workflowFields, stageFields, activities) {
|
|
|
162
187
|
for (const activity of activities) collect(activity.fields);
|
|
163
188
|
return names;
|
|
164
189
|
}
|
|
165
|
-
function desugarStageEditable(
|
|
190
|
+
function desugarStageEditable({
|
|
191
|
+
overrides,
|
|
192
|
+
inScope,
|
|
193
|
+
path,
|
|
194
|
+
ctx
|
|
195
|
+
}) {
|
|
166
196
|
if (overrides === void 0) return;
|
|
167
197
|
const out = {};
|
|
168
198
|
for (const [name, value] of Object.entries(overrides)) {
|
|
169
199
|
if (!inScope.has(name)) {
|
|
170
200
|
ctx.issues.push({
|
|
171
201
|
path: [...path, name],
|
|
172
|
-
message: `stage editable override "${name}" does not narrow an editable
|
|
202
|
+
message: `stage editable override "${name}" does not narrow an editable field in scope \u2014 name a workflow/stage/activity field of this stage that declares \`editable\``
|
|
173
203
|
});
|
|
174
204
|
continue;
|
|
175
205
|
}
|
|
176
|
-
const normalized = normalizeEditable(value, [...path, name], ctx);
|
|
206
|
+
const normalized = normalizeEditable({ editable: value, path: [...path, name], ctx });
|
|
177
207
|
normalized !== void 0 && (out[name] = normalized);
|
|
178
208
|
}
|
|
179
209
|
return Object.keys(out).length > 0 ? out : void 0;
|
|
@@ -181,12 +211,27 @@ function desugarStageEditable(overrides, inScope, path, ctx) {
|
|
|
181
211
|
function layerOf(entries) {
|
|
182
212
|
return new Map((entries ?? []).map((entry) => [entry.name, entry]));
|
|
183
213
|
}
|
|
184
|
-
function desugarActivity(
|
|
185
|
-
|
|
214
|
+
function desugarActivity({
|
|
215
|
+
activity,
|
|
216
|
+
path,
|
|
217
|
+
stageEnv,
|
|
218
|
+
ctx
|
|
219
|
+
}) {
|
|
220
|
+
const activityFields = desugarFieldEntries({
|
|
221
|
+
entries: activity.fields,
|
|
222
|
+
path: [...path, "fields"],
|
|
223
|
+
ctx
|
|
224
|
+
}), env = {
|
|
186
225
|
layers: [{ scope: "activity", entries: layerOf(activityFields) }, ...stageEnv.layers]
|
|
187
|
-
}, ops = desugarOps(
|
|
188
|
-
|
|
189
|
-
|
|
226
|
+
}, ops = desugarOps({
|
|
227
|
+
ops: activity.ops,
|
|
228
|
+
path: [...path, "ops"],
|
|
229
|
+
env,
|
|
230
|
+
firingActivity: activity.name,
|
|
231
|
+
ctx
|
|
232
|
+
}), actions = (activity.actions ?? []).map(
|
|
233
|
+
(action, a) => desugarAction({ action, path: [...path, "actions", a], env, activityName: activity.name, ctx })
|
|
234
|
+
), target = desugarTarget({ target: activity.target, env, path: [...path, "target"], ctx });
|
|
190
235
|
return {
|
|
191
236
|
...stripUndefined({
|
|
192
237
|
name: activity.name,
|
|
@@ -208,18 +253,29 @@ function desugarActivity(activity, path, stageEnv, ctx) {
|
|
|
208
253
|
};
|
|
209
254
|
}
|
|
210
255
|
const TARGET_DOC_KINDS = ["doc.ref", "doc.refs", "release.ref"];
|
|
211
|
-
function desugarTarget(
|
|
256
|
+
function desugarTarget({
|
|
257
|
+
target,
|
|
258
|
+
env,
|
|
259
|
+
path,
|
|
260
|
+
ctx
|
|
261
|
+
}) {
|
|
212
262
|
if (target === void 0 || target.type === "url") return target;
|
|
213
|
-
const ref = typeof target.field == "string" ? { field: target.field } : target.field, field = resolveRef(ref, env, [...path, "field"], ctx) ?? fallbackRef(ref), entry = entryAt(env, field);
|
|
263
|
+
const ref = typeof target.field == "string" ? { field: target.field } : target.field, field = resolveRef({ ref, env, path: [...path, "field"], ctx }) ?? fallbackRef(ref), entry = entryAt(env, field);
|
|
214
264
|
return entry && !TARGET_DOC_KINDS.includes(entry.type) && ctx.issues.push({
|
|
215
265
|
path: [...path, "field"],
|
|
216
266
|
message: `manual activity target references "${field.field}" of kind "${entry.type}" \u2014 a deep-link target needs a document-valued entry (${TARGET_DOC_KINDS.join(", ")})`
|
|
217
267
|
}), { type: "field", field };
|
|
218
268
|
}
|
|
219
|
-
function desugarAction(
|
|
269
|
+
function desugarAction({
|
|
270
|
+
action,
|
|
271
|
+
path,
|
|
272
|
+
env,
|
|
273
|
+
activityName,
|
|
274
|
+
ctx
|
|
275
|
+
}) {
|
|
220
276
|
if ("type" in action)
|
|
221
|
-
return desugarClaimAction(action, path, env, ctx);
|
|
222
|
-
const filter = schema.andConditions([rolesCondition(action.roles, ctx.roleAliases), action.filter]), ops = desugarOps(action.ops, [...path, "ops"], env, activityName, ctx) ?? [];
|
|
277
|
+
return desugarClaimAction({ action, path, env, ctx });
|
|
278
|
+
const filter = schema.andConditions([rolesCondition(action.roles, ctx.roleAliases), action.filter]), ops = desugarOps({ ops: action.ops, path: [...path, "ops"], env, firingActivity: activityName, ctx }) ?? [];
|
|
223
279
|
return action.status !== void 0 && ops.push({ type: "status.set", activity: activityName, status: action.status }), {
|
|
224
280
|
...stripUndefined({
|
|
225
281
|
name: action.name,
|
|
@@ -232,14 +288,26 @@ function desugarAction(action, path, env, activityName, ctx) {
|
|
|
232
288
|
...ops.length > 0 ? { ops } : {}
|
|
233
289
|
};
|
|
234
290
|
}
|
|
235
|
-
function desugarClaimAction(
|
|
236
|
-
|
|
291
|
+
function desugarClaimAction({
|
|
292
|
+
action,
|
|
293
|
+
path,
|
|
294
|
+
env,
|
|
295
|
+
ctx
|
|
296
|
+
}) {
|
|
297
|
+
const ref = typeof action.field == "string" ? { field: action.field } : action.field, resolved = resolveRef({ ref, env, path: [...path, "field"], ctx });
|
|
237
298
|
if (resolved) {
|
|
238
299
|
const entry = entryAt(env, resolved);
|
|
239
300
|
entry && entry.type !== "actor" && ctx.issues.push({
|
|
240
301
|
path: [...path, "field"],
|
|
241
302
|
message: `claim action "${action.name}" references "${resolved.field}" of kind "${entry.type}" \u2014 a claim pair needs an actor-valued entry (a "claim" or "actor" field declaration)`
|
|
242
|
-
}), checkShadowedClaimTarget(
|
|
303
|
+
}), checkShadowedClaimTarget({
|
|
304
|
+
actionName: action.name,
|
|
305
|
+
field: ref.field,
|
|
306
|
+
resolved,
|
|
307
|
+
env,
|
|
308
|
+
path: [...path, "field"],
|
|
309
|
+
ctx
|
|
310
|
+
}), entry && ctx.claimedFields.add(entry);
|
|
243
311
|
}
|
|
244
312
|
const noSteal = `!defined($fields.${ref.field})`, filter = schema.andConditions([
|
|
245
313
|
noSteal,
|
|
@@ -258,7 +326,14 @@ function desugarClaimAction(action, path, env, ctx) {
|
|
|
258
326
|
...ops.length > 0 ? { ops } : {}
|
|
259
327
|
};
|
|
260
328
|
}
|
|
261
|
-
function checkShadowedClaimTarget(
|
|
329
|
+
function checkShadowedClaimTarget({
|
|
330
|
+
actionName,
|
|
331
|
+
field,
|
|
332
|
+
resolved,
|
|
333
|
+
env,
|
|
334
|
+
path,
|
|
335
|
+
ctx
|
|
336
|
+
}) {
|
|
262
337
|
const nearest = env.layers.find((l) => l.entries.has(field));
|
|
263
338
|
nearest === void 0 || nearest.scope === resolved.scope || ctx.issues.push({
|
|
264
339
|
path,
|
|
@@ -272,8 +347,19 @@ function checkUnclaimedClaimFields(ctx) {
|
|
|
272
347
|
message: `claim field "${name}" is never referenced by a claim action \u2014 you announced the pattern and wrote half of it. Declare a defineAction({ type: "claim", field: "${name}" }) or use a raw actor entry`
|
|
273
348
|
});
|
|
274
349
|
}
|
|
275
|
-
function desugarTransition(
|
|
276
|
-
|
|
350
|
+
function desugarTransition({
|
|
351
|
+
transition,
|
|
352
|
+
path,
|
|
353
|
+
stageEnv,
|
|
354
|
+
ctx
|
|
355
|
+
}) {
|
|
356
|
+
const ops = desugarOps({
|
|
357
|
+
ops: transition.ops,
|
|
358
|
+
path: [...path, "ops"],
|
|
359
|
+
env: stageEnv,
|
|
360
|
+
firingActivity: void 0,
|
|
361
|
+
ctx
|
|
362
|
+
});
|
|
277
363
|
return {
|
|
278
364
|
...stripUndefined({
|
|
279
365
|
name: transition.name,
|
|
@@ -286,11 +372,38 @@ function desugarTransition(transition, path, stageEnv, ctx) {
|
|
|
286
372
|
...ops ? { ops } : {}
|
|
287
373
|
};
|
|
288
374
|
}
|
|
289
|
-
function
|
|
290
|
-
|
|
291
|
-
|
|
375
|
+
function desugarGuard(guard) {
|
|
376
|
+
const { match, metadata, ...rest } = guard, { idRefs, ...matchRest } = match;
|
|
377
|
+
return {
|
|
378
|
+
...rest,
|
|
379
|
+
match: {
|
|
380
|
+
...matchRest,
|
|
381
|
+
...idRefs !== void 0 ? { idRefs: idRefs.map(schema.printGuardRead) } : {}
|
|
382
|
+
},
|
|
383
|
+
...metadata !== void 0 ? {
|
|
384
|
+
metadata: Object.fromEntries(
|
|
385
|
+
Object.entries(metadata).map(([key, read]) => [key, schema.printGuardRead(read)])
|
|
386
|
+
)
|
|
387
|
+
} : {}
|
|
388
|
+
};
|
|
292
389
|
}
|
|
293
|
-
function
|
|
390
|
+
function desugarOps({
|
|
391
|
+
ops,
|
|
392
|
+
path,
|
|
393
|
+
env,
|
|
394
|
+
firingActivity,
|
|
395
|
+
ctx
|
|
396
|
+
}) {
|
|
397
|
+
if (ops)
|
|
398
|
+
return ops.map((op, i) => desugarOp({ op, path: [...path, i], env, firingActivity, ctx }));
|
|
399
|
+
}
|
|
400
|
+
function desugarOp({
|
|
401
|
+
op,
|
|
402
|
+
path,
|
|
403
|
+
env,
|
|
404
|
+
firingActivity,
|
|
405
|
+
ctx
|
|
406
|
+
}) {
|
|
294
407
|
if (op.type === "status.set") {
|
|
295
408
|
const activity = op.activity ?? firingActivity;
|
|
296
409
|
return activity === void 0 && ctx.issues.push({
|
|
@@ -298,13 +411,18 @@ function desugarOp(op, path, env, firingActivity, ctx) {
|
|
|
298
411
|
message: "status.set outside an action must name its target activity"
|
|
299
412
|
}), { type: "status.set", activity: activity ?? "", status: op.status };
|
|
300
413
|
}
|
|
301
|
-
if (op.type === "audit") return desugarAuditOp(op, path, env, ctx);
|
|
302
|
-
const target = resolveRef(op.target, env, [...path, "target"], ctx) ?? fallbackRef(op.target);
|
|
414
|
+
if (op.type === "audit") return desugarAuditOp({ op, path, env, ctx });
|
|
415
|
+
const target = resolveRef({ ref: op.target, env, path: [...path, "target"], ctx }) ?? fallbackRef(op.target);
|
|
303
416
|
return { ...op, target };
|
|
304
417
|
}
|
|
305
418
|
const AUDIT_STAMPS = { actor: { type: "actor" }, at: { type: "now" } };
|
|
306
|
-
function desugarAuditOp(
|
|
307
|
-
|
|
419
|
+
function desugarAuditOp({
|
|
420
|
+
op,
|
|
421
|
+
path,
|
|
422
|
+
env,
|
|
423
|
+
ctx
|
|
424
|
+
}) {
|
|
425
|
+
const target = resolveRef({ ref: op.target, env, path: [...path, "target"], ctx }) ?? fallbackRef(op.target);
|
|
308
426
|
if (op.value.type !== "object")
|
|
309
427
|
return ctx.issues.push({
|
|
310
428
|
path: [...path, "value"],
|
|
@@ -326,7 +444,12 @@ function desugarAuditOp(op, path, env, ctx) {
|
|
|
326
444
|
}
|
|
327
445
|
return { type: "field.append", target, value: { type: "object", fields } };
|
|
328
446
|
}
|
|
329
|
-
function resolveRef(
|
|
447
|
+
function resolveRef({
|
|
448
|
+
ref,
|
|
449
|
+
env,
|
|
450
|
+
path,
|
|
451
|
+
ctx
|
|
452
|
+
}) {
|
|
330
453
|
const layers = ref.scope === void 0 ? env.layers : env.layers.filter((l) => l.scope === ref.scope);
|
|
331
454
|
for (const layer of layers)
|
|
332
455
|
if (layer.entries.has(ref.field)) return { scope: layer.scope, field: ref.field };
|
|
@@ -352,91 +475,109 @@ function stripUndefined(obj) {
|
|
|
352
475
|
value !== void 0 && (out[k] = value);
|
|
353
476
|
return out;
|
|
354
477
|
}
|
|
355
|
-
const
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
"assigned",
|
|
359
|
-
"can",
|
|
360
|
-
"row",
|
|
361
|
-
"now",
|
|
362
|
-
"effects",
|
|
363
|
-
"activities",
|
|
364
|
-
"subworkflows",
|
|
365
|
-
"self",
|
|
366
|
-
"stage",
|
|
367
|
-
"parent",
|
|
368
|
-
"ancestors",
|
|
369
|
-
"allActivitiesDone",
|
|
370
|
-
"anyActivityFailed"
|
|
371
|
-
], PREDICATE_CALLER_VARS = ["actor", "assigned", "can"];
|
|
478
|
+
const PREDICATE_CALLER_VARS = schema.CONDITION_VARS.filter((v2) => v2.binding === "caller").map(
|
|
479
|
+
(v2) => v2.name
|
|
480
|
+
);
|
|
372
481
|
function knownList(ids) {
|
|
373
482
|
return [...ids].map((s) => `"${s}"`).join(", ");
|
|
374
483
|
}
|
|
375
|
-
function checkDuplicates(
|
|
484
|
+
function checkDuplicates({
|
|
485
|
+
names,
|
|
486
|
+
what,
|
|
487
|
+
issues
|
|
488
|
+
}) {
|
|
376
489
|
const seen = /* @__PURE__ */ new Set();
|
|
377
490
|
for (const { name, path } of names)
|
|
378
491
|
seen.has(name) && issues.push({ path, message: `duplicate ${what} "${name}" (already declared earlier)` }), seen.add(name);
|
|
379
492
|
return seen;
|
|
380
493
|
}
|
|
381
494
|
function checkStages(def, issues) {
|
|
382
|
-
const stageNames = checkDuplicates(
|
|
383
|
-
def.stages.map((stage, i) => ({ name: stage.name, path: ["stages", i, "name"] })),
|
|
384
|
-
"stage name",
|
|
495
|
+
const stageNames = checkDuplicates({
|
|
496
|
+
names: def.stages.map((stage, i) => ({ name: stage.name, path: ["stages", i, "name"] })),
|
|
497
|
+
what: "stage name",
|
|
385
498
|
issues
|
|
386
|
-
);
|
|
499
|
+
});
|
|
387
500
|
for (const [i, stage] of def.stages.entries()) {
|
|
388
|
-
const activityNames = checkDuplicates(
|
|
389
|
-
(stage.activities ?? []).map((activity, j) => ({
|
|
501
|
+
const activityNames = checkDuplicates({
|
|
502
|
+
names: (stage.activities ?? []).map((activity, j) => ({
|
|
390
503
|
name: activity.name,
|
|
391
504
|
path: ["stages", i, "activities", j, "name"]
|
|
392
505
|
})),
|
|
393
|
-
`activity name in stage "${stage.name}"`,
|
|
506
|
+
what: `activity name in stage "${stage.name}"`,
|
|
394
507
|
issues
|
|
395
|
-
);
|
|
396
|
-
checkDuplicates(
|
|
397
|
-
(stage.transitions ?? []).map((t, k) => ({
|
|
508
|
+
});
|
|
509
|
+
checkDuplicates({
|
|
510
|
+
names: (stage.transitions ?? []).map((t, k) => ({
|
|
398
511
|
name: t.name,
|
|
399
512
|
path: ["stages", i, "transitions", k, "name"]
|
|
400
513
|
})),
|
|
401
|
-
`transition name in stage "${stage.name}"`,
|
|
514
|
+
what: `transition name in stage "${stage.name}"`,
|
|
402
515
|
issues
|
|
403
|
-
), checkActivities(def, i, activityNames, issues);
|
|
516
|
+
}), checkActivities({ def, i, activityNames, issues });
|
|
404
517
|
}
|
|
405
518
|
return stageNames;
|
|
406
519
|
}
|
|
407
|
-
function checkActivities(
|
|
520
|
+
function checkActivities({
|
|
521
|
+
def,
|
|
522
|
+
i,
|
|
523
|
+
activityNames,
|
|
524
|
+
issues
|
|
525
|
+
}) {
|
|
408
526
|
const stage = def.stages[i];
|
|
409
527
|
for (const [j, activity] of (stage.activities ?? []).entries()) {
|
|
410
528
|
const path = ["stages", i, "activities", j];
|
|
411
|
-
checkDuplicates(
|
|
412
|
-
(activity.actions ?? []).map((action, a) => ({
|
|
529
|
+
checkDuplicates({
|
|
530
|
+
names: (activity.actions ?? []).map((action, a) => ({
|
|
413
531
|
name: action.name,
|
|
414
532
|
path: [...path, "actions", a, "name"]
|
|
415
533
|
})),
|
|
416
|
-
`action name in activity "${activity.name}"`,
|
|
534
|
+
what: `action name in activity "${activity.name}"`,
|
|
417
535
|
issues
|
|
418
|
-
), checkStatusSetTargets(activity, activityNames, path, issues);
|
|
536
|
+
}), checkStatusSetTargets({ activity, activityNames, path, issues });
|
|
419
537
|
}
|
|
420
538
|
}
|
|
421
|
-
function checkStatusSetTargets(
|
|
422
|
-
|
|
539
|
+
function checkStatusSetTargets({
|
|
540
|
+
activity,
|
|
541
|
+
activityNames,
|
|
542
|
+
path,
|
|
543
|
+
issues
|
|
544
|
+
}) {
|
|
545
|
+
checkStatusSetOps({ ops: activity.ops, activityNames, path: [...path, "ops"], issues });
|
|
423
546
|
for (const [a, action] of (activity.actions ?? []).entries())
|
|
424
|
-
checkStatusSetOps(
|
|
547
|
+
checkStatusSetOps({
|
|
548
|
+
ops: action.ops,
|
|
549
|
+
activityNames,
|
|
550
|
+
path: [...path, "actions", a, "ops"],
|
|
551
|
+
issues
|
|
552
|
+
});
|
|
425
553
|
}
|
|
426
|
-
function checkStatusSetOps(
|
|
554
|
+
function checkStatusSetOps({
|
|
555
|
+
ops,
|
|
556
|
+
activityNames,
|
|
557
|
+
path,
|
|
558
|
+
issues
|
|
559
|
+
}) {
|
|
427
560
|
for (const [o, op] of (ops ?? []).entries())
|
|
428
561
|
op.type !== "status.set" || activityNames.has(op.activity) || issues.push({
|
|
429
562
|
path: [...path, o, "activity"],
|
|
430
563
|
message: `status.set targets activity "${op.activity}" which is not declared in this stage. Known activities: ${knownList(activityNames)}`
|
|
431
564
|
});
|
|
432
565
|
}
|
|
433
|
-
function checkInitialStage(
|
|
566
|
+
function checkInitialStage({
|
|
567
|
+
def,
|
|
568
|
+
stageNames,
|
|
569
|
+
issues
|
|
570
|
+
}) {
|
|
434
571
|
stageNames.has(def.initialStage) || issues.push({
|
|
435
572
|
path: ["initialStage"],
|
|
436
573
|
message: `initialStage "${def.initialStage}" is not a declared stage. Known stages: ${knownList(stageNames)}`
|
|
437
574
|
});
|
|
438
575
|
}
|
|
439
|
-
function checkTransitionTargets(
|
|
576
|
+
function checkTransitionTargets({
|
|
577
|
+
def,
|
|
578
|
+
stageNames,
|
|
579
|
+
issues
|
|
580
|
+
}) {
|
|
440
581
|
for (const [i, stage] of def.stages.entries())
|
|
441
582
|
for (const [k, t] of (stage.transitions ?? []).entries())
|
|
442
583
|
stageNames.has(t.to) || issues.push({
|
|
@@ -448,20 +589,32 @@ function checkEffectNames(def, issues) {
|
|
|
448
589
|
const sites = [];
|
|
449
590
|
for (const [i, stage] of def.stages.entries()) {
|
|
450
591
|
for (const [j, activity] of (stage.activities ?? []).entries()) {
|
|
451
|
-
collectEffects(
|
|
592
|
+
collectEffects({
|
|
593
|
+
effects: activity.effects,
|
|
594
|
+
path: ["stages", i, "activities", j, "effects"],
|
|
595
|
+
sites
|
|
596
|
+
});
|
|
452
597
|
for (const [a, action] of (activity.actions ?? []).entries())
|
|
453
|
-
collectEffects(
|
|
454
|
-
action.effects,
|
|
455
|
-
["stages", i, "activities", j, "actions", a, "effects"],
|
|
598
|
+
collectEffects({
|
|
599
|
+
effects: action.effects,
|
|
600
|
+
path: ["stages", i, "activities", j, "actions", a, "effects"],
|
|
456
601
|
sites
|
|
457
|
-
);
|
|
602
|
+
});
|
|
458
603
|
}
|
|
459
604
|
for (const [k, t] of (stage.transitions ?? []).entries())
|
|
460
|
-
collectEffects(t.effects, ["stages", i, "transitions", k, "effects"], sites);
|
|
605
|
+
collectEffects({ effects: t.effects, path: ["stages", i, "transitions", k, "effects"], sites });
|
|
461
606
|
}
|
|
462
|
-
checkDuplicates(
|
|
607
|
+
checkDuplicates({
|
|
608
|
+
names: sites,
|
|
609
|
+
what: "effect name (registry key \u2014 unique per definition)",
|
|
610
|
+
issues
|
|
611
|
+
});
|
|
463
612
|
}
|
|
464
|
-
function collectEffects(
|
|
613
|
+
function collectEffects({
|
|
614
|
+
effects,
|
|
615
|
+
path,
|
|
616
|
+
sites
|
|
617
|
+
}) {
|
|
465
618
|
for (const [e, effect] of (effects ?? []).entries())
|
|
466
619
|
sites.push({ name: effect.name, path: [...path, e, "name"] });
|
|
467
620
|
}
|
|
@@ -472,11 +625,11 @@ function checkGuardNames(def, issues) {
|
|
|
472
625
|
path: ["stages", i, "guards", g, "name"]
|
|
473
626
|
}))
|
|
474
627
|
);
|
|
475
|
-
checkDuplicates(
|
|
476
|
-
sites,
|
|
477
|
-
"guard name (the guard lake _id derives from it \u2014 unique per definition)",
|
|
628
|
+
checkDuplicates({
|
|
629
|
+
names: sites,
|
|
630
|
+
what: "guard name (the guard lake _id derives from it \u2014 unique per definition)",
|
|
478
631
|
issues
|
|
479
|
-
);
|
|
632
|
+
});
|
|
480
633
|
}
|
|
481
634
|
function fieldScopes(def) {
|
|
482
635
|
const scopes = [
|
|
@@ -519,23 +672,28 @@ function checkRequiredField(def, issues) {
|
|
|
519
672
|
}
|
|
520
673
|
function checkFieldEntryNames(def, issues) {
|
|
521
674
|
for (const { entries, path, label } of fieldScopes(def))
|
|
522
|
-
checkDuplicates(
|
|
523
|
-
(entries ?? []).map((entry, n) => ({ name: entry.name, path: [...path, n, "name"] })),
|
|
524
|
-
`field entry name in ${label}`,
|
|
675
|
+
checkDuplicates({
|
|
676
|
+
names: (entries ?? []).map((entry, n) => ({ name: entry.name, path: [...path, n, "name"] })),
|
|
677
|
+
what: `field entry name in ${label}`,
|
|
525
678
|
issues
|
|
526
|
-
);
|
|
679
|
+
});
|
|
527
680
|
}
|
|
528
681
|
function checkPredicates(def, issues) {
|
|
529
|
-
const reserved = new Set(RESERVED_CONDITION_VARS), names = Object.keys(def.predicates ?? {});
|
|
682
|
+
const reserved = new Set(schema.RESERVED_CONDITION_VARS), names = Object.keys(def.predicates ?? {});
|
|
530
683
|
for (const name of names)
|
|
531
684
|
reserved.has(name) && issues.push({
|
|
532
685
|
path: ["predicates", name],
|
|
533
686
|
message: `predicate "${name}" shadows the built-in $${name} \u2014 pick another name`
|
|
534
687
|
});
|
|
535
688
|
for (const [name, groq2] of Object.entries(def.predicates ?? {}))
|
|
536
|
-
checkPredicateBody(name, groq2, names, issues);
|
|
537
|
-
}
|
|
538
|
-
function checkPredicateBody(
|
|
689
|
+
checkPredicateBody({ name, groq: groq2, names, issues });
|
|
690
|
+
}
|
|
691
|
+
function checkPredicateBody({
|
|
692
|
+
name,
|
|
693
|
+
groq: groq2,
|
|
694
|
+
names,
|
|
695
|
+
issues
|
|
696
|
+
}) {
|
|
539
697
|
for (const caller of PREDICATE_CALLER_VARS)
|
|
540
698
|
referencesVar(groq2, caller) && issues.push({
|
|
541
699
|
path: ["predicates", name],
|
|
@@ -565,33 +723,74 @@ function nonActionFilterConditionSites(def) {
|
|
|
565
723
|
groq: t.filter,
|
|
566
724
|
path: ["stages", i, "transitions", k, "filter"],
|
|
567
725
|
label: `transition "${t.name}" filter`
|
|
568
|
-
}), collectBindingSites(
|
|
569
|
-
t.effects,
|
|
570
|
-
["stages", i, "transitions", k, "effects"],
|
|
571
|
-
`transition "${t.name}"`,
|
|
726
|
+
}), collectBindingSites({
|
|
727
|
+
effects: t.effects,
|
|
728
|
+
path: ["stages", i, "transitions", k, "effects"],
|
|
729
|
+
label: `transition "${t.name}"`,
|
|
730
|
+
sites
|
|
731
|
+
}), collectOpWhereSites({
|
|
732
|
+
ops: t.ops,
|
|
733
|
+
path: ["stages", i, "transitions", k, "ops"],
|
|
734
|
+
label: `transition "${t.name}"`,
|
|
572
735
|
sites
|
|
573
|
-
);
|
|
736
|
+
});
|
|
574
737
|
for (const [j, activity] of (stage.activities ?? []).entries())
|
|
575
|
-
collectActivityConditionSites(activity, ["stages", i, "activities", j], sites);
|
|
738
|
+
collectActivityConditionSites({ activity, path: ["stages", i, "activities", j], sites });
|
|
576
739
|
}
|
|
577
740
|
return sites;
|
|
578
741
|
}
|
|
579
|
-
function
|
|
742
|
+
function collectOpWhereSites({
|
|
743
|
+
ops,
|
|
744
|
+
path,
|
|
745
|
+
label,
|
|
746
|
+
sites
|
|
747
|
+
}) {
|
|
748
|
+
for (const [o, op] of (ops ?? []).entries())
|
|
749
|
+
op.where !== void 0 && sites.push({
|
|
750
|
+
groq: op.where,
|
|
751
|
+
path: [...path, o, "where"],
|
|
752
|
+
label: `${label} ${op.type} where`
|
|
753
|
+
});
|
|
754
|
+
}
|
|
755
|
+
function collectActivityConditionSites({
|
|
756
|
+
activity,
|
|
757
|
+
path,
|
|
758
|
+
sites
|
|
759
|
+
}) {
|
|
580
760
|
for (const field of ["filter", "completeWhen", "failWhen"]) {
|
|
581
761
|
const groq2 = activity[field];
|
|
582
762
|
groq2 !== void 0 && sites.push({ groq: groq2, path: [...path, field], label: `activity "${activity.name}".${field}` });
|
|
583
763
|
}
|
|
584
|
-
collectBindingSites(
|
|
764
|
+
collectBindingSites({
|
|
765
|
+
effects: activity.effects,
|
|
766
|
+
path: [...path, "effects"],
|
|
767
|
+
label: `activity "${activity.name}"`,
|
|
768
|
+
sites
|
|
769
|
+
}), collectOpWhereSites({
|
|
770
|
+
ops: activity.ops,
|
|
771
|
+
path: [...path, "ops"],
|
|
772
|
+
label: `activity "${activity.name}"`,
|
|
773
|
+
sites
|
|
774
|
+
});
|
|
585
775
|
for (const [a, action] of (activity.actions ?? []).entries())
|
|
586
|
-
collectBindingSites(
|
|
587
|
-
action.effects,
|
|
588
|
-
[...path, "actions", a, "effects"],
|
|
589
|
-
`action "${action.name}"`,
|
|
776
|
+
collectBindingSites({
|
|
777
|
+
effects: action.effects,
|
|
778
|
+
path: [...path, "actions", a, "effects"],
|
|
779
|
+
label: `action "${action.name}"`,
|
|
590
780
|
sites
|
|
591
|
-
)
|
|
592
|
-
|
|
781
|
+
}), collectOpWhereSites({
|
|
782
|
+
ops: action.ops,
|
|
783
|
+
path: [...path, "actions", a, "ops"],
|
|
784
|
+
label: `action "${action.name}"`,
|
|
785
|
+
sites
|
|
786
|
+
});
|
|
787
|
+
collectSubworkflowSites({ activity, path, sites });
|
|
593
788
|
}
|
|
594
|
-
function collectSubworkflowSites(
|
|
789
|
+
function collectSubworkflowSites({
|
|
790
|
+
activity,
|
|
791
|
+
path,
|
|
792
|
+
sites
|
|
793
|
+
}) {
|
|
595
794
|
const sub = activity.subworkflows;
|
|
596
795
|
if (sub === void 0) return;
|
|
597
796
|
const subPath = [...path, "subworkflows"];
|
|
@@ -611,7 +810,12 @@ function collectSubworkflowSites(activity, path, sites) {
|
|
|
611
810
|
label: `activity "${activity.name}".subworkflows.${group} "${key}"`
|
|
612
811
|
});
|
|
613
812
|
}
|
|
614
|
-
function collectBindingSites(
|
|
813
|
+
function collectBindingSites({
|
|
814
|
+
effects,
|
|
815
|
+
path,
|
|
816
|
+
label,
|
|
817
|
+
sites
|
|
818
|
+
}) {
|
|
615
819
|
for (const [e, effect] of (effects ?? []).entries())
|
|
616
820
|
for (const [key, groq2] of Object.entries(effect.bindings ?? {}))
|
|
617
821
|
sites.push({
|
|
@@ -669,36 +873,67 @@ function checkActivityKinds(def, issues) {
|
|
|
669
873
|
}
|
|
670
874
|
function checkWorkflowInvariants(def) {
|
|
671
875
|
const issues = [], stageNames = checkStages(def, issues);
|
|
672
|
-
return checkInitialStage(def, stageNames, issues), checkTransitionTargets(def, stageNames, issues), checkEffectNames(def, issues), checkGuardNames(def, issues), checkFieldEntryNames(def, issues), checkRequiredField(def, issues), checkPredicates(def, issues), checkCanOutsideActionFilters(def, issues), checkAssigneesEntries(def, issues), checkActivityKinds(def, issues), issues;
|
|
876
|
+
return checkInitialStage({ def, stageNames, issues }), checkTransitionTargets({ def, stageNames, issues }), checkEffectNames(def, issues), checkGuardNames(def, issues), checkFieldEntryNames(def, issues), checkRequiredField(def, issues), checkPredicates(def, issues), checkCanOutsideActionFilters(def, issues), checkAssigneesEntries(def, issues), checkActivityKinds(def, issues), issues;
|
|
673
877
|
}
|
|
674
878
|
function defineWorkflow(definition) {
|
|
675
|
-
const label = labelFor("defineWorkflow", definition), parsed = parseOrThrow(schema.AuthoringWorkflowSchema, definition, label), { definition: stored, issues: desugarIssues } = desugarWorkflow(parsed), issues = [...desugarIssues, ...checkWorkflowInvariants(stored)];
|
|
879
|
+
const label = labelFor("defineWorkflow", definition), parsed = parseOrThrow({ schema: schema.AuthoringWorkflowSchema, input: definition, label }), { definition: stored, issues: desugarIssues } = desugarWorkflow(parsed), issues = [...desugarIssues, ...checkWorkflowInvariants(stored)];
|
|
676
880
|
if (issues.length > 0) throw new Error(schema.formatValidationError(label, issues));
|
|
677
881
|
return stored;
|
|
678
882
|
}
|
|
883
|
+
function defineWorkflowConfig(config) {
|
|
884
|
+
return parseOrThrow({ schema: schema.WorkflowConfigSchema, input: config, label: "defineWorkflowConfig" });
|
|
885
|
+
}
|
|
679
886
|
function defineStage(stage) {
|
|
680
|
-
return parseOrThrow(
|
|
887
|
+
return parseOrThrow({
|
|
888
|
+
schema: schema.AuthoringStageSchema,
|
|
889
|
+
input: stage,
|
|
890
|
+
label: labelFor("defineStage", stage)
|
|
891
|
+
});
|
|
681
892
|
}
|
|
682
893
|
function defineActivity(activity) {
|
|
683
|
-
return parseOrThrow(
|
|
894
|
+
return parseOrThrow({
|
|
895
|
+
schema: schema.AuthoringActivitySchema,
|
|
896
|
+
input: activity,
|
|
897
|
+
label: labelFor("defineActivity", activity)
|
|
898
|
+
});
|
|
684
899
|
}
|
|
685
900
|
function defineAction(action) {
|
|
686
|
-
return parseOrThrow(
|
|
901
|
+
return parseOrThrow({
|
|
902
|
+
schema: schema.AuthoringActionSchema,
|
|
903
|
+
input: action,
|
|
904
|
+
label: labelFor("defineAction", action)
|
|
905
|
+
});
|
|
687
906
|
}
|
|
688
907
|
function defineTransition(transition) {
|
|
689
|
-
return parseOrThrow(
|
|
908
|
+
return parseOrThrow({
|
|
909
|
+
schema: schema.AuthoringTransitionSchema,
|
|
910
|
+
input: transition,
|
|
911
|
+
label: transitionLabel(transition)
|
|
912
|
+
});
|
|
690
913
|
}
|
|
691
914
|
function defineField(entry) {
|
|
692
|
-
return parseOrThrow(
|
|
915
|
+
return parseOrThrow({
|
|
916
|
+
schema: schema.AuthoringFieldEntrySchema,
|
|
917
|
+
input: entry,
|
|
918
|
+
label: labelFor("defineField", entry)
|
|
919
|
+
});
|
|
693
920
|
}
|
|
694
921
|
function defineOp(op) {
|
|
695
|
-
return parseOrThrow(schema.AuthoringOpSchema, op, "defineOp");
|
|
922
|
+
return parseOrThrow({ schema: schema.AuthoringOpSchema, input: op, label: "defineOp" });
|
|
696
923
|
}
|
|
697
924
|
function defineGuard(guard) {
|
|
698
|
-
return parseOrThrow(
|
|
925
|
+
return parseOrThrow({
|
|
926
|
+
schema: schema.AuthoringGuardSchema,
|
|
927
|
+
input: guard,
|
|
928
|
+
label: labelFor("defineGuard", guard)
|
|
929
|
+
});
|
|
699
930
|
}
|
|
700
931
|
function defineEffect(effect) {
|
|
701
|
-
return parseOrThrow(
|
|
932
|
+
return parseOrThrow({
|
|
933
|
+
schema: schema.EffectSchema,
|
|
934
|
+
input: effect,
|
|
935
|
+
label: labelFor("defineEffect", effect)
|
|
936
|
+
});
|
|
702
937
|
}
|
|
703
938
|
function transitionLabel(transition) {
|
|
704
939
|
const { name, to } = transition;
|
|
@@ -708,7 +943,11 @@ function defineEffectDescriptor(descriptor) {
|
|
|
708
943
|
if (!descriptor.name) throw new Error("EffectDescriptor missing name");
|
|
709
944
|
return descriptor;
|
|
710
945
|
}
|
|
711
|
-
function parseOrThrow(
|
|
946
|
+
function parseOrThrow({
|
|
947
|
+
schema: schema$1,
|
|
948
|
+
input,
|
|
949
|
+
label
|
|
950
|
+
}) {
|
|
712
951
|
const result = v__namespace.safeParse(schema$1, input);
|
|
713
952
|
if (!result.success)
|
|
714
953
|
throw new Error(schema.formatValidationError(label, schema.issuesFromValibot(result.issues)));
|
|
@@ -721,6 +960,10 @@ function labelFor(fn, value) {
|
|
|
721
960
|
}
|
|
722
961
|
return fn;
|
|
723
962
|
}
|
|
963
|
+
exports.CONDITION_VARS = schema.CONDITION_VARS;
|
|
964
|
+
exports.FILTER_SCOPE_VARS = schema.FILTER_SCOPE_VARS;
|
|
965
|
+
exports.GUARD_PREDICATE_VARS = schema.GUARD_PREDICATE_VARS;
|
|
966
|
+
exports.RESERVED_CONDITION_VARS = schema.RESERVED_CONDITION_VARS;
|
|
724
967
|
exports.defineAction = defineAction;
|
|
725
968
|
exports.defineActivity = defineActivity;
|
|
726
969
|
exports.defineEffect = defineEffect;
|
|
@@ -731,5 +974,6 @@ exports.defineOp = defineOp;
|
|
|
731
974
|
exports.defineStage = defineStage;
|
|
732
975
|
exports.defineTransition = defineTransition;
|
|
733
976
|
exports.defineWorkflow = defineWorkflow;
|
|
977
|
+
exports.defineWorkflowConfig = defineWorkflowConfig;
|
|
734
978
|
exports.groq = groq;
|
|
735
979
|
//# sourceMappingURL=define.cjs.map
|