@sanity/workbench-cli 1.1.0-beta.0

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 (59) hide show
  1. package/README.md +10 -0
  2. package/dist/_exports/build.d.ts +129 -0
  3. package/dist/_exports/build.js +9 -0
  4. package/dist/_exports/build.js.map +1 -0
  5. package/dist/_exports/deploy.d.ts +115 -0
  6. package/dist/_exports/deploy.js +6 -0
  7. package/dist/_exports/deploy.js.map +1 -0
  8. package/dist/_exports/dev.d.ts +166 -0
  9. package/dist/_exports/dev.js +10 -0
  10. package/dist/_exports/dev.js.map +1 -0
  11. package/dist/_exports/index.d.ts +307 -0
  12. package/dist/_exports/index.js +15 -0
  13. package/dist/_exports/index.js.map +1 -0
  14. package/dist/_exports/init.d.ts +12 -0
  15. package/dist/_exports/init.js +5 -0
  16. package/dist/_exports/init.js.map +1 -0
  17. package/dist/actions/build/artifact.js +29 -0
  18. package/dist/actions/build/artifact.js.map +1 -0
  19. package/dist/actions/build/render-remote.js +69 -0
  20. package/dist/actions/build/render-remote.js.map +1 -0
  21. package/dist/actions/build/services/artifact.js +122 -0
  22. package/dist/actions/build/services/artifact.js.map +1 -0
  23. package/dist/actions/build/views/artifact.js +31 -0
  24. package/dist/actions/build/views/artifact.js.map +1 -0
  25. package/dist/actions/build/vite/constants.js +5 -0
  26. package/dist/actions/build/vite/constants.js.map +1 -0
  27. package/dist/actions/build/vite/plugin.js +74 -0
  28. package/dist/actions/build/vite/plugin.js.map +1 -0
  29. package/dist/actions/build/vite/plugins/plugin-module-federation.js +53 -0
  30. package/dist/actions/build/vite/plugins/plugin-module-federation.js.map +1 -0
  31. package/dist/actions/build/vite/plugins/plugin-sanity-environment.js +29 -0
  32. package/dist/actions/build/vite/plugins/plugin-sanity-environment.js.map +1 -0
  33. package/dist/actions/build/vite/plugins/plugin-sanity-extension-artifacts.js +33 -0
  34. package/dist/actions/build/vite/plugins/plugin-sanity-extension-artifacts.js.map +1 -0
  35. package/dist/actions/build/vite/plugins/plugin-sanity-federation-runtime.js +83 -0
  36. package/dist/actions/build/vite/plugins/plugin-sanity-federation-runtime.js.map +1 -0
  37. package/dist/actions/build/vite/workbench-vite-plugins.js +43 -0
  38. package/dist/actions/build/vite/workbench-vite-plugins.js.map +1 -0
  39. package/dist/actions/deploy/getWorkbench.js +40 -0
  40. package/dist/actions/deploy/getWorkbench.js.map +1 -0
  41. package/dist/actions/dev/canonicalizeWatchDir.js +23 -0
  42. package/dist/actions/dev/canonicalizeWatchDir.js.map +1 -0
  43. package/dist/actions/dev/processLiveness.js +109 -0
  44. package/dist/actions/dev/processLiveness.js.map +1 -0
  45. package/dist/actions/dev/registry.js +279 -0
  46. package/dist/actions/dev/registry.js.map +1 -0
  47. package/dist/actions/init/cliConfig.js +45 -0
  48. package/dist/actions/init/cliConfig.js.map +1 -0
  49. package/dist/contract.js +66 -0
  50. package/dist/contract.js.map +1 -0
  51. package/dist/defineApp.js +82 -0
  52. package/dist/defineApp.js.map +1 -0
  53. package/dist/defineService.js +19 -0
  54. package/dist/defineService.js.map +1 -0
  55. package/dist/defineView.js +19 -0
  56. package/dist/defineView.js.map +1 -0
  57. package/dist/resolveWorkbenchApp.js +21 -0
  58. package/dist/resolveWorkbenchApp.js.map +1 -0
  59. package/package.json +83 -0
