@sanity/workbench 0.1.0-alpha.19 → 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.
- package/dist/_chunks-es/studio.js +57 -2
- package/dist/_chunks-es/studio.js.map +1 -1
- package/dist/core.d.ts +334 -2
- package/dist/core.js +3 -0
- package/dist/core.js.map +1 -1
- package/dist/system.d.ts +1107 -100
- package/dist/system.js +314 -110
- package/dist/system.js.map +1 -1
- package/package.json +2 -2
- package/src/core/applications/application.ts +80 -1
- package/src/core/user-applications/core-app.ts +5 -1
- package/src/core/user-applications/studios/schemas.ts +4 -0
- package/src/core/user-applications/user-application.ts +17 -0
- package/src/system/index.ts +5 -0
- package/src/system/load-federated-module.ts +54 -0
- package/src/system/remote.machine.ts +83 -37
- package/src/system/remotes.machine.ts +34 -28
- package/src/system/root.machine.ts +26 -0
- package/src/system/service.machine.ts +207 -0
- package/src/system/services.machine.ts +120 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { type FederationInstance } from "@sanity/federation/runtime";
|
|
2
|
+
import { type ActorRefFrom, enqueueActions, setup } from "xstate";
|
|
3
|
+
|
|
4
|
+
import { serviceLogic } from "./service.machine";
|
|
5
|
+
|
|
6
|
+
/** The shared federation instance, supplied by the root machine. */
|
|
7
|
+
type ServicesInput = {
|
|
8
|
+
instance: FederationInstance;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
type ServicesContext = {
|
|
12
|
+
instance: FederationInstance;
|
|
13
|
+
children: Map<string, ActorRefFrom<typeof serviceLogic>>;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* The full set of background services the workbench should currently be
|
|
18
|
+
* running, re-sent whenever the application list — or any app's declared
|
|
19
|
+
* interfaces — changes. The supervisor reconciles its children against it.
|
|
20
|
+
*/
|
|
21
|
+
type ServicesEvent = {
|
|
22
|
+
type: "services.sync";
|
|
23
|
+
services: ReadonlyArray<{
|
|
24
|
+
appId: string;
|
|
25
|
+
serviceName: string;
|
|
26
|
+
entry: string;
|
|
27
|
+
}>;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/** Stable child key for a service: `${appId}:${serviceName}`. */
|
|
31
|
+
function serviceKey(appId: string, serviceName: string): string {
|
|
32
|
+
return `${appId}:${serviceName}`;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Supervisor machine for background service workers.
|
|
37
|
+
*
|
|
38
|
+
* Uses the shared {@link FederationInstance} (supplied by the root machine and
|
|
39
|
+
* shared with `remotes`, so an app's remote is registered once for both its
|
|
40
|
+
* views and its workers) and spawns one {@link serviceLogic} child per
|
|
41
|
+
* `(app, service)`. Invoked at the root of the OS machine for inspector
|
|
42
|
+
* visibility — boot does not gate on it.
|
|
43
|
+
*
|
|
44
|
+
* On every `services.sync` it reconciles its children against the desired set:
|
|
45
|
+
* a newly-declared worker is spawned, and a worker whose declaration was
|
|
46
|
+
* removed (e.g. deleted from `sanity.cli.ts` during dev — FR-024) is stopped,
|
|
47
|
+
* which disposes its `runWorker` callback and terminates the Web Worker. A
|
|
48
|
+
* service `src` edit still triggers a Vite full page reload (workers have no
|
|
49
|
+
* HMR boundary), which reboots the workbench and respawns with the new code.
|
|
50
|
+
*
|
|
51
|
+
* @internal
|
|
52
|
+
*/
|
|
53
|
+
export const servicesLogic = setup({
|
|
54
|
+
types: {
|
|
55
|
+
input: {} as ServicesInput,
|
|
56
|
+
context: {} as ServicesContext,
|
|
57
|
+
events: {} as ServicesEvent,
|
|
58
|
+
},
|
|
59
|
+
actors: {
|
|
60
|
+
service: serviceLogic,
|
|
61
|
+
},
|
|
62
|
+
actions: {
|
|
63
|
+
/**
|
|
64
|
+
* Reconcile the running workers against the desired set: spawn the ones not
|
|
65
|
+
* yet running, stop (and forget) the ones no longer declared.
|
|
66
|
+
*/
|
|
67
|
+
syncServices: enqueueActions(({ context, event, enqueue }) => {
|
|
68
|
+
const desired = new Map(
|
|
69
|
+
event.services.map((service) => [
|
|
70
|
+
serviceKey(service.appId, service.serviceName),
|
|
71
|
+
service,
|
|
72
|
+
]),
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
// Stop + forget workers whose declaration was removed. Stopping the child
|
|
76
|
+
// disposes its `runWorker` callback, which terminates the Web Worker.
|
|
77
|
+
for (const [key, ref] of context.children) {
|
|
78
|
+
if (!desired.has(key)) enqueue.stopChild(ref);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
enqueue.assign({
|
|
82
|
+
children: ({ context: ctx, spawn }) => {
|
|
83
|
+
const next = new Map<string, ActorRefFrom<typeof serviceLogic>>();
|
|
84
|
+
// Keep the children still declared.
|
|
85
|
+
for (const [key, ref] of ctx.children) {
|
|
86
|
+
if (desired.has(key)) next.set(key, ref);
|
|
87
|
+
}
|
|
88
|
+
// Spawn the newly-declared ones.
|
|
89
|
+
for (const [key, service] of desired) {
|
|
90
|
+
if (next.has(key)) continue;
|
|
91
|
+
next.set(
|
|
92
|
+
key,
|
|
93
|
+
spawn("service", {
|
|
94
|
+
id: key,
|
|
95
|
+
systemId: `services.${key}`,
|
|
96
|
+
input: {
|
|
97
|
+
key,
|
|
98
|
+
appId: service.appId,
|
|
99
|
+
serviceName: service.serviceName,
|
|
100
|
+
entry: service.entry,
|
|
101
|
+
instance: ctx.instance,
|
|
102
|
+
},
|
|
103
|
+
}),
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
return next;
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
}),
|
|
110
|
+
},
|
|
111
|
+
}).createMachine({
|
|
112
|
+
id: "services",
|
|
113
|
+
context: ({ input }) => ({
|
|
114
|
+
instance: input.instance,
|
|
115
|
+
children: new Map(),
|
|
116
|
+
}),
|
|
117
|
+
on: {
|
|
118
|
+
"services.sync": { actions: "syncServices" },
|
|
119
|
+
},
|
|
120
|
+
});
|