@sanity/workbench 0.1.0-alpha.2 → 0.1.0-alpha.21

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.
Files changed (52) hide show
  1. package/README.md +24 -0
  2. package/dist/_chunks-es/index.js +39 -0
  3. package/dist/_chunks-es/index.js.map +1 -0
  4. package/dist/_chunks-es/module-federation.js +59 -0
  5. package/dist/_chunks-es/module-federation.js.map +1 -0
  6. package/dist/_chunks-es/studio.js +892 -0
  7. package/dist/_chunks-es/studio.js.map +1 -0
  8. package/dist/_internal.d.ts +16 -4
  9. package/dist/_internal.js +34 -27
  10. package/dist/_internal.js.map +1 -1
  11. package/dist/core.d.ts +2250 -0
  12. package/dist/core.js +74 -0
  13. package/dist/core.js.map +1 -0
  14. package/dist/system.d.ts +2135 -0
  15. package/dist/system.js +887 -0
  16. package/dist/system.js.map +1 -0
  17. package/package.json +34 -6
  18. package/src/_exports/core.ts +1 -0
  19. package/src/_exports/system.ts +1 -0
  20. package/src/_internal/index.ts +2 -1
  21. package/src/_internal/render.ts +72 -43
  22. package/src/core/applications/application-list.ts +104 -0
  23. package/src/core/applications/application.ts +177 -0
  24. package/src/core/applications/interface.ts +126 -0
  25. package/src/core/canvases.ts +92 -0
  26. package/src/core/config.ts +34 -0
  27. package/src/core/env.ts +43 -0
  28. package/src/core/index.ts +13 -0
  29. package/src/core/log/index.ts +125 -0
  30. package/src/core/media-libraries.ts +93 -0
  31. package/src/core/organizations.ts +115 -0
  32. package/src/core/projects.ts +114 -0
  33. package/src/core/shared/urls.ts +129 -0
  34. package/src/core/user-applications/core-app.ts +148 -0
  35. package/src/core/user-applications/studios/index.ts +3 -0
  36. package/src/core/user-applications/studios/schemas.ts +128 -0
  37. package/src/core/user-applications/studios/studio.ts +533 -0
  38. package/src/core/user-applications/studios/workspace.ts +156 -0
  39. package/src/core/user-applications/user-application.ts +222 -0
  40. package/src/system/auth.machine.ts +223 -0
  41. package/src/system/index.ts +22 -0
  42. package/src/system/inspect.ts +40 -0
  43. package/src/system/load-federated-module.ts +53 -0
  44. package/src/system/module-federation.ts +116 -0
  45. package/src/system/remote.machine.ts +219 -0
  46. package/src/system/remotes.machine.ts +92 -0
  47. package/src/system/root.machine.ts +224 -0
  48. package/src/system/service.machine.ts +207 -0
  49. package/src/system/services.machine.ts +120 -0
  50. package/src/system/system-preferences.machine.ts +215 -0
  51. package/src/system/telemetry.machine.ts +179 -0
  52. package/src/_internal/render.test.ts +0 -18
