@sanity/workflow-engine 0.14.0 → 0.15.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/define.d.cts CHANGED
@@ -1,12 +1,14 @@
1
1
  import * as v from "valibot";
2
2
 
3
- declare type Action = ActionFields<Op>;
3
+ declare type Action = ActionFields<Op, string[]>;
4
4
 
5
- /** Type-mirror of {@link actionFields}, parameterised over the op grammar. */
6
- declare type ActionFields<TOp> = {
5
+ /** Type-mirror of {@link actionFields}, parameterised over the op and
6
+ * group-membership grammars. */
7
+ declare type ActionFields<TOp, TGroup> = {
7
8
  name: string;
8
9
  title?: string | undefined;
9
10
  description?: string | undefined;
11
+ group?: TGroup | undefined;
10
12
  filter?: string | undefined;
11
13
  params?: ActionParam[] | undefined;
12
14
  ops?: TOp[] | undefined;
@@ -53,7 +55,13 @@ declare const ActionParamSchema: v.StrictObjectSchema<
53
55
  undefined
54
56
  >;
55
57
 
56
- declare type Activity = ActivityFields<FieldEntry, Action, Op, ManualTarget>;
58
+ declare type Activity = ActivityFields<
59
+ FieldEntry,
60
+ Action,
61
+ Op,
62
+ ManualTarget,
63
+ string[]
64
+ >;
57
65
 
58
66
  declare const ACTIVITY_KINDS: readonly [
59
67
  "user",
@@ -63,11 +71,13 @@ declare const ACTIVITY_KINDS: readonly [
63
71
  "receive",
64
72
  ];
65
73
 
66
- /** Type-mirror of {@link activityFields}, parameterised over field/action/op/target. */
67
- declare type ActivityFields<TField, TAction, TOp, TTarget> = {
74
+ /** Type-mirror of {@link activityFields}, parameterised over field/action/op/target/group. */
75
+ declare type ActivityFields<TField, TAction, TOp, TTarget, TGroup> = {
68
76
  name: string;
69
77
  title?: string | undefined;
70
78
  description?: string | undefined;
79
+ groups?: Group[] | undefined;
80
+ group?: TGroup | undefined;
71
81
  kind?: ActivityKind | undefined;
72
82
  target?: TTarget | undefined;
73
83
  activation?: "auto" | "manual" | undefined;
@@ -90,7 +100,8 @@ declare type AuthoringActivity = ActivityFields<
90
100
  AuthoringFieldEntry,
91
101
  AuthoringAction,
92
102
  AuthoringOp,
93
- AuthoringManualTarget
103
+ AuthoringManualTarget,
104
+ GroupMembership
94
105
  >;
95
106
 
96
107
  declare type AuthoringEditable = v.InferOutput<typeof AuthoringEditableSchema>;
@@ -313,8 +324,8 @@ declare const AuthoringGuardSchema: v.StrictObjectSchema<
313
324
  undefined
314
325
  >;
315
326
  /**
316
- * Lake GROQ predicate — a distinct eval context reading
317
- * `document.before`/`document.after`, `mutation`, `guard`, and
327
+ * Lake GROQ predicate — a distinct eval context: delta-mode GROQ
328
+ * reading the `before()`/`after()` natives, `mutation`, `guard`, and
318
329
  * `identity()`. Bare ids/fields only. Omitted or empty means
319
330
  * UNCONDITIONAL DENY.
320
331
  */
@@ -724,12 +735,15 @@ declare const AuthoringOpSchema: v.VariantSchema<
724
735
  * field the transition filter reads — `failed` is for work that
725
736
  * genuinely could not complete.
726
737
  */
727
- declare type AuthoringRawAction = ActionFields<AuthoringOp> & {
738
+ declare type AuthoringRawAction = ActionFields<AuthoringOp, GroupMembership> & {
728
739
  roles?: string[] | undefined;
729
740
  status?: TerminalActivityStatus | undefined;
730
741
  };
731
742
 
732
- declare type AuthoringRawFieldEntry = FieldEntryFields<AuthoringEditable>;
743
+ declare type AuthoringRawFieldEntry = FieldEntryFields<
744
+ AuthoringEditable,
745
+ GroupMembership
746
+ >;
733
747
 
734
748
  declare type AuthoringStage = StageFields<
735
749
  AuthoringFieldEntry,
@@ -964,6 +978,7 @@ declare type ClaimAction = {
964
978
  name: string;
965
979
  title?: string | undefined;
966
980
  description?: string | undefined;
981
+ group?: GroupMembership | undefined;
967
982
  field: string | AuthoringFieldRef;
968
983
  roles?: string[] | undefined;
969
984
  filter?: string | undefined;
@@ -982,6 +997,7 @@ declare type ClaimField = {
982
997
  name: string;
983
998
  title?: string | undefined;
984
999
  description?: string | undefined;
1000
+ group?: GroupMembership | undefined;
985
1001
  };
986
1002
 
987
1003
  /**
@@ -997,6 +1013,9 @@ export declare interface ConditionVar {
997
1013
  name: string;
998
1014
  binding: ConditionVarBinding;
999
1015
  description: string;
1016
+ /** Short human phrase for rendered explanations ("all activities in this
1017
+ * stage are finished") — consumer-facing, unlike `description`. */
1018
+ label: string;
1000
1019
  }
1001
1020
 
1002
1021
  /**
@@ -1014,9 +1033,13 @@ export declare interface ConditionVar {
1014
1033
  * fixed and deploy-enforced (see the op-where scope's param-name list in
1015
1034
  * the op applier).
1016
1035
  * 2. **Filter evaluation without a caller** — the engine's cascade evaluates
1017
- * transition filters and `completeWhen`/`failWhen` with no caller, so only
1018
- * the `'always'`-bound subset carries values there ({@link FILTER_SCOPE_VARS}).
1019
- * Caller-bound vars evaluate to `undefined` and fail closed.
1036
+ * transition filters and the activity gates (`filter`, `completeWhen`,
1037
+ * `failWhen`) with no caller, so only the `'always'`-bound subset carries
1038
+ * values there ({@link FILTER_SCOPE_VARS}). Caller-bound vars fail closed
1039
+ * `$assigned` binds its caller-free constant `false`, the rest evaluate to
1040
+ * `undefined` — and deploy rejects them at these sites: routing and gate
1041
+ * resolution must resolve identically no matter whose token triggers the
1042
+ * evaluation.
1020
1043
  * 3. **Guard predicates** — NOT conditions. A lake mutation guard's
1021
1044
  * `predicate` is groq-js **delta-mode** GROQ over a document mutation:
1022
1045
  * `before()`/`after()`/`identity()` are dialect natives, and the wire
@@ -1031,7 +1054,7 @@ export declare interface ConditionVar {
1031
1054
  * - `'caller'` — rides the acting caller; without one the var is `undefined`
1032
1055
  * (conditions referencing it fail closed). Author predicates may not read
1033
1056
  * these — they pre-evaluate once per instance, caller-free.
1034
- * - `'spawn'` — bound only at `subworkflows` sites.
1057
+ * - `'spawn'` — bound only at `subworkflows` sites (the per-row `$row`).
1035
1058
  */
1036
1059
  export declare type ConditionVarBinding = "always" | "caller" | "spawn";
1037
1060
 
@@ -1055,6 +1078,14 @@ export declare function defineField(
1055
1078
  entry: AuthoringFieldEntry,
1056
1079
  ): AuthoringFieldEntry;
1057
1080
 
1081
+ /**
1082
+ * Validate and return a group declaration — advisory "what belongs together"
1083
+ * metadata. Declared in a `groups` array (workflow root, stage, or activity);
1084
+ * fields, activities, and actions join via `group`. The engine stores and
1085
+ * deploy-checks groups but never acts on them.
1086
+ */
1087
+ export declare function defineGroup(group: Group): Group;
1088
+
1058
1089
  export declare function defineGuard(guard: AuthoringGuard): AuthoringGuard;
1059
1090
 
1060
1091
  export declare function defineOp(op: AuthoringOp): AuthoringOp;
@@ -1146,6 +1177,26 @@ declare const EffectSchema: v.StrictObjectSchema<
1146
1177
  v.RecordSchema<v.StringSchema<undefined>, v.UnknownSchema, undefined>,
1147
1178
  undefined
1148
1179
  >;
1180
+ /**
1181
+ * The outputs this effect is allowed to produce, as typed {@link FieldShape}s
1182
+ * (each `name` is an output key, read downstream as `$effects['<name>'].<key>`;
1183
+ * an `array` output is an array of objects shaped by `of`).
1184
+ *
1185
+ * A STRICT allowlist: at completion the handler's returned `outputs` are
1186
+ * validated against these shapes and an undeclared key — or a value that
1187
+ * doesn't fit its shape — fails the completion (nothing is stored). Omitting
1188
+ * `outputs` is an EMPTY allowlist: the effect produces nothing, so any returned
1189
+ * output is rejected — the bound is universal, not opt-in.
1190
+ * Why strict: `effectsContext` lives on the instance document, so the allowlist
1191
+ * keeps it bounded — a handler can't accidentally spread a whole API response
1192
+ * into the instance — and the declared shapes let tooling (e.g. the simulator's
1193
+ * drain UI) suggest an effect's exact output keys. Declaring outputs also
1194
+ * powers the advisory deploy-time producer/consumer lint.
1195
+ */
1196
+ readonly outputs: v.OptionalSchema<
1197
+ v.ArraySchema<v.GenericSchema<FieldShape>, undefined>,
1198
+ undefined
1199
+ >;
1149
1200
  },
1150
1201
  undefined
1151
1202
  >;
@@ -1155,6 +1206,9 @@ declare const EffectSchema: v.StrictObjectSchema<
1155
1206
  * reference kinds, the actor/assignee identities, and the two compositional
1156
1207
  * kinds (`object` with named `fields`, `array` of objects shaped by `of`).
1157
1208
  * This is also the set a nested {@link FieldShape} sub-field may use.
1209
+ *
1210
+ * Exported (module-level, not package API) for the model-surface gate's
1211
+ * enum-value coverage test.
1158
1212
  */
1159
1213
  declare const FIELD_VALUE_KINDS: readonly [
1160
1214
  "doc.ref",
@@ -1174,22 +1228,28 @@ declare const FIELD_VALUE_KINDS: readonly [
1174
1228
  "array",
1175
1229
  ];
1176
1230
 
1177
- /** Type-mirror of {@link fieldBase}, parameterised over the `editable` grammar. */
1178
- declare type FieldBase<TEditable> = {
1231
+ /** Type-mirror of {@link fieldBase}, parameterised over the `editable` and
1232
+ * `group` grammars (stored membership is the canonical list form). */
1233
+ declare type FieldBase<TEditable, TGroup> = {
1179
1234
  name: string;
1180
1235
  title?: string | undefined;
1181
1236
  description?: string | undefined;
1237
+ group?: TGroup | undefined;
1182
1238
  required?: boolean | undefined;
1183
1239
  initialValue?: FieldSource | undefined;
1184
1240
  editable?: TEditable | undefined;
1185
1241
  };
1186
1242
 
1187
- declare type FieldEntry = FieldEntryFields<Editable>;
1243
+ declare type FieldEntry = FieldEntryFields<Editable, string[]>;
1188
1244
 
1189
1245
  /** Type-mirror of {@link fieldEntryFields}: a raw field entry of the given
1190
- * editability grammar. */
1191
- declare type FieldEntryFields<TEditable> = FieldBase<TEditable> & {
1246
+ * editability and group-membership grammars. */
1247
+ declare type FieldEntryFields<TEditable, TGroup> = FieldBase<
1248
+ TEditable,
1249
+ TGroup
1250
+ > & {
1192
1251
  type: FieldValueKind;
1252
+ types?: string[] | undefined;
1193
1253
  fields?: FieldShape[] | undefined;
1194
1254
  of?: FieldShape[] | undefined;
1195
1255
  };
@@ -1230,7 +1290,8 @@ declare type FieldValueKind = (typeof FIELD_VALUE_KINDS)[number];
1230
1290
 
1231
1291
  /**
1232
1292
  * The subset that holds a value when the engine evaluates filters without a
1233
- * caller (the cascade path: transition filters, `completeWhen`/`failWhen`).
1293
+ * caller (the cascade path: transition filters, activity `filter`/
1294
+ * `completeWhen`/`failWhen`).
1234
1295
  */
1235
1296
  export declare const FILTER_SCOPE_VARS: readonly string[];
1236
1297
 
@@ -1254,6 +1315,30 @@ export declare function groq(
1254
1315
  ...values: unknown[]
1255
1316
  ): string;
1256
1317
 
1318
+ /** Type-mirror of {@link GroupSchema} — one declared group. */
1319
+ declare type Group = {
1320
+ name: string;
1321
+ title?: string | undefined;
1322
+ description?: string | undefined;
1323
+ kind?: GroupKind | undefined;
1324
+ };
1325
+
1326
+ declare const GROUP_KINDS: readonly ["core", "details"];
1327
+
1328
+ declare type GroupKind = (typeof GROUP_KINDS)[number];
1329
+
1330
+ /**
1331
+ * Group membership — the declared group(s) a node belongs to. A reference
1332
+ * resolves lexically up the node's enclosing chain (host activity → stage →
1333
+ * workflow; an activity's OWN membership sees stage → workflow — a node is
1334
+ * never a member of a group only it declares). An empty list is an author
1335
+ * error (it would name no groups) — omit `group` instead, and each group is
1336
+ * listed once. Authoring accepts a bare name as convenience; the STORED form
1337
+ * is always a list, so `'seo'` and `['seo']` hash identically under content
1338
+ * addressing and lake-side reads see one shape.
1339
+ */
1340
+ declare type GroupMembership = string | string[];
1341
+
1257
1342
  declare type Guard = v.InferOutput<typeof GuardSchema>;
1258
1343
 
1259
1344
  /**
@@ -1340,8 +1425,8 @@ declare const GuardSchema: v.StrictObjectSchema<
1340
1425
  undefined
1341
1426
  >;
1342
1427
  /**
1343
- * Lake GROQ predicate — a distinct eval context reading
1344
- * `document.before`/`document.after`, `mutation`, `guard`, and
1428
+ * Lake GROQ predicate — a distinct eval context: delta-mode GROQ
1429
+ * reading the `before()`/`after()` natives, `mutation`, `guard`, and
1345
1430
  * `identity()`. Bare ids/fields only. Omitted or empty means
1346
1431
  * UNCONDITIONAL DENY.
1347
1432
  */
@@ -1388,7 +1473,7 @@ declare type ManualTarget = v.InferOutput<typeof StoredManualTargetSchema>;
1388
1473
  * { body, actor, at }` (the `actor`/`at` sub-fields match the `audit` op's
1389
1474
  * stamp names, so it pairs with it). Never a stored kind.
1390
1475
  */
1391
- declare type NotesField = FieldBase<AuthoringEditable> & {
1476
+ declare type NotesField = FieldBase<AuthoringEditable, GroupMembership> & {
1392
1477
  type: "notes";
1393
1478
  };
1394
1479
 
@@ -1472,6 +1557,7 @@ declare type StageFields<TField, TActivity, TTransition, TGuard, TEditable> = {
1472
1557
  name: string;
1473
1558
  title?: string | undefined;
1474
1559
  description?: string | undefined;
1560
+ groups?: Group[] | undefined;
1475
1561
  activities?: TActivity[] | undefined;
1476
1562
  transitions?: TTransition[] | undefined;
1477
1563
  guards?: TGuard[] | undefined;
@@ -1825,7 +1911,14 @@ declare type Subworkflows = v.InferOutput<typeof SubworkflowsSchema>;
1825
1911
 
1826
1912
  declare const SubworkflowsSchema: v.StrictObjectSchema<
1827
1913
  {
1828
- /** GROQ producing one row per subworkflow; each row binds as `$row`. */
1914
+ /**
1915
+ * GROQ producing one row per subworkflow; each row binds as `$row`. Every
1916
+ * row must carry an identity the engine can adopt against on re-entry:
1917
+ * `_key` ?? `_id` ?? GDR `id` for object rows (a GDR value — `{id, type}`
1918
+ * with a GDR-URI `id`, the rows a `doc.refs` field stores — keys on its
1919
+ * `id`; mint a `_key` in the projection for synthetic rows), the value
1920
+ * itself for scalar rows. A row without an identity fails the spawn.
1921
+ */
1829
1922
  readonly forEach: v.SchemaWithPipe<
1830
1923
  readonly [
1831
1924
  v.StringSchema<undefined>,
@@ -1901,6 +1994,23 @@ declare const SubworkflowsSchema: v.StrictObjectSchema<
1901
1994
  >,
1902
1995
  undefined
1903
1996
  >;
1997
+ /**
1998
+ * What happens to still-live children when their cohort's scope stops
1999
+ * applying — the spawning stage exits, or a re-entry's `forEach` no longer
2000
+ * discovers their row. `'detach'` (the default) lets them run to
2001
+ * completion outside the gate; `'abort'` kills them (recursively). The
2002
+ * engine never destroys in-flight work implicitly — `'abort'` is always
2003
+ * an authored choice. Note this governs only the CHILDREN's fate; whether
2004
+ * the parent may move at all is what gates (`completeWhen`, transition
2005
+ * filters over `$subworkflows`) decide.
2006
+ */
2007
+ readonly onExit: v.OptionalSchema<
2008
+ v.PicklistSchema<
2009
+ readonly ["detach", "abort"],
2010
+ `Invalid option: expected one of ${string}`
2011
+ >,
2012
+ undefined
2013
+ >;
1904
2014
  },
1905
2015
  undefined
1906
2016
  >;
@@ -1919,7 +2029,7 @@ declare type TerminalActivityStatus =
1919
2029
  * { label, status, assignee?, dueDate? }`; a plain checklist is this used with
1920
2030
  * `{label, status}` only (open ↔ done). Never a stored kind.
1921
2031
  */
1922
- declare type TodoListField = FieldBase<AuthoringEditable> & {
2032
+ declare type TodoListField = FieldBase<AuthoringEditable, GroupMembership> & {
1923
2033
  type: "todoList";
1924
2034
  };
1925
2035
 
@@ -2202,7 +2312,9 @@ declare const WorkflowConfigSchema: v.ObjectSchema<
2202
2312
  name: string;
2203
2313
  title: string;
2204
2314
  description?: string | undefined;
2315
+ groups?: Group[] | undefined;
2205
2316
  lifecycle?: WorkflowLifecycle | undefined;
2317
+ applicableWhen?: string | undefined;
2206
2318
  initialStage: string;
2207
2319
  fields?: FieldEntry[] | undefined;
2208
2320
  stages: Stage[];
@@ -2218,7 +2330,9 @@ declare const WorkflowConfigSchema: v.ObjectSchema<
2218
2330
  name: string;
2219
2331
  title: string;
2220
2332
  description?: string | undefined;
2333
+ groups?: Group[] | undefined;
2221
2334
  lifecycle?: WorkflowLifecycle | undefined;
2335
+ applicableWhen?: string | undefined;
2222
2336
  initialStage: string;
2223
2337
  fields?: FieldEntry[] | undefined;
2224
2338
  stages: Stage[];
@@ -2282,7 +2396,9 @@ declare const WorkflowConfigSchema: v.ObjectSchema<
2282
2396
  name: string;
2283
2397
  title: string;
2284
2398
  description?: string | undefined;
2399
+ groups?: Group[] | undefined;
2285
2400
  lifecycle?: WorkflowLifecycle | undefined;
2401
+ applicableWhen?: string | undefined;
2286
2402
  initialStage: string;
2287
2403
  fields?: FieldEntry[] | undefined;
2288
2404
  stages: Stage[];
@@ -2340,7 +2456,9 @@ declare const WorkflowConfigSchema: v.ObjectSchema<
2340
2456
  name: string;
2341
2457
  title: string;
2342
2458
  description?: string | undefined;
2459
+ groups?: Group[] | undefined;
2343
2460
  lifecycle?: WorkflowLifecycle | undefined;
2461
+ applicableWhen?: string | undefined;
2344
2462
  initialStage: string;
2345
2463
  fields?: FieldEntry[] | undefined;
2346
2464
  stages: Stage[];
@@ -2352,6 +2470,21 @@ declare const WorkflowConfigSchema: v.ObjectSchema<
2352
2470
  >,
2353
2471
  ]
2354
2472
  >;
2473
+ /**
2474
+ * Custom telemetry destination for the CLI. When set, the CLI's built-in
2475
+ * Sanity-intake shell is not constructed and none of its policy applies:
2476
+ * every event — the command trace and the engine vocabulary — flows to
2477
+ * this logger unconditionally (CI and `DO_NOT_TRACK` environments
2478
+ * included). Consent, environment suppression, transport, and destination
2479
+ * are wholly this implementation's business.
2480
+ */
2481
+ readonly telemetry: v.OptionalSchema<
2482
+ v.CustomSchema<
2483
+ WorkflowTelemetryLogger,
2484
+ v.ErrorMessage<v.CustomIssue> | undefined
2485
+ >,
2486
+ undefined
2487
+ >;
2355
2488
  },
2356
2489
  undefined
2357
2490
  >;
@@ -2382,7 +2515,9 @@ declare type WorkflowFields<TField, TStage> = {
2382
2515
  name: string;
2383
2516
  title: string;
2384
2517
  description?: string | undefined;
2518
+ groups?: Group[] | undefined;
2385
2519
  lifecycle?: WorkflowLifecycle | undefined;
2520
+ applicableWhen?: string | undefined;
2386
2521
  initialStage: string;
2387
2522
  fields?: TField[] | undefined;
2388
2523
  stages: TStage[];
@@ -2395,4 +2530,35 @@ declare type WorkflowFields<TField, TStage> = {
2395
2530
  * {@link isStartableDefinition}. */
2396
2531
  declare type WorkflowLifecycle = (typeof WORKFLOW_LIFECYCLES)[number];
2397
2532
 
2533
+ /**
2534
+ * A telemetry event descriptor — a structural mirror of `@sanity/telemetry`'s
2535
+ * `DefinedTelemetryLog`, so shells hand these straight to their store logger.
2536
+ */
2537
+ declare interface WorkflowTelemetryEvent<Data = void> {
2538
+ type: "log";
2539
+ /** Matched verbatim downstream — frozen once shipped. */
2540
+ name: string;
2541
+ /** Bumped on any payload shape change; the name never changes. */
2542
+ version: number;
2543
+ /** Optional to match the real package's event shape, so an event built
2544
+ * with the real `defineEvent` flows into this seam; the engine's own
2545
+ * vocabulary always sets it. */
2546
+ description?: string;
2547
+ /** Advisory volume cap enforced by the shell's store — at most one
2548
+ * submission per interval (ms). */
2549
+ maxSampleRate?: number;
2550
+ /** Type-level payload carrier — never set at runtime (the real package's
2551
+ * `defineEvent` leaves it unset the same way). */
2552
+ schema: Data;
2553
+ }
2554
+
2555
+ /**
2556
+ * The logger surface the engine emits through — the `log` subset of
2557
+ * `@sanity/telemetry`'s `TelemetryLogger`, so any real logger satisfies it.
2558
+ */
2559
+ declare interface WorkflowTelemetryLogger {
2560
+ log<Data>(event: WorkflowTelemetryEvent<Data>, data: Data): void;
2561
+ log(event: WorkflowTelemetryEvent<void>): void;
2562
+ }
2563
+
2398
2564
  export {};