@sanity/workflow-engine 0.9.0 → 0.11.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/dist/_chunks-cjs/schema.cjs +94 -58
- package/dist/_chunks-cjs/schema.cjs.map +1 -1
- package/dist/_chunks-es/schema.js +94 -58
- package/dist/_chunks-es/schema.js.map +1 -1
- package/dist/define.cjs +109 -58
- package/dist/define.cjs.map +1 -1
- package/dist/define.d.cts +762 -384
- package/dist/define.d.ts +762 -384
- package/dist/define.js +110 -59
- package/dist/define.js.map +1 -1
- package/dist/index.cjs +290 -237
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1481 -765
- package/dist/index.d.ts +1481 -765
- package/dist/index.js +291 -238
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/define.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as v from "valibot";
|
|
2
|
-
import { andConditions, expandRequiredRoles, GROQ_IDENTIFIER, formatValidationError, issuesFromValibot, AuthoringWorkflowSchema, AuthoringStageSchema, AuthoringTaskSchema, AuthoringActionSchema, AuthoringTransitionSchema,
|
|
2
|
+
import { andConditions, expandRequiredRoles, GROQ_IDENTIFIER, formatValidationError, issuesFromValibot, AuthoringWorkflowSchema, AuthoringStageSchema, AuthoringTaskSchema, AuthoringActionSchema, AuthoringTransitionSchema, AuthoringFieldEntrySchema, AuthoringOpSchema, GuardSchema, EffectSchema } from "./_chunks-es/schema.js";
|
|
3
3
|
function groq(strings, ...values) {
|
|
4
4
|
return strings.reduce((out, part, i) => i === 0 ? part : `${out}${serializeGroqValue(values[i - 1])}${part}`, "");
|
|
5
5
|
}
|
|
@@ -14,13 +14,13 @@ function serializeGroqValue(value) {
|
|
|
14
14
|
function desugarWorkflow(authoring) {
|
|
15
15
|
const ctx = {
|
|
16
16
|
issues: [],
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
claimFields: /* @__PURE__ */ new Map(),
|
|
18
|
+
claimedFields: /* @__PURE__ */ new Set(),
|
|
19
19
|
roleAliases: authoring.roleAliases
|
|
20
|
-
},
|
|
21
|
-
const path = ["stages", i],
|
|
20
|
+
}, workflowFields = desugarFieldEntries(authoring.fields, ["fields"], ctx), workflowLayer = layerOf(workflowFields), stages = authoring.stages.map((stage, i) => {
|
|
21
|
+
const path = ["stages", i], stageFields = desugarFieldEntries(stage.fields, [...path, "fields"], ctx), stageEnv = {
|
|
22
22
|
layers: [
|
|
23
|
-
{ scope: "stage", entries: layerOf(
|
|
23
|
+
{ scope: "stage", entries: layerOf(stageFields) },
|
|
24
24
|
{ scope: "workflow", entries: workflowLayer }
|
|
25
25
|
]
|
|
26
26
|
}, tasks = (stage.tasks ?? []).map(
|
|
@@ -29,7 +29,7 @@ function desugarWorkflow(authoring) {
|
|
|
29
29
|
(transition, k) => desugarTransition(transition, [...path, "transitions", k], stageEnv, ctx)
|
|
30
30
|
), editable = desugarStageEditable(
|
|
31
31
|
stage.editable,
|
|
32
|
-
editableSlotNames(
|
|
32
|
+
editableSlotNames(workflowFields, stageFields, tasks),
|
|
33
33
|
[...path, "editable"],
|
|
34
34
|
ctx
|
|
35
35
|
);
|
|
@@ -40,13 +40,13 @@ function desugarWorkflow(authoring) {
|
|
|
40
40
|
description: stage.description,
|
|
41
41
|
guards: stage.guards
|
|
42
42
|
}),
|
|
43
|
-
...
|
|
43
|
+
...stageFields ? { fields: stageFields } : {},
|
|
44
44
|
...tasks.length > 0 ? { tasks } : {},
|
|
45
45
|
...transitions.length > 0 ? { transitions } : {},
|
|
46
46
|
...editable ? { editable } : {}
|
|
47
47
|
};
|
|
48
48
|
});
|
|
49
|
-
return
|
|
49
|
+
return checkUnclaimedClaimFields(ctx), { definition: {
|
|
50
50
|
...stripUndefined({
|
|
51
51
|
name: authoring.name,
|
|
52
52
|
version: authoring.version,
|
|
@@ -57,11 +57,11 @@ function desugarWorkflow(authoring) {
|
|
|
57
57
|
predicates: authoring.predicates,
|
|
58
58
|
roleAliases: authoring.roleAliases
|
|
59
59
|
}),
|
|
60
|
-
...
|
|
60
|
+
...workflowFields ? { fields: workflowFields } : {},
|
|
61
61
|
stages
|
|
62
62
|
}, issues: ctx.issues };
|
|
63
63
|
}
|
|
64
|
-
function
|
|
64
|
+
function desugarFieldEntries(entries, path, ctx) {
|
|
65
65
|
return !entries || entries.length === 0 ? entries === void 0 ? void 0 : [] : entries.map((entry, i) => {
|
|
66
66
|
if (entry.type === "claim") {
|
|
67
67
|
const desugared = {
|
|
@@ -69,7 +69,7 @@ function desugarStateEntries(entries, path, ctx) {
|
|
|
69
69
|
type: "value.actor",
|
|
70
70
|
source: { type: "write" }
|
|
71
71
|
};
|
|
72
|
-
return ctx.
|
|
72
|
+
return ctx.claimFields.set(desugared, { name: entry.name, path: [...path, i] }), desugared;
|
|
73
73
|
}
|
|
74
74
|
const editable = normalizeEditable(entry.editable, [...path, i, "editable"], ctx);
|
|
75
75
|
return {
|
|
@@ -100,12 +100,12 @@ function normalizeEditable(editable, path, ctx) {
|
|
|
100
100
|
}
|
|
101
101
|
return editable;
|
|
102
102
|
}
|
|
103
|
-
function editableSlotNames(
|
|
103
|
+
function editableSlotNames(workflowFields, stageFields, tasks) {
|
|
104
104
|
const names = /* @__PURE__ */ new Set(), collect = (entries) => {
|
|
105
105
|
for (const entry of entries ?? []) entry.editable !== void 0 && names.add(entry.name);
|
|
106
106
|
};
|
|
107
|
-
collect(
|
|
108
|
-
for (const task of tasks) collect(task.
|
|
107
|
+
collect(workflowFields), collect(stageFields);
|
|
108
|
+
for (const task of tasks) collect(task.fields);
|
|
109
109
|
return names;
|
|
110
110
|
}
|
|
111
111
|
function desugarStageEditable(overrides, inScope, path, ctx) {
|
|
@@ -128,16 +128,17 @@ function layerOf(entries) {
|
|
|
128
128
|
return new Map((entries ?? []).map((entry) => [entry.name, entry]));
|
|
129
129
|
}
|
|
130
130
|
function desugarTask(task, path, stageEnv, ctx) {
|
|
131
|
-
const
|
|
132
|
-
layers: [{ scope: "task", entries: layerOf(
|
|
131
|
+
const taskFields = desugarFieldEntries(task.fields, [...path, "fields"], ctx), env = {
|
|
132
|
+
layers: [{ scope: "task", entries: layerOf(taskFields) }, ...stageEnv.layers]
|
|
133
133
|
}, ops = desugarOps(task.ops, [...path, "ops"], env, task.name, ctx), actions = (task.actions ?? []).map(
|
|
134
134
|
(action, a) => desugarAction(action, [...path, "actions", a], env, task.name, ctx)
|
|
135
|
-
);
|
|
135
|
+
), target = desugarTarget(task.target, env, [...path, "target"], ctx);
|
|
136
136
|
return {
|
|
137
137
|
...stripUndefined({
|
|
138
138
|
name: task.name,
|
|
139
139
|
title: task.title,
|
|
140
140
|
description: task.description,
|
|
141
|
+
kind: task.kind,
|
|
141
142
|
filter: task.filter,
|
|
142
143
|
requirements: task.requirements,
|
|
143
144
|
completeWhen: task.completeWhen,
|
|
@@ -146,11 +147,21 @@ function desugarTask(task, path, stageEnv, ctx) {
|
|
|
146
147
|
subworkflows: task.subworkflows
|
|
147
148
|
}),
|
|
148
149
|
activation: task.activation ?? "manual",
|
|
149
|
-
...
|
|
150
|
+
...target ? { target } : {},
|
|
151
|
+
...taskFields ? { fields: taskFields } : {},
|
|
150
152
|
...ops ? { ops } : {},
|
|
151
153
|
...actions.length > 0 ? { actions } : {}
|
|
152
154
|
};
|
|
153
155
|
}
|
|
156
|
+
const TARGET_DOC_KINDS = ["doc.ref", "doc.refs", "release.ref"];
|
|
157
|
+
function desugarTarget(target, env, path, ctx) {
|
|
158
|
+
if (target === void 0 || target.type === "url") return target;
|
|
159
|
+
const ref = typeof target.field == "string" ? { field: target.field } : target.field, field = resolveRef(ref, env, [...path, "field"], ctx) ?? fallbackRef(ref), entry = entryAt(env, field);
|
|
160
|
+
return entry && !TARGET_DOC_KINDS.includes(entry.type) && ctx.issues.push({
|
|
161
|
+
path: [...path, "field"],
|
|
162
|
+
message: `manual task target references "${field.field}" of kind "${entry.type}" \u2014 a deep-link target needs a document-valued entry (${TARGET_DOC_KINDS.join(", ")})`
|
|
163
|
+
}), { type: "field", field };
|
|
164
|
+
}
|
|
154
165
|
function desugarAction(action, path, env, taskName, ctx) {
|
|
155
166
|
if ("type" in action)
|
|
156
167
|
return desugarClaimAction(action, path, env, ctx);
|
|
@@ -168,19 +179,19 @@ function desugarAction(action, path, env, taskName, ctx) {
|
|
|
168
179
|
};
|
|
169
180
|
}
|
|
170
181
|
function desugarClaimAction(action, path, env, ctx) {
|
|
171
|
-
const ref = typeof action.
|
|
182
|
+
const ref = typeof action.field == "string" ? { field: action.field } : action.field, resolved = resolveRef(ref, env, [...path, "field"], ctx);
|
|
172
183
|
if (resolved) {
|
|
173
184
|
const entry = entryAt(env, resolved);
|
|
174
185
|
entry && entry.type !== "value.actor" && ctx.issues.push({
|
|
175
|
-
path: [...path, "
|
|
176
|
-
message: `claim action "${action.name}" references "${resolved.
|
|
177
|
-
}), checkShadowedClaimTarget(action.name, ref.
|
|
186
|
+
path: [...path, "field"],
|
|
187
|
+
message: `claim action "${action.name}" references "${resolved.field}" of kind "${entry.type}" \u2014 a claim pair needs an actor-valued entry (a "claim" or "value.actor" field declaration)`
|
|
188
|
+
}), checkShadowedClaimTarget(action.name, ref.field, resolved, env, [...path, "field"], ctx), entry && ctx.claimedFields.add(entry);
|
|
178
189
|
}
|
|
179
|
-
const noSteal = `!defined($
|
|
190
|
+
const noSteal = `!defined($fields.${ref.field})`, filter = andConditions([
|
|
180
191
|
noSteal,
|
|
181
192
|
rolesCondition(action.roles, ctx.roleAliases),
|
|
182
193
|
action.filter
|
|
183
|
-
]), ops = resolved ? [{ type: "
|
|
194
|
+
]), ops = resolved ? [{ type: "field.set", target: resolved, value: { type: "actor" } }] : [];
|
|
184
195
|
return {
|
|
185
196
|
...stripUndefined({
|
|
186
197
|
name: action.name,
|
|
@@ -193,18 +204,18 @@ function desugarClaimAction(action, path, env, ctx) {
|
|
|
193
204
|
...ops.length > 0 ? { ops } : {}
|
|
194
205
|
};
|
|
195
206
|
}
|
|
196
|
-
function checkShadowedClaimTarget(actionName,
|
|
197
|
-
const nearest = env.layers.find((l) => l.entries.has(
|
|
207
|
+
function checkShadowedClaimTarget(actionName, field, resolved, env, path, ctx) {
|
|
208
|
+
const nearest = env.layers.find((l) => l.entries.has(field));
|
|
198
209
|
nearest === void 0 || nearest.scope === resolved.scope || ctx.issues.push({
|
|
199
210
|
path,
|
|
200
|
-
message: `claim action "${actionName}" targets "${
|
|
211
|
+
message: `claim action "${actionName}" targets "${field}" at scope "${resolved.scope}", but a nearer ${nearest.scope}-scope entry of the same name shadows it in $fields \u2014 the no-steal filter would read the shadowing entry while the claim writes the "${resolved.scope}" one. Rename one of the entries or claim the nearer one`
|
|
201
212
|
});
|
|
202
213
|
}
|
|
203
|
-
function
|
|
204
|
-
for (const [entry, { name, path }] of ctx.
|
|
205
|
-
ctx.
|
|
214
|
+
function checkUnclaimedClaimFields(ctx) {
|
|
215
|
+
for (const [entry, { name, path }] of ctx.claimFields)
|
|
216
|
+
ctx.claimedFields.has(entry) || ctx.issues.push({
|
|
206
217
|
path,
|
|
207
|
-
message: `claim
|
|
218
|
+
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 value.actor entry`
|
|
208
219
|
});
|
|
209
220
|
}
|
|
210
221
|
function desugarTransition(transition, path, stageEnv, ctx) {
|
|
@@ -244,7 +255,7 @@ function desugarAuditOp(op, path, env, ctx) {
|
|
|
244
255
|
return ctx.issues.push({
|
|
245
256
|
path: [...path, "value"],
|
|
246
257
|
message: `audit value must be an object source carrying the domain fields (got "${op.value.type}")`
|
|
247
|
-
}), { type: "
|
|
258
|
+
}), { type: "field.append", target, value: op.value };
|
|
248
259
|
const actorField = op.stampFields?.actor ?? "actor", atField = op.stampFields?.at ?? "at", fields = { ...op.value.fields };
|
|
249
260
|
for (const [stamp, source] of [
|
|
250
261
|
[actorField, AUDIT_STAMPS.actor],
|
|
@@ -259,23 +270,23 @@ function desugarAuditOp(op, path, env, ctx) {
|
|
|
259
270
|
}
|
|
260
271
|
fields[stamp] = source;
|
|
261
272
|
}
|
|
262
|
-
return { type: "
|
|
273
|
+
return { type: "field.append", target, value: { type: "object", fields } };
|
|
263
274
|
}
|
|
264
275
|
function resolveRef(ref, env, path, ctx) {
|
|
265
276
|
const layers = ref.scope === void 0 ? env.layers : env.layers.filter((l) => l.scope === ref.scope);
|
|
266
277
|
for (const layer of layers)
|
|
267
|
-
if (layer.entries.has(ref.
|
|
278
|
+
if (layer.entries.has(ref.field)) return { scope: layer.scope, field: ref.field };
|
|
268
279
|
const reachable = env.layers.flatMap((l) => [...l.entries.keys()].map((n) => `${l.scope}:${n}`));
|
|
269
280
|
ctx.issues.push({
|
|
270
281
|
path,
|
|
271
|
-
message: `
|
|
282
|
+
message: `field reference "${ref.field}"${ref.scope ? ` (scope "${ref.scope}")` : ""} does not resolve to a declared entry. Reachable: ${reachable.join(", ") || "(none)"}`
|
|
272
283
|
});
|
|
273
284
|
}
|
|
274
285
|
function entryAt(env, ref) {
|
|
275
|
-
return env.layers.find((l) => l.scope === ref.scope)?.entries.get(ref.
|
|
286
|
+
return env.layers.find((l) => l.scope === ref.scope)?.entries.get(ref.field);
|
|
276
287
|
}
|
|
277
288
|
function fallbackRef(ref) {
|
|
278
|
-
return { scope: ref.scope ?? "workflow",
|
|
289
|
+
return { scope: ref.scope ?? "workflow", field: ref.field };
|
|
279
290
|
}
|
|
280
291
|
function rolesCondition(roles, aliases) {
|
|
281
292
|
if (!(!roles || roles.length === 0))
|
|
@@ -288,7 +299,7 @@ function stripUndefined(obj) {
|
|
|
288
299
|
return out;
|
|
289
300
|
}
|
|
290
301
|
const RESERVED_CONDITION_VARS = [
|
|
291
|
-
"
|
|
302
|
+
"fields",
|
|
292
303
|
"actor",
|
|
293
304
|
"assigned",
|
|
294
305
|
"can",
|
|
@@ -409,43 +420,43 @@ function checkGuardNames(def, issues) {
|
|
|
409
420
|
issues
|
|
410
421
|
);
|
|
411
422
|
}
|
|
412
|
-
function
|
|
423
|
+
function fieldScopes(def) {
|
|
413
424
|
const scopes = [
|
|
414
|
-
{ entries: def.
|
|
425
|
+
{ entries: def.fields, scope: "workflow", path: ["fields"], label: "workflow fields" }
|
|
415
426
|
];
|
|
416
427
|
for (const [i, stage] of def.stages.entries()) {
|
|
417
428
|
scopes.push({
|
|
418
|
-
entries: stage.
|
|
429
|
+
entries: stage.fields,
|
|
419
430
|
scope: "stage",
|
|
420
|
-
path: ["stages", i, "
|
|
421
|
-
label: `stage "${stage.name}"
|
|
431
|
+
path: ["stages", i, "fields"],
|
|
432
|
+
label: `stage "${stage.name}" fields`
|
|
422
433
|
});
|
|
423
434
|
for (const [j, task] of (stage.tasks ?? []).entries())
|
|
424
435
|
scopes.push({
|
|
425
|
-
entries: task.
|
|
436
|
+
entries: task.fields,
|
|
426
437
|
scope: "task",
|
|
427
|
-
path: ["stages", i, "tasks", j, "
|
|
428
|
-
label: `task "${task.name}"
|
|
438
|
+
path: ["stages", i, "tasks", j, "fields"],
|
|
439
|
+
label: `task "${task.name}" fields`
|
|
429
440
|
});
|
|
430
441
|
}
|
|
431
442
|
return scopes;
|
|
432
443
|
}
|
|
433
|
-
function
|
|
434
|
-
for (const { entries, scope, path, label } of
|
|
444
|
+
function checkRequiredField(def, issues) {
|
|
445
|
+
for (const { entries, scope, path, label } of fieldScopes(def))
|
|
435
446
|
for (const [n, entry] of (entries ?? []).entries())
|
|
436
447
|
entry.required === !0 && (scope !== "workflow" ? issues.push({
|
|
437
448
|
path: [...path, n, "required"],
|
|
438
449
|
message: `${label} entry "${entry.name}" is \`required\`, but \`required\` applies only to workflow-scope \`init\` entries \u2014 only those are caller-supplied at start/spawn`
|
|
439
450
|
}) : entry.source.type !== "init" && issues.push({
|
|
440
451
|
path: [...path, n, "required"],
|
|
441
|
-
message: `
|
|
452
|
+
message: `field entry "${entry.name}" is \`required\` but its source is "${entry.source.type}" \u2014 \`required\` applies only to \`init\`-sourced entries (the caller fills them at start/spawn)`
|
|
442
453
|
}));
|
|
443
454
|
}
|
|
444
|
-
function
|
|
445
|
-
for (const { entries, path, label } of
|
|
455
|
+
function checkFieldEntryNames(def, issues) {
|
|
456
|
+
for (const { entries, path, label } of fieldScopes(def))
|
|
446
457
|
checkDuplicates(
|
|
447
458
|
(entries ?? []).map((entry, n) => ({ name: entry.name, path: [...path, n, "name"] })),
|
|
448
|
-
`
|
|
459
|
+
`field entry name in ${label}`,
|
|
449
460
|
issues
|
|
450
461
|
);
|
|
451
462
|
}
|
|
@@ -545,15 +556,55 @@ function collectBindingSites(effects, path, label, sites) {
|
|
|
545
556
|
});
|
|
546
557
|
}
|
|
547
558
|
function checkAssigneesEntries(def, issues) {
|
|
548
|
-
for (const { entries, path } of
|
|
559
|
+
for (const { entries, path } of fieldScopes(def))
|
|
549
560
|
(entries ?? []).filter((e) => e.type === "assignees").length <= 1 || issues.push({
|
|
550
561
|
path,
|
|
551
|
-
message: "at most one assignees-kind
|
|
562
|
+
message: "at most one assignees-kind field entry per scope \u2014 the inbox reads it by kind"
|
|
552
563
|
});
|
|
553
564
|
}
|
|
565
|
+
function taskShape(task) {
|
|
566
|
+
return {
|
|
567
|
+
hasActions: (task.actions ?? []).length > 0,
|
|
568
|
+
hasEffects: (task.effects ?? []).length > 0,
|
|
569
|
+
hasCompleteWhen: task.completeWhen !== void 0,
|
|
570
|
+
hasSubworkflows: task.subworkflows !== void 0
|
|
571
|
+
};
|
|
572
|
+
}
|
|
573
|
+
const KIND_SHAPE_RULES = {
|
|
574
|
+
user: (s) => s.hasActions ? [] : ["needs at least one action for a person to fire"],
|
|
575
|
+
service: (s) => s.hasEffects ? [] : ["needs at least one effect \u2014 the automated work it performs"],
|
|
576
|
+
manual: (s) => [
|
|
577
|
+
s.hasActions || s.hasCompleteWhen ? void 0 : "needs a way to complete \u2014 an action to acknowledge it, or a `completeWhen` predicate to verify it (otherwise it auto-resolves on activation)",
|
|
578
|
+
s.hasSubworkflows ? "is off-system work, not a fan-out \u2014 drop `subworkflows` or move it to its own task" : void 0
|
|
579
|
+
].filter((m) => m !== void 0),
|
|
580
|
+
receive: (s) => [
|
|
581
|
+
s.hasCompleteWhen || s.hasSubworkflows ? void 0 : "needs a `completeWhen` (or `subworkflows`) condition to wait on",
|
|
582
|
+
s.hasActions ? "has no actor, so it cannot carry actions" : void 0
|
|
583
|
+
].filter((m) => m !== void 0),
|
|
584
|
+
script: (s) => [
|
|
585
|
+
s.hasActions ? "runs inline with no actor, so it cannot carry actions" : void 0,
|
|
586
|
+
s.hasCompleteWhen ? "resolves on activation, so it cannot carry a `completeWhen` (that is a `receive`/`service` wait)" : void 0,
|
|
587
|
+
s.hasSubworkflows ? "resolves on activation, so it cannot fan out with `subworkflows`" : void 0
|
|
588
|
+
].filter((m) => m !== void 0)
|
|
589
|
+
};
|
|
590
|
+
function checkTaskKinds(def, issues) {
|
|
591
|
+
for (const [i, stage] of def.stages.entries())
|
|
592
|
+
for (const [j, task] of (stage.tasks ?? []).entries()) {
|
|
593
|
+
const path = ["stages", i, "tasks", j];
|
|
594
|
+
if (task.target !== void 0 && task.kind !== "manual" && issues.push({
|
|
595
|
+
path: [...path, "target"],
|
|
596
|
+
message: `task "${task.name}" has a \`target\` but is not \`kind: "manual"\` \u2014 a target is the deep-link for off-system manual work`
|
|
597
|
+
}), task.kind !== void 0)
|
|
598
|
+
for (const fault of KIND_SHAPE_RULES[task.kind](taskShape(task)))
|
|
599
|
+
issues.push({
|
|
600
|
+
path: [...path, "kind"],
|
|
601
|
+
message: `task "${task.name}" declares kind "${task.kind}" but ${fault}`
|
|
602
|
+
});
|
|
603
|
+
}
|
|
604
|
+
}
|
|
554
605
|
function checkWorkflowInvariants(def) {
|
|
555
606
|
const issues = [], stageNames = checkStages(def, issues);
|
|
556
|
-
return checkInitialStage(def, stageNames, issues), checkTransitionTargets(def, stageNames, issues), checkEffectNames(def, issues), checkGuardNames(def, issues),
|
|
607
|
+
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), checkTaskKinds(def, issues), issues;
|
|
557
608
|
}
|
|
558
609
|
function defineWorkflow(definition) {
|
|
559
610
|
const label = labelFor("defineWorkflow", definition), parsed = parseOrThrow(AuthoringWorkflowSchema, definition, label), { definition: stored, issues: desugarIssues } = desugarWorkflow(parsed), issues = [...desugarIssues, ...checkWorkflowInvariants(stored)];
|
|
@@ -572,8 +623,8 @@ function defineAction(action) {
|
|
|
572
623
|
function defineTransition(transition) {
|
|
573
624
|
return parseOrThrow(AuthoringTransitionSchema, transition, transitionLabel(transition));
|
|
574
625
|
}
|
|
575
|
-
function
|
|
576
|
-
return parseOrThrow(
|
|
626
|
+
function defineField(entry) {
|
|
627
|
+
return parseOrThrow(AuthoringFieldEntrySchema, entry, labelFor("defineField", entry));
|
|
577
628
|
}
|
|
578
629
|
function defineOp(op) {
|
|
579
630
|
return parseOrThrow(AuthoringOpSchema, op, "defineOp");
|
|
@@ -609,10 +660,10 @@ export {
|
|
|
609
660
|
defineAction,
|
|
610
661
|
defineEffect,
|
|
611
662
|
defineEffectDescriptor,
|
|
663
|
+
defineField,
|
|
612
664
|
defineGuard,
|
|
613
665
|
defineOp,
|
|
614
666
|
defineStage,
|
|
615
|
-
defineState,
|
|
616
667
|
defineTask,
|
|
617
668
|
defineTransition,
|
|
618
669
|
defineWorkflow,
|