@sanity/workflow-engine 0.23.0 → 0.25.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/index.d.ts CHANGED
@@ -20,6 +20,8 @@ import { humanize } from "@sanity/groq-condition-describe";
20
20
  import { InsightPhrase } from "@sanity/groq-condition-describe";
21
21
  import { isComparisonOp } from "@sanity/groq-condition-describe";
22
22
  import { MAX_COUNTERFACTUAL_INDEX } from "@sanity/groq-condition-describe";
23
+ import { NEUTRAL_MARK } from "@sanity/groq-condition-describe";
24
+ import { OUTCOME_MARKS } from "@sanity/groq-condition-describe";
23
25
  import { quoted } from "@sanity/groq-condition-describe";
24
26
  import type { SanityDocument } from "@sanity/types";
25
27
  import { ScopeAssignment } from "@sanity/groq-condition-describe";
@@ -551,14 +553,17 @@ export declare type ActivityStatus = (typeof ACTIVITY_STATUSES)[number];
551
553
  * read time, and only the lake's own token identity is authenticated — hard
552
554
  * enforcement lives there.
553
555
  *
554
- * `id` is the account-global user id (the global API host's `/users/me`)
555
- * the one identity namespace that is stable across projects and org-level
556
- * resources. Robot tokens carry a single universal id, so for them `id`
557
- * equals what every host returns. Instances written before ids were
558
- * namespace-classified carry the workflow resource's local principal id in
559
- * `id` instead; readers interpret those through the prefix classifier in
560
- * `core/identity.ts` with the document's home resource as the implied
561
- * scope.
556
+ * `id` is the account-global user id the one identity namespace that is
557
+ * stable across projects and org-level resources. The engine takes it from the
558
+ * first route that can answer for the token: an id either host's `/users/me`
559
+ * already carries in account-global form (the id itself, or the one embedded in
560
+ * an `e-` principal), and otherwise the project's own user directory
561
+ * (`sanityUserId`) the route a session scoped to a single project depends on,
562
+ * since no global record exists for it. Robot tokens carry a single universal
563
+ * id, so for them `id` equals what every host returns. Instances written before
564
+ * ids were namespace-classified carry the workflow resource's local principal id
565
+ * in `id` instead; readers interpret those through the prefix classifier in
566
+ * `core/identity.ts` with the document's home resource as the implied scope.
562
567
  */
563
568
  export declare interface Actor {
564
569
  kind: ActorKind;
@@ -1680,7 +1685,8 @@ export declare interface ClientProjectUser {
1680
1685
  readonly [key: string]: unknown;
1681
1686
  }
1682
1687
 
1683
- /** Project-user directory for CLI, MCP, and server runtimes using the engine client. */
1688
+ /** Project-user directory served straight from the engine's own client — the
1689
+ * project API's user endpoints, no host adapter. */
1684
1690
  export declare function clientProjectUserDirectory(
1685
1691
  client: WorkflowClient,
1686
1692
  projectId: string,
@@ -2357,6 +2363,15 @@ export declare const DATA_MODEL_CHANGES: readonly [
2357
2363
  applicability: "detectable";
2358
2364
  summary: "Start and activity readiness use named polymorphic requirement arrays.";
2359
2365
  }>,
2366
+ Readonly<{
2367
+ id: "due-date-field-kinds";
2368
+ introducedInModel: 5;
2369
+ minReaderModel: 0;
2370
+ documentTypes: readonly ["definition", "instance"];
2371
+ compatibility: "additive";
2372
+ applicability: "detectable";
2373
+ summary: string;
2374
+ }>,
2360
2375
  ];
2361
2376
 
2362
2377
  /**
@@ -2381,7 +2396,7 @@ export declare const DATA_MODEL_MIN_READER = 4;
2381
2396
  * job. Declare every bump in `DATAMODEL.md`; the model-surface snapshot test
2382
2397
  * keeps undeclared drift red.
2383
2398
  */
2384
- export declare const DATA_MODEL_VERSION = 4;
2399
+ export declare const DATA_MODEL_VERSION = 5;
2385
2400
 
2386
2401
  export declare interface DataModelChange {
2387
2402
  readonly id: string;
@@ -2537,10 +2552,13 @@ export declare class DefinitionInUseError extends WorkflowError<"definition-in-u
2537
2552
  }
2538
2553
 
2539
2554
  /**
2540
- * Pure GROQ builder for resolving a deployed workflow definition. Composes the
2541
- * doc-type constant and the tag-scope predicate so the engine's internal
2542
- * lookups and the CLI share one definition of "tag-scoped, latest-or-pinned
2555
+ * Pure GROQ builders for deployed workflow definitions. Composes the doc-type
2556
+ * constant and the tag-scope predicate so the engine's internal lookups and the
2557
+ * CLI share one definition of "tag-scoped, latest-or-pinned
2543
2558
  * `workflow.definition`" instead of hand-writing the query at each call site.
2559
+ *
2560
+ * The tag enumerations are the deliberate exception: they span partitions, for a
2561
+ * caller holding a resource but no tag yet.
2544
2562
  */
2545
2563
  /**
2546
2564
  * GROQ resolving a single deployed {@link WORKFLOW_DEFINITION_TYPE} visible to
@@ -2599,6 +2617,19 @@ export declare function definitionsListGroq(
2599
2617
  versionOrder: "asc" | "desc",
2600
2618
  ): string;
2601
2619
 
2620
+ /**
2621
+ * GROQ listing every tag partition that holds any version of one definition
2622
+ * name — {@link deployedTagsGroq} narrowed from "what exists here" to "where
2623
+ * is this".
2624
+ *
2625
+ * Several hits is ambiguity to refuse, not resolve: version numbers are
2626
+ * per-partition, so the highest one may sit in an environment the caller did
2627
+ * not mean, and the answer would carry no sign of it.
2628
+ *
2629
+ * Params: `$definition`.
2630
+ */
2631
+ export declare function definitionTagsGroq(): string;
2632
+
2602
2633
  export declare interface DeleteDefinitionArgs {
2603
2634
  /** The definition's `name` — delete addresses the workflow, not a doc id. */
2604
2635
  definition: string;
@@ -2748,6 +2779,13 @@ export declare type DeployedDefinition = WorkflowDefinition & {
2748
2779
  minReaderModel?: number;
2749
2780
  };
2750
2781
 
2782
+ /**
2783
+ * GROQ listing every tag partition holding a deployed
2784
+ * {@link WORKFLOW_DEFINITION_TYPE} in the resource. The un-scoped
2785
+ * inverse of {@link tagScopeFilter}, this deliberately spans partitions.
2786
+ */
2787
+ export declare function deployedTagsGroq(): string;
2788
+
2751
2789
  /**
2752
2790
  * Deploy every guard for a stage being entered (idempotent upsert), but only
2753
2791
  * while the instance is still committed to that stage. A deploy that lost the
@@ -3999,7 +4037,7 @@ export declare interface EvaluateArgs {
3999
4037
  instanceId: string;
4000
4038
  /**
4001
4039
  * URL path on the supplied client where the engine should fetch
4002
- * grants. The actor always token-resolves via `/users/me`; without
4040
+ * grants. The actor always token-resolves from the supplied client; without
4003
4041
  * a grants path the rendered `$can` is undefined, so conditions
4004
4042
  * referencing it fail closed — and the real Sanity write boundary
4005
4043
  * still enforces.
@@ -4337,10 +4375,18 @@ export declare const FIELD_KIND_DISPLAY: {
4337
4375
  title: string;
4338
4376
  description: string;
4339
4377
  };
4378
+ dueDate: {
4379
+ title: string;
4380
+ description: string;
4381
+ };
4340
4382
  datetime: {
4341
4383
  title: string;
4342
4384
  description: string;
4343
4385
  };
4386
+ dueDatetime: {
4387
+ title: string;
4388
+ description: string;
4389
+ };
4344
4390
  url: {
4345
4391
  title: string;
4346
4392
  description: string;
@@ -4389,7 +4435,9 @@ declare const FIELD_VALUE_KINDS: readonly [
4389
4435
  "progress",
4390
4436
  "boolean",
4391
4437
  "date",
4438
+ "dueDate",
4392
4439
  "datetime",
4440
+ "dueDatetime",
4393
4441
  "url",
4394
4442
  "actor",
4395
4443
  "assignee",
@@ -4534,8 +4582,12 @@ export declare interface FieldValueMap {
4534
4582
  boolean: boolean | null;
4535
4583
  /** Date-only (`YYYY-MM-DD`), no time component. */
4536
4584
  date: string | null;
4585
+ /** THE due date of a level — same value as {@link FieldValueMap.date}. */
4586
+ dueDate: string | null;
4537
4587
  /** ISO-8601 timestamp. */
4538
4588
  datetime: string | null;
4589
+ /** THE due datetime of a level — same value as {@link FieldValueMap.datetime}. */
4590
+ dueDatetime: string | null;
4539
4591
  url: string | null;
4540
4592
  actor: Actor | null;
4541
4593
  /** A single {@link Assignee} — the singular of {@link FieldValueMap.assignees}. */
@@ -6368,6 +6420,8 @@ export declare function narrateAutonomyWaits(
6368
6420
  ctx: DescribeContext,
6369
6421
  ): string[];
6370
6422
 
6423
+ export { NEUTRAL_MARK };
6424
+
6371
6425
  /** The default logger: emit nothing. The engine's twin of `@sanity/telemetry`'s `noopLogger`. */
6372
6426
  export declare const noopTelemetry: WorkflowTelemetryLogger;
6373
6427
 
@@ -6470,6 +6524,8 @@ export declare interface OperationResult {
6470
6524
  ranOps?: OpAppliedSummary[];
6471
6525
  }
6472
6526
 
6527
+ export { OUTCOME_MARKS };
6528
+
6473
6529
  /**
6474
6530
  * The instance's direct parent — the last entry of the root-first
6475
6531
  * {@link WorkflowInstance.ancestors} chain; `undefined` for a root instance.
@@ -6796,7 +6852,7 @@ export declare class ReaderModelAcknowledgementError extends WorkflowError<"read
6796
6852
  readonly code = "WORKFLOW_READER_MODEL_ACKNOWLEDGEMENT_MISMATCH";
6797
6853
  readonly expectedMinReaderModel: unknown;
6798
6854
  readonly engineMinReaderModel = 4;
6799
- readonly engineModelVersion = 4;
6855
+ readonly engineModelVersion = 5;
6800
6856
  readonly documentationUrl =
6801
6857
  "https://www.sanity.io/docs/editorial-workflows/prerelease";
6802
6858
  constructor(expectedMinReaderModel: unknown, context?: string);
@@ -7690,8 +7746,8 @@ export declare interface StartInstanceArgs {
7690
7746
  instanceId?: string;
7691
7747
  /**
7692
7748
  * URL path on the supplied client where the engine fetches the
7693
- * caller's ACL grants. Identity is always token-resolved — `actor`
7694
- * comes from `client.request({ uri: "/users/me" })` — and grants
7749
+ * caller's ACL grants. Identity is always token-resolved — `actor` is
7750
+ * resolved from the supplied client's token, never passed in — and grants
7695
7751
  * feed the advisory `$can.*` params action conditions can read;
7696
7752
  * omitting this leaves the rendered `$can` undefined (conditions
7697
7753
  * referencing it fail closed, nothing else is gated engine-side —
@@ -8639,6 +8695,10 @@ export declare function toBareId(id: string): string;
8639
8695
  * `todoList` — ad-hoc, status-tracked work items. Sugar over `array of object
8640
8696
  * { label, status, assignee?, dueDate? }`; a plain checklist is this used with
8641
8697
  * `{label, status}` only (open ↔ done). Never a stored kind.
8698
+ *
8699
+ * The `dueDate` column is a `date` NAMED `dueDate`, not the {@link
8700
+ * FieldValueMap.dueDate} kind — that kind reserves one deadline slot per level,
8701
+ * and a repeating row has nothing to reserve.
8642
8702
  */
8643
8703
  declare type TodoListField = FieldBase<AuthoringEditable, GroupMembership> & {
8644
8704
  type: "todoList";
@@ -9332,10 +9392,14 @@ export declare interface WorkflowAutonomy extends AutonomyAnswer {
9332
9392
 
9333
9393
  export declare interface WorkflowClient {
9334
9394
  /**
9335
- * Read the effective client configuration. The engine probes `apiHost`
9336
- * before deriving the global `/users/me` sibling because `@sanity/client`
9337
- * shallow-merges `withConfig` overrides and otherwise preserves an explicit
9338
- * project host even when `useProjectHostname` is set to `false`.
9395
+ * Read the effective client configuration. The engine reads two fields from
9396
+ * it. `apiHost` is probed before deriving the global `/users/me` sibling,
9397
+ * because `@sanity/client` shallow-merges `withConfig` overrides and
9398
+ * otherwise preserves an explicit project host even when
9399
+ * `useProjectHostname` is set to `false`. `projectId` addresses the project's
9400
+ * user directory when a project-scoped principal has to be bridged to its
9401
+ * account-global id — a client reporting none has no directory to ask, and
9402
+ * such a session is refused rather than stamped locally.
9339
9403
  */
9340
9404
  config?: () => WorkflowClientConfig;
9341
9405
  fetch: <T = unknown>(
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
- import { terminalState, andConditions, deriveActivityKind, parseDefinitionSnapshot, CALLER_BOUND_VARS, START_REQUIREMENT_VARS, CONDITION_VARS, isSubjectEntry, isUnevaluable, ContractViolationError, isStartableDefinition, conditionFieldReadNames, rethrowWithContext, isGdr, errorMessage, conditionParameterNames, START_FILTER_VARS, gdrFromResource, selfGdr, isSingleDocRefKind, parentRef, actorFulfillsRole, toBareId, WorkflowError, sameResource, resourceFromParsed, tryParseGdr, isTerminalActivityStatus, FieldValueShapeError, validateFieldValue, validateFieldAppendItem, evaluateCondition, isSingleDocRefEntry, choiceValueIssues, scalarValidationIssues, StoredFieldOpSchema, formatIssues, conditionSyntaxIssues, checkWorkflowInvariants, formatIssuePath, isGuardReadExpr, conditionEffectReads, EFFECTS_READ, datasetResourceParts, evaluatePredicates, WORKFLOW_DEFINITION_TYPE, tagScopeFilter, isCascadeFired, WORKFLOW_INSTANCE_TYPE, parseGdr, isGdrUri, gdrRef, isInputSourced, parseFieldValue, VersionSpecificDatasetGdrError, toPhysicalGdr, isBareSeedId, tolerantEntries, NonEmptyString, FIELD_VALUE_KINDS, tolerantObject, ActorShape, IsoTimestamp, ACTIVITY_STATUSES, GdrShape, DRIVER_KINDS, FIELD_SCOPES, fieldValueSchemas, parsePersistedDoc, ACTOR_KINDS, classifyPrincipalId, assertReadableModel, InstanceNotFoundError, modelStampFor, evaluateConditionOutcome, runGroq, FIELD_READ, MUTATION_GUARD_ACTIONS, resourceGdr, minReaderModelOf, resourceFromGdrUri, refTypeIssues, rejectedRefTypes, DOCUMENT_VALUE_PERMISSIONS, lakePrincipalId, driverKind, EffectNotFoundError, deriveExecutorClassification, validateTag, extractDocumentId, parseStoredDefinition, validateResourceAliasName, labelFor, DefinitionNotFoundError, definitionDocId, SpawnContractsInvalidError, gdrResourcePrefix, RESOURCE_ALIAS_NAME_SOURCE, isUnprimed, DefinitionInUseError, assertReaderModelAcknowledgement, isParseableInstant, groupMembershipNames } from "./_chunks-es/invariants.js";
1
+ import { terminalState, andConditions, deriveActivityKind, parseDefinitionSnapshot, CALLER_BOUND_VARS, START_REQUIREMENT_VARS, CONDITION_VARS, isSubjectEntry, isUnevaluable, ContractViolationError, isStartableDefinition, conditionFieldReadNames, rethrowWithContext, isGdr, errorMessage, conditionParameterNames, START_FILTER_VARS, gdrFromResource, selfGdr, isSingleDocRefKind, parentRef, actorFulfillsRole, toBareId, WorkflowError, sameResource, resourceFromParsed, tryParseGdr, isTerminalActivityStatus, FieldValueShapeError, validateFieldValue, validateFieldAppendItem, evaluateCondition, isSingleDocRefEntry, choiceValueIssues, scalarValidationIssues, StoredFieldOpSchema, formatIssues, conditionSyntaxIssues, checkWorkflowInvariants, formatIssuePath, isGuardReadExpr, conditionEffectReads, EFFECTS_READ, datasetResourceParts, evaluatePredicates, WORKFLOW_DEFINITION_TYPE, tagScopeFilter, isCascadeFired, WORKFLOW_INSTANCE_TYPE, parseGdr, isGdrUri, gdrRef, isInputSourced, parseFieldValue, VersionSpecificDatasetGdrError, toPhysicalGdr, isBareSeedId, tolerantEntries, NonEmptyString, FIELD_VALUE_KINDS, tolerantObject, ActorShape, IsoTimestamp, ACTIVITY_STATUSES, GdrShape, DRIVER_KINDS, FIELD_SCOPES, fieldValueSchemas, parsePersistedDoc, ACTOR_KINDS, classifyPrincipalId, directoryBridgeId, assertReadableModel, InstanceNotFoundError, modelStampFor, evaluateConditionOutcome, runGroq, FIELD_READ, MUTATION_GUARD_ACTIONS, resourceGdr, minReaderModelOf, resourceFromGdrUri, refTypeIssues, rejectedRefTypes, DOCUMENT_VALUE_PERMISSIONS, lakePrincipalId, driverKind, EffectNotFoundError, firstCarriedGlobalId, deriveExecutorClassification, validateTag, extractDocumentId, parseStoredDefinition, validateResourceAliasName, labelFor, DefinitionNotFoundError, definitionDocId, SpawnContractsInvalidError, gdrResourcePrefix, RESOURCE_ALIAS_NAME_SOURCE, isUnprimed, DefinitionInUseError, assertReaderModelAcknowledgement, isParseableInstant, groupMembershipNames } from "./_chunks-es/invariants.js";
2
2
 
3
3
  import { ACTION_SEMANTICS, ACTIVITY_KINDS, ANONYMOUS_IDENTITY, DATA_MODEL_CHANGES, DATA_MODEL_MIN_READER, DATA_MODEL_VERSION, DEFAULT_TRANSITION_WHEN, EXECUTOR_CLASSIFICATIONS, FILTER_SCOPE_VARS, GROUP_KINDS, GUARD_PREDICATE_VARS, ModelVersionAheadError, PersistedDocShapeError, READER_MODEL_ROLLOUT_URL, RESERVED_CONDITION_VARS, ReaderModelAcknowledgementError, SYSTEM_IDENTITY, clientConfigFromResource, fieldTreeShape, gdrUri, isNotesEntry, isTodoListEntry, isTodoListItem, modelVersionOf, parseDefinitionSnapshotValue, parseResourceGdr, readsRootDocument, refCanvas, refDashboard, refDataset, refKindAcceptsTypes, refMediaLibrary, releaseDocId, releaseRef, requiredModelFeatures, requiredReaderModel, resourceAliasesToMap, schemaTreeShape, startKindOf } from "./_chunks-es/invariants.js";
4
4
 
5
5
  import { atomNode, dedupeBy, analyzeCondition, atomReadsDataset, checklistLines as checklistLines$1, phrase, quoted, listAnd, describeAtom as describeAtom$1, describeCondition as describeCondition$1, guillemets, formatValue, humanize, listOr, scopeReadOf, describeRead, explainCondition, dedupeReads, whatIfCondition, MAX_COUNTERFACTUAL_INDEX } from "@sanity/groq-condition-describe";
6
6
 
7
- import { MAX_COUNTERFACTUAL_INDEX as MAX_COUNTERFACTUAL_INDEX2, analyzeCondition as analyzeCondition2, atomReadsDataset as atomReadsDataset2, explainCondition as explainCondition2, formatRead, guillemets as guillemets2, humanize as humanize2, isComparisonOp, quoted as quoted2, sentenceCase, whatIfCondition as whatIfCondition2, withAssignment } from "@sanity/groq-condition-describe";
7
+ import { MAX_COUNTERFACTUAL_INDEX as MAX_COUNTERFACTUAL_INDEX2, NEUTRAL_MARK, OUTCOME_MARKS, analyzeCondition as analyzeCondition2, atomReadsDataset as atomReadsDataset2, explainCondition as explainCondition2, formatRead, guillemets as guillemets2, humanize as humanize2, isComparisonOp, quoted as quoted2, sentenceCase, whatIfCondition as whatIfCondition2, withAssignment } from "@sanity/groq-condition-describe";
8
8
 
9
9
  import { evaluate, parse } from "groq-js";
10
10
 
@@ -3301,6 +3301,14 @@ function latestDefinitionsGroq() {
3301
3301
  return `*[${scoped} && version == math::max(*[${scoped} && name == ^.name].version)] | order(name asc)`;
3302
3302
  }
3303
3303
 
3304
+ function deployedTagsGroq() {
3305
+ return `array::unique(*[_type == "${WORKFLOW_DEFINITION_TYPE}"].tag) | order(@ asc)`;
3306
+ }
3307
+
3308
+ function definitionTagsGroq() {
3309
+ return `array::unique(*[_type == "${WORKFLOW_DEFINITION_TYPE}" && name == $definition].tag) | order(@ asc)`;
3310
+ }
3311
+
3304
3312
  function latestDeployedDefinitions(rows) {
3305
3313
  const byName = /* @__PURE__ */ new Map;
3306
3314
  for (const row of rows) {
@@ -4113,7 +4121,7 @@ const OptionalRefTypes = v.exactOptional(v.array(v.string())), ResolvedFieldEntr
4113
4121
  })), v.looseObject(tolerantEntries()({
4114
4122
  ...fieldArm("subject", fieldValueSchemas.subject),
4115
4123
  types: OptionalRefTypes
4116
- })), v.looseObject(tolerantEntries()(fieldArm("release.ref", fieldValueSchemas["release.ref"]))), v.looseObject(tolerantEntries()(fieldArm("string", fieldValueSchemas.string))), v.looseObject(tolerantEntries()(fieldArm("text", fieldValueSchemas.text))), v.looseObject(tolerantEntries()(fieldArm("number", fieldValueSchemas.number))), v.looseObject(tolerantEntries()(fieldArm("progress", fieldValueSchemas.progress))), v.looseObject(tolerantEntries()(fieldArm("boolean", fieldValueSchemas.boolean))), v.looseObject(tolerantEntries()(fieldArm("date", fieldValueSchemas.date))), v.looseObject(tolerantEntries()(fieldArm("datetime", fieldValueSchemas.datetime))), v.looseObject(tolerantEntries()(fieldArm("url", fieldValueSchemas.url))), v.looseObject(tolerantEntries()(fieldArm("actor", fieldValueSchemas.actor))), v.looseObject(tolerantEntries()(fieldArm("assignee", fieldValueSchemas.assignee))), v.looseObject(tolerantEntries()(fieldArm("assignees", fieldValueSchemas.assignees))), v.looseObject(tolerantEntries()({
4124
+ })), v.looseObject(tolerantEntries()(fieldArm("release.ref", fieldValueSchemas["release.ref"]))), v.looseObject(tolerantEntries()(fieldArm("string", fieldValueSchemas.string))), v.looseObject(tolerantEntries()(fieldArm("text", fieldValueSchemas.text))), v.looseObject(tolerantEntries()(fieldArm("number", fieldValueSchemas.number))), v.looseObject(tolerantEntries()(fieldArm("progress", fieldValueSchemas.progress))), v.looseObject(tolerantEntries()(fieldArm("boolean", fieldValueSchemas.boolean))), v.looseObject(tolerantEntries()(fieldArm("date", fieldValueSchemas.date))), v.looseObject(tolerantEntries()(fieldArm("dueDate", fieldValueSchemas.dueDate))), v.looseObject(tolerantEntries()(fieldArm("datetime", fieldValueSchemas.datetime))), v.looseObject(tolerantEntries()(fieldArm("dueDatetime", fieldValueSchemas.dueDatetime))), v.looseObject(tolerantEntries()(fieldArm("url", fieldValueSchemas.url))), v.looseObject(tolerantEntries()(fieldArm("actor", fieldValueSchemas.actor))), v.looseObject(tolerantEntries()(fieldArm("assignee", fieldValueSchemas.assignee))), v.looseObject(tolerantEntries()(fieldArm("assignees", fieldValueSchemas.assignees))), v.looseObject(tolerantEntries()({
4117
4125
  ...fieldArm("object", v.union([ v.null(), UnknownRecord ])),
4118
4126
  fields: v.array(PersistedFieldShapeSchema)
4119
4127
  })), v.looseObject(tolerantEntries()({
@@ -4790,8 +4798,11 @@ function cacheFor(client) {
4790
4798
 
4791
4799
  function ingestDirectoryRows(args) {
4792
4800
  const records = Array.isArray(args.response) ? args.response : [ args.response ];
4793
- for (const row of records) typeof row?.id != "string" || typeof row.sanityUserId != "string" || args.requested.has(row.id) && classifyPrincipalId(row.sanityUserId).namespace === "global" && (args.cache.set(row.id, row.sanityUserId),
4794
- args.out.set(row.id, row.sanityUserId));
4801
+ for (const row of records) {
4802
+ if (typeof row?.id != "string" || !args.requested.has(row.id)) continue;
4803
+ const globalId = directoryBridgeId(row.sanityUserId);
4804
+ globalId !== void 0 && (args.cache.set(row.id, globalId), args.out.set(row.id, globalId));
4805
+ }
4795
4806
  }
4796
4807
 
4797
4808
  async function getInstanceDocument(client, instanceId) {
@@ -5437,10 +5448,14 @@ async function resolveGlobalProjectUser(args) {
5437
5448
  async function ingestMemberJoin(args) {
5438
5449
  const {request: request, projectId: projectId, cache: cache} = args, memberIds = await projectMemberIds(request, projectId);
5439
5450
  if (memberIds.length === 0) return;
5440
- const response = await request({
5451
+ const requested = new Set(memberIds), response = await request({
5441
5452
  uri: `/projects/${encodeURIComponent(projectId)}/users/${memberIds.map(encodeURIComponent).join(",")}`
5442
5453
  });
5443
- for (const row of Array.isArray(response) ? response : [ response ]) isClientProjectUser(row) && typeof row.sanityUserId == "string" && cache.set(`${projectId}:${row.sanityUserId}`, row);
5454
+ for (const row of Array.isArray(response) ? response : [ response ]) {
5455
+ if (!isClientProjectUser(row) || !requested.has(row.id)) continue;
5456
+ const globalId = directoryBridgeId(row.sanityUserId);
5457
+ globalId !== void 0 && cache.set(`${projectId}:${globalId}`, row);
5458
+ }
5444
5459
  }
5445
5460
 
5446
5461
  function clientProjectUserDirectory(client, projectId) {
@@ -5462,7 +5477,10 @@ function clientProjectUserDirectory(client, projectId) {
5462
5477
  }), candidate = Array.isArray(response) ? response[0] : response;
5463
5478
  return candidate == null ? {
5464
5479
  status: "missing"
5465
- } : isClientProjectUser(candidate) ? {
5480
+ } : isClientProjectUser(candidate) ? candidate.id !== id ? {
5481
+ status: "inaccessible",
5482
+ cause: new Error(`Project-user response answered id "${candidate.id}", not the requested "${id}"`)
5483
+ } : {
5466
5484
  status: "resolved",
5467
5485
  user: candidate
5468
5486
  } : {
@@ -8423,14 +8441,20 @@ function cachedGrants({client: client, requestFn: requestFn, resourcePath: resou
8423
8441
  }
8424
8442
 
8425
8443
  async function fetchActor(client, requestFn) {
8426
- const [resourceUser, globalUser] = await Promise.all([ fetchCurrentUser(requestFn, "the workflow resource host"), fetchGlobalUser(client) ]), resourceId = usableId(resourceUser), globalId = usableId(globalUser.user), id = globalId ?? resourceId;
8427
- if (id === void 0) return;
8428
- refuseProjectPrincipalWithoutGlobal({
8429
- resourceId: resourceId,
8430
- globalId: globalId,
8431
- globalUser: globalUser
8432
- });
8433
- const roleNames = (resourceUser?.roles?.length ? resourceUser : globalUser.user)?.roles?.map(r => r.name).filter(n => !!n) ?? [];
8444
+ const [resourceUser, globalUser] = await Promise.all([ fetchCurrentUser(requestFn, "the workflow resource host"), fetchGlobalUser(client) ]), resourceId = usableId(resourceUser), globalHostId = usableId(globalUser.user), carriedId = firstCarriedGlobalId([ globalHostId, resourceId ]), sessionId = carriedId ?? globalHostId ?? resourceId;
8445
+ if (sessionId === void 0) return;
8446
+ const bridge = carriedId === void 0 ? await bridgeProjectPrincipal({
8447
+ client: client,
8448
+ sessionId: sessionId,
8449
+ resourceId: resourceId
8450
+ }) : NO_BRIDGE, id = bridge.status === "resolved" ? bridge.globalId : sessionId;
8451
+ refuseProjectScopedActor({
8452
+ id: id,
8453
+ globalUser: globalUser,
8454
+ globalHostId: globalHostId,
8455
+ bridgeFailure: bridge.status === "unavailable" ? bridge : void 0
8456
+ });
8457
+ const roleNames = roleNamesFor(resourceUser, globalUser);
8434
8458
  return {
8435
8459
  actor: {
8436
8460
  kind: "person",
@@ -8445,13 +8469,62 @@ async function fetchActor(client, requestFn) {
8445
8469
  };
8446
8470
  }
8447
8471
 
8448
- function refuseProjectPrincipalWithoutGlobal(args) {
8449
- const {resourceId: resourceId, globalId: globalId, globalUser: globalUser} = args;
8450
- if (globalId !== void 0 || resourceId === void 0 || classifyPrincipalId(resourceId).namespace !== "project") return;
8451
- const reason = "reason" in globalUser ? globalUser.reason : "no record";
8452
- throw new Error(`workflow: the caller's identity on the workflow resource host is project-scoped ("${resourceId}") and the account-global record could not be resolved (${reason}). The engine speaks account-global user ids only and never acts as a project-scoped principal.`, "cause" in globalUser ? {
8453
- cause: globalUser.cause
8454
- } : void 0);
8472
+ function roleNamesFor(resourceUser, globalUser) {
8473
+ return (resourceUser?.roles?.length ? resourceUser : globalUser.user)?.roles?.map(r => r.name).filter(n => !!n) ?? [];
8474
+ }
8475
+
8476
+ const NO_BRIDGE = {
8477
+ status: "not-applicable"
8478
+ };
8479
+
8480
+ function globalRouteReason(globalUser, globalHostId) {
8481
+ return "reason" in globalUser ? globalUser.reason : globalHostId === void 0 ? "no record" : `the global host answered with project-scoped principal "${globalHostId}"`;
8482
+ }
8483
+
8484
+ async function bridgeProjectPrincipal(args) {
8485
+ const {client: client, sessionId: sessionId, resourceId: resourceId} = args;
8486
+ return classifyPrincipalId(sessionId).namespace !== "project" ? NO_BRIDGE : resourceId === void 0 || classifyPrincipalId(resourceId).namespace !== "project" ? {
8487
+ status: "unavailable",
8488
+ reason: "no project-scoped principal from the resource host to address the directory with"
8489
+ } : directoryGlobalId({
8490
+ client: client,
8491
+ principalId: resourceId
8492
+ });
8493
+ }
8494
+
8495
+ async function directoryGlobalId(args) {
8496
+ const {client: client, principalId: principalId} = args, projectId = typeof client.config == "function" ? client.config().projectId : void 0;
8497
+ if (projectId === void 0) return {
8498
+ status: "unavailable",
8499
+ reason: "the client reports no projectId, so its user directory has no address"
8500
+ };
8501
+ const lookup = await clientProjectUserDirectory(withRequestTag(client, REQUEST_TAG.accessResolveActor), projectId).findById(principalId);
8502
+ if (lookup.status !== "resolved") return {
8503
+ status: "unavailable",
8504
+ reason: `project "${projectId}"'s user directory reported the principal ${lookup.status}`,
8505
+ ...lookup.status === "inaccessible" && lookup.cause !== void 0 ? {
8506
+ cause: lookup.cause
8507
+ } : {}
8508
+ };
8509
+ const globalId = directoryBridgeId(lookup.user.sanityUserId);
8510
+ return globalId === void 0 ? {
8511
+ status: "unavailable",
8512
+ reason: `project "${projectId}"'s user directory row for the principal carries no account-global sanityUserId`
8513
+ } : {
8514
+ status: "resolved",
8515
+ globalId: globalId
8516
+ };
8517
+ }
8518
+
8519
+ function refuseProjectScopedActor(args) {
8520
+ const {id: id, globalUser: globalUser, globalHostId: globalHostId, bridgeFailure: bridgeFailure} = args;
8521
+ if (classifyPrincipalId(id).namespace !== "project") return;
8522
+ const routes = [ `The account-global record: ${globalRouteReason(globalUser, globalHostId)}.` ];
8523
+ bridgeFailure !== void 0 && routes.push(`The project user directory: ${bridgeFailure.reason}.`);
8524
+ const cause = bridgeFailure?.cause ?? ("cause" in globalUser ? globalUser.cause : void 0);
8525
+ throw new Error(`workflow: the caller's identity resolves to the project-scoped principal "${id}" and its account-global id could not be resolved. ${routes.join(" ")} The engine speaks account-global user ids only and never acts as a project-scoped principal.`, cause === void 0 ? void 0 : {
8526
+ cause: cause
8527
+ });
8455
8528
  }
8456
8529
 
8457
8530
  function usableId(user) {
@@ -12759,10 +12832,18 @@ const HISTORY_DISPLAY = {
12759
12832
  title: "Date value",
12760
12833
  description: "Date-only (YYYY-MM-DD) entry, no time component."
12761
12834
  },
12835
+ dueDate: {
12836
+ title: "Due date",
12837
+ description: "THE due date for a level — same value as a date, elevated so surfaces identify the deadline by kind."
12838
+ },
12762
12839
  datetime: {
12763
12840
  title: "Date / time value",
12764
12841
  description: "ISO-8601 timestamp entry."
12765
12842
  },
12843
+ dueDatetime: {
12844
+ title: "Due date / time",
12845
+ description: "THE due datetime for a level — same value as a date/time, the timestamp counterpart of a due date."
12846
+ },
12766
12847
  url: {
12767
12848
  title: "URL value",
12768
12849
  description: "Validated URL entry."
@@ -12913,4 +12994,4 @@ function displayDescription(typeKey) {
12913
12994
  if (typeKey) return DISPLAY[typeKey]?.description;
12914
12995
  }
12915
12996
 
12916
- export { ACTION_SEMANTICS, ACTIVITY_KINDS, ACTIVITY_KIND_DISPLAY, ACTOR_KINDS, ANONYMOUS_IDENTITY, AUTHORING_DISPLAY, ActionDisabledError, ActionParamsInvalidError, CONDITION_VARS, CONTEXT_ENTRY_DISPLAY, CascadeLimitError, ConcurrentCommitEffectOpsError, ConcurrentCompleteEffectError, ConcurrentEditFieldError, ConcurrentFireActionError, ContractViolationError, DATA_MODEL_CHANGES, DATA_MODEL_MIN_READER, DATA_MODEL_VERSION, DEFAULT_CONTENT_PERSPECTIVE, DEFAULT_EFFECT_LEASE_MS, DEFAULT_IDEMPOTENCY_TTL_MS, DEFAULT_TRANSITION_WHEN, DISPLAY, DRIVER_KINDS, DRIVER_KIND_DISPLAY, DefinitionInUseError, DefinitionNotFoundError, EFFECT_COMMIT_DISPATCH_CAP, EFFECT_COMMIT_QUEUE_DEPTH, ENGINE_API_VERSION, EXECUTION_KINDS, EXECUTOR_CLASSIFICATIONS, EXECUTOR_CLASSIFICATION_DISPLAY, EditFieldDeniedError, EffectCommitQueueOverflowError, EffectNotFoundError, EffectOpsInvalidError, EffectOutputsInvalidError, FIELD_KIND_DISPLAY, FILTER_SCOPE_VARS, FieldValueShapeError, GROUP_KINDS, GROUP_KIND_DISPLAY, GUARD_DOC_TYPE, GUARD_OWNER, GUARD_PREDICATE_VARS, HISTORY_DISPLAY, InitialFieldsInvalidError, InstanceNotFoundError, MAX_COUNTERFACTUAL_INDEX2 as MAX_COUNTERFACTUAL_INDEX, MissingHandlerError, ModelVersionAheadError, MutationGuardDeniedError, MutationGuardDocSchema, OP_DISPLAY, PartialGuardDeployError, PersistedDocShapeError, READER_MODEL_ROLLOUT_URL, RESERVED_CONDITION_VARS, ReaderModelAcknowledgementError, RefResourceUndeclaredError, RequiredFieldNotProvidedError, START_FILTER_VARS, START_REQUIREMENT_VARS, SYSTEM_IDENTITY, SpawnContractsInvalidError, StaleEffectClaimError, StartNotAllowedError, StartNotPrimedError, StartNotSettledError, WORKFLOW_DEFINITION_TYPE, WORKFLOW_INSTANCE_TYPE, WorkflowActionFired, WorkflowActivityReset, WorkflowDefinitionDeleted, WorkflowDefinitionDeployed, WorkflowEffectCompleted, WorkflowEffectStateReported, WorkflowEffectsDrained, WorkflowError, WorkflowFieldEdited, WorkflowInstanceAborted, WorkflowInstanceSchema, WorkflowInstanceStarted, WorkflowInstanceTicked, WorkflowStageSet, WorkflowStageTransitioned, WorkflowStateDivergedError, abortReason, acceptsDocumentType, aclPathForResource, actionDisabledDetail, actionRendering, actionVerdict, activityAutonomyOf, analyzeCondition2 as analyzeCondition, applicableDefinitions, assertReadableModel, assertReaderModelAcknowledgement, atomReadsDataset2 as atomReadsDataset, autonomySummary, availableActions, buildInitialFields, buildSnapshot, checklistLines, classifyPrincipalId, clientConfigFromResource, clientProjectUserDirectory, compileGuard, computeDiffEntries, conditionFieldReadNames, conditionSitesOf, contentDocQuery, contentDraftFallback, contentReleaseName, contextMap, createEngine, createTelemetryIntake, datasetResourceParts, defaultLoggerFactory, definitionDeployedData, definitionLookupGroq, definitionsListGroq, deniedGuardLabels, deniedGuardRefs, denyingGuards, deployStageGuards, deriveActivityKind, deriveExecutorClassification, deriveWorkflowAutonomy, describeAtom, describeAutonomyWait, describeCondition, describeDefinition, describeFieldInsight, describeNode, describeSite, describeSiteHeading, diagnoseInputFromEvaluation, diagnoseInstance, diffEntry, displayDescription, displayTitle, documentActionDenials, documentPrefilter, driverKind, effectOutputsMap, entryDocRefs, errorMessage, evaluateFromSnapshot, evaluateMutationGuard, evaluateStartFilter, expandResourceAliases, explainCondition2 as explainCondition, explainStartRequirement, extractDocumentId, fieldTreeShape, findCurrentActivityEntry, findOpenStageEntry, formatRead, gdrFromResource, gdrRef, gdrUri, groupMembershipNames, groupSitesOf, guardMatches, guardsForDefinition, guardsForInstance, guardsForResource, guillemets2 as guillemets, hasSingleSubjectRequirement, hashDefinitionContent, humanize2 as humanize, inFlightFilter, initialFieldIssues, instanceDocId, instanceGuardQuery, instanceWatchesDocument, instancesGuardQuery, instancesQuery, isCascadeFired, isClaimExpired, isClientProjectUser, isComparisonOp, isDefinitionApplicable, isFilterScopedOut, isGdr, isInputSourced, isNotesEntry, isProjectUserNotFoundError, isSingleDocRefEntry, isSingleDocRefKind, isStartableDefinition, isSubjectEntry, isTelemetryEnvDenied, isTerminalActivityStatus, isTerminalStage, isTodoListEntry, isTodoListItem, isUnprimed, lakeGuardId, lakePrincipalId, latestDefinitionsGroq, latestDeployedDefinitions, lintEffectOutputs, minReaderModelOf, missingRequiredInputs, modelVersionOf, narrateAutonomyWaits, noopTelemetry, parentRef, parseDefinitionInput, parseDefinitionSnapshot, parseDefinitionSnapshotValue, parseGdr, parseGuardDocument, parseInstanceDocument, parseResourceGdr, processShellUserProperties, projectStartSliceRow, projectToWatchRef, quoted2 as quoted, readInstanceDoc, readsRaw, readsRootDocument, refCanvas, refDashboard, refDataset, refKindAcceptsTypes, refMediaLibrary, refsOf, rejectedRefTypes, releaseDocId, releaseRef, remediationsFor, requiredModelFeatures, requiredReaderModel, resolveAccess, resolveActor, resolveClientActor, resolveFieldEntry$1 as resolveFieldEntry, resourceAliasesToMap, resourceFromParsed, resourceGdr, retractStageGuards, sameResource, scalarValidationIssues, schemaTreeShape, sentenceCase, silentLogger, singleSubjectRequirementRefused, stageAutonomyOf, startFieldsParam, startKindOf, startRefusal, stripSystemFields, subjectDenialLabels, subscriptionDocument, subscriptionDocumentsForInstance, sweepStaleClaims, tagScopeFilter, terminalState, toBareId, tryParseGdr, unboundRequirementReads, unsatisfiedTransitionSummaries, validateDefinition, validateTag, verdictGuardsForInstance, wallClock, whatIfCondition2 as whatIfCondition, withAssignment, workflow };
12997
+ export { ACTION_SEMANTICS, ACTIVITY_KINDS, ACTIVITY_KIND_DISPLAY, ACTOR_KINDS, ANONYMOUS_IDENTITY, AUTHORING_DISPLAY, ActionDisabledError, ActionParamsInvalidError, CONDITION_VARS, CONTEXT_ENTRY_DISPLAY, CascadeLimitError, ConcurrentCommitEffectOpsError, ConcurrentCompleteEffectError, ConcurrentEditFieldError, ConcurrentFireActionError, ContractViolationError, DATA_MODEL_CHANGES, DATA_MODEL_MIN_READER, DATA_MODEL_VERSION, DEFAULT_CONTENT_PERSPECTIVE, DEFAULT_EFFECT_LEASE_MS, DEFAULT_IDEMPOTENCY_TTL_MS, DEFAULT_TRANSITION_WHEN, DISPLAY, DRIVER_KINDS, DRIVER_KIND_DISPLAY, DefinitionInUseError, DefinitionNotFoundError, EFFECT_COMMIT_DISPATCH_CAP, EFFECT_COMMIT_QUEUE_DEPTH, ENGINE_API_VERSION, EXECUTION_KINDS, EXECUTOR_CLASSIFICATIONS, EXECUTOR_CLASSIFICATION_DISPLAY, EditFieldDeniedError, EffectCommitQueueOverflowError, EffectNotFoundError, EffectOpsInvalidError, EffectOutputsInvalidError, FIELD_KIND_DISPLAY, FILTER_SCOPE_VARS, FieldValueShapeError, GROUP_KINDS, GROUP_KIND_DISPLAY, GUARD_DOC_TYPE, GUARD_OWNER, GUARD_PREDICATE_VARS, HISTORY_DISPLAY, InitialFieldsInvalidError, InstanceNotFoundError, MAX_COUNTERFACTUAL_INDEX2 as MAX_COUNTERFACTUAL_INDEX, MissingHandlerError, ModelVersionAheadError, MutationGuardDeniedError, MutationGuardDocSchema, NEUTRAL_MARK, OP_DISPLAY, OUTCOME_MARKS, PartialGuardDeployError, PersistedDocShapeError, READER_MODEL_ROLLOUT_URL, RESERVED_CONDITION_VARS, ReaderModelAcknowledgementError, RefResourceUndeclaredError, RequiredFieldNotProvidedError, START_FILTER_VARS, START_REQUIREMENT_VARS, SYSTEM_IDENTITY, SpawnContractsInvalidError, StaleEffectClaimError, StartNotAllowedError, StartNotPrimedError, StartNotSettledError, WORKFLOW_DEFINITION_TYPE, WORKFLOW_INSTANCE_TYPE, WorkflowActionFired, WorkflowActivityReset, WorkflowDefinitionDeleted, WorkflowDefinitionDeployed, WorkflowEffectCompleted, WorkflowEffectStateReported, WorkflowEffectsDrained, WorkflowError, WorkflowFieldEdited, WorkflowInstanceAborted, WorkflowInstanceSchema, WorkflowInstanceStarted, WorkflowInstanceTicked, WorkflowStageSet, WorkflowStageTransitioned, WorkflowStateDivergedError, abortReason, acceptsDocumentType, aclPathForResource, actionDisabledDetail, actionRendering, actionVerdict, activityAutonomyOf, analyzeCondition2 as analyzeCondition, applicableDefinitions, assertReadableModel, assertReaderModelAcknowledgement, atomReadsDataset2 as atomReadsDataset, autonomySummary, availableActions, buildInitialFields, buildSnapshot, checklistLines, classifyPrincipalId, clientConfigFromResource, clientProjectUserDirectory, compileGuard, computeDiffEntries, conditionFieldReadNames, conditionSitesOf, contentDocQuery, contentDraftFallback, contentReleaseName, contextMap, createEngine, createTelemetryIntake, datasetResourceParts, defaultLoggerFactory, definitionDeployedData, definitionLookupGroq, definitionTagsGroq, definitionsListGroq, deniedGuardLabels, deniedGuardRefs, denyingGuards, deployStageGuards, deployedTagsGroq, deriveActivityKind, deriveExecutorClassification, deriveWorkflowAutonomy, describeAtom, describeAutonomyWait, describeCondition, describeDefinition, describeFieldInsight, describeNode, describeSite, describeSiteHeading, diagnoseInputFromEvaluation, diagnoseInstance, diffEntry, displayDescription, displayTitle, documentActionDenials, documentPrefilter, driverKind, effectOutputsMap, entryDocRefs, errorMessage, evaluateFromSnapshot, evaluateMutationGuard, evaluateStartFilter, expandResourceAliases, explainCondition2 as explainCondition, explainStartRequirement, extractDocumentId, fieldTreeShape, findCurrentActivityEntry, findOpenStageEntry, formatRead, gdrFromResource, gdrRef, gdrUri, groupMembershipNames, groupSitesOf, guardMatches, guardsForDefinition, guardsForInstance, guardsForResource, guillemets2 as guillemets, hasSingleSubjectRequirement, hashDefinitionContent, humanize2 as humanize, inFlightFilter, initialFieldIssues, instanceDocId, instanceGuardQuery, instanceWatchesDocument, instancesGuardQuery, instancesQuery, isCascadeFired, isClaimExpired, isClientProjectUser, isComparisonOp, isDefinitionApplicable, isFilterScopedOut, isGdr, isInputSourced, isNotesEntry, isProjectUserNotFoundError, isSingleDocRefEntry, isSingleDocRefKind, isStartableDefinition, isSubjectEntry, isTelemetryEnvDenied, isTerminalActivityStatus, isTerminalStage, isTodoListEntry, isTodoListItem, isUnprimed, lakeGuardId, lakePrincipalId, latestDefinitionsGroq, latestDeployedDefinitions, lintEffectOutputs, minReaderModelOf, missingRequiredInputs, modelVersionOf, narrateAutonomyWaits, noopTelemetry, parentRef, parseDefinitionInput, parseDefinitionSnapshot, parseDefinitionSnapshotValue, parseGdr, parseGuardDocument, parseInstanceDocument, parseResourceGdr, processShellUserProperties, projectStartSliceRow, projectToWatchRef, quoted2 as quoted, readInstanceDoc, readsRaw, readsRootDocument, refCanvas, refDashboard, refDataset, refKindAcceptsTypes, refMediaLibrary, refsOf, rejectedRefTypes, releaseDocId, releaseRef, remediationsFor, requiredModelFeatures, requiredReaderModel, resolveAccess, resolveActor, resolveClientActor, resolveFieldEntry$1 as resolveFieldEntry, resourceAliasesToMap, resourceFromParsed, resourceGdr, retractStageGuards, sameResource, scalarValidationIssues, schemaTreeShape, sentenceCase, silentLogger, singleSubjectRequirementRefused, stageAutonomyOf, startFieldsParam, startKindOf, startRefusal, stripSystemFields, subjectDenialLabels, subscriptionDocument, subscriptionDocumentsForInstance, sweepStaleClaims, tagScopeFilter, terminalState, toBareId, tryParseGdr, unboundRequirementReads, unsatisfiedTransitionSummaries, validateDefinition, validateTag, verdictGuardsForInstance, wallClock, whatIfCondition2 as whatIfCondition, withAssignment, workflow };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sanity/workflow-engine",
3
- "version": "0.23.0",
3
+ "version": "0.25.0",
4
4
  "description": "Workflow / BPM engine for Sanity content — define workflows as data, run them as instances against a Sanity client.",
5
5
  "keywords": [
6
6
  "bpm",
@@ -53,7 +53,7 @@
53
53
  "@sanity/types": "^5.28.0",
54
54
  "groq-js": "^1.30.2",
55
55
  "valibot": "^1.4.1",
56
- "@sanity/groq-condition-describe": "0.3.0"
56
+ "@sanity/groq-condition-describe": "0.4.0"
57
57
  },
58
58
  "devDependencies": {
59
59
  "@sanity-labs/client-fake-for-test": "^0.10.0",