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

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