@sanity/workflow-engine 0.27.0 → 0.28.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/CHANGELOG.md +47 -0
- package/dist/_chunks-cjs/invariants.cjs +35 -356
- package/dist/_chunks-es/invariants.js +36 -317
- package/dist/define.cjs +1 -6
- package/dist/define.d.cts +45 -15
- package/dist/define.d.ts +45 -15
- package/dist/define.js +2 -7
- package/dist/index.cjs +378 -87
- package/dist/index.d.cts +38 -15
- package/dist/index.d.ts +38 -15
- package/dist/index.js +293 -4
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,52 @@
|
|
|
1
1
|
# @sanity/workflow-engine
|
|
2
2
|
|
|
3
|
+
## 0.28.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 5050b06: **BREAKING:** Authoring a deployment now types through `WorkflowDeploymentInput` / `WorkflowConfigInput`, which require `expectedMinReaderModel` as the current reader-floor literal. Passing a parsed `WorkflowDeployment` / `WorkflowConfig` (where the floor is optional/unverified) into `defineWorkflowConfig` or `defineWorkflows` is a type error — share the authored deployment object instead of `config.deployments[n]`. The same pin shows up on the blueprint resource: `EditorialWorkflowsResource.deployment` and `parseWorkflowDeployment`'s return type are now `AcknowledgedDeployment` (floor asserted to the current literal), so a hand-constructed provider resource must carry that literal too.
|
|
8
|
+
|
|
9
|
+
At runtime, config parse no longer rejects a stale or missing floor on an untargeted deployment. Only deployment-scoped commands assert, and only the selected deployment: definition deploy, `--check` / `--dry-run`, blueprint provision, `start`, `definition delete`, and `definition diff` (the last is a deployment-scoped read). Instance-id commands (`fire-action`, `abort`, `set-stage`, `reset-activity`) deliberately do not assert — they resolve by instance id, not by a declared deployment's acknowledgement — so an unacknowledged floor does not stop those instance commits.
|
|
10
|
+
|
|
11
|
+
Upgrade TypeScript configs and blueprint manifests that fed a parsed deployment into those helpers: keep a shared authored object (`satisfies WorkflowDeploymentInput`) for both `defineWorkflowConfig` and `defineWorkflows`, and give any hand-built `EditorialWorkflowsResource` the current floor literal on `deployment`. Existing configs that already acknowledge the current floor keep working at runtime; a stale selected deployment still fails with `ReaderModelAcknowledgementError` (headline + short steps; the CLI renders it through the clean styled-error path).
|
|
12
|
+
|
|
13
|
+
**Docs impact:** Update the CLI / blueprint authoring examples and the prerelease reader-floor guidance so they name `WorkflowConfigInput` / `WorkflowDeploymentInput` / `AcknowledgedDeployment`, forbid passing `config.deployments[n]` into `defineWorkflows`, state that instance-id writes are outside the acknowledgement gate, and stop implying whole-config parse-time rejection for commands that never select a deployment.
|
|
14
|
+
|
|
15
|
+
- a044ba5: Report a Studio start whose auto-advance lost a write race as the finished run
|
|
16
|
+
it is. Starting a workflow from the Studio while another runtime (a deployed
|
|
17
|
+
Function, a script) drives the same instance could hand the editor a warning
|
|
18
|
+
toast — "'…' started but didn't finish", with a raw `unexpected revision ID`
|
|
19
|
+
mutation error under it — for a run that had in fact completed: the Studio's own
|
|
20
|
+
auto-advance simply lost the write race to whoever committed the equivalent move
|
|
21
|
+
first. That toast was indistinguishable from a genuinely stuck workflow. The
|
|
22
|
+
Studio now confirms the completed start instead of warning about it.
|
|
23
|
+
|
|
24
|
+
Narrow by design: only a lost revision race whose run is already complete is
|
|
25
|
+
reclassified. A conflict that left the run in flight, and any other reason an
|
|
26
|
+
auto-advance failed, still surface as before.
|
|
27
|
+
|
|
28
|
+
`@sanity/workflow-engine` exports `isRevisionConflict`, the predicate that tells
|
|
29
|
+
a lost optimistic-locking race from a real error, so integrations can classify
|
|
30
|
+
one without matching on message text. It answers on the error alone, so narrow
|
|
31
|
+
to a single rev-guarded write before asking — a bare 409 also covers a create-id
|
|
32
|
+
collision.
|
|
33
|
+
|
|
34
|
+
**No upgrade action required.** Engine behaviour is unchanged and the new export
|
|
35
|
+
is additive.
|
|
36
|
+
|
|
37
|
+
**Docs impact:** `isRevisionConflict` is new public engine surface, added to the
|
|
38
|
+
errors section of `docs/reference.md` alongside the concurrency errors it
|
|
39
|
+
classifies; mirror that entry wherever published reference material lists the
|
|
40
|
+
engine's error helpers.
|
|
41
|
+
|
|
42
|
+
### Patch Changes
|
|
43
|
+
|
|
44
|
+
- 1e4a5da: When two runtimes both try to create the same stage guard after each observing it absent — for example a deployed Function reacting to instance commits while a script advances the same workflow — the losing create no longer aborts guard deploy. It falls through to the body-reconciling patch the existing-document path already uses, and writes its own resolution of the guard's conditions rather than assuming the two are identical. Concurrent deploys of an already-present guard were already a patch and are unchanged.
|
|
45
|
+
|
|
46
|
+
**No upgrade action required.**
|
|
47
|
+
|
|
48
|
+
**Docs impact: None** — `docs/reference.md` already documents `deployStageGuards` as an idempotent upsert.
|
|
49
|
+
|
|
3
50
|
## 0.27.0
|
|
4
51
|
|
|
5
52
|
### Minor Changes
|
|
@@ -20,6 +20,41 @@ function _interopNamespaceCompat(e) {
|
|
|
20
20
|
|
|
21
21
|
var v__namespace = /* @__PURE__ */ _interopNamespaceCompat(v);
|
|
22
22
|
|
|
23
|
+
function isCascadeFired(action) {
|
|
24
|
+
return action.when !== void 0;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function deriveActivityKind(activity) {
|
|
28
|
+
if (activity.target !== void 0) return "manual";
|
|
29
|
+
const actions = activity.actions ?? [];
|
|
30
|
+
return actions.some(a => !isCascadeFired(a)) ? "user" : actions.some(a => (a.effects ?? []).length > 0 || a.spawn !== void 0) ? "service" : actions.length > 0 ? "receive" : "script";
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function deriveExecutorClassification(activity) {
|
|
34
|
+
if (activity.target !== void 0) return "off-system";
|
|
35
|
+
const actions = activity.actions ?? [], cascadeFired = actions.filter(isCascadeFired).length;
|
|
36
|
+
return cascadeFired === actions.length ? "autonomous" : cascadeFired === 0 ? "interactive" : "hybrid";
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function driverKind(actor) {
|
|
40
|
+
return actor.kind === "person" || actor.kind === "agent" ? actor.kind : "service";
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function errorMessage(err) {
|
|
44
|
+
return (err instanceof Error ? err.message : String(err)).replace(/[^\P{Cc}\n\t]/gu, "");
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function rethrowWithContext(err, context) {
|
|
48
|
+
throw new Error(`${context}: ${errorMessage(err)}`, {
|
|
49
|
+
cause: err
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function andConditions(parts) {
|
|
54
|
+
const present = parts.filter(p => p !== void 0);
|
|
55
|
+
if (present.length !== 0) return present.length === 1 ? present[0] : present.map(p => `(${p})`).join(" && ");
|
|
56
|
+
}
|
|
57
|
+
|
|
23
58
|
class WorkflowError extends Error {
|
|
24
59
|
kind;
|
|
25
60
|
constructor(kind, message, options) {
|
|
@@ -93,322 +128,6 @@ function effectNotFoundMessage(args) {
|
|
|
93
128
|
return args.settled.status === "cancelled" ? `${base} — it was cancelled at ${args.settled.ranAt}${cause}` : `${base} — it already settled "${args.settled.status}" at ${args.settled.ranAt}${cause}`;
|
|
94
129
|
}
|
|
95
130
|
|
|
96
|
-
function errorMessage(err) {
|
|
97
|
-
return (err instanceof Error ? err.message : String(err)).replace(/[^\P{Cc}\n\t]/gu, "");
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
function rethrowWithContext(err, context) {
|
|
101
|
-
throw new Error(`${context}: ${errorMessage(err)}`, {
|
|
102
|
-
cause: err
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const WORKFLOW_INSTANCE_TYPE = "sanity.workflow.instance";
|
|
107
|
-
|
|
108
|
-
function terminalState(instance) {
|
|
109
|
-
return instance.abortedAt !== void 0 ? "aborted" : instance.completedAt !== void 0 ? "completed" : "in-flight";
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
function isUnprimed(instance) {
|
|
113
|
-
return instance.stages.length === 0 && terminalState(instance) === "in-flight";
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
function parseDefinitionSnapshotValue(instance) {
|
|
117
|
-
try {
|
|
118
|
-
return normalizeLegacyActivityRequirements(JSON.parse(instance.definitionSnapshot));
|
|
119
|
-
} catch (err) {
|
|
120
|
-
rethrowWithContext(err, `Failed to parse definitionSnapshot on instance "${instance._id}"`);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
function normalizeLegacyActivityRequirements(value) {
|
|
125
|
-
for (const stage of arrayMember(value, "stages")) for (const activity of arrayMember(stage, "activities")) normalizeLegacyRequirementMap(activity);
|
|
126
|
-
return value;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
function arrayMember(value, key) {
|
|
130
|
-
if (typeof value != "object" || value === null) return [];
|
|
131
|
-
const member = value[key];
|
|
132
|
-
return Array.isArray(member) ? member : [];
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
function normalizeLegacyRequirementMap(value) {
|
|
136
|
-
if (typeof value != "object" || value === null) return;
|
|
137
|
-
const activity = value, requirements = activity.requirements;
|
|
138
|
-
typeof requirements != "object" || requirements === null || Array.isArray(requirements) || (activity.requirements = Object.entries(requirements).map(([name, query]) => ({
|
|
139
|
-
type: "groq",
|
|
140
|
-
name: name,
|
|
141
|
-
query: query
|
|
142
|
-
})));
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
function parseDefinitionSnapshot(instance) {
|
|
146
|
-
return parseDefinitionSnapshotValue(instance);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
function parentRef(instance) {
|
|
150
|
-
return instance.ancestors.at(-1);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
const DATA_MODEL_VERSION = 5, DATA_MODEL_MIN_READER = 4, READER_MODEL_ROLLOUT_URL = "https://www.sanity.io/docs/editorial-workflows/prerelease";
|
|
154
|
-
|
|
155
|
-
class ReaderModelAcknowledgementError extends WorkflowError {
|
|
156
|
-
code="WORKFLOW_READER_MODEL_ACKNOWLEDGEMENT_MISMATCH";
|
|
157
|
-
expectedMinReaderModel;
|
|
158
|
-
engineMinReaderModel=DATA_MODEL_MIN_READER;
|
|
159
|
-
engineModelVersion=DATA_MODEL_VERSION;
|
|
160
|
-
documentationUrl=READER_MODEL_ROLLOUT_URL;
|
|
161
|
-
constructor(expectedMinReaderModel, context = "Deployment") {
|
|
162
|
-
const expected = expectedMinReaderModel === void 0 ? "missing" : String(expectedMinReaderModel);
|
|
163
|
-
super("reader-model-acknowledgement", `${context} expected reader floor ${expected}; the installed engine requires acknowledgement ${DATA_MODEL_MIN_READER}. Do not change the acknowledgement yet: accepting ${DATA_MODEL_MIN_READER} authorizes this engine to write documents that older readers will refuse. Upgrade every Studio, CLI, MCP server, Function, and other runtime that reads engine-owned documents; verify that rollout in every environment sharing the workflow resource; then change the literal in deployment configuration and deploy the writer. Rollout guide: ${READER_MODEL_ROLLOUT_URL}`),
|
|
164
|
-
this.name = "ReaderModelAcknowledgementError", this.expectedMinReaderModel = expectedMinReaderModel;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
function assertReaderModelAcknowledgement(expectedMinReaderModel, context) {
|
|
169
|
-
if (typeof expectedMinReaderModel != "number" || !Number.isFinite(expectedMinReaderModel) || !Number.isInteger(expectedMinReaderModel) || expectedMinReaderModel < 0 || expectedMinReaderModel !== DATA_MODEL_MIN_READER) throw new ReaderModelAcknowledgementError(expectedMinReaderModel, context);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
const DATA_MODEL_CHANGES = Object.freeze([ Object.freeze({
|
|
173
|
-
id: "governed-model-stamps",
|
|
174
|
-
introducedInModel: 1,
|
|
175
|
-
minReaderModel: 0,
|
|
176
|
-
documentTypes: Object.freeze([ "definition", "instance" ]),
|
|
177
|
-
compatibility: "additive",
|
|
178
|
-
applicability: "unconditional",
|
|
179
|
-
summary: "Definition and instance documents carry model provenance and reader-floor stamps."
|
|
180
|
-
}), Object.freeze({
|
|
181
|
-
id: "subject-field-kind",
|
|
182
|
-
introducedInModel: 2,
|
|
183
|
-
minReaderModel: 0,
|
|
184
|
-
documentTypes: Object.freeze([ "definition", "instance" ]),
|
|
185
|
-
compatibility: "additive",
|
|
186
|
-
applicability: "detectable",
|
|
187
|
-
summary: "A workflow-level subject field identifies the document a workflow is about."
|
|
188
|
-
}), Object.freeze({
|
|
189
|
-
id: "typed-scalar-choice-lists",
|
|
190
|
-
introducedInModel: 2,
|
|
191
|
-
minReaderModel: 2,
|
|
192
|
-
documentTypes: Object.freeze([ "definition", "instance" ]),
|
|
193
|
-
compatibility: "reader-floor",
|
|
194
|
-
applicability: "detectable",
|
|
195
|
-
summary: "Scalar fields may constrain writes to a persisted typed choice list."
|
|
196
|
-
}), Object.freeze({
|
|
197
|
-
id: "action-semantics",
|
|
198
|
-
introducedInModel: 2,
|
|
199
|
-
minReaderModel: 0,
|
|
200
|
-
documentTypes: Object.freeze([ "definition" ]),
|
|
201
|
-
compatibility: "additive",
|
|
202
|
-
applicability: "detectable",
|
|
203
|
-
summary: "Ordinary actions may carry a closed bag of advisory workflow semantics."
|
|
204
|
-
}), Object.freeze({
|
|
205
|
-
id: "inclusive-scalar-bounds",
|
|
206
|
-
introducedInModel: 2,
|
|
207
|
-
minReaderModel: 2,
|
|
208
|
-
documentTypes: Object.freeze([ "definition", "instance" ]),
|
|
209
|
-
compatibility: "reader-floor",
|
|
210
|
-
applicability: "detectable",
|
|
211
|
-
summary: "String, text, and number values may carry persisted inclusive bounds."
|
|
212
|
-
}), Object.freeze({
|
|
213
|
-
id: "progress-field-kind",
|
|
214
|
-
introducedInModel: 3,
|
|
215
|
-
minReaderModel: 0,
|
|
216
|
-
documentTypes: Object.freeze([ "definition", "instance" ]),
|
|
217
|
-
compatibility: "additive",
|
|
218
|
-
applicability: "detectable",
|
|
219
|
-
summary: "A progress field kind carries application-defined 0–100 completion."
|
|
220
|
-
}), Object.freeze({
|
|
221
|
-
id: "effect-claim-tokens",
|
|
222
|
-
introducedInModel: 3,
|
|
223
|
-
minReaderModel: 0,
|
|
224
|
-
documentTypes: Object.freeze([ "instance" ]),
|
|
225
|
-
compatibility: "additive",
|
|
226
|
-
applicability: "detectable",
|
|
227
|
-
summary: "Pending-effect claims carry an exact-claim token gating mid-dispatch state reports."
|
|
228
|
-
}), Object.freeze({
|
|
229
|
-
id: "classified-principal-ids",
|
|
230
|
-
introducedInModel: 4,
|
|
231
|
-
minReaderModel: 4,
|
|
232
|
-
documentTypes: Object.freeze([ "instance" ]),
|
|
233
|
-
compatibility: "reader-floor",
|
|
234
|
-
applicability: "unconditional",
|
|
235
|
-
summary: "Principal ids are namespace-classified: actor and assignee writes carry the account-global user id only, and readers resolve legacy project-scoped ids through the prefix classifier at the instance read funnel."
|
|
236
|
-
}), Object.freeze({
|
|
237
|
-
id: "readiness-requirements",
|
|
238
|
-
introducedInModel: 4,
|
|
239
|
-
minReaderModel: 4,
|
|
240
|
-
documentTypes: Object.freeze([ "definition" ]),
|
|
241
|
-
compatibility: "reader-floor",
|
|
242
|
-
applicability: "detectable",
|
|
243
|
-
summary: "Start and activity readiness use named polymorphic requirement arrays."
|
|
244
|
-
}), Object.freeze({
|
|
245
|
-
id: "due-date-field-kinds",
|
|
246
|
-
introducedInModel: 5,
|
|
247
|
-
minReaderModel: 0,
|
|
248
|
-
documentTypes: Object.freeze([ "definition", "instance" ]),
|
|
249
|
-
compatibility: "additive",
|
|
250
|
-
applicability: "detectable",
|
|
251
|
-
summary: "Due-date field kinds (dueDate, dueDatetime) mark a level deadline, elevated aliases of date/datetime carrying the same stored value."
|
|
252
|
-
}) ]);
|
|
253
|
-
|
|
254
|
-
function recordOf(value) {
|
|
255
|
-
return value !== null && typeof value == "object" && !Array.isArray(value) ? value : void 0;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
function recordsAt(record, key) {
|
|
259
|
-
const value = record[key];
|
|
260
|
-
return Array.isArray(value) ? value.map(recordOf).filter(item => item !== void 0) : [];
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
function nestedFieldEntries(entries) {
|
|
264
|
-
return entries.flatMap(entry => [ entry, ...nestedFieldEntries(recordsAt(entry, "fields")), ...nestedFieldEntries(recordsAt(entry, "of")) ]);
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
function parsedDefinitionSnapshot(root) {
|
|
268
|
-
if (typeof root.definitionSnapshot == "string") return recordOf(parseDefinitionSnapshotValue({
|
|
269
|
-
_id: typeof root._id == "string" ? root._id : "<unknown instance>",
|
|
270
|
-
definitionSnapshot: root.definitionSnapshot
|
|
271
|
-
}));
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
function persistedFieldEntries(document) {
|
|
275
|
-
const root = recordOf(document);
|
|
276
|
-
if (root === void 0) return [];
|
|
277
|
-
const snapshot = parsedDefinitionSnapshot(root), roots = snapshot === void 0 ? [ root ] : [ root, snapshot ], stages = roots.flatMap(candidate => recordsAt(candidate, "stages")), activities = stages.flatMap(stage => recordsAt(stage, "activities")), actions = activities.flatMap(activity => recordsAt(activity, "actions")), effects = actions.flatMap(action => recordsAt(action, "effects"));
|
|
278
|
-
return nestedFieldEntries([ ...roots.flatMap(candidate => recordsAt(candidate, "fields")), ...stages.flatMap(stage => recordsAt(stage, "fields")), ...activities.flatMap(activity => recordsAt(activity, "fields")), ...actions.flatMap(action => recordsAt(action, "params")), ...effects.flatMap(effect => recordsAt(effect, "outputs")) ]);
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
function hasChoiceList(document) {
|
|
282
|
-
return persistedFieldEntries(document).some(entry => {
|
|
283
|
-
const options = recordOf(entry.options);
|
|
284
|
-
return options !== void 0 && Array.isArray(options.list);
|
|
285
|
-
});
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
function hasFieldKind(document, kind) {
|
|
289
|
-
return persistedFieldEntries(document).some(entry => entry.type === kind || entry._type === kind);
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
function hasActionSemantics(document) {
|
|
293
|
-
const root = recordOf(document);
|
|
294
|
-
return root === void 0 ? !1 : recordsAt(root, "stages").flatMap(stage => recordsAt(stage, "activities")).flatMap(activity => recordsAt(activity, "actions")).some(action => Array.isArray(action.semantics));
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
function hasScalarValidation(document) {
|
|
298
|
-
return persistedFieldEntries(document).some(entry => {
|
|
299
|
-
const validation = recordOf(entry.validation);
|
|
300
|
-
return typeof validation?.min == "number" || typeof validation?.max == "number";
|
|
301
|
-
});
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
function hasClaimTokens(document) {
|
|
305
|
-
const root = recordOf(document);
|
|
306
|
-
return root === void 0 ? !1 : recordsAt(root, "pendingEffects").some(entry => {
|
|
307
|
-
const claim = recordOf(entry.claim);
|
|
308
|
-
return claim !== void 0 && typeof claim.claimToken == "string";
|
|
309
|
-
});
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
function hasReadinessRequirements(document) {
|
|
313
|
-
const root = recordOf(document);
|
|
314
|
-
return root === void 0 ? !1 : Array.isArray(recordOf(root.start)?.requirements) ? !0 : recordsAt(root, "stages").some(stage => recordsAt(stage, "activities").some(activity => Array.isArray(activity.requirements)));
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
const featureDetectors = {
|
|
318
|
-
"governed-model-stamps": () => !0,
|
|
319
|
-
"subject-field-kind": document => hasFieldKind(document, "subject"),
|
|
320
|
-
"typed-scalar-choice-lists": hasChoiceList,
|
|
321
|
-
"action-semantics": hasActionSemantics,
|
|
322
|
-
"inclusive-scalar-bounds": hasScalarValidation,
|
|
323
|
-
"progress-field-kind": document => hasFieldKind(document, "progress"),
|
|
324
|
-
"effect-claim-tokens": hasClaimTokens,
|
|
325
|
-
"classified-principal-ids": () => !0,
|
|
326
|
-
"readiness-requirements": hasReadinessRequirements,
|
|
327
|
-
"due-date-field-kinds": document => hasFieldKind(document, "dueDate") || hasFieldKind(document, "dueDatetime")
|
|
328
|
-
};
|
|
329
|
-
|
|
330
|
-
function requiredModelFeatures(documentType, document) {
|
|
331
|
-
return DATA_MODEL_CHANGES.filter(change => change.documentTypes.some(candidate => candidate === documentType) && featureDetectors[change.id](document));
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
function requiredReaderModel(documentType, document) {
|
|
335
|
-
return Math.max(0, ...requiredModelFeatures(documentType, document).map(change => change.minReaderModel));
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
function modelStampFor(args) {
|
|
339
|
-
return {
|
|
340
|
-
modelVersion: DATA_MODEL_VERSION,
|
|
341
|
-
minReaderModel: Math.max(DATA_MODEL_MIN_READER, args.storedMinReaderModel ?? 0, requiredReaderModel(args.documentType, args.document))
|
|
342
|
-
};
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
function fieldTreeShape(value) {
|
|
346
|
-
if (Array.isArray(value)) return value.map(fieldTreeShape);
|
|
347
|
-
if (value === null) return "null";
|
|
348
|
-
if (typeof value == "object") {
|
|
349
|
-
const record = value;
|
|
350
|
-
return Object.fromEntries(Object.keys(record).toSorted().map(key => [ key, fieldTreeShape(record[key]) ]));
|
|
351
|
-
}
|
|
352
|
-
return typeof value;
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
function modelVersionOf(doc) {
|
|
356
|
-
const stamp = doc.modelVersion;
|
|
357
|
-
return typeof stamp == "number" ? stamp : 0;
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
function minReaderModelOf(doc) {
|
|
361
|
-
const floor = doc.minReaderModel;
|
|
362
|
-
return typeof floor == "number" ? floor : modelVersionOf(doc);
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
class ModelVersionAheadError extends WorkflowError {
|
|
366
|
-
documentId;
|
|
367
|
-
documentModelVersion;
|
|
368
|
-
requiredReaderModel;
|
|
369
|
-
engineModelVersion;
|
|
370
|
-
constructor(args) {
|
|
371
|
-
super("model-version-ahead", `Document "${args.documentId}" was written by engine data model ${args.documentModelVersion} and requires a reader at model ${args.requiredReaderModel} or newer; this engine reads up to model ${DATA_MODEL_VERSION}. Upgrade @sanity/workflow-engine to a version that understands it.`),
|
|
372
|
-
this.name = "ModelVersionAheadError", this.documentId = args.documentId, this.documentModelVersion = args.documentModelVersion,
|
|
373
|
-
this.requiredReaderModel = args.requiredReaderModel, this.engineModelVersion = DATA_MODEL_VERSION;
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
function assertReadableModel(doc) {
|
|
378
|
-
const documentReaderModel = minReaderModelOf(doc);
|
|
379
|
-
if (documentReaderModel > DATA_MODEL_VERSION) throw new ModelVersionAheadError({
|
|
380
|
-
documentId: doc._id,
|
|
381
|
-
documentModelVersion: modelVersionOf(doc),
|
|
382
|
-
requiredReaderModel: documentReaderModel
|
|
383
|
-
});
|
|
384
|
-
return doc;
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
function isCascadeFired(action) {
|
|
388
|
-
return action.when !== void 0;
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
function deriveActivityKind(activity) {
|
|
392
|
-
if (activity.target !== void 0) return "manual";
|
|
393
|
-
const actions = activity.actions ?? [];
|
|
394
|
-
return actions.some(a => !isCascadeFired(a)) ? "user" : actions.some(a => (a.effects ?? []).length > 0 || a.spawn !== void 0) ? "service" : actions.length > 0 ? "receive" : "script";
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
function deriveExecutorClassification(activity) {
|
|
398
|
-
if (activity.target !== void 0) return "off-system";
|
|
399
|
-
const actions = activity.actions ?? [], cascadeFired = actions.filter(isCascadeFired).length;
|
|
400
|
-
return cascadeFired === actions.length ? "autonomous" : cascadeFired === 0 ? "interactive" : "hybrid";
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
function driverKind(actor) {
|
|
404
|
-
return actor.kind === "person" || actor.kind === "agent" ? actor.kind : "service";
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
function andConditions(parts) {
|
|
408
|
-
const present = parts.filter(p => p !== void 0);
|
|
409
|
-
if (present.length !== 0) return present.length === 1 ? present[0] : present.map(p => `(${p})`).join(" && ");
|
|
410
|
-
}
|
|
411
|
-
|
|
412
131
|
const KNOWN_SCHEMES = /* @__PURE__ */ new Set([ "dataset", "canvas", "media-library", "dashboard" ]), KNOWN_SCHEMES_TEXT = [ ...KNOWN_SCHEMES ].join(", ");
|
|
413
132
|
|
|
414
133
|
class VersionSpecificDatasetGdrError extends Error {
|
|
@@ -4068,12 +3787,6 @@ exports.CONDITION_VARS = CONDITION_VARS;
|
|
|
4068
3787
|
|
|
4069
3788
|
exports.ContractViolationError = ContractViolationError;
|
|
4070
3789
|
|
|
4071
|
-
exports.DATA_MODEL_CHANGES = DATA_MODEL_CHANGES;
|
|
4072
|
-
|
|
4073
|
-
exports.DATA_MODEL_MIN_READER = DATA_MODEL_MIN_READER;
|
|
4074
|
-
|
|
4075
|
-
exports.DATA_MODEL_VERSION = DATA_MODEL_VERSION;
|
|
4076
|
-
|
|
4077
3790
|
exports.DEFAULT_TRANSITION_WHEN = DEFAULT_TRANSITION_WHEN;
|
|
4078
3791
|
|
|
4079
3792
|
exports.DOCUMENT_VALUE_PERMISSIONS = DOCUMENT_VALUE_PERMISSIONS;
|
|
@@ -4116,20 +3829,14 @@ exports.IsoTimestamp = IsoTimestamp;
|
|
|
4116
3829
|
|
|
4117
3830
|
exports.MUTATION_GUARD_ACTIONS = MUTATION_GUARD_ACTIONS;
|
|
4118
3831
|
|
|
4119
|
-
exports.ModelVersionAheadError = ModelVersionAheadError;
|
|
4120
|
-
|
|
4121
3832
|
exports.NonEmptyString = NonEmptyString;
|
|
4122
3833
|
|
|
4123
3834
|
exports.PersistedDocShapeError = PersistedDocShapeError;
|
|
4124
3835
|
|
|
4125
|
-
exports.READER_MODEL_ROLLOUT_URL = READER_MODEL_ROLLOUT_URL;
|
|
4126
|
-
|
|
4127
3836
|
exports.RESERVED_CONDITION_VARS = RESERVED_CONDITION_VARS;
|
|
4128
3837
|
|
|
4129
3838
|
exports.RESOURCE_ALIAS_NAME_SOURCE = RESOURCE_ALIAS_NAME_SOURCE;
|
|
4130
3839
|
|
|
4131
|
-
exports.ReaderModelAcknowledgementError = ReaderModelAcknowledgementError;
|
|
4132
|
-
|
|
4133
3840
|
exports.START_FILTER_VARS = START_FILTER_VARS;
|
|
4134
3841
|
|
|
4135
3842
|
exports.START_REQUIREMENT_VARS = START_REQUIREMENT_VARS;
|
|
@@ -4144,8 +3851,6 @@ exports.VersionSpecificDatasetGdrError = VersionSpecificDatasetGdrError;
|
|
|
4144
3851
|
|
|
4145
3852
|
exports.WORKFLOW_DEFINITION_TYPE = WORKFLOW_DEFINITION_TYPE;
|
|
4146
3853
|
|
|
4147
|
-
exports.WORKFLOW_INSTANCE_TYPE = WORKFLOW_INSTANCE_TYPE;
|
|
4148
|
-
|
|
4149
3854
|
exports.WorkflowConfigSchema = WorkflowConfigSchema;
|
|
4150
3855
|
|
|
4151
3856
|
exports.WorkflowError = WorkflowError;
|
|
@@ -4154,10 +3859,6 @@ exports.actorFulfillsRole = actorFulfillsRole;
|
|
|
4154
3859
|
|
|
4155
3860
|
exports.andConditions = andConditions;
|
|
4156
3861
|
|
|
4157
|
-
exports.assertReadableModel = assertReadableModel;
|
|
4158
|
-
|
|
4159
|
-
exports.assertReaderModelAcknowledgement = assertReaderModelAcknowledgement;
|
|
4160
|
-
|
|
4161
3862
|
exports.checkWorkflowInvariants = checkWorkflowInvariants;
|
|
4162
3863
|
|
|
4163
3864
|
exports.choiceValueIssues = choiceValueIssues;
|
|
@@ -4198,8 +3899,6 @@ exports.evaluatePredicates = evaluatePredicates;
|
|
|
4198
3899
|
|
|
4199
3900
|
exports.extractDocumentId = extractDocumentId;
|
|
4200
3901
|
|
|
4201
|
-
exports.fieldTreeShape = fieldTreeShape;
|
|
4202
|
-
|
|
4203
3902
|
exports.fieldValueSchemas = fieldValueSchemas;
|
|
4204
3903
|
|
|
4205
3904
|
exports.firstCarriedGlobalId = firstCarriedGlobalId;
|
|
@@ -4254,24 +3953,10 @@ exports.isTodoListItem = isTodoListItem;
|
|
|
4254
3953
|
|
|
4255
3954
|
exports.isUnevaluable = isUnevaluable;
|
|
4256
3955
|
|
|
4257
|
-
exports.isUnprimed = isUnprimed;
|
|
4258
|
-
|
|
4259
3956
|
exports.labelFor = labelFor;
|
|
4260
3957
|
|
|
4261
3958
|
exports.lakePrincipalId = lakePrincipalId;
|
|
4262
3959
|
|
|
4263
|
-
exports.minReaderModelOf = minReaderModelOf;
|
|
4264
|
-
|
|
4265
|
-
exports.modelStampFor = modelStampFor;
|
|
4266
|
-
|
|
4267
|
-
exports.modelVersionOf = modelVersionOf;
|
|
4268
|
-
|
|
4269
|
-
exports.parentRef = parentRef;
|
|
4270
|
-
|
|
4271
|
-
exports.parseDefinitionSnapshot = parseDefinitionSnapshot;
|
|
4272
|
-
|
|
4273
|
-
exports.parseDefinitionSnapshotValue = parseDefinitionSnapshotValue;
|
|
4274
|
-
|
|
4275
3960
|
exports.parseFieldValue = parseFieldValue;
|
|
4276
3961
|
|
|
4277
3962
|
exports.parseGdr = parseGdr;
|
|
@@ -4304,10 +3989,6 @@ exports.releaseDocId = releaseDocId;
|
|
|
4304
3989
|
|
|
4305
3990
|
exports.releaseRef = releaseRef;
|
|
4306
3991
|
|
|
4307
|
-
exports.requiredModelFeatures = requiredModelFeatures;
|
|
4308
|
-
|
|
4309
|
-
exports.requiredReaderModel = requiredReaderModel;
|
|
4310
|
-
|
|
4311
3992
|
exports.resourceAliasesToMap = resourceAliasesToMap;
|
|
4312
3993
|
|
|
4313
3994
|
exports.resourceFromGdrUri = resourceFromGdrUri;
|
|
@@ -4332,8 +4013,6 @@ exports.startKindOf = startKindOf;
|
|
|
4332
4013
|
|
|
4333
4014
|
exports.tagScopeFilter = tagScopeFilter;
|
|
4334
4015
|
|
|
4335
|
-
exports.terminalState = terminalState;
|
|
4336
|
-
|
|
4337
4016
|
exports.toBareId = toBareId;
|
|
4338
4017
|
|
|
4339
4018
|
exports.toPhysicalGdr = toPhysicalGdr;
|