@sanity/workbench 0.1.0-alpha.11 → 0.1.0-alpha.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_chunks-es/index.js +6 -1
- package/dist/_chunks-es/index.js.map +1 -1
- package/dist/_chunks-es/studio.js +798 -0
- package/dist/_chunks-es/studio.js.map +1 -0
- package/dist/core.d.ts +135 -35
- package/dist/core.js +3 -722
- package/dist/core.js.map +1 -1
- package/dist/system.d.ts +456 -0
- package/dist/system.js +436 -0
- package/dist/system.js.map +1 -0
- package/package.json +12 -1
- package/src/_exports/system.ts +1 -0
- package/src/core/log/index.ts +33 -0
- package/src/core/projects.ts +1 -1
- package/src/core/user-applications/core-app.ts +19 -6
- package/src/core/user-applications/studios/schemas.ts +12 -1
- package/src/core/user-applications/studios/studio.ts +92 -77
- package/src/core/user-applications/studios/workspace.ts +5 -0
- package/src/core/user-applications/user-application.ts +24 -1
- package/src/system/auth.machine.ts +223 -0
- package/src/system/index.ts +6 -0
- package/src/system/inspect.ts +40 -0
- package/src/system/root.machine.ts +165 -0
- package/src/system/telemetry.machine.ts +179 -0
package/dist/system.js
ADDED
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
import { getAuthState, logout, AuthStateType, getClient, createSanityInstance } from "@sanity/sdk";
|
|
2
|
+
import { fromObservable, fromPromise, setup, assign, sendTo, raise } from "xstate";
|
|
3
|
+
import "./_chunks-es/studio.js";
|
|
4
|
+
import { logger } from "./_chunks-es/index.js";
|
|
5
|
+
import { createSessionId, createBatchedStore } from "@sanity/telemetry";
|
|
6
|
+
const authStateLogic = fromObservable(
|
|
7
|
+
({ input }) => getAuthState(input.instance).observable
|
|
8
|
+
), logoutActorLogic = fromPromise(async ({ input }) => {
|
|
9
|
+
await logout(input.instance);
|
|
10
|
+
}), authLogic = setup({
|
|
11
|
+
types: {
|
|
12
|
+
input: {},
|
|
13
|
+
context: {},
|
|
14
|
+
events: {},
|
|
15
|
+
tags: {}
|
|
16
|
+
},
|
|
17
|
+
actors: {
|
|
18
|
+
authState: authStateLogic,
|
|
19
|
+
logoutActor: logoutActorLogic
|
|
20
|
+
},
|
|
21
|
+
delays: {
|
|
22
|
+
authTimeout: 3e4
|
|
23
|
+
},
|
|
24
|
+
guards: {
|
|
25
|
+
isLoggedInComplete: (_, params) => params.state?.type === AuthStateType.LOGGED_IN && !!params.state.token && params.state.currentUser !== null,
|
|
26
|
+
isAuthState: (_, params) => params.state?.type === params.type
|
|
27
|
+
},
|
|
28
|
+
actions: {
|
|
29
|
+
setLoggedIn: assign({
|
|
30
|
+
token: (_, params) => params.token,
|
|
31
|
+
currentUser: (_, params) => params.currentUser,
|
|
32
|
+
error: () => null
|
|
33
|
+
}),
|
|
34
|
+
clearAuth: assign({
|
|
35
|
+
token: () => null,
|
|
36
|
+
currentUser: () => null,
|
|
37
|
+
error: () => null
|
|
38
|
+
}),
|
|
39
|
+
setError: assign({
|
|
40
|
+
token: () => null,
|
|
41
|
+
currentUser: () => null,
|
|
42
|
+
error: (_, params) => params.error
|
|
43
|
+
})
|
|
44
|
+
}
|
|
45
|
+
}).createMachine({
|
|
46
|
+
id: "auth",
|
|
47
|
+
initial: "init",
|
|
48
|
+
context: ({ input }) => ({
|
|
49
|
+
instance: input.instance,
|
|
50
|
+
token: null,
|
|
51
|
+
currentUser: null,
|
|
52
|
+
error: null
|
|
53
|
+
}),
|
|
54
|
+
invoke: {
|
|
55
|
+
src: "authState",
|
|
56
|
+
input: ({ context }) => ({ instance: context.instance }),
|
|
57
|
+
onSnapshot: [
|
|
58
|
+
{
|
|
59
|
+
guard: {
|
|
60
|
+
type: "isLoggedInComplete",
|
|
61
|
+
params: ({ event }) => ({
|
|
62
|
+
state: event.snapshot.context
|
|
63
|
+
})
|
|
64
|
+
},
|
|
65
|
+
actions: [
|
|
66
|
+
{
|
|
67
|
+
type: "setLoggedIn",
|
|
68
|
+
params: ({ event }) => {
|
|
69
|
+
const state = event.snapshot.context;
|
|
70
|
+
return {
|
|
71
|
+
token: state.token,
|
|
72
|
+
currentUser: state.currentUser
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
],
|
|
77
|
+
target: `.${AuthStateType.LOGGED_IN}`
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
guard: {
|
|
81
|
+
type: "isAuthState",
|
|
82
|
+
params: ({ event }) => ({
|
|
83
|
+
state: event.snapshot.context,
|
|
84
|
+
type: AuthStateType.LOGGING_IN
|
|
85
|
+
})
|
|
86
|
+
},
|
|
87
|
+
actions: [{ type: "clearAuth" }],
|
|
88
|
+
target: `.${AuthStateType.LOGGING_IN}`
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
guard: {
|
|
92
|
+
type: "isAuthState",
|
|
93
|
+
params: ({ event }) => ({
|
|
94
|
+
state: event.snapshot.context,
|
|
95
|
+
type: AuthStateType.ERROR
|
|
96
|
+
})
|
|
97
|
+
},
|
|
98
|
+
actions: [
|
|
99
|
+
{
|
|
100
|
+
type: "setError",
|
|
101
|
+
params: ({ event }) => ({
|
|
102
|
+
error: event.snapshot.context?.type === AuthStateType.ERROR ? event.snapshot.context.error : null
|
|
103
|
+
})
|
|
104
|
+
}
|
|
105
|
+
],
|
|
106
|
+
target: `.${AuthStateType.ERROR}`
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
guard: {
|
|
110
|
+
type: "isAuthState",
|
|
111
|
+
params: ({ event }) => ({
|
|
112
|
+
state: event.snapshot.context,
|
|
113
|
+
type: AuthStateType.LOGGED_OUT
|
|
114
|
+
})
|
|
115
|
+
},
|
|
116
|
+
actions: [{ type: "clearAuth" }],
|
|
117
|
+
target: `.${AuthStateType.LOGGED_OUT}`
|
|
118
|
+
}
|
|
119
|
+
]
|
|
120
|
+
},
|
|
121
|
+
states: {
|
|
122
|
+
init: {
|
|
123
|
+
tags: ["authenticating"],
|
|
124
|
+
after: {
|
|
125
|
+
authTimeout: {
|
|
126
|
+
actions: [
|
|
127
|
+
{
|
|
128
|
+
type: "setError",
|
|
129
|
+
params: () => ({
|
|
130
|
+
error: new Error("Authentication timed out")
|
|
131
|
+
})
|
|
132
|
+
}
|
|
133
|
+
],
|
|
134
|
+
target: AuthStateType.ERROR
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
[AuthStateType.LOGGING_IN]: {
|
|
139
|
+
tags: ["authenticating"],
|
|
140
|
+
after: {
|
|
141
|
+
authTimeout: {
|
|
142
|
+
actions: [
|
|
143
|
+
{
|
|
144
|
+
type: "setError",
|
|
145
|
+
params: () => ({
|
|
146
|
+
error: new Error("Authentication timed out")
|
|
147
|
+
})
|
|
148
|
+
}
|
|
149
|
+
],
|
|
150
|
+
target: AuthStateType.ERROR
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
[AuthStateType.LOGGED_IN]: {
|
|
155
|
+
tags: ["authenticated"],
|
|
156
|
+
on: {
|
|
157
|
+
"auth.logout": { target: "logging-out" }
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
"logging-out": {
|
|
161
|
+
invoke: {
|
|
162
|
+
src: "logoutActor",
|
|
163
|
+
input: ({ context }) => ({ instance: context.instance }),
|
|
164
|
+
onDone: {
|
|
165
|
+
target: AuthStateType.LOGGED_OUT
|
|
166
|
+
},
|
|
167
|
+
onError: {
|
|
168
|
+
actions: [
|
|
169
|
+
{
|
|
170
|
+
type: "setError",
|
|
171
|
+
params: ({ event }) => ({ error: event.error })
|
|
172
|
+
}
|
|
173
|
+
],
|
|
174
|
+
target: AuthStateType.ERROR
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
},
|
|
178
|
+
[AuthStateType.LOGGED_OUT]: {},
|
|
179
|
+
[AuthStateType.ERROR]: { tags: ["error"] }
|
|
180
|
+
}
|
|
181
|
+
}), actorPath = (ref) => {
|
|
182
|
+
const segments = [];
|
|
183
|
+
let current = ref;
|
|
184
|
+
for (; current; )
|
|
185
|
+
segments.unshift(current.id ?? current.sessionId), current = current._parent;
|
|
186
|
+
return segments.join(":");
|
|
187
|
+
}, inspect = (event) => {
|
|
188
|
+
const ref = event.actorRef, log = logger.child(actorPath(ref));
|
|
189
|
+
switch (event.type) {
|
|
190
|
+
case "@xstate.snapshot": {
|
|
191
|
+
log.debug("snapshot", event.snapshot);
|
|
192
|
+
break;
|
|
193
|
+
}
|
|
194
|
+
case "@xstate.event":
|
|
195
|
+
log.debug("event", event.event);
|
|
196
|
+
break;
|
|
197
|
+
case "@xstate.action":
|
|
198
|
+
log.debug("action", event.action);
|
|
199
|
+
break;
|
|
200
|
+
}
|
|
201
|
+
}, TELEMETRY_API_VERSION = "2024-11-12", FLUSH_INTERVAL_MS = 3e4, checkConsentLogic = fromPromise(async ({ input, signal }) => {
|
|
202
|
+
try {
|
|
203
|
+
return await getClient(input.instance, {
|
|
204
|
+
apiVersion: TELEMETRY_API_VERSION
|
|
205
|
+
}).request({
|
|
206
|
+
uri: "/intake/telemetry-status",
|
|
207
|
+
tag: "telemetry-consent",
|
|
208
|
+
signal
|
|
209
|
+
});
|
|
210
|
+
} catch {
|
|
211
|
+
return { status: "undetermined" };
|
|
212
|
+
}
|
|
213
|
+
}), telemetryLogic = setup({
|
|
214
|
+
types: {
|
|
215
|
+
input: {},
|
|
216
|
+
context: {},
|
|
217
|
+
events: {}
|
|
218
|
+
},
|
|
219
|
+
actors: {
|
|
220
|
+
checkConsent: checkConsentLogic
|
|
221
|
+
},
|
|
222
|
+
guards: {
|
|
223
|
+
isConsentGranted: (_, params) => params.status === "granted"
|
|
224
|
+
},
|
|
225
|
+
actions: {
|
|
226
|
+
createStore: assign({
|
|
227
|
+
store: ({ context }) => {
|
|
228
|
+
const sessionId = createSessionId(), client = getClient(context.instance, {
|
|
229
|
+
apiVersion: TELEMETRY_API_VERSION
|
|
230
|
+
}), store = createBatchedStore(sessionId, {
|
|
231
|
+
flushInterval: FLUSH_INTERVAL_MS,
|
|
232
|
+
resolveConsent: () => client.request({
|
|
233
|
+
uri: "/intake/telemetry-status",
|
|
234
|
+
tag: "telemetry-consent"
|
|
235
|
+
}),
|
|
236
|
+
sendEvents: (batch) => client.request({
|
|
237
|
+
uri: "/intake/batch",
|
|
238
|
+
method: "POST",
|
|
239
|
+
body: { batch },
|
|
240
|
+
tag: "telemetry.batch"
|
|
241
|
+
}),
|
|
242
|
+
sendBeacon: (batch) => typeof navigator > "u" ? !1 : navigator.sendBeacon(
|
|
243
|
+
client.getUrl("/intake/batch"),
|
|
244
|
+
JSON.stringify({ batch })
|
|
245
|
+
)
|
|
246
|
+
});
|
|
247
|
+
return store.logger.updateUserProperties(context.userProperties), store;
|
|
248
|
+
}
|
|
249
|
+
}),
|
|
250
|
+
teardownStore: ({ context }) => {
|
|
251
|
+
context.store?.end();
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}).createMachine({
|
|
255
|
+
id: "telemetry",
|
|
256
|
+
initial: "idle",
|
|
257
|
+
context: ({ input }) => ({
|
|
258
|
+
instance: input.instance,
|
|
259
|
+
store: null,
|
|
260
|
+
userProperties: {
|
|
261
|
+
version: input.version,
|
|
262
|
+
organizationId: input.organizationId,
|
|
263
|
+
environment: input.environment,
|
|
264
|
+
userAgent: input.userAgent
|
|
265
|
+
}
|
|
266
|
+
}),
|
|
267
|
+
states: {
|
|
268
|
+
idle: {
|
|
269
|
+
on: {
|
|
270
|
+
"telemetry.start": {
|
|
271
|
+
target: "checkingConsent"
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
},
|
|
275
|
+
checkingConsent: {
|
|
276
|
+
invoke: {
|
|
277
|
+
src: "checkConsent",
|
|
278
|
+
input: ({ context }) => ({
|
|
279
|
+
instance: context.instance
|
|
280
|
+
}),
|
|
281
|
+
onDone: [
|
|
282
|
+
{
|
|
283
|
+
guard: {
|
|
284
|
+
type: "isConsentGranted",
|
|
285
|
+
params: ({ event }) => ({
|
|
286
|
+
status: event.output.status
|
|
287
|
+
})
|
|
288
|
+
},
|
|
289
|
+
actions: [{ type: "createStore" }],
|
|
290
|
+
target: "active"
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
target: "denied"
|
|
294
|
+
}
|
|
295
|
+
]
|
|
296
|
+
}
|
|
297
|
+
},
|
|
298
|
+
active: {
|
|
299
|
+
tags: ["telemetry-resolved"],
|
|
300
|
+
exit: [{ type: "teardownStore" }],
|
|
301
|
+
on: {
|
|
302
|
+
"telemetry.stop": { target: "stopped" }
|
|
303
|
+
}
|
|
304
|
+
},
|
|
305
|
+
stopped: {
|
|
306
|
+
type: "final"
|
|
307
|
+
},
|
|
308
|
+
denied: {
|
|
309
|
+
tags: ["telemetry-resolved"]
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}), os = setup({
|
|
313
|
+
types: {
|
|
314
|
+
input: {},
|
|
315
|
+
context: {},
|
|
316
|
+
events: {},
|
|
317
|
+
// https://github.com/statelyai/xstate/issues/5515
|
|
318
|
+
children: {}
|
|
319
|
+
},
|
|
320
|
+
actors: {
|
|
321
|
+
auth: authLogic,
|
|
322
|
+
telemetry: telemetryLogic
|
|
323
|
+
},
|
|
324
|
+
guards: {
|
|
325
|
+
hasTag: (_, params) => params.hasTag
|
|
326
|
+
},
|
|
327
|
+
actions: {
|
|
328
|
+
raiseAuthReady: raise({ type: "boot.auth.ready" }),
|
|
329
|
+
raiseAuthFailed: raise({ type: "boot.auth.failed" }),
|
|
330
|
+
raiseTelemetryReady: raise({
|
|
331
|
+
type: "boot.telemetry.ready"
|
|
332
|
+
}),
|
|
333
|
+
startTelemetry: sendTo("telemetry", {
|
|
334
|
+
type: "telemetry.start"
|
|
335
|
+
})
|
|
336
|
+
}
|
|
337
|
+
}).createMachine({
|
|
338
|
+
id: "os",
|
|
339
|
+
context: ({ input }) => ({
|
|
340
|
+
instance: createSanityInstance(),
|
|
341
|
+
userProperties: {
|
|
342
|
+
version: input.version,
|
|
343
|
+
organizationId: input.organizationId,
|
|
344
|
+
environment: input.environment,
|
|
345
|
+
userAgent: input.userAgent
|
|
346
|
+
}
|
|
347
|
+
}),
|
|
348
|
+
initial: "booting",
|
|
349
|
+
invoke: [
|
|
350
|
+
{
|
|
351
|
+
id: "auth",
|
|
352
|
+
systemId: "auth",
|
|
353
|
+
src: "auth",
|
|
354
|
+
input: ({ context }) => ({ instance: context.instance }),
|
|
355
|
+
onSnapshot: [
|
|
356
|
+
{
|
|
357
|
+
guard: {
|
|
358
|
+
type: "hasTag",
|
|
359
|
+
params: ({ event }) => ({
|
|
360
|
+
hasTag: event.snapshot.hasTag("authenticated")
|
|
361
|
+
})
|
|
362
|
+
},
|
|
363
|
+
actions: [{ type: "raiseAuthReady" }]
|
|
364
|
+
},
|
|
365
|
+
{
|
|
366
|
+
guard: {
|
|
367
|
+
type: "hasTag",
|
|
368
|
+
params: ({ event }) => ({
|
|
369
|
+
hasTag: event.snapshot.hasTag("error")
|
|
370
|
+
})
|
|
371
|
+
},
|
|
372
|
+
actions: [{ type: "raiseAuthFailed" }]
|
|
373
|
+
}
|
|
374
|
+
]
|
|
375
|
+
},
|
|
376
|
+
{
|
|
377
|
+
id: "telemetry",
|
|
378
|
+
systemId: "telemetry",
|
|
379
|
+
src: "telemetry",
|
|
380
|
+
input: ({ context }) => ({
|
|
381
|
+
instance: context.instance,
|
|
382
|
+
...context.userProperties
|
|
383
|
+
}),
|
|
384
|
+
onSnapshot: [
|
|
385
|
+
{
|
|
386
|
+
guard: {
|
|
387
|
+
type: "hasTag",
|
|
388
|
+
params: ({ event }) => ({
|
|
389
|
+
hasTag: event.snapshot.hasTag("telemetry-resolved")
|
|
390
|
+
})
|
|
391
|
+
},
|
|
392
|
+
actions: [{ type: "raiseTelemetryReady" }]
|
|
393
|
+
}
|
|
394
|
+
]
|
|
395
|
+
}
|
|
396
|
+
],
|
|
397
|
+
states: {
|
|
398
|
+
booting: {
|
|
399
|
+
initial: "auth",
|
|
400
|
+
states: {
|
|
401
|
+
auth: {
|
|
402
|
+
on: {
|
|
403
|
+
"boot.auth.ready": {
|
|
404
|
+
target: "telemetry",
|
|
405
|
+
actions: [{ type: "startTelemetry" }]
|
|
406
|
+
},
|
|
407
|
+
"boot.auth.failed": { target: "error" }
|
|
408
|
+
}
|
|
409
|
+
},
|
|
410
|
+
telemetry: {
|
|
411
|
+
on: {
|
|
412
|
+
"boot.telemetry.ready": { target: "done" }
|
|
413
|
+
}
|
|
414
|
+
},
|
|
415
|
+
error: {},
|
|
416
|
+
done: { type: "final" }
|
|
417
|
+
},
|
|
418
|
+
onDone: { target: "running" }
|
|
419
|
+
},
|
|
420
|
+
running: {
|
|
421
|
+
type: "parallel"
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
});
|
|
425
|
+
function createOSOptions(input) {
|
|
426
|
+
return {
|
|
427
|
+
id: "os",
|
|
428
|
+
input,
|
|
429
|
+
inspect
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
export {
|
|
433
|
+
createOSOptions,
|
|
434
|
+
os
|
|
435
|
+
};
|
|
436
|
+
//# sourceMappingURL=system.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"system.js","sources":["../src/system/auth.machine.ts","../src/system/inspect.ts","../src/system/telemetry.machine.ts","../src/system/root.machine.ts"],"sourcesContent":["import {\n type AuthState,\n AuthStateType,\n type CurrentUser,\n getAuthState,\n type LoggedInAuthState,\n logout,\n type SanityInstance,\n} from \"@sanity/sdk\";\nimport { assign, fromObservable, fromPromise, setup } from \"xstate\";\n\nimport type { OSBaseInput } from \"./root.machine\";\n\n/**\n * @internal\n */\nexport interface AuthInput extends OSBaseInput {}\n\nconst authStateLogic = fromObservable<AuthState, AuthInput>(\n ({ input }) => getAuthState(input.instance).observable,\n);\n\n/**\n * @internal\n */\nexport interface LogoutInput extends OSBaseInput {}\n\nconst logoutActorLogic = fromPromise<void, LogoutInput>(async ({ input }) => {\n await logout(input.instance);\n});\n\ntype AuthContext = {\n instance: SanityInstance;\n token: string | null;\n currentUser: CurrentUser | null;\n error: unknown;\n};\n\ntype AuthEvent = { type: \"auth.logout\" };\n\nexport const authLogic = setup({\n types: {\n input: {} as AuthInput,\n context: {} as AuthContext,\n events: {} as AuthEvent,\n tags: {} as \"authenticating\" | \"authenticated\" | \"error\",\n },\n actors: {\n authState: authStateLogic,\n logoutActor: logoutActorLogic,\n },\n delays: {\n authTimeout: 30_000,\n },\n guards: {\n isLoggedInComplete: (_, params: { state: AuthState | undefined }) =>\n params.state?.type === AuthStateType.LOGGED_IN &&\n Boolean((params.state as LoggedInAuthState).token) &&\n (params.state as LoggedInAuthState).currentUser !== null,\n isAuthState: (\n _,\n params: { state: AuthState | undefined; type: AuthStateType },\n ) => params.state?.type === params.type,\n },\n actions: {\n setLoggedIn: assign({\n token: (_, params: { token: string; currentUser: CurrentUser }) =>\n params.token,\n currentUser: (_, params: { token: string; currentUser: CurrentUser }) =>\n params.currentUser,\n error: () => null,\n }),\n clearAuth: assign({\n token: () => null,\n currentUser: () => null,\n error: () => null,\n }),\n setError: assign({\n token: () => null,\n currentUser: () => null,\n error: (_, params: { error: unknown }) => params.error,\n }),\n },\n}).createMachine({\n id: \"auth\",\n initial: \"init\",\n context: ({ input }) => ({\n instance: input.instance,\n token: null,\n currentUser: null,\n error: null,\n }),\n invoke: {\n src: \"authState\",\n input: ({ context }) => ({ instance: context.instance }),\n onSnapshot: [\n {\n guard: {\n type: \"isLoggedInComplete\",\n params: ({ event }) => ({\n state: event.snapshot.context,\n }),\n },\n actions: [\n {\n type: \"setLoggedIn\",\n params: ({ event }) => {\n const state = event.snapshot.context as LoggedInAuthState;\n return {\n token: state.token,\n currentUser: state.currentUser!,\n };\n },\n },\n ],\n target: `.${AuthStateType.LOGGED_IN}`,\n },\n {\n guard: {\n type: \"isAuthState\",\n params: ({ event }) => ({\n state: event.snapshot.context,\n type: AuthStateType.LOGGING_IN,\n }),\n },\n actions: [{ type: \"clearAuth\" }],\n target: `.${AuthStateType.LOGGING_IN}`,\n },\n {\n guard: {\n type: \"isAuthState\",\n params: ({ event }) => ({\n state: event.snapshot.context,\n type: AuthStateType.ERROR,\n }),\n },\n actions: [\n {\n type: \"setError\",\n params: ({ event }) => ({\n error:\n event.snapshot.context?.type === AuthStateType.ERROR\n ? event.snapshot.context.error\n : null,\n }),\n },\n ],\n target: `.${AuthStateType.ERROR}`,\n },\n {\n guard: {\n type: \"isAuthState\",\n params: ({ event }) => ({\n state: event.snapshot.context,\n type: AuthStateType.LOGGED_OUT,\n }),\n },\n actions: [{ type: \"clearAuth\" }],\n target: `.${AuthStateType.LOGGED_OUT}`,\n },\n ],\n },\n states: {\n init: {\n tags: [\"authenticating\"],\n after: {\n authTimeout: {\n actions: [\n {\n type: \"setError\",\n params: () => ({\n error: new Error(\"Authentication timed out\"),\n }),\n },\n ],\n target: AuthStateType.ERROR,\n },\n },\n },\n [AuthStateType.LOGGING_IN]: {\n tags: [\"authenticating\"],\n after: {\n authTimeout: {\n actions: [\n {\n type: \"setError\",\n params: () => ({\n error: new Error(\"Authentication timed out\"),\n }),\n },\n ],\n target: AuthStateType.ERROR,\n },\n },\n },\n [AuthStateType.LOGGED_IN]: {\n tags: [\"authenticated\"],\n on: {\n \"auth.logout\": { target: \"logging-out\" },\n },\n },\n [\"logging-out\"]: {\n invoke: {\n src: \"logoutActor\",\n input: ({ context }) => ({ instance: context.instance }),\n onDone: {\n target: AuthStateType.LOGGED_OUT,\n },\n onError: {\n actions: [\n {\n type: \"setError\",\n params: ({ event }) => ({ error: event.error }),\n },\n ],\n target: AuthStateType.ERROR,\n },\n },\n },\n [AuthStateType.LOGGED_OUT]: {},\n [AuthStateType.ERROR]: { tags: [\"error\"] },\n },\n});\n","import { type ActorRefLike, type InspectionEvent } from \"xstate\";\n\nimport { logger } from \"../core\";\n\n// Mirrors @statelyai/inspect's ActorRefLikeWithData — the inspect\n// callback receives full Actor instances at runtime, but the type is\n// narrowed for @xstate/store compat.\ntype ActorRefWithAncestry = ActorRefLike & {\n id?: string;\n _parent?: ActorRefWithAncestry;\n};\n\nconst actorPath = (ref: ActorRefWithAncestry): string => {\n const segments: string[] = [];\n let current: ActorRefWithAncestry | undefined = ref;\n while (current) {\n segments.unshift(current.id ?? current.sessionId);\n current = current._parent;\n }\n return segments.join(\":\");\n};\n\n/** @internal exported for testing */\nexport const inspect = (event: InspectionEvent): void => {\n const ref = event.actorRef as ActorRefWithAncestry;\n const log = logger.child(actorPath(ref));\n\n switch (event.type) {\n case \"@xstate.snapshot\": {\n log.debug(\"snapshot\", event.snapshot);\n break;\n }\n case \"@xstate.event\":\n log.debug(\"event\", event.event);\n break;\n case \"@xstate.action\":\n log.debug(\"action\", event.action);\n break;\n }\n};\n","import { getClient, type SanityInstance } from \"@sanity/sdk\";\nimport {\n type ConsentStatus,\n createBatchedStore,\n createSessionId,\n type TelemetryEvent,\n type TelemetryStore,\n} from \"@sanity/telemetry\";\nimport { assign, fromPromise, setup } from \"xstate\";\n\nimport type { OSBaseInput } from \"./root.machine\";\n\n/**\n * @public\n */\nexport type WorkbenchUserProperties = {\n version: string;\n organizationId: string;\n environment: string;\n userAgent: string;\n};\n\n/**\n * @internal\n */\nexport interface TelemetryInput extends OSBaseInput, WorkbenchUserProperties {}\n\n/**\n * TODO: this shouldn't be unique to the telemetry machine,\n * remove this and set it globally with a single client actor.\n */\nconst TELEMETRY_API_VERSION = \"2024-11-12\";\n/**\n * 30 seconds, in milliseconds, is the default flush interval\n * for the telemetry store.\n */\nconst FLUSH_INTERVAL_MS = 30_000;\n\ntype ConsentResult = { status: ConsentStatus };\n\nconst checkConsentLogic = fromPromise<\n ConsentResult,\n { instance: SanityInstance }\n>(async ({ input, signal }) => {\n try {\n const client = getClient(input.instance, {\n apiVersion: TELEMETRY_API_VERSION,\n });\n return await client.request<ConsentResult>({\n uri: \"/intake/telemetry-status\",\n tag: \"telemetry-consent\",\n signal,\n });\n } catch {\n return { status: \"undetermined\" } satisfies ConsentResult;\n }\n});\n\ntype TelemetryContext = {\n instance: SanityInstance;\n store: TelemetryStore<WorkbenchUserProperties> | null;\n userProperties: WorkbenchUserProperties;\n};\n\ntype TelemetryMachineEvent =\n | { type: \"telemetry.start\" }\n | { type: \"telemetry.stop\" };\n\nexport const telemetryLogic = setup({\n types: {\n input: {} as TelemetryInput,\n context: {} as TelemetryContext,\n events: {} as TelemetryMachineEvent,\n },\n actors: {\n checkConsent: checkConsentLogic,\n },\n guards: {\n isConsentGranted: (_, params: { status: ConsentStatus }) =>\n params.status === \"granted\",\n },\n actions: {\n createStore: assign({\n store: ({ context }) => {\n const sessionId = createSessionId();\n const client = getClient(context.instance, {\n apiVersion: TELEMETRY_API_VERSION,\n });\n const store = createBatchedStore<WorkbenchUserProperties>(sessionId, {\n flushInterval: FLUSH_INTERVAL_MS,\n resolveConsent: () =>\n client.request<{ status: ConsentStatus }>({\n uri: \"/intake/telemetry-status\",\n tag: \"telemetry-consent\",\n }),\n sendEvents: (batch: TelemetryEvent[]) =>\n client.request({\n uri: \"/intake/batch\",\n method: \"POST\",\n body: { batch },\n tag: \"telemetry.batch\",\n }),\n sendBeacon: (batch: TelemetryEvent[]) => {\n if (typeof navigator === \"undefined\") {\n return false;\n }\n return navigator.sendBeacon(\n client.getUrl(\"/intake/batch\"),\n JSON.stringify({ batch }),\n );\n },\n });\n store.logger.updateUserProperties(context.userProperties);\n return store;\n },\n }),\n teardownStore: ({ context }) => {\n context.store?.end();\n },\n },\n}).createMachine({\n id: \"telemetry\",\n initial: \"idle\",\n context: ({ input }) => ({\n instance: input.instance,\n store: null,\n userProperties: {\n version: input.version,\n organizationId: input.organizationId,\n environment: input.environment,\n userAgent: input.userAgent,\n },\n }),\n states: {\n idle: {\n on: {\n \"telemetry.start\": {\n target: \"checkingConsent\",\n },\n },\n },\n checkingConsent: {\n invoke: {\n src: \"checkConsent\",\n input: ({ context }) => ({\n instance: context.instance,\n }),\n onDone: [\n {\n guard: {\n type: \"isConsentGranted\",\n params: ({ event }) => ({\n status: event.output.status,\n }),\n },\n actions: [{ type: \"createStore\" }],\n target: \"active\",\n },\n {\n target: \"denied\",\n },\n ],\n },\n },\n active: {\n tags: [\"telemetry-resolved\"],\n exit: [{ type: \"teardownStore\" }],\n on: {\n \"telemetry.stop\": { target: \"stopped\" },\n },\n },\n stopped: {\n type: \"final\",\n },\n denied: {\n tags: [\"telemetry-resolved\"],\n },\n },\n});\n","import { createSanityInstance, type SanityInstance } from \"@sanity/sdk\";\nimport { raise, sendTo, setup, type ActorOptions } from \"xstate\";\n\nimport { authLogic } from \"./auth.machine\";\nimport { inspect } from \"./inspect\";\nimport {\n telemetryLogic,\n type WorkbenchUserProperties,\n} from \"./telemetry.machine\";\n\ntype OSInput = WorkbenchUserProperties;\ntype OSContext = {\n instance: SanityInstance;\n userProperties: WorkbenchUserProperties;\n};\n\n/**\n * The base inputs for the OS machine.\n * @internal\n */\nexport interface OSBaseInput extends Pick<OSContext, \"instance\"> {}\n\n/**\n * The sanity OS machine, responsible for managing the global state of the OS.\n * @public\n * @example\n * ```ts\n * import { os, createOSOptions } from \"@sanity/workbench/system\";\n * import { useActor } from \"@xstate/react\";\n *\n * const [state, send] = useActor(os, createOSOptions());\n * ```\n */\nexport const os = setup({\n types: {\n input: {} as OSInput,\n context: {} as OSContext,\n events: {} as\n | { type: \"boot.auth.ready\" }\n | { type: \"boot.auth.failed\" }\n | { type: \"boot.telemetry.ready\" },\n // https://github.com/statelyai/xstate/issues/5515\n children: {} as {\n auth: \"auth\";\n telemetry: \"telemetry\";\n },\n },\n actors: {\n auth: authLogic,\n telemetry: telemetryLogic,\n },\n guards: {\n hasTag: (_, params: { hasTag: boolean }) => params.hasTag,\n },\n actions: {\n raiseAuthReady: raise({ type: \"boot.auth.ready\" }),\n raiseAuthFailed: raise({ type: \"boot.auth.failed\" }),\n raiseTelemetryReady: raise({\n type: \"boot.telemetry.ready\",\n }),\n startTelemetry: sendTo(\"telemetry\", {\n type: \"telemetry.start\",\n }),\n },\n}).createMachine({\n id: \"os\",\n context: ({ input }) => ({\n instance: createSanityInstance(),\n userProperties: {\n version: input.version,\n organizationId: input.organizationId,\n environment: input.environment,\n userAgent: input.userAgent,\n },\n }),\n initial: \"booting\",\n invoke: [\n {\n id: \"auth\",\n systemId: \"auth\",\n src: \"auth\",\n input: ({ context }) => ({ instance: context.instance }),\n onSnapshot: [\n {\n guard: {\n type: \"hasTag\",\n params: ({ event }) => ({\n hasTag: event.snapshot.hasTag(\"authenticated\"),\n }),\n },\n actions: [{ type: \"raiseAuthReady\" }],\n },\n {\n guard: {\n type: \"hasTag\",\n params: ({ event }) => ({\n hasTag: event.snapshot.hasTag(\"error\"),\n }),\n },\n actions: [{ type: \"raiseAuthFailed\" }],\n },\n ],\n },\n {\n id: \"telemetry\",\n systemId: \"telemetry\",\n src: \"telemetry\",\n input: ({ context }) => ({\n instance: context.instance,\n ...context.userProperties,\n }),\n onSnapshot: [\n {\n guard: {\n type: \"hasTag\",\n params: ({ event }) => ({\n hasTag: event.snapshot.hasTag(\"telemetry-resolved\"),\n }),\n },\n actions: [{ type: \"raiseTelemetryReady\" }],\n },\n ],\n },\n ],\n states: {\n booting: {\n initial: \"auth\",\n states: {\n auth: {\n on: {\n \"boot.auth.ready\": {\n target: \"telemetry\",\n actions: [{ type: \"startTelemetry\" }],\n },\n \"boot.auth.failed\": { target: \"error\" },\n },\n },\n telemetry: {\n on: {\n \"boot.telemetry.ready\": { target: \"done\" },\n },\n },\n error: {},\n done: { type: \"final\" },\n },\n onDone: { target: \"running\" },\n },\n running: {\n type: \"parallel\",\n },\n },\n});\n\n/**\n * Creates a set of default options for the OS machine, including passing\n * the sanity configuration for the internal instance.\n * @public\n */\nexport function createOSOptions(input: OSInput) {\n return {\n id: \"os\",\n input,\n inspect,\n } satisfies ActorOptions<typeof os>;\n}\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sanity/workbench",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.13",
|
|
4
4
|
"description": "Workbench component for the Sanity Content Operating System",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"homepage": "https://github.com/sanity-io/workbench/packages/@sanity/workbench#readme",
|
|
@@ -34,23 +34,34 @@
|
|
|
34
34
|
"development": "./src/_exports/core.ts",
|
|
35
35
|
"default": "./dist/core.js"
|
|
36
36
|
},
|
|
37
|
+
"./system": {
|
|
38
|
+
"source": "./src/_exports/system.ts",
|
|
39
|
+
"development": "./src/_exports/system.ts",
|
|
40
|
+
"default": "./dist/system.js"
|
|
41
|
+
},
|
|
37
42
|
"./package.json": "./package.json"
|
|
38
43
|
},
|
|
39
44
|
"dependencies": {
|
|
40
45
|
"@sanity/message-protocol": "^0.23.0",
|
|
46
|
+
"@sanity/telemetry": "^1.1.0",
|
|
41
47
|
"rxjs": "^7.8.2",
|
|
42
48
|
"semver": "^7.7.4",
|
|
49
|
+
"xstate": "^5.31.0",
|
|
43
50
|
"zod": "^4.3.6",
|
|
44
51
|
"@sanity/federation": "0.1.0-alpha.7"
|
|
45
52
|
},
|
|
46
53
|
"devDependencies": {
|
|
47
54
|
"@sanity/pkg-utils": "^9.2.3",
|
|
55
|
+
"@sanity/sdk": "https://pkg.pr.new/sanity-io/sdk/@sanity/sdk@fbc9e08",
|
|
48
56
|
"@types/semver": "^7.7.1",
|
|
49
57
|
"typescript": "^6.0.2",
|
|
50
58
|
"vite": "^7.3.1",
|
|
51
59
|
"@repo/tsconfig": "0.0.1",
|
|
52
60
|
"@repo/oxc-config": "0.0.0"
|
|
53
61
|
},
|
|
62
|
+
"peerDependencies": {
|
|
63
|
+
"@sanity/sdk": "^2.9.0"
|
|
64
|
+
},
|
|
54
65
|
"browserslist": "extends @sanity/browserslist-config",
|
|
55
66
|
"engines": {
|
|
56
67
|
"node": ">=20.19.1 <22 || >=22.12"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "../system";
|
package/src/core/log/index.ts
CHANGED
|
@@ -26,6 +26,7 @@ export interface Logger {
|
|
|
26
26
|
warn: (message: string, context?: LogContext) => void;
|
|
27
27
|
info: (message: string, context?: LogContext) => void;
|
|
28
28
|
debug: (message: string, context?: LogContext) => void;
|
|
29
|
+
child: (domain: string, context?: LogContext) => Logger;
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
const LEVELS: readonly LogLevel[] = ["none", "error", "warn", "info", "debug"];
|
|
@@ -37,6 +38,31 @@ interface LoggerOptions {
|
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
/**
|
|
41
|
+
* Creates a leveled logger with an optional namespace prefix and bound
|
|
42
|
+
* context. Calls below the configured `logLevel` are suppressed; `"none"`
|
|
43
|
+
* silences the logger entirely.
|
|
44
|
+
*
|
|
45
|
+
* Use {@link Logger.child} to derive a sub-logger with an extended namespace
|
|
46
|
+
* (e.g. `parent:domain`) that inherits the parent's level and merges its
|
|
47
|
+
* bound context.
|
|
48
|
+
*
|
|
49
|
+
* @param options - Logger configuration.
|
|
50
|
+
* @param options.namespace - Prepended to every message in `[brackets]`.
|
|
51
|
+
* @param options.context - Bound context merged with per-call context.
|
|
52
|
+
* Per-call keys win on conflict.
|
|
53
|
+
* @param options.logLevel - Maximum verbosity to emit. Default `"info"`.
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```ts
|
|
57
|
+
* const log = createLogger({ namespace: "checkout", logLevel: "debug" });
|
|
58
|
+
* log.info("placed", { orderId: "abc" });
|
|
59
|
+
* // → [checkout] placed { orderId: "abc" }
|
|
60
|
+
*
|
|
61
|
+
* const auth = log.child("auth", { tenant: "acme" });
|
|
62
|
+
* auth.warn("token expiring");
|
|
63
|
+
* // → [checkout:auth] token expiring { tenant: "acme" }
|
|
64
|
+
* ```
|
|
65
|
+
*
|
|
40
66
|
* @public
|
|
41
67
|
*/
|
|
42
68
|
export function createLogger({
|
|
@@ -76,6 +102,13 @@ export function createLogger({
|
|
|
76
102
|
warn: (message, context) => logAtLevel("warn", message, context),
|
|
77
103
|
info: (message, context) => logAtLevel("info", message, context),
|
|
78
104
|
debug: (message, context) => logAtLevel("debug", message, context),
|
|
105
|
+
child: (domain, context) =>
|
|
106
|
+
createLogger({
|
|
107
|
+
logLevel,
|
|
108
|
+
namespace: namespace ? `${namespace}:${domain}` : domain,
|
|
109
|
+
context:
|
|
110
|
+
baseContext || context ? { ...baseContext, ...context } : undefined,
|
|
111
|
+
}),
|
|
79
112
|
};
|
|
80
113
|
}
|
|
81
114
|
|
package/src/core/projects.ts
CHANGED
|
@@ -57,7 +57,7 @@ export const Project = z.object({
|
|
|
57
57
|
externalStudioHost: z.string().optional(),
|
|
58
58
|
initialTemplate: z.string().optional(),
|
|
59
59
|
cliInitializedAt: z.string().optional(),
|
|
60
|
-
integration: z.
|
|
60
|
+
integration: z.string().optional(),
|
|
61
61
|
}),
|
|
62
62
|
isBlocked: z.boolean(),
|
|
63
63
|
isDisabled: z.boolean(),
|
|
@@ -29,19 +29,22 @@ const CoreAppUserApplicationBase = UserApplicationBase.extend({
|
|
|
29
29
|
title: z.string(),
|
|
30
30
|
organizationId: OrganizationId,
|
|
31
31
|
type: z.literal("coreApp"),
|
|
32
|
-
manifest: CoreAppUserApplicationManifest.nullable().optional(),
|
|
33
32
|
});
|
|
34
33
|
|
|
34
|
+
// Core apps surface their manifest exclusively via `activeDeployment.manifest`
|
|
35
|
+
// — they have no top-level `manifest` field and no `manifestData`.
|
|
36
|
+
const CoreAppActiveDeployment = ActiveDeployment.extend({
|
|
37
|
+
manifest: CoreAppUserApplicationManifest.nullable(),
|
|
38
|
+
}).nullable();
|
|
39
|
+
|
|
35
40
|
const InternalCoreAppUserApplication = CoreAppUserApplicationBase.extend({
|
|
36
41
|
urlType: z.literal("internal"),
|
|
37
|
-
activeDeployment:
|
|
38
|
-
manifest: CoreAppUserApplicationManifest.nullable().optional(),
|
|
39
|
-
}).nullable(),
|
|
42
|
+
activeDeployment: CoreAppActiveDeployment,
|
|
40
43
|
});
|
|
41
44
|
|
|
42
45
|
const ExternalCoreAppUserApplication = CoreAppUserApplicationBase.extend({
|
|
43
46
|
urlType: z.literal("external"),
|
|
44
|
-
activeDeployment:
|
|
47
|
+
activeDeployment: CoreAppActiveDeployment,
|
|
45
48
|
});
|
|
46
49
|
|
|
47
50
|
/**
|
|
@@ -98,7 +101,17 @@ export class CoreAppApplication extends UserApplication<
|
|
|
98
101
|
}
|
|
99
102
|
|
|
100
103
|
get title() {
|
|
101
|
-
return this.
|
|
104
|
+
return this.manifest?.title ?? this.application.title;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Resolves the core app's manifest from `activeDeployment.manifest`. This
|
|
109
|
+
* is the canonical (and only) slot for core app manifests — both for
|
|
110
|
+
* Sanity-deployed apps and for local CLI dev-server apps, which synthesise
|
|
111
|
+
* a deployment to surface the live manifest.
|
|
112
|
+
*/
|
|
113
|
+
get manifest(): CoreAppUserApplicationManifest | null {
|
|
114
|
+
return this.activeDeployment?.manifest ?? null;
|
|
102
115
|
}
|
|
103
116
|
|
|
104
117
|
get subtitle() {
|
|
@@ -18,7 +18,10 @@ const Workspace = z.object({
|
|
|
18
18
|
*/
|
|
19
19
|
export type Workspace = z.output<typeof Workspace>;
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
/**
|
|
22
|
+
* @public
|
|
23
|
+
*/
|
|
24
|
+
export const ServerManifest = z.object({
|
|
22
25
|
buildId: z.string().optional(),
|
|
23
26
|
bundleVersion: z.string().optional(),
|
|
24
27
|
version: z.string().optional(),
|
|
@@ -32,6 +35,11 @@ const ServerManifest = z.object({
|
|
|
32
35
|
.optional(),
|
|
33
36
|
});
|
|
34
37
|
|
|
38
|
+
/**
|
|
39
|
+
* @public
|
|
40
|
+
*/
|
|
41
|
+
export type ServerManifest = z.output<typeof ServerManifest>;
|
|
42
|
+
|
|
35
43
|
/**
|
|
36
44
|
* @public
|
|
37
45
|
*/
|
|
@@ -56,6 +64,9 @@ const StudioUserApplicationBase = UserApplicationBase.extend({
|
|
|
56
64
|
title: z.string().nullable(),
|
|
57
65
|
projectId: ProjectId,
|
|
58
66
|
type: z.literal("studio"),
|
|
67
|
+
/**
|
|
68
|
+
* @deprecated Use `manifestData` instead.
|
|
69
|
+
*/
|
|
59
70
|
manifest: ClientManifest.nullable(),
|
|
60
71
|
manifestData: z.object({ value: ClientManifest }).nullable(),
|
|
61
72
|
autoUpdatingVersion: z.string().nullable(),
|