@sanity/workflow-studio 0.6.0 → 0.7.1
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 +377 -0
- package/README.md +21 -17
- package/dist/index.cjs +245 -190
- package/dist/index.d.cts +40 -14
- package/dist/index.d.ts +40 -14
- package/dist/index.js +244 -201
- package/package.json +7 -6
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
# @sanity/workflow-studio
|
|
2
|
+
|
|
3
|
+
## 0.7.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 79c54db: Reactive session reads now match the engine's own reads.
|
|
8
|
+
- The session feeder projects every observed doc onto its watch ref's identity the way the lake's perspective reads do: the published-form id becomes `_id` (Studio/SDK stores resolve drafts and release versions under `drafts.*`/`versions.*` ids, which keyed the session's overlay and snapshot where no transition `when` condition or `$fields.<docref>` deref ever looks — an editor's uncommitted draft could not satisfy a condition the engine's `tick()` would read as satisfied), and a draft/version's stored id rides along as `_originalId`, so conditions like `_originalId in path("versions.**")` read what the engine's own hydration returns. The projection is an engine export (`projectToWatchRef`), one encoding beside `contentDraftFallback`/`contentDocQuery`, and it is strict: only the exact representations a store may legitimately resolve under the instance's perspective are accepted — anything else (another doc's dotted id under a version prefix, a version from an unbound release, a draft the perspective makes invisible) fails loudly instead of being fed under the watched identity.
|
|
9
|
+
- Watches whose perspective makes drafts invisible to the engine no longer fall back to the draft. The engine hydrates a `[release]` stack as version-over-published (and `'published'`/`'raw'` scalars as published/raw) with drafts invisible; the Studio adapter resolved `version ?? draft ?? published` and the SDK's per-doc store has the same fallback built in. The Studio adapter now skips the draft arm unless the effective perspective names `'drafts'`, and the SDK adapter observes such refs through the query store under the instance's exact perspective stack. The SDK's query-store route reads committed state (live), so local uncommitted edits to a release version doc no longer feed the session there — Studio keeps its optimistic `editState` reads. New engine helpers `contentDraftFallback` and `contentDocQuery` are the single encoding of the rule, shared with the engine's own hydration.
|
|
10
|
+
- `useWorkflowSession` resets its surfaced `evaluation` to `undefined` on an `instanceId` swap, as the contract promises, instead of leaving the previous instance's projection visible until the new instance first evaluates.
|
|
11
|
+
|
|
12
|
+
- Updated dependencies [11e2d6f]
|
|
13
|
+
- Updated dependencies [7510fd5]
|
|
14
|
+
- Updated dependencies [01e8042]
|
|
15
|
+
- Updated dependencies [79c54db]
|
|
16
|
+
- Updated dependencies [9dc592d]
|
|
17
|
+
- Updated dependencies [1a4712a]
|
|
18
|
+
- Updated dependencies [6a46db1]
|
|
19
|
+
- Updated dependencies [35b9b85]
|
|
20
|
+
- Updated dependencies [e5f5b77]
|
|
21
|
+
- Updated dependencies [01e8042]
|
|
22
|
+
- @sanity/workflow-engine@0.16.0
|
|
23
|
+
- @sanity/workflow-react@0.11.0
|
|
24
|
+
- @sanity/workflow-sdk@0.8.0
|
|
25
|
+
|
|
26
|
+
## 0.7.0
|
|
27
|
+
|
|
28
|
+
### Minor Changes
|
|
29
|
+
|
|
30
|
+
- adf32f7: **BREAKING:** `useWorkflowSession`'s `access` argument is removed — identity is the Studio client's token. `useWorkflowEngine` now declares `executionContext {kind: 'studio'}` so history records the environment.
|
|
31
|
+
- d6e92ed: Now published with public npm access (previously restricted) — installable without `@sanity` org membership.
|
|
32
|
+
- 2834704: **BREAKING:** `useWorkflowEngine` no longer takes an `apiVersion` option. The engine now owns its API version for all engine traffic — including the clients `studioResourceClients` resolves — so the option had no remaining effect except steering routed subject reads onto a caller-chosen version, the silent-incomplete failure mode the engine pin removes. The workspace client is used as-is; nothing version-related needs configuring.
|
|
33
|
+
- 2511bb5: **BREAKING:** `makeStudioObserver` requires a `client` option (a workspace-bound `SanityClient`) — it carries the store contract's new `ensureDocumentExists` writes, which address the mounted dataset. `useStudioObserver` (now exported) supplies the source client automatically, so hook consumers are unaffected.
|
|
34
|
+
- 15337f1: `useWorkflowEngine` feeds Studio's telemetry logger into the engine seam, and sessions report the `studio` host on the session-start adoption event. Studio owns store/consent/transport; engine request tags compose under Studio's `sanity.studio` request-tag prefix.
|
|
35
|
+
- 2511bb5: `useWorkflowEngine` accepts optional `effectHandlers` and `missingHandler`, forwarded to `createEngine` — a Studio-built engine can now drain effects (`engine.drainEffects`) with in-browser handlers without dropping down to manual engine construction.
|
|
36
|
+
- ced40e4: Request tags move to workflows-owned families with the runtime as the segment: `sanity.workflows.cli`, `sanity.workflows.studio`, `sanity.workflows.sdk` — never another team's family (`sanity.cli.*`, `sanity.studio.*`) — and platform analysis zero-rates `sanity.workflows.*`. The MCP server deliberately sits outside that family as `sanity.workflows-mcp` (no dot boundary), so agent-driven traffic bills. Under any workflows-family prefix the engine's tag wrapper strips the now-redundant `workflow.` root from every relative op tag — stamped fallback and explicit alike — so traffic lands as `sanity.workflows.cli.deploy` with exactly one workflows segment; on raw consumer clients and under foreign host prefixes the root stays, since there it is what identifies the traffic. The Studio adapter's engine and resource-router clients and the SDK telemetry shell's intake client now set their family prefix themselves instead of riding the host's.
|
|
37
|
+
|
|
38
|
+
### Patch Changes
|
|
39
|
+
|
|
40
|
+
- 325c2d1: README: the `useWorkflowSession` return shape now lists `previewField` / `discardFieldPreview`.
|
|
41
|
+
- dc64968: Published tarballs no longer include sourcemaps (whose `sourcesContent` embedded the complete TypeScript source) or inline code comments in the compiled JS — license markers and bundler annotations (`/*@__PURE__*/`-style tree-shaking hints) are preserved. Types and TSDoc in `.d.ts` files ship unchanged, and the tarballs shrink accordingly (workflow-engine: ~3× smaller). Each tarball now ships its `CHANGELOG.md`, so release notes reach consumers who can install the package but cannot see the repository.
|
|
42
|
+
- 2511bb5: The studio observer's streams (edit state, guard list, instance list) survive listener errors: an RxJS error terminates the subscription, which previously froze the store on its last snapshot with nothing logged. The error is now logged naming the stream, and the store resubscribes after a 5-second pause; a pending resubscribe is cancelled on teardown.
|
|
43
|
+
- 9f5a40f: Correct the `studioResourceClients` routing docs: a resolver `undefined` no longer falls back to the engine's own client — the engine derives a sibling client for the target resource from its own credentials.
|
|
44
|
+
- 325c2d1: `useWorkflowSession`'s TSDoc now points at the full `WorkflowSession` return shape instead of enumerating a stale subset that omitted the preview verbs.
|
|
45
|
+
- 114dcae: Ship the MIT `LICENSE` file in the published package. The package.json already declared `"license": "MIT"`, but the license text itself was missing from the tarball.
|
|
46
|
+
- Updated dependencies [325c2d1]
|
|
47
|
+
- Updated dependencies [4ca17bb]
|
|
48
|
+
- Updated dependencies [5143707]
|
|
49
|
+
- Updated dependencies [0709ab1]
|
|
50
|
+
- Updated dependencies [6bbf3ca]
|
|
51
|
+
- Updated dependencies [9f5a40f]
|
|
52
|
+
- Updated dependencies [d192d68]
|
|
53
|
+
- Updated dependencies [6c21009]
|
|
54
|
+
- Updated dependencies [109f900]
|
|
55
|
+
- Updated dependencies [109f900]
|
|
56
|
+
- Updated dependencies [444b0e6]
|
|
57
|
+
- Updated dependencies [2511bb5]
|
|
58
|
+
- Updated dependencies [d4fd8e6]
|
|
59
|
+
- Updated dependencies [30ed0e8]
|
|
60
|
+
- Updated dependencies [2834704]
|
|
61
|
+
- Updated dependencies [2511bb5]
|
|
62
|
+
- Updated dependencies [2511bb5]
|
|
63
|
+
- Updated dependencies [2511bb5]
|
|
64
|
+
- Updated dependencies [4607d59]
|
|
65
|
+
- Updated dependencies [52f6024]
|
|
66
|
+
- Updated dependencies [a8f1cb9]
|
|
67
|
+
- Updated dependencies [adf32f7]
|
|
68
|
+
- Updated dependencies [adf32f7]
|
|
69
|
+
- Updated dependencies [adf32f7]
|
|
70
|
+
- Updated dependencies [5cb0850]
|
|
71
|
+
- Updated dependencies [70a136c]
|
|
72
|
+
- Updated dependencies [91540de]
|
|
73
|
+
- Updated dependencies [91540de]
|
|
74
|
+
- Updated dependencies [8455fbb]
|
|
75
|
+
- Updated dependencies [325c2d1]
|
|
76
|
+
- Updated dependencies [325c2d1]
|
|
77
|
+
- Updated dependencies [d6e92ed]
|
|
78
|
+
- Updated dependencies [6c21009]
|
|
79
|
+
- Updated dependencies [2511bb5]
|
|
80
|
+
- Updated dependencies [15337f1]
|
|
81
|
+
- Updated dependencies [325c2d1]
|
|
82
|
+
- Updated dependencies [7ffdc77]
|
|
83
|
+
- Updated dependencies [2511bb5]
|
|
84
|
+
- Updated dependencies [325c2d1]
|
|
85
|
+
- Updated dependencies [15337f1]
|
|
86
|
+
- Updated dependencies [325c2d1]
|
|
87
|
+
- Updated dependencies [7ffdc77]
|
|
88
|
+
- Updated dependencies [ced40e4]
|
|
89
|
+
- Updated dependencies [9b1b40d]
|
|
90
|
+
- Updated dependencies [8c319b2]
|
|
91
|
+
- Updated dependencies [dc64968]
|
|
92
|
+
- Updated dependencies [23cf131]
|
|
93
|
+
- Updated dependencies [d192d68]
|
|
94
|
+
- Updated dependencies [15337f1]
|
|
95
|
+
- Updated dependencies [2d1a8e1]
|
|
96
|
+
- Updated dependencies [12cdbd6]
|
|
97
|
+
- Updated dependencies [437b544]
|
|
98
|
+
- Updated dependencies [114dcae]
|
|
99
|
+
- Updated dependencies [ced40e4]
|
|
100
|
+
- @sanity/workflow-sdk@0.7.0
|
|
101
|
+
- @sanity/workflow-engine@0.15.0
|
|
102
|
+
- @sanity/workflow-react@0.10.0
|
|
103
|
+
|
|
104
|
+
## 0.6.0
|
|
105
|
+
|
|
106
|
+
### Minor Changes
|
|
107
|
+
|
|
108
|
+
- df00bbb: New live instance-list hooks: `useWorkflowInstances({engine, filter})` and `useDocumentWorkflows({engine, document})`, each returning `{instances, loading}`. The Studio adapter reads the list through `documentStore.listenQuery` when the engine dataset is the workspace's own, else through the App SDK store (`sdkInstancesStore`, newly exported from `@sanity/workflow-sdk`) — the same routing and `sdk` bootstrap rules as the instance doc. The Studio package also gains `useWorkflowEngine({workflowResource, tag, resourceClients?})`, which builds the engine once from the workspace client with default per-resource routing to any `dataset:` GDR.
|
|
109
|
+
- 5c69928: **BREAKING:** runtime API coherence pass — one result shape, one session noun, nameable engine args.
|
|
110
|
+
- `DispatchResult` → `OperationResult`, and its `fired` flag → `changed` with one meaning honored by every verb: this call changed the instance's workflow state (`false` = successful no-op — an idempotent re-fire, a tick that wrote nothing, a `setStage` already at the target, an abort of an already-terminal instance; failures still throw). `tick` derives it from the instance revision, so a persisted activity-gate flip that didn't unlock a transition still reports `changed: true`. `abortInstance` documents its always-`0` cascade (a terminal instance doesn't cascade; ancestor propagation reports on the ancestors).
|
|
111
|
+
- `startInstance` now returns `OperationResult` instead of a bare `WorkflowInstance` — its cascade is finally observable. Reach the instance via `result.instance`.
|
|
112
|
+
- Engine argument types are exported and nameable: the exported `*Args` shapes are now exactly what `Engine` methods take, and the raw `workflow.*` namespace takes `<Verb>Args & EngineScopeArgs` (the new exported scope type: `client` / `tag` / `workflowResource` / `resourceClients`). New named args for the read/housekeeping verbs: `InstanceRefArgs`, `ChildrenArgs`, `GuardsForDefinitionArgs`, `InstancesForDocumentArgs`, `QueryArgs`, `QueryInScopeArgs`, `FindPendingEffectsArgs`, `DrainEffectsArgs`, `SessionArgs`. `EvaluateArgs` is likewise scope-free now.
|
|
113
|
+
- Verb-surface parity between `Engine` and `workflow.*` is exact and documented: `Engine.evaluateInstance` → `Engine.evaluate` (matching `workflow.evaluate`); engine-only members (`session`, `subscriptionDocumentsForInstance`, `drainEffects`, `verifyDeployedDefinitions`) and the namespace-only `workflow.permissions` are called out as deliberate.
|
|
114
|
+
- One noun for the reactive session handle: `engine.instance(doc, opts?)` → `engine.session({instance, access?, grantsFromPath?})` (args object — no positional outlier), still returning `InstanceSession`; workflow-react's `WorkflowInstanceController` → `WorkflowSession`; the studio/sdk hooks `useWorkflowInstance` → `useWorkflowSession`. "Instance" now always means the document.
|
|
115
|
+
- Test bench mirrors the engine: `bench.startInstance` returns `OperationResult`, and the `Bench*Args` types are the engine-bound shapes minus `access`.
|
|
116
|
+
- CLI reports follow the rename: the report objects for `fire-action` / `move-stage` / `abort` (and `fire-action`'s `--json` payload) now say `changed` instead of `fired`.
|
|
117
|
+
|
|
118
|
+
- ad9b6f6: **BREAKING:** the observer's guard stream reports `undefined` until the first `listenQuery` emission, instead of masking loading as an empty guard list — the signal `@sanity/workflow-react` now uses to gate `ready` on guards.
|
|
119
|
+
- 748b23e: Read the Studio session token for the auto-bootstrapped App SDK instance from the source client's config (public `getClient` API) instead of scraping Studio's private localStorage entry — cookie-authenticated studios funnel into the same actionable error. Consume the SDK store layer through `@sanity/workflow-sdk/observer` and drop the unused `@sanity/sdk-react` peer dependency. The README now states the packaging truth (this adapter is a superset of the SDK store layer, not its peer) and documents the one remaining non-public Studio seam (`pair.editState`, `@hidden`/`@beta`).
|
|
120
|
+
|
|
121
|
+
### Patch Changes
|
|
122
|
+
|
|
123
|
+
- 113a796: READMEs: the documented controller shape now includes `editField` (with its discrete-commit caveat — bind inline-field UIs to blur/Enter/debounce, never an `onChange` per keystroke), and the App SDK README's `createEngine` sample passes the shipped `tag` argument instead of the nonexistent `tags`.
|
|
124
|
+
- Updated dependencies [df00bbb]
|
|
125
|
+
- Updated dependencies [df00bbb]
|
|
126
|
+
- Updated dependencies [a0443c4]
|
|
127
|
+
- Updated dependencies [a0443c4]
|
|
128
|
+
- Updated dependencies [ad9b6f6]
|
|
129
|
+
- Updated dependencies [83d5924]
|
|
130
|
+
- Updated dependencies [7a655bd]
|
|
131
|
+
- Updated dependencies [d9c8179]
|
|
132
|
+
- Updated dependencies [0a7979a]
|
|
133
|
+
- Updated dependencies [df00bbb]
|
|
134
|
+
- Updated dependencies [df00bbb]
|
|
135
|
+
- Updated dependencies [df00bbb]
|
|
136
|
+
- Updated dependencies [ad9b6f6]
|
|
137
|
+
- Updated dependencies [5c69928]
|
|
138
|
+
- Updated dependencies [ad9b6f6]
|
|
139
|
+
- Updated dependencies [748b23e]
|
|
140
|
+
- Updated dependencies [2f081a3]
|
|
141
|
+
- Updated dependencies [df00bbb]
|
|
142
|
+
- Updated dependencies [113a796]
|
|
143
|
+
- Updated dependencies [113a796]
|
|
144
|
+
- Updated dependencies [df00bbb]
|
|
145
|
+
- Updated dependencies [8553787]
|
|
146
|
+
- Updated dependencies [2829643]
|
|
147
|
+
- Updated dependencies [6ee9068]
|
|
148
|
+
- Updated dependencies [6ee9068]
|
|
149
|
+
- Updated dependencies [2829643]
|
|
150
|
+
- Updated dependencies [a0443c4]
|
|
151
|
+
- @sanity/workflow-sdk@0.6.0
|
|
152
|
+
- @sanity/workflow-react@0.9.0
|
|
153
|
+
- @sanity/workflow-engine@0.14.0
|
|
154
|
+
|
|
155
|
+
## 0.5.0
|
|
156
|
+
|
|
157
|
+
### Minor Changes
|
|
158
|
+
|
|
159
|
+
- 5bbc3f0: **BREAKING:** `useWorkflowInstance` now takes a single options object, with the former `opts` bag flattened to top-level fields (matching `@sanity/workflow-sdk`'s hook):
|
|
160
|
+
- `useWorkflowInstance(engine, instanceId, opts)` → `useWorkflowInstance({engine, instanceId, access?, grantsFromPath?, sdk?})`
|
|
161
|
+
|
|
162
|
+
Behavior is unchanged — only the calling convention.
|
|
163
|
+
|
|
164
|
+
### Patch Changes
|
|
165
|
+
|
|
166
|
+
- Updated dependencies [416d4c9]
|
|
167
|
+
- Updated dependencies [4dfe72a]
|
|
168
|
+
- Updated dependencies [5bbc3f0]
|
|
169
|
+
- Updated dependencies [5bbc3f0]
|
|
170
|
+
- Updated dependencies [5bbc3f0]
|
|
171
|
+
- Updated dependencies [0bf7503]
|
|
172
|
+
- Updated dependencies [6e51913]
|
|
173
|
+
- Updated dependencies [3229f41]
|
|
174
|
+
- @sanity/workflow-engine@0.13.0
|
|
175
|
+
- @sanity/workflow-react@0.8.0
|
|
176
|
+
- @sanity/workflow-sdk@0.5.0
|
|
177
|
+
|
|
178
|
+
## 0.4.2
|
|
179
|
+
|
|
180
|
+
### Patch Changes
|
|
181
|
+
|
|
182
|
+
- Updated dependencies [5b10863]
|
|
183
|
+
- Updated dependencies [ae1434e]
|
|
184
|
+
- Updated dependencies [d850aef]
|
|
185
|
+
- Updated dependencies [9519c76]
|
|
186
|
+
- Updated dependencies [9233cd3]
|
|
187
|
+
- Updated dependencies [3ea4953]
|
|
188
|
+
- Updated dependencies [e5a862a]
|
|
189
|
+
- @sanity/workflow-engine@0.12.0
|
|
190
|
+
- @sanity/workflow-react@0.7.0
|
|
191
|
+
- @sanity/workflow-sdk@0.4.2
|
|
192
|
+
|
|
193
|
+
## 0.4.1
|
|
194
|
+
|
|
195
|
+
### Patch Changes
|
|
196
|
+
|
|
197
|
+
- Updated dependencies [3b8f3de]
|
|
198
|
+
- @sanity/workflow-engine@0.11.0
|
|
199
|
+
- @sanity/workflow-react@0.6.1
|
|
200
|
+
- @sanity/workflow-sdk@0.4.1
|
|
201
|
+
|
|
202
|
+
## 0.4.0
|
|
203
|
+
|
|
204
|
+
### Minor Changes
|
|
205
|
+
|
|
206
|
+
- fae3553: **BREAKING:** Rename the domain concept **state → fields** across the whole API and persisted data model.
|
|
207
|
+
|
|
208
|
+
"State" was too easily conflated with "stage". The typed, valued data attached to workflows, stages, and tasks is now called **fields** — clearer, and aligned with Sanity schemas: the fields on a workflow, stage, and task can have typed values. This is a clean break (no migration, no back-compat); already-deployed definitions and instances must be redeployed/recreated.
|
|
209
|
+
|
|
210
|
+
**Authoring DSL**
|
|
211
|
+
- `defineState(...)` → `defineField(...)`
|
|
212
|
+
- The `state: [...]` array on a workflow / stage / task → `fields: [...]`
|
|
213
|
+
- The `$state.<name>` GROQ scope token → `$fields.<name>`
|
|
214
|
+
- A `claim` action's `state:` reference → `field:`
|
|
215
|
+
- A `stateRead` source → `fieldRead`; its `state:` (entry name) → `field:`
|
|
216
|
+
- Op targets address the entry by `field:` instead of `state:`
|
|
217
|
+
|
|
218
|
+
**Persisted / wire format**
|
|
219
|
+
- Op type strings `state.set` / `state.unset` / `state.append` / `state.updateWhere` / `state.removeWhere` → `field.*`
|
|
220
|
+
- The stored `state[]` array on instances, stage entries, and task entries → `fields[]`
|
|
221
|
+
- `startInstance({ initialState })` → `startInstance({ initialFields })`
|
|
222
|
+
|
|
223
|
+
**Types & functions** (engine)
|
|
224
|
+
|
|
225
|
+
`StateEntry`→`FieldEntry`, `AuthoringStateEntry`→`AuthoringFieldEntry`, `ResolvedStateEntry`→`ResolvedFieldEntry`, `InitialStateValue`→`InitialFieldValue`, `StateKind`→`FieldKind`, `StateValueMap`→`FieldValueMap`, `StateScope`→`FieldScope`, `StoredStateRef`→`StoredFieldRef`, `STATE_SLOT_DISPLAY`→`FIELD_SLOT_DISPLAY`, `EditStateArgs`→`EditFieldArgs`, `EditStateTarget`→`EditFieldTarget`, `EditStateDeniedError`→`EditFieldDeniedError`, `ConcurrentEditStateError`→`ConcurrentEditFieldError`, `RequiredStateNotProvidedError`→`RequiredFieldNotProvidedError`, and the `editState` verb → `editField`.
|
|
226
|
+
|
|
227
|
+
Unchanged: runtime/lifecycle instance "state" (stage moves, `WorkflowStateDivergedError`, the projected instance snapshot), the `field`/`fields` JSON-matching primitives in `updateWhere`/`removeWhere` predicates and object Sources, and the Content Lake release `state`.
|
|
228
|
+
|
|
229
|
+
### Patch Changes
|
|
230
|
+
|
|
231
|
+
- Updated dependencies [fae3553]
|
|
232
|
+
- @sanity/workflow-engine@0.10.0
|
|
233
|
+
- @sanity/workflow-react@0.6.0
|
|
234
|
+
- @sanity/workflow-sdk@0.4.0
|
|
235
|
+
|
|
236
|
+
## 0.3.5
|
|
237
|
+
|
|
238
|
+
### Patch Changes
|
|
239
|
+
|
|
240
|
+
- 2e4c980: Add a generic edit seam for declared-editable workflow state.
|
|
241
|
+
|
|
242
|
+
State slots can now declare `editable` (default off) and be written directly
|
|
243
|
+
through one `editState` verb — reassign, reschedule, claim-by-hand, append to a
|
|
244
|
+
log — instead of a bespoke action per field.
|
|
245
|
+
- `editable` on a state slot — default off. _Who_ may edit is expressed with
|
|
246
|
+
the gating actions already have, not a new permission concept: `true` (anyone
|
|
247
|
+
in the slot's scope window), a **role list** (the same `action.roles` sugar —
|
|
248
|
+
it desugars to the identical `count($actor.roles[@ in [...]]) > 0` membership
|
|
249
|
+
predicate), or a raw GROQ predicate (checked like `action.filter`). A stage
|
|
250
|
+
may TIGHTEN a slot via an `editable` override map — the override is ANDed with
|
|
251
|
+
the slot's baseline, so it can only narrow, never open a closed slot.
|
|
252
|
+
- `editState` engine verb (and `engine.editState` / `instanceSession.editState`):
|
|
253
|
+
gates on the slot's editability and scope window, applies the edit as a
|
|
254
|
+
`state.*` op (so provenance + history are stamped by the op path), refreshes
|
|
255
|
+
the stage's guards, then cascades — an edit to a value a transition reads can
|
|
256
|
+
move the instance. Advisory like every engine gate; the lake ACL + guards are
|
|
257
|
+
the only hard locks.
|
|
258
|
+
- Scope is the editable window: a workflow slot is editable while the instance
|
|
259
|
+
is live, a stage slot while its stage is current, a task slot while its task
|
|
260
|
+
is active.
|
|
261
|
+
- The projection gains `editableSlots`: each declared-editable slot in scope
|
|
262
|
+
with this actor's edit verdict and the current value's provenance (`setBy` /
|
|
263
|
+
`setAt`, read off `opApplied` history — no denormalised copy). `EditDisabledReason`
|
|
264
|
+
and `EditStateDeniedError` mirror the action verdict surface.
|
|
265
|
+
- `@sanity/workflow-react`'s controller exposes `editState`, threaded through
|
|
266
|
+
the Studio and App SDK adapters.
|
|
267
|
+
|
|
268
|
+
- Updated dependencies [2e4c980]
|
|
269
|
+
- Updated dependencies [fd6b866]
|
|
270
|
+
- @sanity/workflow-engine@0.9.0
|
|
271
|
+
- @sanity/workflow-react@0.5.0
|
|
272
|
+
- @sanity/workflow-sdk@0.3.5
|
|
273
|
+
|
|
274
|
+
## 0.3.4
|
|
275
|
+
|
|
276
|
+
### Patch Changes
|
|
277
|
+
|
|
278
|
+
- Updated dependencies [c298ee2]
|
|
279
|
+
- Updated dependencies [8131dd5]
|
|
280
|
+
- Updated dependencies [8bf467e]
|
|
281
|
+
- @sanity/workflow-engine@0.8.0
|
|
282
|
+
- @sanity/workflow-react@0.4.2
|
|
283
|
+
- @sanity/workflow-sdk@0.3.4
|
|
284
|
+
|
|
285
|
+
## 0.3.3
|
|
286
|
+
|
|
287
|
+
### Patch Changes
|
|
288
|
+
|
|
289
|
+
- Updated dependencies [ef927bc]
|
|
290
|
+
- Updated dependencies [32f5e64]
|
|
291
|
+
- Updated dependencies [df7582f]
|
|
292
|
+
- Updated dependencies [ed4174c]
|
|
293
|
+
- Updated dependencies [129258c]
|
|
294
|
+
- @sanity/workflow-engine@0.7.0
|
|
295
|
+
- @sanity/workflow-sdk@0.3.3
|
|
296
|
+
- @sanity/workflow-react@0.4.1
|
|
297
|
+
|
|
298
|
+
## 0.3.2
|
|
299
|
+
|
|
300
|
+
### Patch Changes
|
|
301
|
+
|
|
302
|
+
- 6d5290b: `makeStudioObserver`'s guard stream now spans every dataset resource the instance's GDRs name: guards in the mounted workspace dataset observe through `documentStore.listenQuery`, guards in any other dataset (the engine's own, or a subject's) through the embedded App SDK — the same routing `observeDocs` already uses for foreign content refs. Previously only the engine dataset was read, so a guard locking a subject in another dataset was invisible. Tracks the updated `observeGuards` contract in `@sanity/workflow-react`.
|
|
303
|
+
- Updated dependencies [6d5290b]
|
|
304
|
+
- Updated dependencies [6d5290b]
|
|
305
|
+
- Updated dependencies [c6d1762]
|
|
306
|
+
- @sanity/workflow-react@0.4.0
|
|
307
|
+
- @sanity/workflow-sdk@0.3.2
|
|
308
|
+
- @sanity/workflow-engine@0.6.0
|
|
309
|
+
|
|
310
|
+
## 0.3.1
|
|
311
|
+
|
|
312
|
+
### Patch Changes
|
|
313
|
+
|
|
314
|
+
- Updated dependencies [dbc4afa]
|
|
315
|
+
- Updated dependencies [e2a6d5d]
|
|
316
|
+
- Updated dependencies [aa87a1c]
|
|
317
|
+
- @sanity/workflow-engine@0.5.0
|
|
318
|
+
- @sanity/workflow-react@0.3.1
|
|
319
|
+
- @sanity/workflow-sdk@0.3.1
|
|
320
|
+
|
|
321
|
+
## 0.3.0
|
|
322
|
+
|
|
323
|
+
### Minor Changes
|
|
324
|
+
|
|
325
|
+
- 12e23b0: Support a dedicated workflow-state dataset: the engine's `workflowResource` is routinely a different dataset (e.g. `workflows`) from every content workspace, so the adapters now route **instance and guard observation** to the engine's dataset, derived automatically from `engine.workflowResource`.
|
|
326
|
+
- `@sanity/workflow-react`: `datasetResourceId(workflowResource)` + `sameDataset` helpers.
|
|
327
|
+
- `@sanity/workflow-sdk` (breaking for direct `makeSdkObserver` callers): the observer takes `{engineResource}`; new exports `sdkInstanceDocStore` / `sdkGuardStore` observe the instance + guards in the engine dataset via per-resource SDK stores.
|
|
328
|
+
- `@sanity/workflow-studio` (breaking for direct `makeStudioObserver` callers): the observer takes `{mounted, engineResource, sdk?}` and is now exported alongside `StudioObserverOptions` (matching `makeSdkObserver`); when the engine dataset is not the workspace, the hook bootstraps an App SDK instance automatically from the Studio session (override with `opts.sdk`; cookie-authenticated studios must supply one — the failure is loud and actionable), and instance + guard observation delegate to it. `documentStore` is used only for what it can address: the mounted dataset.
|
|
329
|
+
|
|
330
|
+
Adds `apps/test-studio` + `apps/test-sdk` — private validation harnesses that render the controller state as plain JSON against the live multi-dataset topology (see `apps/README.md`).
|
|
331
|
+
|
|
332
|
+
- 12e23b0: Watched refs now route to a store that can actually address them — never a silent wrong-dataset read.
|
|
333
|
+
|
|
334
|
+
**workflow-react:** new `classifyRef(ref, mounted)` — the routing verdict (`mounted-dataset` vs `foreign-resource`) the Studio adapter keys its per-ref dispatch on (the SDK adapter routes every ref per-resource unconditionally).
|
|
335
|
+
|
|
336
|
+
**workflow-sdk:** `sdkContentDocStore` (exported) routes each content ref to the App SDK document store keyed by the ref's own `projectId`/`dataset` — the SDK store spins up a per-resource listener + resource-scoped client, so cross-dataset refs are observed live (the instance's auth must cover the resource). Non-`dataset:` schemes (`canvas:`, `media-library:`, `dashboard:`) now throw an actionable error instead of being silently misread against the default dataset.
|
|
337
|
+
|
|
338
|
+
**workflow-studio (breaking for direct `makeStudioObserver` callers — now exported):** the observer takes `{mounted, engineResource, sdk?}` and routes per ref — refs in the mounted workspace dataset observe through `documentStore.pair.editState` (Studio's local uncommitted edits included); every other resource observes through an App SDK instance: the one supplied via `useWorkflowInstance(engine, id, {sdk})`, or the one the hook bootstraps automatically when the engine dataset is foreign (see the engine-dataset routing entry in this release). A foreign ref with no SDK instance available throws the config-mismatch error the adapter always needed instead of silently watching the workspace dataset under the same `_id`.
|
|
339
|
+
|
|
340
|
+
- fcf938a: The document-store observers now watch the renamed `sanity.workflow.instance` document type, importing the engine's exported `WORKFLOW_INSTANCE_TYPE` constant instead of hardcoding the old `workflow.instance` type string — so instance documents resolve again in the App SDK and Studio adapters.
|
|
341
|
+
- 12e23b0: Live lake mutation guards now flow through the reactive stack and into evaluation.
|
|
342
|
+
|
|
343
|
+
**Engine:** `InstanceSession` gains `updateGuards(guards)`, and `evaluateFromSnapshot` accepts `guards` — every action commit is an `update` write to the instance doc, so a held guard that matches the instance and denies that write disables every action with the (previously declared but never produced) `mutation-guard-denied` reason, carrying the denying `guardIds`. A lifted guard (predicate `"true"`) allows; deny-all (`""`) denies; fail-closed. `fireAction`'s soft-gate uses the same projection, so firing while guard-denied throws `ActionDisabledError` with the structured reason. The stateless fetch path agrees: `workflow.evaluate` / `workflow.fireAction` load the instance's guards (new `verdictGuardsForInstance`) before evaluating, so both paths produce the same verdicts for the same state. Verdict loads are **physically scoped to the engine's own datasource** — a guard enforces solely within the datasource it lives in, so neither an honestly-stamped foreign guard nor a forged guard doc planted in a watched content dataset can ever flip a verdict (the cross-datasource `guardsForInstance` union remains housekeeping-only). `tick` (session and stateless) pre-flights the same instance write and fails fast with `MutationGuardDeniedError` before entering the multi-step cascade, instead of risking a partially-applied move; best-effort — the lake remains the final arbiter and the rollback machinery stays the backstop. New `instanceGuardQuery(instanceId)` is the single definition of the per-instance guard filter, shared by the verdict load and the adapters' subscriptions.
|
|
344
|
+
|
|
345
|
+
**Adapters:** `useWorkflowInstance` / `useWorkflowSession` expose a live `guards` field and feed the stream into the session, so action verdicts re-evaluate as guards are deployed on stage entry and lifted on exit. Driven by a new required `observeGuards` method on `WorkflowObserver` (breaking for custom observers; the first-party SDK and Studio observers implement it via the SDK query store / Studio's `listenQuery`, engine-dataset-scoped), built on the engine's `instanceGuardQuery` and workflow-react's shared `NO_GUARDS` unresolved snapshot.
|
|
346
|
+
|
|
347
|
+
### Patch Changes
|
|
348
|
+
|
|
349
|
+
- Updated dependencies [fcf938a]
|
|
350
|
+
- Updated dependencies [4b5f59a]
|
|
351
|
+
- Updated dependencies [fcf938a]
|
|
352
|
+
- Updated dependencies [12e23b0]
|
|
353
|
+
- Updated dependencies [12e23b0]
|
|
354
|
+
- Updated dependencies [6c4e0a0]
|
|
355
|
+
- Updated dependencies [fcf938a]
|
|
356
|
+
- Updated dependencies [12e23b0]
|
|
357
|
+
- Updated dependencies [12e23b0]
|
|
358
|
+
- @sanity/workflow-react@0.3.0
|
|
359
|
+
- @sanity/workflow-engine@0.4.0
|
|
360
|
+
- @sanity/workflow-sdk@0.3.0
|
|
361
|
+
|
|
362
|
+
## 0.2.0
|
|
363
|
+
|
|
364
|
+
### Minor Changes
|
|
365
|
+
|
|
366
|
+
- 3abbd22: New package: a React adapter that drives the `@sanity/workflow-engine` reactive session from the Sanity Studio document store.
|
|
367
|
+
- `useWorkflowInstance(engine, instanceId)` → `{evaluation, ready, tick, fireAction}`. A thin wrapper over `@sanity/workflow-react`: it builds a `WorkflowObserver` over `documentStore.pair.editState` (Studio's optimistic, replayed store) and hands it to `useWorkflowSession`, which owns the session orchestration.
|
|
368
|
+
- Content docs resolve under the perspective's release via the `editState` version arg (from the engine's `contentReleaseName`); instance / ancestor / `system.release` docs read raw. `editState.ready` gates the feed. Observe-only — `tick`/`fireAction` commit through the engine's own lake-guarded client.
|
|
369
|
+
- Peer-deps `react` / `sanity` (Sanity-plugin pattern). Must render inside Studio source context. `documentStore.pair.editState` is `@beta`/`@internal` in Studio, so the `sanity` peer range is pinned tightly.
|
|
370
|
+
|
|
371
|
+
### Patch Changes
|
|
372
|
+
|
|
373
|
+
- Updated dependencies [41ddd80]
|
|
374
|
+
- Updated dependencies [0c6ccde]
|
|
375
|
+
- Updated dependencies [bdcba10]
|
|
376
|
+
- @sanity/workflow-engine@0.3.0
|
|
377
|
+
- @sanity/workflow-react@0.2.0
|
package/README.md
CHANGED
|
@@ -3,16 +3,18 @@
|
|
|
3
3
|
Reactive workflow adapter for **Sanity Studio**. Everything must render inside
|
|
4
4
|
Studio source context (`useDocumentStore` / `useSource` / `useClient`).
|
|
5
5
|
|
|
6
|
-
- `useWorkflowEngine({workflowResource, tag, resourceClients
|
|
6
|
+
- `useWorkflowEngine({workflowResource, tag, resourceClients?})` —
|
|
7
7
|
build the Studio-side engine once: the workspace client rebound to the
|
|
8
|
-
engine's state dataset (
|
|
9
|
-
`
|
|
10
|
-
default per-resource routing that reaches any `dataset:`
|
|
11
|
-
the same client. A custom `resourceClients` replaces the default — delegate
|
|
12
|
-
to `studioResourceClients` for the dataset arm
|
|
13
|
-
(media-library, canvas)
|
|
8
|
+
engine's state dataset (engine traffic always rides the engine's own API
|
|
9
|
+
version — `createEngine` pins it), with `studioResourceClients` (also
|
|
10
|
+
exported) as the default per-resource routing that reaches any `dataset:`
|
|
11
|
+
GDR by rebinding the same client, pinned to the engine version too. A custom `resourceClients` replaces the default — delegate
|
|
12
|
+
to `studioResourceClients` for the dataset arm; schemes it returns
|
|
13
|
+
`undefined` for (media-library, canvas) are routed by the engine itself,
|
|
14
|
+
which derives a sibling client from the engine client's credentials.
|
|
14
15
|
- `useWorkflowSession` — drives an engine session for one instance and
|
|
15
|
-
returns
|
|
16
|
+
returns
|
|
17
|
+
`{evaluation, ready, guards, tick, fireAction, editField, previewField, discardFieldPreview}`.
|
|
16
18
|
- `useWorkflowInstances` / `useDocumentWorkflows` — live instance lists
|
|
17
19
|
(filterable collection / per-document discovery), each returning
|
|
18
20
|
`{instances, loading}`. The list observes `documentStore.listenQuery` when
|
|
@@ -27,13 +29,13 @@ Studio source context (`useDocumentStore` / `useSource` / `useClient`).
|
|
|
27
29
|
Each ref in the watch-set is classified against the workspace's own
|
|
28
30
|
project + dataset and observed by the store that can actually address it:
|
|
29
31
|
|
|
30
|
-
| Ref
|
|
31
|
-
|
|
|
32
|
-
| **Mounted workspace dataset**
|
|
33
|
-
| **Engine state dataset** (instance doc)
|
|
34
|
-
| **Guards** (`observeGuards`)
|
|
35
|
-
| **Any other dataset / project**
|
|
36
|
-
|
|
|
32
|
+
| Ref | Observed via |
|
|
33
|
+
| ---------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
34
|
+
| **Mounted workspace dataset** | `documentStore.pair.editState` — Studio's optimistic pair store, **including local uncommitted edits** (the one stream only Studio has). Non-public Studio surface — see **Private Studio seam** below |
|
|
35
|
+
| **Engine state dataset** (instance doc) | The workspace's `documentStore` when the engine dataset IS the workspace; otherwise the **App SDK store** (`sdkInstanceDocStore` from `@sanity/workflow-sdk/observer`) |
|
|
36
|
+
| **Guards** (`observeGuards`) | Fanned per-resource across the datasets the instance's GDRs name: mounted-dataset guards via `documentStore.listenQuery`, any foreign dataset (engine's or a subject's) via `sdkGuardStore`, merged by `combineGuardStores` |
|
|
37
|
+
| **Any other dataset / project** | The **App SDK document store** (`sdkContentDocStore` from `@sanity/workflow-sdk/observer`) — live, GDR-routed per-resource — through the bootstrapped or supplied SDK instance (see below) |
|
|
38
|
+
| **`canvas:` / `media-library:` schemes** | Routed like foreign resources through the **App SDK store**, observed live via the handle's `resource` field (`{canvasId}` / `{mediaLibraryId}`) — the same path the Canvas app uses. `dashboard:` is the exception: the App SDK store has no dashboard resource, so a `dashboard:` ref **throws** and a workflow with a dashboard subject can't be driven reactively — run it engine-direct instead |
|
|
37
39
|
|
|
38
40
|
There is **no silent fallback**: a ref the configured stores can't address
|
|
39
41
|
throws, instead of being misread from the workspace dataset under the same
|
|
@@ -58,8 +60,10 @@ throws, instead of being misread from the workspace dataset under the same
|
|
|
58
60
|
instance, the same path foreign content refs take.
|
|
59
61
|
- **Auth caveat for foreign refs:** the SDK instance's auth must cover the
|
|
60
62
|
foreign resource; a foreign _project_ needs a session/token valid there.
|
|
61
|
-
- `makeStudioObserver(documentStore, {mounted, engineResource, sdk?})`
|
|
62
|
-
exported for custom wiring, matching `makeSdkObserver`.
|
|
63
|
+
- `makeStudioObserver(documentStore, {mounted, client, engineResource, sdk?})`
|
|
64
|
+
is exported for custom wiring, matching `makeSdkObserver`. `client` is
|
|
65
|
+
required: a workspace-bound client that carries `ensureDocumentExists`
|
|
66
|
+
writes into the mounted dataset.
|
|
63
67
|
|
|
64
68
|
Remaining gaps (ancestor-instance guards, full cascade write-set pre-flight,
|
|
65
69
|
live cross-dataset end-to-end verification) are known follow-up work.
|