@@ -0,0 +1,307 @@
1
+ import { z } from "zod/mini";
2
+
3
+ /**
4
+ * User-facing input for `unstable_defineApp`. Excludes the internal
5
+ * `applicationType` — that field is validated by the schema but is not part of
6
+ * the public surface (Sanity-owned apps set it via `@ts-expect-error`).
7
+ * @public
8
+ */
9
+ export declare type DefineAppInput = Omit<
10
+ z.output<typeof DefineAppInputSchema>,
11
+ "applicationType"
12
+ >;
13
+
14
+ /**
15
+ * Runtime-validation schema for `unstable_defineApp`. Validates the full shape
16
+ * including the internal `applicationType`; the user-facing `DefineAppInput`
17
+ * type below omits that field.
18
+ * @internal
19
+ */
20
+ declare const DefineAppInputSchema: z.ZodMiniObject<
21
+ {
22
+ applicationType: z.ZodMiniOptional<
23
+ z.ZodMiniEnum<{
24
+ coreApp: "coreApp";
25
+ studio: "studio";
26
+ canvas: "canvas";
27
+ dashboard: "dashboard";
28
+ "media-library": "media-library";
29
+ }>
30
+ >;
31
+ entry: z.ZodMiniOptional<z.ZodMiniString<string>>;
32
+ group: z.ZodMiniOptional<
33
+ z.ZodMiniEnum<{
34
+ "dock.system": "dock.system";
35
+ "dock.applications": "dock.applications";
36
+ "dock.user": "dock.user";
37
+ }>
38
+ >;
39
+ icon: z.ZodMiniOptional<z.ZodMiniString<string>>;
40
+ name: z.ZodMiniString<string>;
41
+ organizationId: z.ZodMiniString<string>;
42
+ priority: z.ZodMiniOptional<z.ZodMiniNumber<number>>;
43
+ services: z.ZodMiniOptional<
44
+ z.ZodMiniArray<
45
+ z.ZodMiniDiscriminatedUnion<
46
+ [
47
+ z.ZodMiniObject<
48
+ {
49
+ name: z.ZodMiniString<string>;
50
+ src: z.ZodMiniString<string>;
51
+ type: z.ZodMiniLiteral<"worker">;
52
+ },
53
+ z.core.$strip
54
+ >,
55
+ ],
56
+ "type"
57
+ >
58
+ >
59
+ >;
60
+ title: z.ZodMiniString<string>;
61
+ views: z.ZodMiniOptional<
62
+ z.ZodMiniArray<
63
+ z.ZodMiniDiscriminatedUnion<
64
+ [
65
+ z.ZodMiniObject<
66
+ {
67
+ name: z.ZodMiniString<string>;
68
+ src: z.ZodMiniString<string>;
69
+ type: z.ZodMiniLiteral<"panel">;
70
+ },
71
+ z.core.$strip
72
+ >,
73
+ ],
74
+ "type"
75
+ >
76
+ >
77
+ >;
78
+ },
79
+ z.core.$strip
80
+ >;
81
+
82
+ /**
83
+ * The branded result of `unstable_defineApp`. Carries the same fields as the
84
+ * input plus the internal brand — users only ever see `DefineAppInput`.
85
+ * @public
86
+ */
87
+ export declare interface DefineAppResult extends DefineAppInput {
88
+ readonly [WORKBENCH_APP]: true;
89
+ }
90
+
91
+ /**
92
+ * The result of `unstable_defineService`: the author's callback, the service
93
+ * type, and the internal contract version the worker artifact targets.
94
+ * @public
95
+ */
96
+ export declare interface DefinedService<
97
+ TType extends ServiceType = ServiceType,
98
+ > {
99
+ readonly run: ServiceCallbacksByType[TType];
100
+ readonly type: TType;
101
+ /** @internal */
102
+ readonly version: typeof SERVICE_CONTRACT_VERSION;
103
+ }
104
+
105
+ /**
106
+ * The result of `unstable_defineView`: the author's component(s), the view type,
107
+ * and the internal contract version the build artifact targets.
108
+ * @public
109
+ */
110
+ export declare interface DefinedView<
111
+ TType extends InterfaceType = InterfaceType,
112
+ > {
113
+ readonly components: ViewComponentsByType[TType];
114
+ readonly type: TType;
115
+ /** @internal */
116
+ readonly version: typeof VIEW_CONTRACT_VERSION;
117
+ }
118
+
119
+ /**
120
+ * Dock group identifier. The API does not block a user app from declaring a
121
+ * reserved group (e.g. `dock.system`); priority conventions keep Sanity-owned
122
+ * apps ahead.
123
+ * @public
124
+ */
125
+ export declare type DockGroup = z.output<typeof DockGroupSchema>;
126
+
127
+ /** Dock groups an app can place itself into. */
128
+ declare const DockGroupSchema: z.ZodMiniEnum<{
129
+ "dock.system": "dock.system";
130
+ "dock.applications": "dock.applications";
131
+ "dock.user": "dock.user";
132
+ }>;
133
+
134
+ /**
135
+ * Every supported interface type — the first argument to `unstable_defineView`.
136
+ * @public
137
+ */
138
+ export declare type InterfaceType = keyof typeof VIEW_COMPONENTS;
139
+
140
+ /**
141
+ * A panel's view-component slot — the module-federation expose for one island.
142
+ * @public
143
+ */
144
+ export declare type PanelComponent = keyof PanelViewComponents;
145
+
146
+ /**
147
+ * The component slots a `panel` view exposes — each its own module-federation
148
+ * island, typed with the panel props.
149
+ * @public
150
+ */
151
+ export declare interface PanelViewComponents {
152
+ panel: ViewComponent<PanelViewProps>;
153
+ title: ViewComponent<PanelViewProps>;
154
+ }
155
+
156
+ /**
157
+ * Props a panel component receives: its interface record, minus the
158
+ * service-assigned `id`/`deployment_id` a local dev server can't provide. Mirrors
159
+ * the `panel` record the workbench host renders from (the wire format owned by
160
+ * `@sanity/workbench`); drift is guarded by the stamped contract version.
161
+ * @public
162
+ */
163
+ export declare type PanelViewProps = ViewComponentBaseProps<{
164
+ entry_point: string;
165
+ interface_type: "panel";
166
+ name: string;
167
+ }>;
168
+
169
+ /**
170
+ * Contract version stamped on every defined service. Lets the workbench host
171
+ * and the generated worker artifact evolve the service contract without
172
+ * breaking already-deployed services; bumped only on a breaking change.
173
+ * @internal
174
+ */
175
+ declare const SERVICE_CONTRACT_VERSION = 1;
176
+
177
+ /**
178
+ * A service callback. Runs once inside the worker on start; returns an optional
179
+ * disposer the host calls before terminating the worker.
180
+ * @public
181
+ */
182
+ export declare type ServiceCallback = (
183
+ context: ServiceContext,
184
+ ) => (() => void) | void;
185
+
186
+ /** The callback shape each service type defines, keyed by type. */
187
+ declare interface ServiceCallbacksByType {
188
+ worker: ServiceCallback;
189
+ }
190
+
191
+ /**
192
+ * Context every service callback receives when its worker starts. Mirrors how a
193
+ * view component receives its `view` — the service receives its own `service`.
194
+ * @public
195
+ */
196
+ export declare interface ServiceContext {
197
+ readonly service: ServiceInfo;
198
+ }
199
+
200
+ /**
201
+ * The service's own declaration, surfaced to the callback.
202
+ * @public
203
+ */
204
+ export declare interface ServiceInfo {
205
+ readonly name: string;
206
+ readonly type: string;
207
+ }
208
+
209
+ /**
210
+ * Every supported service type — the first argument to `unstable_defineService`.
211
+ * Add a service type by adding its declaration schema below and registering it
212
+ * here.
213
+ * @public
214
+ */
215
+ export declare type ServiceType = "worker";
216
+
217
+ /**
218
+ * Declare a Sanity Workbench application. Identity at runtime — returns the same
219
+ * object reference, tagged with the workbench brand. Field validation (the
220
+ * `name` pattern etc.) runs at build time in the CLI via `DefineAppInputSchema`;
221
+ * this helper stays a thin, pure identity wrapper.
222
+ * @public
223
+ */
224
+ export declare function unstable_defineApp(
225
+ input: DefineAppInput,
226
+ ): DefineAppResult;
227
+
228
+ /**
229
+ * Define a Sanity Workbench background service. The first argument narrows the
230
+ * callback shape — `"worker"` runs the callback inside a Web Worker, where it
231
+ * can emit dock-badge updates and return a disposer.
232
+ *
233
+ * Identity at runtime: returns the callback tagged with its type and the contract
234
+ * version, for the CLI build to generate a worker artifact from. Used as the
235
+ * default export of a service's `src` file.
236
+ * @public
237
+ */
238
+ export declare function unstable_defineService<TType extends ServiceType>(
239
+ type: TType,
240
+ run: ServiceCallbacksByType[TType],
241
+ ): DefinedService<TType>;
242
+
243
+ /**
244
+ * Define a Sanity Workbench view. The first argument narrows the component shape
245
+ * and the props each component receives — `"panel"` yields a `{title, panel}`
246
+ * record whose components are typed with the panel props.
247
+ *
248
+ * Returns the component(s) tagged with their type and the contract version, for
249
+ * the CLI build to generate render artifacts from. Used as the default export of
250
+ * a view's `src` file.
251
+ * @public
252
+ */
253
+ export declare function unstable_defineView<TType extends InterfaceType>(
254
+ type: TType,
255
+ components: ViewComponentsByType[TType],
256
+ ): DefinedView<TType>;
257
+
258
+ /**
259
+ * Component slots each interface type exposes, in render order — the source of
260
+ * truth for {@link InterfaceType} and for the build (the vite plugin expands a
261
+ * view into one render artifact per component). Add a type by registering it here.
262
+ * @internal
263
+ */
264
+ declare const VIEW_COMPONENTS: {
265
+ readonly panel: readonly ["title", "panel"];
266
+ };
267
+
268
+ /**
269
+ * Contract version stamped on every defined view — lets the host and the
270
+ * generated artifact evolve the contract without breaking deployed views.
271
+ * @internal
272
+ */
273
+ declare const VIEW_CONTRACT_VERSION = 1;
274
+
275
+ /**
276
+ * A view component. The return is opaque so the runtime helpers carry no React
277
+ * dependency — the generated artifact renders it with the app's own React.
278
+ * @public
279
+ */
280
+ declare type ViewComponent<TProps> = (props: TProps) => unknown;
281
+
282
+ /**
283
+ * Props every view component receives, whatever its type. Per-type props
284
+ * compose from this, so a prop added here reaches every view.
285
+ * @public
286
+ */
287
+ declare interface ViewComponentBaseProps<TView> {
288
+ view: TView;
289
+ }
290
+
291
+ /**
292
+ * The components each interface type exposes, keyed by type.
293
+ * @public
294
+ */
295
+ export declare interface ViewComponentsByType {
296
+ panel: PanelViewComponents;
297
+ }
298
+
299
+ /**
300
+ * Nominal brand the CLI discriminates on to enable the workbench build/deploy
301
+ * codepath. Registered via `Symbol.for` so the marker survives module-realm
302
+ * boundaries — `@sanity/cli-core` re-derives the same global symbol with
303
+ * `Symbol.for` rather than importing it, so it stays internal to this module.
304
+ */
305
+ declare const WORKBENCH_APP: unique symbol;
306
+
307
+ export {};
@@ -0,0 +1,15 @@
1
+ // Public, browser-safe entry for `@sanity/workbench-cli` — the authoring API app
2
+ // authors call from `sanity.cli.ts` (re-exported by `sanity/cli` and the
3
+ // `sanity` runtime entry). Calling `unstable_defineApp` is the *sole* workbench
4
+ // opt-in: it stamps the global brand `Symbol.for('sanity.workbench.defineApp')`,
5
+ // which the CLI discriminates on (see `isWorkbenchApp` in `@sanity/cli-core`).
6
+ //
7
+ // This module graph must stay browser-safe: zod-only, no `node:*`, no vite, no
8
+ // `@sanity/cli-core`. View/service `src` files bundle to the browser, so anything
9
+ // reachable from here ships in the frontend bundle. The Node-only build glue
10
+ // lives behind the separate `./vite` entry and never leaks in.
11
+ export { unstable_defineApp } from '../defineApp.js';
12
+ export { unstable_defineService } from '../defineService.js';
13
+ export { unstable_defineView } from '../defineView.js';
14
+
15
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/_exports/index.ts"],"sourcesContent":["// Public, browser-safe entry for `@sanity/workbench-cli` — the authoring API app\n// authors call from `sanity.cli.ts` (re-exported by `sanity/cli` and the\n// `sanity` runtime entry). Calling `unstable_defineApp` is the *sole* workbench\n// opt-in: it stamps the global brand `Symbol.for('sanity.workbench.defineApp')`,\n// which the CLI discriminates on (see `isWorkbenchApp` in `@sanity/cli-core`).\n//\n// This module graph must stay browser-safe: zod-only, no `node:*`, no vite, no\n// `@sanity/cli-core`. View/service `src` files bundle to the browser, so anything\n// reachable from here ships in the frontend bundle. The Node-only build glue\n// lives behind the separate `./vite` entry and never leaks in.\nexport type {InterfaceType, ServiceType} from '../contract.js'\nexport {unstable_defineApp} from '../defineApp.js'\nexport type {DefineAppInput, DefineAppResult, DockGroup} from '../defineApp.js'\nexport {unstable_defineService} from '../defineService.js'\nexport type {\n DefinedService,\n ServiceCallback,\n ServiceContext,\n ServiceInfo,\n} from '../defineService.js'\nexport {unstable_defineView} from '../defineView.js'\nexport type {\n DefinedView,\n PanelComponent,\n PanelViewComponents,\n PanelViewProps,\n ViewComponentsByType,\n} from '../defineView.js'\n"],"names":["unstable_defineApp","unstable_defineService","unstable_defineView"],"mappings":"AAAA,iFAAiF;AACjF,yEAAyE;AACzE,gFAAgF;AAChF,iFAAiF;AACjF,+EAA+E;AAC/E,EAAE;AACF,+EAA+E;AAC/E,kFAAkF;AAClF,6EAA6E;AAC7E,+DAA+D;AAE/D,SAAQA,kBAAkB,QAAO,kBAAiB;AAElD,SAAQC,sBAAsB,QAAO,sBAAqB;AAO1D,SAAQC,mBAAmB,QAAO,mBAAkB"}
@@ -0,0 +1,12 @@
1
+ /** App scaffold — `entry` auto-declares the navigable app view. */
2
+ export declare const workbenchAppConfigTemplate =
3
+ "\nimport {defineCliConfig, unstable_defineApp} from 'sanity/cli'\n\nexport default defineCliConfig({\n app: unstable_defineApp({\n name: '%name%',\n title: '%title%',\n organizationId: '%organizationId%',\n entry: '%entry%',\n }),\n})\n";
4
+
5
+ /**
6
+ * Studio scaffold — brands with name/title only, no `entry` (studio app views
7
+ * aren't implemented yet).
8
+ */
9
+ export declare const workbenchStudioConfigTemplate =
10
+ "\nimport {defineCliConfig, unstable_defineApp} from 'sanity/cli'\n\nexport default defineCliConfig({\n api: {\n projectId: '%projectId%',\n dataset: '%dataset%'\n },\n app: unstable_defineApp({\n name: '%name%',\n title: '%title%',\n organizationId: '%organizationId%',\n }),\n deployment: {\n /**\n * Enable auto-updates for studios.\n * Learn more at https://www.sanity.io/docs/studio/latest-version-of-sanity#k47faf43faf56\n */\n autoUpdates: __BOOL__autoUpdates__,\n },\n})\n";
11
+
12
+ export {};
@@ -0,0 +1,5 @@
1
+ // Browser-safe `init` entry: the workbench `sanity.cli.ts` config templates the
2
+ // CLI's init scaffolding fills in. Plain strings — no runtime deps.
3
+ export { workbenchAppConfigTemplate, workbenchStudioConfigTemplate } from '../actions/init/cliConfig.js';
4
+
5
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/_exports/init.ts"],"sourcesContent":["// Browser-safe `init` entry: the workbench `sanity.cli.ts` config templates the\n// CLI's init scaffolding fills in. Plain strings — no runtime deps.\nexport {\n workbenchAppConfigTemplate,\n workbenchStudioConfigTemplate,\n} from '../actions/init/cliConfig.js'\n"],"names":["workbenchAppConfigTemplate","workbenchStudioConfigTemplate"],"mappings":"AAAA,gFAAgF;AAChF,oEAAoE;AACpE,SACEA,0BAA0B,EAC1BC,6BAA6B,QACxB,+BAA8B"}
@@ -0,0 +1,29 @@
1
+ import { serviceArtifacts } from './services/artifact.js';
2
+ import { viewArtifacts } from './views/artifact.js';
3
+ /**
4
+ * Map the artifacts the host loads directly (those with an `expose`) to their
5
+ * runtime-dir paths, for the module-federation `exposes` field. `toExposePath`
6
+ * turns a runtime-relative artifact path into the value federation wants — the
7
+ * caller owns the runtime-dir location and any entry resolution.
8
+ */ export function artifactExposes(artifacts, toExposePath) {
9
+ const exposes = {};
10
+ for (const artifact of artifacts){
11
+ if (artifact.expose) {
12
+ exposes[artifact.expose] = toExposePath(artifact.path);
13
+ }
14
+ }
15
+ return exposes;
16
+ }
17
+ /**
18
+ * Expand a workbench app's declared views and services into the flat artifact
19
+ * set the federation build writes and exposes — the single place that composes
20
+ * the per-type expanders, so the expose mapping and the file writing read from
21
+ * one expansion rather than re-deriving it.
22
+ */ export function workbenchArtifacts(options) {
23
+ return [
24
+ ...viewArtifacts(options.views),
25
+ ...serviceArtifacts(options.services ?? [])
26
+ ];
27
+ }
28
+
29
+ //# sourceMappingURL=artifact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/actions/build/artifact.ts"],"sourcesContent":["import {type ServiceArtifact, serviceArtifacts} from './services/artifact.js'\nimport {type InterfaceArtifact, viewArtifacts} from './views/artifact.js'\n\n/**\n * What a {@link GeneratedArtifact.source} builder receives from the build — the\n * one thing it can't compute on its own, since only the build knows where the\n * runtime dir sits relative to the app's `src`.\n */\ninterface ArtifactContext {\n /** Import specifier for an app `src` file, relative to this artifact. */\n resolveImport: (src: string) => string\n}\n\n/**\n * One file the federation build generates into the runtime dir for a declared\n * interface. Each interface type — views, services — expands its declarations\n * into a flat list of these; the build then writes them and maps the ones the\n * host loads directly into the module-federation manifest.\n *\n * Adding an interface type is adding a builder that returns\n * `GeneratedArtifact[]` — the write loop and the expose mapping never change.\n */\nexport interface GeneratedArtifact {\n /** Path relative to the federation runtime dir, e.g. `views/feed/panel.js`. */\n path: string\n /** Build the file's contents. */\n source: (context: ArtifactContext) => string\n\n /**\n * Module-federation expose key when the host loads this artifact directly —\n * a view component `./views/feed/panel`, a service loader `./services/unread`.\n * Omitted for a file the host never loads on its own, like a worker bundle\n * (reached through its sibling loader).\n */\n expose?: string\n}\n\n/**\n * Map the artifacts the host loads directly (those with an `expose`) to their\n * runtime-dir paths, for the module-federation `exposes` field. `toExposePath`\n * turns a runtime-relative artifact path into the value federation wants — the\n * caller owns the runtime-dir location and any entry resolution.\n */\nexport function artifactExposes(\n artifacts: readonly GeneratedArtifact[],\n toExposePath: (artifactPath: string) => string,\n): Record<string, string> {\n const exposes: Record<string, string> = {}\n for (const artifact of artifacts) {\n if (artifact.expose) {\n exposes[artifact.expose] = toExposePath(artifact.path)\n }\n }\n return exposes\n}\n\n/**\n * Expand a workbench app's declared views and services into the flat artifact\n * set the federation build writes and exposes — the single place that composes\n * the per-type expanders, so the expose mapping and the file writing read from\n * one expansion rather than re-deriving it.\n */\nexport function workbenchArtifacts(options: {\n services?: readonly ServiceArtifact[]\n views: readonly InterfaceArtifact[]\n}): GeneratedArtifact[] {\n return [...viewArtifacts(options.views), ...serviceArtifacts(options.services ?? [])]\n}\n"],"names":["serviceArtifacts","viewArtifacts","artifactExposes","artifacts","toExposePath","exposes","artifact","expose","path","workbenchArtifacts","options","views","services"],"mappings":"AAAA,SAA8BA,gBAAgB,QAAO,yBAAwB;AAC7E,SAAgCC,aAAa,QAAO,sBAAqB;AAoCzE;;;;;CAKC,GACD,OAAO,SAASC,gBACdC,SAAuC,EACvCC,YAA8C;IAE9C,MAAMC,UAAkC,CAAC;IACzC,KAAK,MAAMC,YAAYH,UAAW;QAChC,IAAIG,SAASC,MAAM,EAAE;YACnBF,OAAO,CAACC,SAASC,MAAM,CAAC,GAAGH,aAAaE,SAASE,IAAI;QACvD;IACF;IACA,OAAOH;AACT;AAEA;;;;;CAKC,GACD,OAAO,SAASI,mBAAmBC,OAGlC;IACC,OAAO;WAAIT,cAAcS,QAAQC,KAAK;WAAMX,iBAAiBU,QAAQE,QAAQ,IAAI,EAAE;KAAE;AACvF"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Every entry the federation build generates — the studio/app remote entries
3
+ * and the per-view-component artifacts — is the same thing: a *render-contract
4
+ * module* that owns its own React, renders into a host node via
5
+ * `render(rootElement, props, renderOptions)`, and returns a disposer.
6
+ *
7
+ * They differ only in *what* they render. So each module binds an `App` to that
8
+ * (the SDK app, a `Studio` with config, a view component) and the render body —
9
+ * identical everywhere — just renders `App`. {@link renderRemote} assembles a
10
+ * module from a `preamble` (its imports), the `app` expression, and, optionally,
11
+ * the shared HMR snippet.
12
+ */ /**
13
+ * Hot-reload: on an update, re-render every live root through the new module —
14
+ * so whatever it now binds `App` to (a recompiled component, a new studio
15
+ * config) takes effect without a full page reload. Stripped from prod builds.
16
+ */ const HMR_REMOUNT = `if (import.meta.hot) {
17
+ import.meta.hot.accept((next) => {
18
+ if (!next) return
19
+ for (const [rootElement, args] of renderArgs) {
20
+ rootMap.get(rootElement)?.unmount()
21
+ rootMap.delete(rootElement)
22
+ next.render(rootElement, args.props, args.renderOptions)
23
+ }
24
+ })
25
+ }`;
26
+ /**
27
+ * Assemble a render-contract module: its `preamble` (imports), the `App` it
28
+ * renders, the render body, and — when `hmr` — the shared HMR snippet.
29
+ *
30
+ * - `app` is the expression bound to `App`; omit it when the preamble imports an
31
+ * `App` directly (the SDK-app entry).
32
+ * - `version` is an expression the host reads to check contract compatibility;
33
+ * omit it when the module carries no version (the studio/app entries).
34
+ */ export function renderRemote({ app, hmr = false, preamble, version }) {
35
+ return `\
36
+ // This file is auto-generated on 'sanity build' / 'sanity dev'
37
+ // Modifications to this file are automatically discarded
38
+ import { createElement, StrictMode } from 'react'
39
+ import { createRoot } from 'react-dom/client'
40
+ ${preamble}
41
+ ${app ? `\nconst App = ${app}\n` : ''}${version ? `\nexport const version = ${version}\n` : ''}
42
+ const rootMap = new Map()
43
+ const renderArgs = new Map()
44
+
45
+ function mount(rootElement, args) {
46
+ let root = rootMap.get(rootElement)
47
+ if (!root) {
48
+ root = createRoot(rootElement)
49
+ rootMap.set(rootElement, root)
50
+ }
51
+ const element = createElement(App, args.props)
52
+ root.render(args?.renderOptions?.reactStrictMode ? createElement(StrictMode, null, element) : element)
53
+ }
54
+
55
+ export function render(rootElement, props, renderOptions) {
56
+ const args = { props, renderOptions }
57
+ renderArgs.set(rootElement, args)
58
+ mount(rootElement, args)
59
+ return () => {
60
+ const root = rootMap.get(rootElement)
61
+ rootMap.delete(rootElement)
62
+ renderArgs.delete(rootElement)
63
+ root?.unmount()
64
+ }
65
+ }${hmr ? `\n\n${HMR_REMOUNT}` : ''}
66
+ `;
67
+ }
68
+
69
+ //# sourceMappingURL=render-remote.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/actions/build/render-remote.ts"],"sourcesContent":["/**\n * Every entry the federation build generates — the studio/app remote entries\n * and the per-view-component artifacts — is the same thing: a *render-contract\n * module* that owns its own React, renders into a host node via\n * `render(rootElement, props, renderOptions)`, and returns a disposer.\n *\n * They differ only in *what* they render. So each module binds an `App` to that\n * (the SDK app, a `Studio` with config, a view component) and the render body —\n * identical everywhere — just renders `App`. {@link renderRemote} assembles a\n * module from a `preamble` (its imports), the `app` expression, and, optionally,\n * the shared HMR snippet.\n */\n\n/**\n * Hot-reload: on an update, re-render every live root through the new module —\n * so whatever it now binds `App` to (a recompiled component, a new studio\n * config) takes effect without a full page reload. Stripped from prod builds.\n */\nconst HMR_REMOUNT = `if (import.meta.hot) {\n import.meta.hot.accept((next) => {\n if (!next) return\n for (const [rootElement, args] of renderArgs) {\n rootMap.get(rootElement)?.unmount()\n rootMap.delete(rootElement)\n next.render(rootElement, args.props, args.renderOptions)\n }\n })\n}`\n\n/**\n * Assemble a render-contract module: its `preamble` (imports), the `App` it\n * renders, the render body, and — when `hmr` — the shared HMR snippet.\n *\n * - `app` is the expression bound to `App`; omit it when the preamble imports an\n * `App` directly (the SDK-app entry).\n * - `version` is an expression the host reads to check contract compatibility;\n * omit it when the module carries no version (the studio/app entries).\n */\nexport function renderRemote({\n app,\n hmr = false,\n preamble,\n version,\n}: {\n app?: string\n hmr?: boolean\n preamble: string\n version?: string\n}): string {\n return `\\\n// This file is auto-generated on 'sanity build' / 'sanity dev'\n// Modifications to this file are automatically discarded\nimport { createElement, StrictMode } from 'react'\nimport { createRoot } from 'react-dom/client'\n${preamble}\n${app ? `\\nconst App = ${app}\\n` : ''}${version ? `\\nexport const version = ${version}\\n` : ''}\nconst rootMap = new Map()\nconst renderArgs = new Map()\n\nfunction mount(rootElement, args) {\n let root = rootMap.get(rootElement)\n if (!root) {\n root = createRoot(rootElement)\n rootMap.set(rootElement, root)\n }\n const element = createElement(App, args.props)\n root.render(args?.renderOptions?.reactStrictMode ? createElement(StrictMode, null, element) : element)\n}\n\nexport function render(rootElement, props, renderOptions) {\n const args = { props, renderOptions }\n renderArgs.set(rootElement, args)\n mount(rootElement, args)\n return () => {\n const root = rootMap.get(rootElement)\n rootMap.delete(rootElement)\n renderArgs.delete(rootElement)\n root?.unmount()\n }\n}${hmr ? `\\n\\n${HMR_REMOUNT}` : ''}\n`\n}\n"],"names":["HMR_REMOUNT","renderRemote","app","hmr","preamble","version"],"mappings":"AAAA;;;;;;;;;;;CAWC,GAED;;;;CAIC,GACD,MAAMA,cAAc,CAAC;;;;;;;;;CASpB,CAAC;AAEF;;;;;;;;CAQC,GACD,OAAO,SAASC,aAAa,EAC3BC,GAAG,EACHC,MAAM,KAAK,EACXC,QAAQ,EACRC,OAAO,EAMR;IACC,OAAO,CAAC;;;;;AAKV,EAAED,SAAS;AACX,EAAEF,MAAM,CAAC,cAAc,EAAEA,IAAI,EAAE,CAAC,GAAG,KAAKG,UAAU,CAAC,yBAAyB,EAAEA,QAAQ,EAAE,CAAC,GAAG,GAAG;;;;;;;;;;;;;;;;;;;;;;;;CAwB9F,EAAEF,MAAM,CAAC,IAAI,EAAEH,aAAa,GAAG,GAAG;AACnC,CAAC;AACD"}
@@ -0,0 +1,122 @@
1
+ import { SERVICE_CONTRACT_VERSION } from '../../../contract.js';
2
+ /** Subdirectory under the federation runtime dir where service artifacts live. */ const SERVICES_DIR_NAME = 'services';
3
+ const SERVICE_TYPES = [
4
+ 'worker'
5
+ ];
6
+ /**
7
+ * Expand each service into its two generated artifacts: a self-contained worker
8
+ * bundle (imports the user's `src`, runs the callback) and a loader module the
9
+ * host loads to read the worker's URL. Only the loader is a federation expose —
10
+ * the host reaches the worker bundle through it, never directly.
11
+ */ export function serviceArtifacts(services) {
12
+ return services.filter((service)=>SERVICE_TYPES.includes(service.type)).flatMap((service)=>{
13
+ const dir = `${SERVICES_DIR_NAME}/${service.name}`;
14
+ return [
15
+ {
16
+ path: `${dir}/worker.js`,
17
+ source: ({ resolveImport })=>serviceWorkerArtifactSource({
18
+ importPath: resolveImport(service.src),
19
+ service
20
+ })
21
+ },
22
+ {
23
+ expose: `./${dir}`,
24
+ path: `${dir}/index.js`,
25
+ source: ()=>serviceLoaderArtifactSource({
26
+ service
27
+ })
28
+ }
29
+ ];
30
+ });
31
+ }
32
+ /**
33
+ * Source for one service's **worker** bundle — the Web Worker entry. Imports
34
+ * the user's `unstable_defineService` result and runs its callback with the
35
+ * service's own declaration (mirroring how a view component receives its
36
+ * `view`), then wires the returned disposer to the host's terminate message.
37
+ * Crashes — and the worker's `console.*`, which is patched to forward to the
38
+ * host — are surfaced through the host logger (the host owns logging; a worker's
39
+ * own console isn't visible in the page DevTools anyway).
40
+ */ function serviceWorkerArtifactSource(input) {
41
+ return `\
42
+ // This file is auto-generated on 'sanity build' / 'sanity dev'
43
+ // Modifications to this file are automatically discarded
44
+ import service from ${JSON.stringify(input.importPath)}
45
+
46
+ const SERVICE = { type: ${JSON.stringify(input.service.type)}, name: ${JSON.stringify(input.service.name)} }
47
+
48
+ // Bridge the worker's console to the host. A worker's own console isn't visible
49
+ // in the page DevTools, so patch console.* to forward each call as a message
50
+ // the host re-emits through the workbench logger — any console.log in the
51
+ // service (or its deps) just shows up in the page console.
52
+ const __format = (arg) => {
53
+ if (typeof arg === 'string') return arg
54
+ try { return JSON.stringify(arg) } catch (_) { return String(arg) }
55
+ }
56
+ for (const __level of ['log', 'info', 'warn', 'error', 'debug']) {
57
+ const __native = typeof console[__level] === 'function' ? console[__level].bind(console) : () => {}
58
+ console[__level] = (...args) => {
59
+ __native(...args)
60
+ try {
61
+ self.postMessage({ kind: 'workbench.worker.log', payload: { level: __level, message: args.map(__format).join(' ') } })
62
+ } catch (_) {}
63
+ }
64
+ }
65
+
66
+ let dispose
67
+ try {
68
+ const result = service.run({ service: SERVICE })
69
+ if (typeof result === 'function') dispose = result
70
+ } catch (error) {
71
+ self.postMessage({ kind: 'workbench.worker.error', payload: { message: String(error) } })
72
+ }
73
+
74
+ self.addEventListener('message', (event) => {
75
+ if (event.data && event.data.kind === 'workbench.worker.terminate') {
76
+ try { dispose && dispose() } finally { self.close() }
77
+ }
78
+ })
79
+
80
+ self.addEventListener('error', (event) => {
81
+ self.postMessage({ kind: 'workbench.worker.error', payload: { message: String(event.message || event) } })
82
+ })
83
+
84
+ // An async run callback (or async work it kicks off) rejects without hitting
85
+ // the synchronous try/catch above; module workers surface that as
86
+ // 'unhandledrejection' on self, not 'error'. Forward it so the crash reaches
87
+ // the host either way.
88
+ self.addEventListener('unhandledrejection', (event) => {
89
+ self.postMessage({ kind: 'workbench.worker.error', payload: { message: String(event.reason) } })
90
+ })
91
+ `;
92
+ }
93
+ /**
94
+ * Source for one service's **loader** — the module-federation expose. Hands the
95
+ * host the worker bundle's URL (via Vite `?worker&url`) plus the service's
96
+ * type/version.
97
+ *
98
+ * A URL (not an inlined worker) on purpose: the host can't `new Worker()` it
99
+ * directly — cross-origin in dev/prod, and `?worker&inline` only self-contains
100
+ * the worker in a build, not under `sanity dev`. Instead the host bootstraps a
101
+ * same-origin worker that dynamically `import()`s this URL, so the worker
102
+ * resolves its own imports against the app origin. Works in dev and build alike.
103
+ *
104
+ * No HMR boundary: a worker lives in its own `?worker&url` module graph with no
105
+ * accepting importer, so Vite full-reloads the page on a `src` edit (which
106
+ * re-loads the worker with the new code) — in-place worker HMR isn't possible.
107
+ */ function serviceLoaderArtifactSource(input) {
108
+ return `\
109
+ // This file is auto-generated on 'sanity build' / 'sanity dev'
110
+ // Modifications to this file are automatically discarded
111
+ import workerUrl from './worker.js?worker&url'
112
+
113
+ /** URL of the worker bundle, on the app's origin. */
114
+ export const url = workerUrl
115
+ /** Service type and contract version, surfaced for the host to dispatch on. */
116
+ export const type = ${JSON.stringify(input.service.type)}
117
+ export const name = ${JSON.stringify(input.service.name)}
118
+ export const version = ${SERVICE_CONTRACT_VERSION}
119
+ `;
120
+ }
121
+
122
+ //# sourceMappingURL=artifact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/actions/build/services/artifact.ts"],"sourcesContent":["import {SERVICE_CONTRACT_VERSION, type ServiceType} from '../../../contract.js'\nimport {type GeneratedArtifact} from '../artifact.js'\n\n/** Subdirectory under the federation runtime dir where service artifacts live. */\nconst SERVICES_DIR_NAME = 'services'\n\nconst SERVICE_TYPES: readonly ServiceType[] = ['worker']\n\n/**\n * A service to generate a worker artifact for. The `src` file default-exports\n * an `unstable_defineService(...)` result; the build emits a self-contained Web\n * Worker bundle plus a loader module that hands the host its URL.\n * @internal\n */\nexport interface ServiceArtifact {\n /** Service name, unique within the app. */\n name: string\n /** Path to the service `src` file, relative to the app root (or absolute). */\n src: string\n /** Service type, e.g. `\"worker\"`. */\n type: string\n}\n\n/**\n * Expand each service into its two generated artifacts: a self-contained worker\n * bundle (imports the user's `src`, runs the callback) and a loader module the\n * host loads to read the worker's URL. Only the loader is a federation expose —\n * the host reaches the worker bundle through it, never directly.\n */\nexport function serviceArtifacts(services: readonly ServiceArtifact[]): GeneratedArtifact[] {\n return services\n .filter((service) => (SERVICE_TYPES as readonly string[]).includes(service.type))\n .flatMap((service): GeneratedArtifact[] => {\n const dir = `${SERVICES_DIR_NAME}/${service.name}`\n return [\n {\n path: `${dir}/worker.js`,\n source: ({resolveImport}) =>\n serviceWorkerArtifactSource({\n importPath: resolveImport(service.src),\n service,\n }),\n },\n {\n expose: `./${dir}`,\n path: `${dir}/index.js`,\n source: () => serviceLoaderArtifactSource({service}),\n },\n ]\n })\n}\n\n/**\n * Source for one service's **worker** bundle — the Web Worker entry. Imports\n * the user's `unstable_defineService` result and runs its callback with the\n * service's own declaration (mirroring how a view component receives its\n * `view`), then wires the returned disposer to the host's terminate message.\n * Crashes — and the worker's `console.*`, which is patched to forward to the\n * host — are surfaced through the host logger (the host owns logging; a worker's\n * own console isn't visible in the page DevTools anyway).\n */\nfunction serviceWorkerArtifactSource(input: {\n importPath: string\n service: {name: string; type: string}\n}): string {\n return `\\\n// This file is auto-generated on 'sanity build' / 'sanity dev'\n// Modifications to this file are automatically discarded\nimport service from ${JSON.stringify(input.importPath)}\n\nconst SERVICE = { type: ${JSON.stringify(input.service.type)}, name: ${JSON.stringify(input.service.name)} }\n\n// Bridge the worker's console to the host. A worker's own console isn't visible\n// in the page DevTools, so patch console.* to forward each call as a message\n// the host re-emits through the workbench logger — any console.log in the\n// service (or its deps) just shows up in the page console.\nconst __format = (arg) => {\n if (typeof arg === 'string') return arg\n try { return JSON.stringify(arg) } catch (_) { return String(arg) }\n}\nfor (const __level of ['log', 'info', 'warn', 'error', 'debug']) {\n const __native = typeof console[__level] === 'function' ? console[__level].bind(console) : () => {}\n console[__level] = (...args) => {\n __native(...args)\n try {\n self.postMessage({ kind: 'workbench.worker.log', payload: { level: __level, message: args.map(__format).join(' ') } })\n } catch (_) {}\n }\n}\n\nlet dispose\ntry {\n const result = service.run({ service: SERVICE })\n if (typeof result === 'function') dispose = result\n} catch (error) {\n self.postMessage({ kind: 'workbench.worker.error', payload: { message: String(error) } })\n}\n\nself.addEventListener('message', (event) => {\n if (event.data && event.data.kind === 'workbench.worker.terminate') {\n try { dispose && dispose() } finally { self.close() }\n }\n})\n\nself.addEventListener('error', (event) => {\n self.postMessage({ kind: 'workbench.worker.error', payload: { message: String(event.message || event) } })\n})\n\n// An async run callback (or async work it kicks off) rejects without hitting\n// the synchronous try/catch above; module workers surface that as\n// 'unhandledrejection' on self, not 'error'. Forward it so the crash reaches\n// the host either way.\nself.addEventListener('unhandledrejection', (event) => {\n self.postMessage({ kind: 'workbench.worker.error', payload: { message: String(event.reason) } })\n})\n`\n}\n\n/**\n * Source for one service's **loader** — the module-federation expose. Hands the\n * host the worker bundle's URL (via Vite `?worker&url`) plus the service's\n * type/version.\n *\n * A URL (not an inlined worker) on purpose: the host can't `new Worker()` it\n * directly — cross-origin in dev/prod, and `?worker&inline` only self-contains\n * the worker in a build, not under `sanity dev`. Instead the host bootstraps a\n * same-origin worker that dynamically `import()`s this URL, so the worker\n * resolves its own imports against the app origin. Works in dev and build alike.\n *\n * No HMR boundary: a worker lives in its own `?worker&url` module graph with no\n * accepting importer, so Vite full-reloads the page on a `src` edit (which\n * re-loads the worker with the new code) — in-place worker HMR isn't possible.\n */\nfunction serviceLoaderArtifactSource(input: {service: {name: string; type: string}}): string {\n return `\\\n// This file is auto-generated on 'sanity build' / 'sanity dev'\n// Modifications to this file are automatically discarded\nimport workerUrl from './worker.js?worker&url'\n\n/** URL of the worker bundle, on the app's origin. */\nexport const url = workerUrl\n/** Service type and contract version, surfaced for the host to dispatch on. */\nexport const type = ${JSON.stringify(input.service.type)}\nexport const name = ${JSON.stringify(input.service.name)}\nexport const version = ${SERVICE_CONTRACT_VERSION}\n`\n}\n"],"names":["SERVICE_CONTRACT_VERSION","SERVICES_DIR_NAME","SERVICE_TYPES","serviceArtifacts","services","filter","service","includes","type","flatMap","dir","name","path","source","resolveImport","serviceWorkerArtifactSource","importPath","src","expose","serviceLoaderArtifactSource","input","JSON","stringify"],"mappings":"AAAA,SAAQA,wBAAwB,QAAyB,uBAAsB;AAG/E,gFAAgF,GAChF,MAAMC,oBAAoB;AAE1B,MAAMC,gBAAwC;IAAC;CAAS;AAiBxD;;;;;CAKC,GACD,OAAO,SAASC,iBAAiBC,QAAoC;IACnE,OAAOA,SACJC,MAAM,CAAC,CAACC,UAAY,AAACJ,cAAoCK,QAAQ,CAACD,QAAQE,IAAI,GAC9EC,OAAO,CAAC,CAACH;QACR,MAAMI,MAAM,GAAGT,kBAAkB,CAAC,EAAEK,QAAQK,IAAI,EAAE;QAClD,OAAO;YACL;gBACEC,MAAM,GAAGF,IAAI,UAAU,CAAC;gBACxBG,QAAQ,CAAC,EAACC,aAAa,EAAC,GACtBC,4BAA4B;wBAC1BC,YAAYF,cAAcR,QAAQW,GAAG;wBACrCX;oBACF;YACJ;YACA;gBACEY,QAAQ,CAAC,EAAE,EAAER,KAAK;gBAClBE,MAAM,GAAGF,IAAI,SAAS,CAAC;gBACvBG,QAAQ,IAAMM,4BAA4B;wBAACb;oBAAO;YACpD;SACD;IACH;AACJ;AAEA;;;;;;;;CAQC,GACD,SAASS,4BAA4BK,KAGpC;IACC,OAAO,CAAC;;;oBAGU,EAAEC,KAAKC,SAAS,CAACF,MAAMJ,UAAU,EAAE;;wBAE/B,EAAEK,KAAKC,SAAS,CAACF,MAAMd,OAAO,CAACE,IAAI,EAAE,QAAQ,EAAEa,KAAKC,SAAS,CAACF,MAAMd,OAAO,CAACK,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6C1G,CAAC;AACD;AAEA;;;;;;;;;;;;;;CAcC,GACD,SAASQ,4BAA4BC,KAA8C;IACjF,OAAO,CAAC;;;;;;;;oBAQU,EAAEC,KAAKC,SAAS,CAACF,MAAMd,OAAO,CAACE,IAAI,EAAE;oBACrC,EAAEa,KAAKC,SAAS,CAACF,MAAMd,OAAO,CAACK,IAAI,EAAE;uBAClC,EAAEX,yBAAyB;AAClD,CAAC;AACD"}
@@ -0,0 +1,31 @@
1
+ import { VIEW_COMPONENTS } from '../../../contract.js';
2
+ import { renderRemote } from '../render-remote.js';
3
+ /** Subdirectory under the federation runtime dir where view artifacts are written. */ const VIEWS_DIR_NAME = 'views';
4
+ /**
5
+ * Expand each view into one generated artifact per component it exposes. A
6
+ * panel's `title` and `panel` each become their own render-contract module and
7
+ * module-federation expose, so the host renders each as an independent island.
8
+ *
9
+ * Each artifact binds its component as the `App` the render contract renders —
10
+ * a single-component view exports a bare function, a multi-component one keys by
11
+ * name — behind an HMR boundary so view edits re-render through the new module.
12
+ */ export function viewArtifacts(views) {
13
+ const artifacts = [];
14
+ for (const view of views){
15
+ for (const component of VIEW_COMPONENTS[view.type]){
16
+ artifacts.push({
17
+ expose: `./${VIEWS_DIR_NAME}/${view.name}/${component}`,
18
+ path: `${VIEWS_DIR_NAME}/${view.name}/${component}.js`,
19
+ source: ({ resolveImport })=>renderRemote({
20
+ app: `typeof view.components === 'function' ? view.components : view.components[${JSON.stringify(component)}]`,
21
+ hmr: true,
22
+ preamble: `import view from ${JSON.stringify(resolveImport(view.src))}`,
23
+ version: `view.version`
24
+ })
25
+ });
26
+ }
27
+ }
28
+ return artifacts;
29
+ }
30
+
31
+ //# sourceMappingURL=artifact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/actions/build/views/artifact.ts"],"sourcesContent":["import {type InterfaceType, VIEW_COMPONENTS} from '../../../contract.js'\nimport {type GeneratedArtifact} from '../artifact.js'\nimport {renderRemote} from '../render-remote.js'\n\n/** Subdirectory under the federation runtime dir where view artifacts are written. */\nconst VIEWS_DIR_NAME = 'views'\n\n/**\n * An interface to generate render artifacts for. The `src` file default-exports\n * an `unstable_defineView(...)` result; the build emits one render-contract\n * artifact per component the interface type exposes.\n * @internal\n */\nexport interface InterfaceArtifact {\n /** Interface name, unique within the app. */\n name: string\n /** Path to the interface `src` file, relative to the app root (or absolute). */\n src: string\n /** Interface type — selects which components the build expands. */\n type: InterfaceType\n}\n\n/**\n * Expand each view into one generated artifact per component it exposes. A\n * panel's `title` and `panel` each become their own render-contract module and\n * module-federation expose, so the host renders each as an independent island.\n *\n * Each artifact binds its component as the `App` the render contract renders —\n * a single-component view exports a bare function, a multi-component one keys by\n * name — behind an HMR boundary so view edits re-render through the new module.\n */\nexport function viewArtifacts(views: readonly InterfaceArtifact[]): GeneratedArtifact[] {\n const artifacts: GeneratedArtifact[] = []\n for (const view of views) {\n for (const component of VIEW_COMPONENTS[view.type]) {\n artifacts.push({\n expose: `./${VIEWS_DIR_NAME}/${view.name}/${component}`,\n path: `${VIEWS_DIR_NAME}/${view.name}/${component}.js`,\n source: ({resolveImport}) =>\n renderRemote({\n app: `typeof view.components === 'function' ? view.components : view.components[${JSON.stringify(component)}]`,\n hmr: true,\n preamble: `import view from ${JSON.stringify(resolveImport(view.src))}`,\n version: `view.version`,\n }),\n })\n }\n }\n return artifacts\n}\n"],"names":["VIEW_COMPONENTS","renderRemote","VIEWS_DIR_NAME","viewArtifacts","views","artifacts","view","component","type","push","expose","name","path","source","resolveImport","app","JSON","stringify","hmr","preamble","src","version"],"mappings":"AAAA,SAA4BA,eAAe,QAAO,uBAAsB;AAExE,SAAQC,YAAY,QAAO,sBAAqB;AAEhD,oFAAoF,GACpF,MAAMC,iBAAiB;AAiBvB;;;;;;;;CAQC,GACD,OAAO,SAASC,cAAcC,KAAmC;IAC/D,MAAMC,YAAiC,EAAE;IACzC,KAAK,MAAMC,QAAQF,MAAO;QACxB,KAAK,MAAMG,aAAaP,eAAe,CAACM,KAAKE,IAAI,CAAC,CAAE;YAClDH,UAAUI,IAAI,CAAC;gBACbC,QAAQ,CAAC,EAAE,EAAER,eAAe,CAAC,EAAEI,KAAKK,IAAI,CAAC,CAAC,EAAEJ,WAAW;gBACvDK,MAAM,GAAGV,eAAe,CAAC,EAAEI,KAAKK,IAAI,CAAC,CAAC,EAAEJ,UAAU,GAAG,CAAC;gBACtDM,QAAQ,CAAC,EAACC,aAAa,EAAC,GACtBb,aAAa;wBACXc,KAAK,CAAC,0EAA0E,EAAEC,KAAKC,SAAS,CAACV,WAAW,CAAC,CAAC;wBAC9GW,KAAK;wBACLC,UAAU,CAAC,iBAAiB,EAAEH,KAAKC,SAAS,CAACH,cAAcR,KAAKc,GAAG,IAAI;wBACvEC,SAAS,CAAC,YAAY,CAAC;oBACzB;YACJ;QACF;IACF;IACA,OAAOhB;AACT"}
@@ -0,0 +1,5 @@
1
+ export const FEDERATION_FILE_NAME = 'remote-entry';
2
+ export const FEDERATION_DIR_NAME = 'federation';
3
+ export const RUNTIME_DIR = `.sanity/${FEDERATION_DIR_NAME}`;
4
+
5
+ //# sourceMappingURL=constants.js.map