package/dist/system.js ADDED
@@ -0,0 +1,887 @@
1
+ import { fromPromise, setup, assign, sendParent, fromObservable, fromCallback, enqueueActions, sendTo, raise } from "xstate";
2
+ import { logger } from "./_chunks-es/index.js";
3
+ import { getAuthState, logout, AuthStateType, getClient, createSanityInstance } from "@sanity/sdk";
4
+ import "./_chunks-es/studio.js";
5
+ import { createInstance, log } from "./_chunks-es/module-federation.js";
6
+ import { createSessionId, createBatchedStore } from "@sanity/telemetry";
7
+ async function loadRemoteModule(instance, { moduleId, entry }) {
8
+ const name = moduleId.slice(0, moduleId.indexOf("/"));
9
+ return instance.registerRemotes([{ name, entry }]), await instance.loadRemote(moduleId) ?? null;
10
+ }
11
+ async function loadFederatedModule(instance, ref) {
12
+ try {
13
+ return await loadRemoteModule(instance, ref);
14
+ } catch (error) {
15
+ return logger.error(`Failed to load federated module "${ref.moduleId}"`, error), null;
16
+ }
17
+ }
18
+ class ModuleShapeError extends Error {
19
+ constructor(remoteId) {
20
+ super(`Remote "${remoteId}" did not expose a render function`);
21
+ }
22
+ }
23
+ class ModuleLoadError extends Error {
24
+ constructor(remoteId) {
25
+ super(`Remote module "${remoteId}" failed to load`);
26
+ }
27
+ }
28
+ const loadLogic = fromPromise(async ({ input }) => {
29
+ const remoteModule = await loadRemoteModule(input.instance, {
30
+ moduleId: input.moduleId,
31
+ entry: input.entry
32
+ });
33
+ if (remoteModule == null)
34
+ throw new ModuleLoadError(input.moduleId);
35
+ return remoteModule;
36
+ }), remoteLogic = setup({
37
+ types: {
38
+ input: {},
39
+ context: {},
40
+ tags: {}
41
+ },
42
+ actors: {
43
+ load: loadLogic
44
+ },
45
+ actions: {
46
+ setModule: assign({
47
+ module: (_, params) => params.module,
48
+ error: () => null
49
+ }),
50
+ setError: assign({
51
+ module: () => null,
52
+ error: (_, params) => normaliseError(params.error)
53
+ })
54
+ }
55
+ }).createMachine({
56
+ id: "remote",
57
+ initial: "loading",
58
+ context: ({ input }) => ({
59
+ ...input,
60
+ module: null,
61
+ error: null
62
+ }),
63
+ states: {
64
+ loading: {
65
+ tags: ["loading"],
66
+ invoke: {
67
+ src: "load",
68
+ input: ({ context }) => ({
69
+ moduleId: context.moduleId,
70
+ entry: context.entry,
71
+ instance: context.instance
72
+ }),
73
+ onDone: {
74
+ target: "loaded",
75
+ actions: [
76
+ {
77
+ type: "setModule",
78
+ params: ({ event }) => ({ module: event.output })
79
+ }
80
+ ]
81
+ },
82
+ onError: {
83
+ target: "error",
84
+ actions: [
85
+ {
86
+ type: "setError",
87
+ params: ({ event }) => ({ error: event.error })
88
+ }
89
+ ]
90
+ }
91
+ }
92
+ },
93
+ loaded: {
94
+ tags: ["ready"],
95
+ entry: sendParent(({ context }) => ({
96
+ type: "remote.settled",
97
+ moduleId: context.moduleId,
98
+ status: "loaded"
99
+ }))
100
+ },
101
+ error: {
102
+ tags: ["failed"],
103
+ entry: sendParent(({ context }) => ({
104
+ type: "remote.settled",
105
+ moduleId: context.moduleId,
106
+ status: "error"
107
+ }))
108
+ }
109
+ }
110
+ });
111
+ function normaliseError(error) {
112
+ return error instanceof Error ? { message: error.message, cause: error } : { message: String(error), cause: error };
113
+ }
114
+ const authStateLogic = fromObservable(
115
+ ({ input }) => getAuthState(input.instance).observable
116
+ ), logoutActorLogic = fromPromise(async ({ input }) => {
117
+ await logout(input.instance);
118
+ }), authLogic = setup({
119
+ types: {
120
+ input: {},
121
+ context: {},
122
+ events: {},
123
+ tags: {}
124
+ },
125
+ actors: {
126
+ authState: authStateLogic,
127
+ logoutActor: logoutActorLogic
128
+ },
129
+ delays: {
130
+ authTimeout: 3e4
131
+ },
132
+ guards: {
133
+ isLoggedInComplete: (_, params) => params.state?.type === AuthStateType.LOGGED_IN && !!params.state.token && params.state.currentUser !== null,
134
+ isAuthState: (_, params) => params.state?.type === params.type
135
+ },
136
+ actions: {
137
+ setLoggedIn: assign({
138
+ token: (_, params) => params.token,
139
+ currentUser: (_, params) => params.currentUser,
140
+ error: () => null
141
+ }),
142
+ clearAuth: assign({
143
+ token: () => null,
144
+ currentUser: () => null,
145
+ error: () => null
146
+ }),
147
+ setError: assign({
148
+ token: () => null,
149
+ currentUser: () => null,
150
+ error: (_, params) => params.error
151
+ })
152
+ }
153
+ }).createMachine({
154
+ id: "auth",
155
+ initial: "init",
156
+ context: ({ input }) => ({
157
+ instance: input.instance,
158
+ token: null,
159
+ currentUser: null,
160
+ error: null
161
+ }),
162
+ invoke: {
163
+ src: "authState",
164
+ input: ({ context }) => ({ instance: context.instance }),
165
+ onSnapshot: [
166
+ {
167
+ guard: {
168
+ type: "isLoggedInComplete",
169
+ params: ({ event }) => ({
170
+ state: event.snapshot.context
171
+ })
172
+ },
173
+ actions: [
174
+ {
175
+ type: "setLoggedIn",
176
+ params: ({ event }) => {
177
+ const state = event.snapshot.context;
178
+ return {
179
+ token: state.token,
180
+ currentUser: state.currentUser
181
+ };
182
+ }
183
+ }
184
+ ],
185
+ target: `.${AuthStateType.LOGGED_IN}`
186
+ },
187
+ {
188
+ guard: {
189
+ type: "isAuthState",
190
+ params: ({ event }) => ({
191
+ state: event.snapshot.context,
192
+ type: AuthStateType.LOGGING_IN
193
+ })
194
+ },
195
+ actions: [{ type: "clearAuth" }],
196
+ target: `.${AuthStateType.LOGGING_IN}`
197
+ },
198
+ {
199
+ guard: {
200
+ type: "isAuthState",
201
+ params: ({ event }) => ({
202
+ state: event.snapshot.context,
203
+ type: AuthStateType.ERROR
204
+ })
205
+ },
206
+ actions: [
207
+ {
208
+ type: "setError",
209
+ params: ({ event }) => ({
210
+ error: event.snapshot.context?.type === AuthStateType.ERROR ? event.snapshot.context.error : null
211
+ })
212
+ }
213
+ ],
214
+ target: `.${AuthStateType.ERROR}`
215
+ },
216
+ {
217
+ guard: {
218
+ type: "isAuthState",
219
+ params: ({ event }) => ({
220
+ state: event.snapshot.context,
221
+ type: AuthStateType.LOGGED_OUT
222
+ })
223
+ },
224
+ actions: [{ type: "clearAuth" }],
225
+ target: `.${AuthStateType.LOGGED_OUT}`
226
+ }
227
+ ]
228
+ },
229
+ states: {
230
+ init: {
231
+ tags: ["authenticating"],
232
+ after: {
233
+ authTimeout: {
234
+ actions: [
235
+ {
236
+ type: "setError",
237
+ params: () => ({
238
+ error: new Error("Authentication timed out")
239
+ })
240
+ }
241
+ ],
242
+ target: AuthStateType.ERROR
243
+ }
244
+ }
245
+ },
246
+ [AuthStateType.LOGGING_IN]: {
247
+ tags: ["authenticating"],
248
+ after: {
249
+ authTimeout: {
250
+ actions: [
251
+ {
252
+ type: "setError",
253
+ params: () => ({
254
+ error: new Error("Authentication timed out")
255
+ })
256
+ }
257
+ ],
258
+ target: AuthStateType.ERROR
259
+ }
260
+ }
261
+ },
262
+ [AuthStateType.LOGGED_IN]: {
263
+ tags: ["authenticated"],
264
+ on: {
265
+ "auth.logout": { target: "logging-out" }
266
+ }
267
+ },
268
+ "logging-out": {
269
+ invoke: {
270
+ src: "logoutActor",
271
+ input: ({ context }) => ({ instance: context.instance }),
272
+ onDone: {
273
+ target: AuthStateType.LOGGED_OUT
274
+ },
275
+ onError: {
276
+ actions: [
277
+ {
278
+ type: "setError",
279
+ params: ({ event }) => ({ error: event.error })
280
+ }
281
+ ],
282
+ target: AuthStateType.ERROR
283
+ }
284
+ }
285
+ },
286
+ [AuthStateType.LOGGED_OUT]: {},
287
+ [AuthStateType.ERROR]: { tags: ["error"] }
288
+ }
289
+ }), actorPath = (ref) => {
290
+ const segments = [];
291
+ let current = ref;
292
+ for (; current; )
293
+ segments.unshift(current.id ?? current.sessionId), current = current._parent;
294
+ return segments.join(":");
295
+ }, inspect = (event) => {
296
+ const ref = event.actorRef, log2 = logger.child(actorPath(ref));
297
+ switch (event.type) {
298
+ case "@xstate.snapshot": {
299
+ log2.debug("snapshot", event.snapshot);
300
+ break;
301
+ }
302
+ case "@xstate.event":
303
+ log2.debug("event", event.event);
304
+ break;
305
+ case "@xstate.action":
306
+ log2.debug("action", event.action);
307
+ break;
308
+ }
309
+ }, remotesLogic = setup({
310
+ types: {
311
+ input: {},
312
+ context: {},
313
+ events: {}
314
+ },
315
+ actors: {
316
+ remote: remoteLogic
317
+ },
318
+ guards: {
319
+ remoteNotKnown: ({ context }, params) => !context.children.has(params.moduleId)
320
+ },
321
+ actions: {
322
+ spawnRemote: assign({
323
+ children: ({ context, spawn }, params) => {
324
+ const ref = spawn("remote", {
325
+ id: params.moduleId,
326
+ systemId: `remotes.${params.moduleId}`,
327
+ input: {
328
+ moduleId: params.moduleId,
329
+ entry: params.entry,
330
+ instance: context.instance
331
+ }
332
+ });
333
+ return new Map(context.children).set(params.moduleId, ref);
334
+ }
335
+ })
336
+ }
337
+ }).createMachine({
338
+ id: "remotes",
339
+ context: ({ input }) => ({
340
+ instance: input.instance,
341
+ children: /* @__PURE__ */ new Map()
342
+ }),
343
+ on: {
344
+ "remote.load.request": {
345
+ guard: {
346
+ type: "remoteNotKnown",
347
+ params: ({ event }) => ({ moduleId: event.moduleId })
348
+ },
349
+ actions: [
350
+ {
351
+ type: "spawnRemote",
352
+ params: ({ event }) => ({
353
+ moduleId: event.moduleId,
354
+ entry: event.entry
355
+ })
356
+ }
357
+ ]
358
+ },
359
+ // Reserved for future supervision/retry. Forwarded by per-remote
360
+ // children on entry to `loaded` or `error`; currently a no-op so the
361
+ // event is part of the typed surface rather than a silent unknown.
362
+ "remote.settled": {}
363
+ }
364
+ }), SERVICES_MODULE = "services", runWorker = fromCallback(({ input }) => {
365
+ let worker, blobUrl;
366
+ try {
367
+ const bootstrap = `import(${JSON.stringify(input.workerUrl)})`;
368
+ blobUrl = URL.createObjectURL(
369
+ new Blob([bootstrap], { type: "text/javascript" })
370
+ ), worker = new Worker(blobUrl, { type: "module" }), worker.addEventListener("message", (event) => {
371
+ if (event.data?.kind === "workbench.worker.error")
372
+ logger.error(
373
+ `Service "${input.key}" worker error`,
374
+ event.data.payload?.message
375
+ );
376
+ else if (event.data?.kind === "workbench.worker.log") {
377
+ const { level, message } = event.data.payload ?? {};
378
+ ({
379
+ warn: logger.warn,
380
+ error: logger.error,
381
+ debug: logger.debug
382
+ }[level] ?? logger.info)(
383
+ `[service:${input.serviceName}] ${message ?? ""}`
384
+ );
385
+ }
386
+ }), worker.addEventListener("error", (event) => {
387
+ logger.error(
388
+ `Service "${input.key}" worker error: ${event.message || String(event)}`
389
+ );
390
+ });
391
+ } catch (error) {
392
+ logger.error(`Service "${input.key}" failed to start its worker`, error);
393
+ }
394
+ return () => {
395
+ try {
396
+ worker?.postMessage({ kind: "workbench.worker.terminate" });
397
+ } finally {
398
+ worker?.terminate(), blobUrl && URL.revokeObjectURL(blobUrl);
399
+ }
400
+ };
401
+ }), serviceLogic = setup({
402
+ types: {
403
+ input: {},
404
+ context: {},
405
+ tags: {}
406
+ },
407
+ actors: {
408
+ loadInterface: remoteLogic,
409
+ runWorker
410
+ }
411
+ }).createMachine({
412
+ id: "service",
413
+ initial: "loading",
414
+ context: ({ input }) => ({ ...input, workerUrl: null }),
415
+ // The invoked loader `sendParent`s a `remote.settled` on settle; this machine
416
+ // reacts via `onSnapshot` instead, so the event is a no-op here.
417
+ on: { "remote.settled": {} },
418
+ states: {
419
+ loading: {
420
+ tags: ["loading"],
421
+ invoke: {
422
+ id: "loader",
423
+ src: "loadInterface",
424
+ input: ({ context }) => ({
425
+ moduleId: `${context.appId}/${SERVICES_MODULE}/${context.serviceName}`,
426
+ entry: context.entry,
427
+ instance: context.instance
428
+ }),
429
+ onSnapshot: [
430
+ {
431
+ // Loaded and exposing a bundle URL → run it.
432
+ guard: ({ event }) => {
433
+ const module = event.snapshot.context.module;
434
+ return event.snapshot.hasTag("ready") && typeof module?.url == "string";
435
+ },
436
+ target: "running",
437
+ actions: assign({
438
+ workerUrl: ({ context, event }) => {
439
+ const module = event.snapshot.context.module;
440
+ return new URL(module.url, new URL(context.entry).origin).href;
441
+ }
442
+ })
443
+ },
444
+ {
445
+ // Load failed, or loaded without a usable URL → no worker.
446
+ guard: ({ event }) => {
447
+ const module = event.snapshot.context.module;
448
+ return event.snapshot.hasTag("failed") || event.snapshot.hasTag("ready") && typeof module?.url != "string";
449
+ },
450
+ target: "error",
451
+ // A worker has no UI surface (unlike a view's error boundary), so a
452
+ // failed load would otherwise be silent — log it through the host.
453
+ actions: ({ context, event }) => {
454
+ const cause = event.snapshot.context.error?.message;
455
+ logger.error(
456
+ `Service "${context.key}" failed to load its worker${cause ? `: ${cause}` : ""}`
457
+ );
458
+ }
459
+ }
460
+ ]
461
+ }
462
+ },
463
+ running: {
464
+ tags: ["running"],
465
+ invoke: {
466
+ src: "runWorker",
467
+ input: ({ context }) => ({
468
+ key: context.key,
469
+ serviceName: context.serviceName,
470
+ // `workerUrl` is set on entry to `running` from `loading`'s output.
471
+ workerUrl: context.workerUrl
472
+ })
473
+ }
474
+ },
475
+ error: {
476
+ tags: ["failed"]
477
+ }
478
+ }
479
+ });
480
+ function serviceKey(appId, serviceName) {
481
+ return `${appId}:${serviceName}`;
482
+ }
483
+ const servicesLogic = setup({
484
+ types: {
485
+ input: {},
486
+ context: {},
487
+ events: {}
488
+ },
489
+ actors: {
490
+ service: serviceLogic
491
+ },
492
+ actions: {
493
+ /**
494
+ * Reconcile the running workers against the desired set: spawn the ones not
495
+ * yet running, stop (and forget) the ones no longer declared.
496
+ */
497
+ syncServices: enqueueActions(({ context, event, enqueue }) => {
498
+ const desired = new Map(
499
+ event.services.map((service) => [
500
+ serviceKey(service.appId, service.serviceName),
501
+ service
502
+ ])
503
+ );
504
+ for (const [key, ref] of context.children)
505
+ desired.has(key) || enqueue.stopChild(ref);
506
+ enqueue.assign({
507
+ children: ({ context: ctx, spawn }) => {
508
+ const next = /* @__PURE__ */ new Map();
509
+ for (const [key, ref] of ctx.children)
510
+ desired.has(key) && next.set(key, ref);
511
+ for (const [key, service] of desired)
512
+ next.has(key) || next.set(
513
+ key,
514
+ spawn("service", {
515
+ id: key,
516
+ systemId: `services.${key}`,
517
+ input: {
518
+ key,
519
+ appId: service.appId,
520
+ serviceName: service.serviceName,
521
+ entry: service.entry,
522
+ instance: ctx.instance
523
+ }
524
+ })
525
+ );
526
+ return next;
527
+ }
528
+ });
529
+ })
530
+ }
531
+ }).createMachine({
532
+ id: "services",
533
+ context: ({ input }) => ({
534
+ instance: input.instance,
535
+ children: /* @__PURE__ */ new Map()
536
+ }),
537
+ on: {
538
+ "services.sync": { actions: "syncServices" }
539
+ }
540
+ }), DEFAULT_PREFERRED_COLOR_SCHEME = "system", DEFAULT_OS_COLOR_SCHEME = "light", resolveColorScheme = (preferred, osColorScheme) => preferred === "system" ? osColorScheme : preferred, adapterBridgeLogic = fromCallback(({ input: adapter, sendBack, receive }) => {
541
+ if (!adapter) return;
542
+ const unsubscribePreferredColorScheme = adapter.subscribePreferredColorScheme(
543
+ (next) => {
544
+ sendBack({
545
+ type: "preferredColorScheme.set",
546
+ preferredColorScheme: next ?? "system"
547
+ });
548
+ }
549
+ ), unsubscribeOs = adapter.subscribeOsColorScheme((next) => {
550
+ sendBack({ type: "osColorScheme.set", osColorScheme: next });
551
+ });
552
+ return receive((event) => {
553
+ adapter.getPreferredColorScheme() !== event.preferredColorScheme && adapter.persistPreferredColorScheme(event.preferredColorScheme);
554
+ }), () => {
555
+ unsubscribePreferredColorScheme(), unsubscribeOs();
556
+ };
557
+ }), systemPreferencesLogic = setup({
558
+ types: {
559
+ input: {},
560
+ context: {},
561
+ events: {}
562
+ },
563
+ actors: {
564
+ adapterBridge: adapterBridgeLogic
565
+ },
566
+ actions: {
567
+ setPreferredColorScheme: assign({
568
+ preferredColorScheme: (_, params) => params.preferredColorScheme,
569
+ colorScheme: ({ context }, params) => resolveColorScheme(params.preferredColorScheme, context.osColorScheme)
570
+ }),
571
+ setOsColorScheme: assign({
572
+ osColorScheme: (_, params) => params.osColorScheme,
573
+ colorScheme: ({ context }, params) => resolveColorScheme(context.preferredColorScheme, params.osColorScheme)
574
+ })
575
+ }
576
+ }).createMachine({
577
+ id: "system-preferences",
578
+ initial: "ready",
579
+ context: ({ input }) => {
580
+ const adapter = input.adapter, preferredColorScheme = adapter?.getPreferredColorScheme() ?? DEFAULT_PREFERRED_COLOR_SCHEME, osColorScheme = adapter?.getOsColorScheme() ?? DEFAULT_OS_COLOR_SCHEME;
581
+ return {
582
+ adapter,
583
+ preferredColorScheme,
584
+ osColorScheme,
585
+ colorScheme: resolveColorScheme(preferredColorScheme, osColorScheme)
586
+ };
587
+ },
588
+ invoke: {
589
+ id: "adapter",
590
+ src: "adapterBridge",
591
+ input: ({ context }) => context.adapter
592
+ },
593
+ states: {
594
+ ready: {
595
+ on: {
596
+ "preferredColorScheme.set": {
597
+ actions: [
598
+ {
599
+ type: "setPreferredColorScheme",
600
+ params: ({ event }) => ({
601
+ preferredColorScheme: event.preferredColorScheme
602
+ })
603
+ },
604
+ // Forward to the adapter bridge so it can persist the user's
605
+ // choice. The bridge guards against redundant writes, so
606
+ // round-tripping a `preferredColorScheme.set` it sourced itself
607
+ // (e.g. from a `storage` event in another tab) is a no-op.
608
+ sendTo("adapter", ({ event }) => event)
609
+ ]
610
+ },
611
+ "osColorScheme.set": {
612
+ actions: [
613
+ {
614
+ type: "setOsColorScheme",
615
+ params: ({ event }) => ({
616
+ osColorScheme: event.osColorScheme
617
+ })
618
+ }
619
+ ]
620
+ }
621
+ }
622
+ }
623
+ }
624
+ }), TELEMETRY_API_VERSION = "2024-11-12", FLUSH_INTERVAL_MS = 3e4, checkConsentLogic = fromPromise(async ({ input, signal }) => {
625
+ try {
626
+ return await getClient(input.instance, {
627
+ apiVersion: TELEMETRY_API_VERSION
628
+ }).request({
629
+ uri: "/intake/telemetry-status",
630
+ tag: "telemetry-consent",
631
+ signal
632
+ });
633
+ } catch {
634
+ return { status: "undetermined" };
635
+ }
636
+ }), telemetryLogic = setup({
637
+ types: {
638
+ input: {},
639
+ context: {},
640
+ events: {}
641
+ },
642
+ actors: {
643
+ checkConsent: checkConsentLogic
644
+ },
645
+ guards: {
646
+ isConsentGranted: (_, params) => params.status === "granted"
647
+ },
648
+ actions: {
649
+ createStore: assign({
650
+ store: ({ context }) => {
651
+ const sessionId = createSessionId(), client = getClient(context.instance, {
652
+ apiVersion: TELEMETRY_API_VERSION
653
+ }), store = createBatchedStore(sessionId, {
654
+ flushInterval: FLUSH_INTERVAL_MS,
655
+ resolveConsent: () => client.request({
656
+ uri: "/intake/telemetry-status",
657
+ tag: "telemetry-consent"
658
+ }),
659
+ sendEvents: (batch) => client.request({
660
+ uri: "/intake/batch",
661
+ method: "POST",
662
+ body: { batch },
663
+ tag: "telemetry.batch"
664
+ }),
665
+ sendBeacon: (batch) => typeof navigator > "u" ? !1 : navigator.sendBeacon(
666
+ client.getUrl("/intake/batch"),
667
+ JSON.stringify({ batch })
668
+ )
669
+ });
670
+ return store.logger.updateUserProperties(context.userProperties), store;
671
+ }
672
+ }),
673
+ teardownStore: ({ context }) => {
674
+ context.store?.end();
675
+ }
676
+ }
677
+ }).createMachine({
678
+ id: "telemetry",
679
+ initial: "idle",
680
+ context: ({ input }) => ({
681
+ instance: input.instance,
682
+ store: null,
683
+ userProperties: {
684
+ version: input.version,
685
+ organizationId: input.organizationId,
686
+ environment: input.environment,
687
+ userAgent: input.userAgent
688
+ }
689
+ }),
690
+ states: {
691
+ idle: {
692
+ on: {
693
+ "telemetry.start": {
694
+ target: "checkingConsent"
695
+ }
696
+ }
697
+ },
698
+ checkingConsent: {
699
+ invoke: {
700
+ src: "checkConsent",
701
+ input: ({ context }) => ({
702
+ instance: context.instance
703
+ }),
704
+ onDone: [
705
+ {
706
+ guard: {
707
+ type: "isConsentGranted",
708
+ params: ({ event }) => ({
709
+ status: event.output.status
710
+ })
711
+ },
712
+ actions: [{ type: "createStore" }],
713
+ target: "active"
714
+ },
715
+ {
716
+ target: "denied"
717
+ }
718
+ ]
719
+ }
720
+ },
721
+ active: {
722
+ tags: ["telemetry-resolved"],
723
+ exit: [{ type: "teardownStore" }],
724
+ on: {
725
+ "telemetry.stop": { target: "stopped" }
726
+ }
727
+ },
728
+ stopped: {
729
+ type: "final"
730
+ },
731
+ denied: {
732
+ tags: ["telemetry-resolved"]
733
+ }
734
+ }
735
+ }), os = setup({
736
+ types: {
737
+ input: {},
738
+ context: {},
739
+ events: {},
740
+ // https://github.com/statelyai/xstate/issues/5515
741
+ children: {}
742
+ },
743
+ actors: {
744
+ auth: authLogic,
745
+ telemetry: telemetryLogic,
746
+ systemPreferences: systemPreferencesLogic,
747
+ remotes: remotesLogic,
748
+ services: servicesLogic
749
+ },
750
+ guards: {
751
+ hasTag: (_, params) => params.hasTag
752
+ },
753
+ actions: {
754
+ raiseAuthReady: raise({ type: "boot.auth.ready" }),
755
+ raiseAuthFailed: raise({ type: "boot.auth.failed" }),
756
+ raiseTelemetryReady: raise({
757
+ type: "boot.telemetry.ready"
758
+ }),
759
+ startTelemetry: sendTo("telemetry", {
760
+ type: "telemetry.start"
761
+ })
762
+ }
763
+ }).createMachine({
764
+ id: "os",
765
+ context: ({ input }) => ({
766
+ instance: createSanityInstance(),
767
+ federationInstance: createInstance({
768
+ name: "workbench-applications",
769
+ plugins: [log(logger.debug)]
770
+ }),
771
+ userProperties: {
772
+ version: input.version,
773
+ organizationId: input.organizationId,
774
+ environment: input.environment,
775
+ userAgent: input.userAgent
776
+ },
777
+ systemPreferencesAdapter: input.systemPreferencesAdapter
778
+ }),
779
+ initial: "booting",
780
+ invoke: [
781
+ {
782
+ id: "auth",
783
+ systemId: "auth",
784
+ src: "auth",
785
+ input: ({ context }) => ({ instance: context.instance }),
786
+ onSnapshot: [
787
+ {
788
+ guard: {
789
+ type: "hasTag",
790
+ params: ({ event }) => ({
791
+ hasTag: event.snapshot.hasTag("authenticated")
792
+ })
793
+ },
794
+ actions: [{ type: "raiseAuthReady" }]
795
+ },
796
+ {
797
+ guard: {
798
+ type: "hasTag",
799
+ params: ({ event }) => ({
800
+ hasTag: event.snapshot.hasTag("error")
801
+ })
802
+ },
803
+ actions: [{ type: "raiseAuthFailed" }]
804
+ }
805
+ ]
806
+ },
807
+ {
808
+ id: "telemetry",
809
+ systemId: "telemetry",
810
+ src: "telemetry",
811
+ input: ({ context }) => ({
812
+ instance: context.instance,
813
+ ...context.userProperties
814
+ }),
815
+ onSnapshot: [
816
+ {
817
+ guard: {
818
+ type: "hasTag",
819
+ params: ({ event }) => ({
820
+ hasTag: event.snapshot.hasTag("telemetry-resolved")
821
+ })
822
+ },
823
+ actions: [{ type: "raiseTelemetryReady" }]
824
+ }
825
+ ]
826
+ },
827
+ {
828
+ id: "system-preferences",
829
+ systemId: "system-preferences",
830
+ src: "systemPreferences",
831
+ input: ({ context }) => ({ adapter: context.systemPreferencesAdapter })
832
+ },
833
+ {
834
+ id: "remotes",
835
+ systemId: "remotes",
836
+ src: "remotes",
837
+ input: ({ context }) => ({ instance: context.federationInstance })
838
+ },
839
+ {
840
+ id: "services",
841
+ systemId: "services",
842
+ src: "services",
843
+ input: ({ context }) => ({ instance: context.federationInstance })
844
+ }
845
+ ],
846
+ states: {
847
+ booting: {
848
+ initial: "auth",
849
+ states: {
850
+ auth: {
851
+ on: {
852
+ "boot.auth.ready": {
853
+ target: "telemetry",
854
+ actions: [{ type: "startTelemetry" }]
855
+ },
856
+ "boot.auth.failed": { target: "error" }
857
+ }
858
+ },
859
+ telemetry: {
860
+ on: {
861
+ "boot.telemetry.ready": { target: "done" }
862
+ }
863
+ },
864
+ error: {},
865
+ done: { type: "final" }
866
+ },
867
+ onDone: { target: "running" }
868
+ },
869
+ running: {
870
+ type: "parallel"
871
+ }
872
+ }
873
+ });
874
+ function createOSOptions(input) {
875
+ return {
876
+ id: "os",
877
+ input,
878
+ inspect
879
+ };
880
+ }
881
+ export {
882
+ ModuleShapeError,
883
+ createOSOptions,
884
+ loadFederatedModule,
885
+ os
886
+ };
887
+ //# sourceMappingURL=system.js.map