@sanity/workbench-cli 1.4.0 → 1.6.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 (41) hide show
  1. package/dist/_exports/build.d.ts +46 -1
  2. package/dist/_exports/build.js +1 -0
  3. package/dist/_exports/build.js.map +1 -1
  4. package/dist/_exports/deploy.d.ts +49 -6
  5. package/dist/_exports/dev.d.ts +52 -9
  6. package/dist/_exports/index.d.ts +8 -1
  7. package/dist/_exports/preview.d.ts +169 -0
  8. package/dist/_exports/preview.js +3 -0
  9. package/dist/_exports/preview.js.map +1 -0
  10. package/dist/_exports/undeploy.d.ts +13 -1
  11. package/dist/actions/build/vite/optimize-deps.js +84 -0
  12. package/dist/actions/build/vite/optimize-deps.js.map +1 -0
  13. package/dist/actions/deploy/buildExposes.js +23 -10
  14. package/dist/actions/deploy/buildExposes.js.map +1 -1
  15. package/dist/actions/deploy/checkBuiltOutput.js +16 -2
  16. package/dist/actions/deploy/checkBuiltOutput.js.map +1 -1
  17. package/dist/actions/deploy/deployWorkbenchApp.js +19 -4
  18. package/dist/actions/deploy/deployWorkbenchApp.js.map +1 -1
  19. package/dist/actions/dev/deriveInterfaces.js +41 -25
  20. package/dist/actions/dev/deriveInterfaces.js.map +1 -1
  21. package/dist/actions/dev/registry.js +99 -19
  22. package/dist/actions/dev/registry.js.map +1 -1
  23. package/dist/actions/dev/startWorkbenchDev.js +6 -41
  24. package/dist/actions/dev/startWorkbenchDev.js.map +1 -1
  25. package/dist/actions/dev/startWorkbenchDevServer.js +7 -3
  26. package/dist/actions/dev/startWorkbenchDevServer.js.map +1 -1
  27. package/dist/actions/preview/serveBuiltApplication.js +53 -0
  28. package/dist/actions/preview/serveBuiltApplication.js.map +1 -0
  29. package/dist/actions/preview/startWorkbenchPreview.js +91 -0
  30. package/dist/actions/preview/startWorkbenchPreview.js.map +1 -0
  31. package/dist/contract.js +32 -0
  32. package/dist/contract.js.map +1 -1
  33. package/dist/defineApp.js +13 -6
  34. package/dist/defineApp.js.map +1 -1
  35. package/dist/resolveWorkbenchApp.js +3 -1
  36. package/dist/resolveWorkbenchApp.js.map +1 -1
  37. package/dist/services/applications.js +15 -1
  38. package/dist/services/applications.js.map +1 -1
  39. package/dist/util/serverOrchestration.js +75 -0
  40. package/dist/util/serverOrchestration.js.map +1 -0
  41. package/package.json +16 -12
@@ -1,3 +1,4 @@
1
+ import { AppVisibility } from "@sanity/cli-core";
1
2
  import { CliConfig } from "@sanity/cli-core";
2
3
  import { PluginOption } from "vite";
3
4
  import { z } from "zod/mini";
@@ -86,7 +87,7 @@ declare const DefineAppInputSchema: z.ZodMiniObject<
86
87
  >
87
88
  >
88
89
  >;
89
- slug: z.ZodMiniOptional<z.ZodMiniString<string>>;
90
+ slug: z.ZodMiniString<string>;
90
91
  title: z.ZodMiniString<string>;
91
92
  views: z.ZodMiniOptional<
92
93
  z.ZodMiniArray<
@@ -106,6 +107,13 @@ declare const DefineAppInputSchema: z.ZodMiniObject<
106
107
  >
107
108
  >
108
109
  >;
110
+ visibility: z.ZodMiniOptional<
111
+ z.ZodMiniEnum<{
112
+ default: "default";
113
+ unlisted: "unlisted";
114
+ disabled: "disabled";
115
+ }>
116
+ >;
109
117
  },
110
118
  z.core.$strip
111
119
  >;
@@ -133,10 +141,14 @@ declare interface ResolvedWorkbenchApp {
133
141
  readonly config?: WorkbenchApp["config"];
134
142
  /** SDK app-view entrypoint, when declared. */
135
143
  readonly entry?: string;
144
+ /** Path to the app's icon SVG, resolved and shipped to Brett on deploy. */
145
+ readonly icon?: string;
136
146
  /** Explicit singleton flag (a Sanity-owned app); `undefined` when the app doesn't set it. */
137
147
  readonly isSingleton?: boolean;
138
148
  /** Hostname the application is created at on first deploy. */
139
149
  readonly slug?: string;
150
+ /** Dashboard visibility declared by the app; `undefined` when unset. */
151
+ readonly visibility?: AppVisibility;
140
152
  }
141
153
 
142
154
  /**
@@ -175,6 +187,39 @@ export declare interface WorkbenchExposes {
175
187
  views?: DefineAppInput["views"];
176
188
  }
177
189
 
190
+ /**
191
+ * Dep pre-bundling inputs for a workbench app's dev server.
192
+ *
193
+ * Vite's dep scanner crawls from the app's HTML entry, which reaches only the
194
+ * app's `entry` (or a studio's config) — never the federation `exposes` (dock
195
+ * views, worker services, media-library config fields), which the host loads
196
+ * dynamically at runtime. So a dep imported only by an exposed module (e.g.
197
+ * `sanity/workbench` in a service or view) escapes the startup scan; Vite
198
+ * discovers it on first request, re-optimizes, and full-page reloads — which
199
+ * flakes Playwright in e2e.
200
+ *
201
+ * Point `entries` at the source of every interface: the app `entry` (or, for a
202
+ * studio, its config), plus each view, service, and installation-config source.
203
+ * `entries` follows real import statements, so it covers whatever those sources
204
+ * transitively use — correct subpaths and all — with no hand-maintained dep
205
+ * list, and never crashes on an unresolvable name the way a bad `include` entry
206
+ * does. Each source is resolved to its on-disk file so an extensionless path
207
+ * (like the default `./src/App`) still matches `entries`' filesystem glob.
208
+ *
209
+ * @param cwd - Project root; `entries` are returned relative to it.
210
+ * @param appSources - Absolute paths to the app's `entry` and/or studio config.
211
+ * @param exposes - The app's declared views/services/config.
212
+ * @internal
213
+ */
214
+ export declare function workbenchOptimizeDeps(options: {
215
+ appSources: readonly string[];
216
+ cwd: string;
217
+ exposes?: WorkbenchExposes;
218
+ }): {
219
+ entries: string[];
220
+ include: string[];
221
+ };
222
+
178
223
  declare interface WorkbenchViteOptions {
179
224
  /** Project root — read for the federation remote name, and the plugin workDir. */
180
225
  cwd: string;
@@ -3,6 +3,7 @@
3
3
  // resolver the build reads declared views/services from. The build needs no
4
4
  // deploy-time guards, so it takes the bare `resolveWorkbenchApp` — the guarded
5
5
  // view (`getWorkbench`) is the deploy entry's export.
6
+ export { workbenchOptimizeDeps } from '../actions/build/vite/optimize-deps.js';
6
7
  export { workbenchVitePlugins } from '../actions/build/vite/workbench-vite-plugins.js';
7
8
  export { resolveWorkbenchApp } from '../resolveWorkbenchApp.js';
8
9
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/_exports/build.ts"],"sourcesContent":["// Node-only build entry: the module-federation Vite plugins that\n// `@sanity/cli-build`'s `getViteConfig` swaps in for a workbench app, plus the\n// resolver the build reads declared views/services from. The build needs no\n// deploy-time guards, so it takes the bare `resolveWorkbenchApp` — the guarded\n// view (`getWorkbench`) is the deploy entry's export.\n\nexport {workbenchVitePlugins} from '../actions/build/vite/workbench-vite-plugins.js'\nexport {resolveWorkbenchApp, type WorkbenchExposes} from '../resolveWorkbenchApp.js'\n"],"names":["workbenchVitePlugins","resolveWorkbenchApp"],"mappings":"AAAA,iEAAiE;AACjE,+EAA+E;AAC/E,4EAA4E;AAC5E,+EAA+E;AAC/E,sDAAsD;AAEtD,SAAQA,oBAAoB,QAAO,kDAAiD;AACpF,SAAQC,mBAAmB,QAA8B,4BAA2B"}
1
+ {"version":3,"sources":["../../src/_exports/build.ts"],"sourcesContent":["// Node-only build entry: the module-federation Vite plugins that\n// `@sanity/cli-build`'s `getViteConfig` swaps in for a workbench app, plus the\n// resolver the build reads declared views/services from. The build needs no\n// deploy-time guards, so it takes the bare `resolveWorkbenchApp` — the guarded\n// view (`getWorkbench`) is the deploy entry's export.\n\nexport {workbenchOptimizeDeps} from '../actions/build/vite/optimize-deps.js'\nexport {workbenchVitePlugins} from '../actions/build/vite/workbench-vite-plugins.js'\nexport {resolveWorkbenchApp, type WorkbenchExposes} from '../resolveWorkbenchApp.js'\n"],"names":["workbenchOptimizeDeps","workbenchVitePlugins","resolveWorkbenchApp"],"mappings":"AAAA,iEAAiE;AACjE,+EAA+E;AAC/E,4EAA4E;AAC5E,+EAA+E;AAC/E,sDAAsD;AAEtD,SAAQA,qBAAqB,QAAO,yCAAwC;AAC5E,SAAQC,oBAAoB,QAAO,kDAAiD;AACpF,SAAQC,mBAAmB,QAA8B,4BAA2B"}
@@ -1,7 +1,24 @@
1
+ import { AppVisibility } from "@sanity/cli-core";
1
2
  import { CliConfig } from "@sanity/cli-core";
2
3
  import { Output } from "@sanity/cli-core";
3
4
  import { z } from "zod/mini";
4
5
 
6
+ /** @internal */
7
+ declare type AppInterfaceMetadata = z.infer<typeof AppInterfaceMetadataSchema>;
8
+
9
+ /**
10
+ * The `app` interface's dock-placement metadata. Interface metadata is
11
+ * discriminated on `type`; `app` is the only type with a shape so far.
12
+ * @internal
13
+ */
14
+ declare const AppInterfaceMetadataSchema: z.ZodMiniObject<
15
+ {
16
+ group: z.ZodMiniOptional<z.ZodMiniString<string>>;
17
+ priority: z.ZodMiniOptional<z.ZodMiniNumber<number>>;
18
+ },
19
+ z.core.$strip
20
+ >;
21
+
5
22
  export declare interface Application {
6
23
  id: string;
7
24
  organizationId: string;
@@ -13,16 +30,28 @@ export declare interface Application {
13
30
  declare type ApplicationType = "coreApp" | "studio";
14
31
 
15
32
  /**
16
- * An interface as Brett stores it: the declared `type` (validated server-side,
17
- * not here) and the remote-relative `moduleId` the workbench loads it by the
18
- * host prepends the app's own id.
33
+ * An interface as Brett stores it, discriminated on `type`. `moduleId` is
34
+ * remote-relative the host prepends the app's id. Brett assigns the id.
19
35
  * @internal
20
36
  */
21
- export declare interface BrettInterface {
37
+ export declare type BrettInterface =
38
+ | (BrettInterfaceBase & {
39
+ metadata: AppInterfaceMetadata | null;
40
+ type: "app";
41
+ })
42
+ | (BrettInterfaceBase & {
43
+ metadata: null;
44
+ type: "panel";
45
+ })
46
+ | (BrettInterfaceBase & {
47
+ metadata: null;
48
+ type: "worker";
49
+ });
50
+
51
+ declare interface BrettInterfaceBase {
22
52
  moduleId: string;
23
53
  name: string;
24
54
  title: string;
25
- type: string;
26
55
  version: string;
27
56
  }
28
57
 
@@ -148,7 +177,7 @@ declare const DefineAppInputSchema: z.ZodMiniObject<
148
177
  >
149
178
  >
150
179
  >;
151
- slug: z.ZodMiniOptional<z.ZodMiniString<string>>;
180
+ slug: z.ZodMiniString<string>;
152
181
  title: z.ZodMiniString<string>;
153
182
  views: z.ZodMiniOptional<
154
183
  z.ZodMiniArray<
@@ -168,6 +197,13 @@ declare const DefineAppInputSchema: z.ZodMiniObject<
168
197
  >
169
198
  >
170
199
  >;
200
+ visibility: z.ZodMiniOptional<
201
+ z.ZodMiniEnum<{
202
+ default: "default";
203
+ unlisted: "unlisted";
204
+ disabled: "disabled";
205
+ }>
206
+ >;
171
207
  },
172
208
  z.core.$strip
173
209
  >;
@@ -225,6 +261,7 @@ export declare function deployConfig(options: {
225
261
  */
226
262
  export declare function deployCoreApp(options: {
227
263
  appId: string | undefined;
264
+ icon?: string;
228
265
  interfaces: readonly BrettInterface[];
229
266
  isAutoUpdating: boolean;
230
267
  isSingleton?: boolean;
@@ -233,6 +270,7 @@ export declare function deployCoreApp(options: {
233
270
  sourceDir: string;
234
271
  title: string;
235
272
  version: string;
273
+ visibility?: AppVisibility;
236
274
  }): Promise<{
237
275
  applicationId: string;
238
276
  }>;
@@ -253,6 +291,7 @@ export declare interface DeployedExpose {
253
291
  */
254
292
  export declare function deployStudio(options: {
255
293
  appId: string | undefined;
294
+ icon?: string;
256
295
  interfaces: readonly BrettInterface[];
257
296
  isAutoUpdating: boolean;
258
297
  organizationId: string;
@@ -296,10 +335,14 @@ declare interface ResolvedWorkbenchApp {
296
335
  readonly config?: WorkbenchApp["config"];
297
336
  /** SDK app-view entrypoint, when declared. */
298
337
  readonly entry?: string;
338
+ /** Path to the app's icon SVG, resolved and shipped to Brett on deploy. */
339
+ readonly icon?: string;
299
340
  /** Explicit singleton flag (a Sanity-owned app); `undefined` when the app doesn't set it. */
300
341
  readonly isSingleton?: boolean;
301
342
  /** Hostname the application is created at on first deploy. */
302
343
  readonly slug?: string;
344
+ /** Dashboard visibility declared by the app; `undefined` when unset. */
345
+ readonly visibility?: AppVisibility;
303
346
  }
304
347
 
305
348
  /**
@@ -58,15 +58,57 @@ declare const devServerManifestSchema: z.ZodMiniObject<
58
58
  id: z.ZodMiniOptional<z.ZodMiniString<string>>;
59
59
  interfaces: z.ZodMiniOptional<
60
60
  z.ZodMiniArray<
61
- z.ZodMiniObject<
62
- {
63
- name: z.ZodMiniString<string>;
64
- src: z.ZodMiniString<string>;
65
- title: z.ZodMiniString<string>;
66
- type: z.ZodMiniString<string>;
67
- version: z.ZodMiniOptional<z.ZodMiniNumber<number>>;
68
- },
69
- z.core.$strip
61
+ z.ZodMiniDiscriminatedUnion<
62
+ [
63
+ z.ZodMiniObject<
64
+ {
65
+ metadata: z.ZodMiniNullable<
66
+ z.ZodMiniObject<
67
+ {
68
+ group: z.ZodMiniOptional<z.ZodMiniString<string>>;
69
+ priority: z.ZodMiniOptional<z.ZodMiniNumber<number>>;
70
+ },
71
+ z.core.$strip
72
+ >
73
+ >;
74
+ type: z.ZodMiniLiteral<"app">;
75
+ id: z.ZodMiniString<string>;
76
+ moduleId: z.ZodMiniString<string>;
77
+ name: z.ZodMiniString<string>;
78
+ src: z.ZodMiniString<string>;
79
+ title: z.ZodMiniString<string>;
80
+ version: z.ZodMiniOptional<z.ZodMiniString<string>>;
81
+ },
82
+ z.core.$strip
83
+ >,
84
+ z.ZodMiniObject<
85
+ {
86
+ metadata: z.ZodMiniNull;
87
+ type: z.ZodMiniLiteral<"panel">;
88
+ id: z.ZodMiniString<string>;
89
+ moduleId: z.ZodMiniString<string>;
90
+ name: z.ZodMiniString<string>;
91
+ src: z.ZodMiniString<string>;
92
+ title: z.ZodMiniString<string>;
93
+ version: z.ZodMiniOptional<z.ZodMiniString<string>>;
94
+ },
95
+ z.core.$strip
96
+ >,
97
+ z.ZodMiniObject<
98
+ {
99
+ metadata: z.ZodMiniNull;
100
+ type: z.ZodMiniLiteral<"worker">;
101
+ id: z.ZodMiniString<string>;
102
+ moduleId: z.ZodMiniString<string>;
103
+ name: z.ZodMiniString<string>;
104
+ src: z.ZodMiniString<string>;
105
+ title: z.ZodMiniString<string>;
106
+ version: z.ZodMiniOptional<z.ZodMiniString<string>>;
107
+ },
108
+ z.core.$strip
109
+ >,
110
+ ],
111
+ "type"
70
112
  >
71
113
  >
72
114
  >;
@@ -79,6 +121,7 @@ declare const devServerManifestSchema: z.ZodMiniObject<
79
121
  group: z.ZodMiniOptional<z.ZodMiniString<string>>;
80
122
  icon: z.ZodMiniOptional<z.ZodMiniString<string>>;
81
123
  priority: z.ZodMiniOptional<z.ZodMiniNumber<number>>;
124
+ slug: z.ZodMiniOptional<z.ZodMiniString<string>>;
82
125
  title: z.ZodMiniOptional<z.ZodMiniString<string>>;
83
126
  version: z.ZodMiniString<string>;
84
127
  },
@@ -84,7 +84,7 @@ declare const DefineAppInputSchema: z.ZodMiniObject<
84
84
  >
85
85
  >
86
86
  >;
87
- slug: z.ZodMiniOptional<z.ZodMiniString<string>>;
87
+ slug: z.ZodMiniString<string>;
88
88
  title: z.ZodMiniString<string>;
89
89
  views: z.ZodMiniOptional<
90
90
  z.ZodMiniArray<
@@ -104,6 +104,13 @@ declare const DefineAppInputSchema: z.ZodMiniObject<
104
104
  >
105
105
  >
106
106
  >;
107
+ visibility: z.ZodMiniOptional<
108
+ z.ZodMiniEnum<{
109
+ default: "default";
110
+ unlisted: "unlisted";
111
+ disabled: "disabled";
112
+ }>
113
+ >;
107
114
  },
108
115
  z.core.$strip
109
116
  >;
@@ -0,0 +1,169 @@
1
+ import { CliConfig } from "@sanity/cli-core";
2
+ import { Output } from "@sanity/cli-core";
3
+ import { z } from "zod/mini";
4
+
5
+ /**
6
+ * A manifest describing a running dev server process (studio or app).
7
+ * Stored as `~/.sanity/dev-servers/<pid>.json`.
8
+ *
9
+ * The workbench singleton is tracked separately via the lock file — see
10
+ * `acquireWorkbenchLock` and `readWorkbenchLock` below.
11
+ */
12
+ declare type DevServerManifest = z.infer<typeof devServerManifestSchema>;
13
+
14
+ declare const devServerManifestSchema: z.ZodMiniObject<
15
+ {
16
+ configs: z.ZodMiniOptional<
17
+ z.ZodMiniArray<
18
+ z.ZodMiniObject<
19
+ {
20
+ appType: z.ZodMiniOptional<z.ZodMiniString<string>>;
21
+ fields: z.ZodMiniArray<
22
+ z.ZodMiniObject<
23
+ {
24
+ name: z.ZodMiniString<string>;
25
+ public: z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>;
26
+ src: z.ZodMiniString<string>;
27
+ title: z.ZodMiniString<string>;
28
+ },
29
+ z.core.$strip
30
+ >
31
+ >;
32
+ id: z.ZodMiniString<string>;
33
+ moduleName: z.ZodMiniOptional<z.ZodMiniString<string>>;
34
+ version: z.ZodMiniNumber<number>;
35
+ },
36
+ z.core.$strip
37
+ >
38
+ >
39
+ >;
40
+ host: z.ZodMiniString<string>;
41
+ id: z.ZodMiniOptional<z.ZodMiniString<string>>;
42
+ interfaces: z.ZodMiniOptional<
43
+ z.ZodMiniArray<
44
+ z.ZodMiniDiscriminatedUnion<
45
+ [
46
+ z.ZodMiniObject<
47
+ {
48
+ metadata: z.ZodMiniNullable<
49
+ z.ZodMiniObject<
50
+ {
51
+ group: z.ZodMiniOptional<z.ZodMiniString<string>>;
52
+ priority: z.ZodMiniOptional<z.ZodMiniNumber<number>>;
53
+ },
54
+ z.core.$strip
55
+ >
56
+ >;
57
+ type: z.ZodMiniLiteral<"app">;
58
+ id: z.ZodMiniString<string>;
59
+ moduleId: z.ZodMiniString<string>;
60
+ name: z.ZodMiniString<string>;
61
+ src: z.ZodMiniString<string>;
62
+ title: z.ZodMiniString<string>;
63
+ version: z.ZodMiniOptional<z.ZodMiniString<string>>;
64
+ },
65
+ z.core.$strip
66
+ >,
67
+ z.ZodMiniObject<
68
+ {
69
+ metadata: z.ZodMiniNull;
70
+ type: z.ZodMiniLiteral<"panel">;
71
+ id: z.ZodMiniString<string>;
72
+ moduleId: z.ZodMiniString<string>;
73
+ name: z.ZodMiniString<string>;
74
+ src: z.ZodMiniString<string>;
75
+ title: z.ZodMiniString<string>;
76
+ version: z.ZodMiniOptional<z.ZodMiniString<string>>;
77
+ },
78
+ z.core.$strip
79
+ >,
80
+ z.ZodMiniObject<
81
+ {
82
+ metadata: z.ZodMiniNull;
83
+ type: z.ZodMiniLiteral<"worker">;
84
+ id: z.ZodMiniString<string>;
85
+ moduleId: z.ZodMiniString<string>;
86
+ name: z.ZodMiniString<string>;
87
+ src: z.ZodMiniString<string>;
88
+ title: z.ZodMiniString<string>;
89
+ version: z.ZodMiniOptional<z.ZodMiniString<string>>;
90
+ },
91
+ z.core.$strip
92
+ >,
93
+ ],
94
+ "type"
95
+ >
96
+ >
97
+ >;
98
+ manifest: z.ZodMiniOptional<
99
+ z.ZodMiniUnion<
100
+ readonly [
101
+ z.ZodMiniRecord<z.ZodMiniString<string>, z.ZodMiniUnknown>,
102
+ z.ZodMiniObject<
103
+ {
104
+ group: z.ZodMiniOptional<z.ZodMiniString<string>>;
105
+ icon: z.ZodMiniOptional<z.ZodMiniString<string>>;
106
+ priority: z.ZodMiniOptional<z.ZodMiniNumber<number>>;
107
+ slug: z.ZodMiniOptional<z.ZodMiniString<string>>;
108
+ title: z.ZodMiniOptional<z.ZodMiniString<string>>;
109
+ version: z.ZodMiniString<string>;
110
+ },
111
+ z.core.$strip
112
+ >,
113
+ ]
114
+ >
115
+ >;
116
+ manifestUpdatedAt: z.ZodMiniOptional<z.ZodMiniString<string>>;
117
+ pid: z.ZodMiniNumber<number>;
118
+ port: z.ZodMiniNumber<number>;
119
+ projectId: z.ZodMiniOptional<z.ZodMiniString<string>>;
120
+ startedAt: z.ZodMiniString<string>;
121
+ type: z.ZodMiniEnum<{
122
+ coreApp: "coreApp";
123
+ studio: "studio";
124
+ }>;
125
+ version: z.ZodMiniLiteral<1>;
126
+ workDir: z.ZodMiniString<string>;
127
+ },
128
+ z.core.$strip
129
+ >;
130
+
131
+ /**
132
+ * `sanity start` for a workbench app: serve a production build the way dev serves
133
+ * a live one. The same singleton workbench shell renders it and the same registry
134
+ * advertises it — only the remote differs, static files from the build output
135
+ * instead of a live Vite dev server. There's no config watcher or rebuild: a
136
+ * build is fixed, so nothing re-syncs.
137
+ *
138
+ * A running workbench claims the configured port, so the built remote binds the
139
+ * next one. Without one the remote takes the configured port and announces its
140
+ * own URL.
141
+ */
142
+ export declare function startWorkbenchPreview(
143
+ options: StartWorkbenchPreviewOptions,
144
+ ): Promise<{
145
+ close: () => Promise<void>;
146
+ }>;
147
+
148
+ export declare interface StartWorkbenchPreviewOptions {
149
+ /** Directory for the workbench Vite server's dependency cache. */
150
+ cacheDir: string;
151
+ /** CLI-domain `app.id`/`deployment.appId` deprecation check, run before registering. */
152
+ checkForDeprecatedAppId: () => void;
153
+ cliConfig: CliConfig;
154
+ /** Extract the project manifest to inline into the registry (studio-vs-app handled by the CLI). */
155
+ extractManifest: (params: {
156
+ configPath: string;
157
+ workDir: string;
158
+ }) => Promise<DevServerManifest["manifest"]>;
159
+ httpHost: string;
160
+ httpPort: number;
161
+ isApp: boolean;
162
+ /** The built `dist` directory to serve as the federation remote. */
163
+ outDir: string;
164
+ output: Output;
165
+ reactStrictMode: boolean;
166
+ workDir: string;
167
+ }
168
+
169
+ export {};
@@ -0,0 +1,3 @@
1
+ export { startWorkbenchPreview } from '../actions/preview/startWorkbenchPreview.js';
2
+
3
+ //# sourceMappingURL=preview.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/_exports/preview.ts"],"sourcesContent":["export {\n startWorkbenchPreview,\n type StartWorkbenchPreviewOptions,\n} from '../actions/preview/startWorkbenchPreview.js'\n"],"names":["startWorkbenchPreview"],"mappings":"AAAA,SACEA,qBAAqB,QAEhB,8CAA6C"}
@@ -1,3 +1,4 @@
1
+ import { AppVisibility } from "@sanity/cli-core";
1
2
  import { UndeployAdapter } from "@sanity/cli-core/undeploy";
2
3
  import { UndeployApplicationTarget } from "@sanity/cli-core/undeploy";
3
4
  import { UndeployConfigTarget } from "@sanity/cli-core/undeploy";
@@ -101,7 +102,7 @@ declare const DefineAppInputSchema: z.ZodMiniObject<
101
102
  >
102
103
  >
103
104
  >;
104
- slug: z.ZodMiniOptional<z.ZodMiniString<string>>;
105
+ slug: z.ZodMiniString<string>;
105
106
  title: z.ZodMiniString<string>;
106
107
  views: z.ZodMiniOptional<
107
108
  z.ZodMiniArray<
@@ -121,6 +122,13 @@ declare const DefineAppInputSchema: z.ZodMiniObject<
121
122
  >
122
123
  >
123
124
  >;
125
+ visibility: z.ZodMiniOptional<
126
+ z.ZodMiniEnum<{
127
+ default: "default";
128
+ unlisted: "unlisted";
129
+ disabled: "disabled";
130
+ }>
131
+ >;
124
132
  },
125
133
  z.core.$strip
126
134
  >;
@@ -177,10 +185,14 @@ declare interface ResolvedWorkbenchApp {
177
185
  readonly config?: WorkbenchApp["config"];
178
186
  /** SDK app-view entrypoint, when declared. */
179
187
  readonly entry?: string;
188
+ /** Path to the app's icon SVG, resolved and shipped to Brett on deploy. */
189
+ readonly icon?: string;
180
190
  /** Explicit singleton flag (a Sanity-owned app); `undefined` when the app doesn't set it. */
181
191
  readonly isSingleton?: boolean;
182
192
  /** Hostname the application is created at on first deploy. */
183
193
  readonly slug?: string;
194
+ /** Dashboard visibility declared by the app; `undefined` when unset. */
195
+ readonly visibility?: AppVisibility;
184
196
  }
185
197
 
186
198
  declare type ViewDeploymentPayload = z.infer<
@@ -0,0 +1,84 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ /**
4
+ * React APIs only the generated render-contract modules import — the SPA
5
+ * bootstrap (`getEntryModule`) and every render artifact (`renderRemote`)
6
+ * `createRoot` from `react-dom/client` and `createElement` from `react`. No
7
+ * app/interface source imports `react-dom/client` itself, so scanning `entries`
8
+ * never surfaces it; every workbench app depends on react/react-dom, so both
9
+ * always resolve.
10
+ */ const RENDER_CONTRACT_DEPS = [
11
+ 'react',
12
+ 'react-dom/client'
13
+ ];
14
+ /** Extensions an import-style source path may omit, in resolution order. */ const SOURCE_EXTENSIONS = [
15
+ '.tsx',
16
+ '.ts',
17
+ '.jsx',
18
+ '.js',
19
+ '.mjs',
20
+ '.cjs'
21
+ ];
22
+ /**
23
+ * Resolve an import-style source path to the file on disk. The app `entry`
24
+ * defaults to the extensionless `./src/App` (and a user may omit the extension
25
+ * anywhere), which the runtime imports fine through Vite's resolver — but
26
+ * `optimizeDeps.entries` is matched against the filesystem, so an extensionless
27
+ * path never matches and its deps go unscanned. Try the path as-is, then the
28
+ * common source extensions; fall back to the input so an already-resolved path
29
+ * (or a genuinely missing one) passes through unchanged.
30
+ */ function resolveSourceFile(absPath) {
31
+ if (fs.existsSync(absPath) && fs.statSync(absPath).isFile()) return absPath;
32
+ for (const extension of SOURCE_EXTENSIONS){
33
+ if (fs.existsSync(`${absPath}${extension}`)) return `${absPath}${extension}`;
34
+ }
35
+ return absPath;
36
+ }
37
+ /**
38
+ * Dep pre-bundling inputs for a workbench app's dev server.
39
+ *
40
+ * Vite's dep scanner crawls from the app's HTML entry, which reaches only the
41
+ * app's `entry` (or a studio's config) — never the federation `exposes` (dock
42
+ * views, worker services, media-library config fields), which the host loads
43
+ * dynamically at runtime. So a dep imported only by an exposed module (e.g.
44
+ * `sanity/workbench` in a service or view) escapes the startup scan; Vite
45
+ * discovers it on first request, re-optimizes, and full-page reloads — which
46
+ * flakes Playwright in e2e.
47
+ *
48
+ * Point `entries` at the source of every interface: the app `entry` (or, for a
49
+ * studio, its config), plus each view, service, and installation-config source.
50
+ * `entries` follows real import statements, so it covers whatever those sources
51
+ * transitively use — correct subpaths and all — with no hand-maintained dep
52
+ * list, and never crashes on an unresolvable name the way a bad `include` entry
53
+ * does. Each source is resolved to its on-disk file so an extensionless path
54
+ * (like the default `./src/App`) still matches `entries`' filesystem glob.
55
+ *
56
+ * @param cwd - Project root; `entries` are returned relative to it.
57
+ * @param appSources - Absolute paths to the app's `entry` and/or studio config.
58
+ * @param exposes - The app's declared views/services/config.
59
+ * @internal
60
+ */ export function workbenchOptimizeDeps(options) {
61
+ const { appSources, cwd, exposes } = options;
62
+ const interfaceSources = [
63
+ ...(exposes?.views ?? []).map((view)=>view.src),
64
+ ...(exposes?.services ?? []).map((service)=>service.src),
65
+ ...(exposes?.config?.fields ?? []).map((field)=>field.src)
66
+ ].map((src)=>path.resolve(cwd, src));
67
+ const entries = [
68
+ ...appSources,
69
+ ...interfaceSources
70
+ ].map((absPath)=>{
71
+ const resolved = resolveSourceFile(absPath);
72
+ return path.relative(cwd, resolved).split(path.sep).join('/');
73
+ });
74
+ return {
75
+ entries: [
76
+ ...new Set(entries)
77
+ ],
78
+ include: [
79
+ ...RENDER_CONTRACT_DEPS
80
+ ]
81
+ };
82
+ }
83
+
84
+ //# sourceMappingURL=optimize-deps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/actions/build/vite/optimize-deps.ts"],"sourcesContent":["import fs from 'node:fs'\nimport path from 'node:path'\n\nimport {type WorkbenchExposes} from '../../../resolveWorkbenchApp.js'\n\n/**\n * React APIs only the generated render-contract modules import — the SPA\n * bootstrap (`getEntryModule`) and every render artifact (`renderRemote`)\n * `createRoot` from `react-dom/client` and `createElement` from `react`. No\n * app/interface source imports `react-dom/client` itself, so scanning `entries`\n * never surfaces it; every workbench app depends on react/react-dom, so both\n * always resolve.\n */\nconst RENDER_CONTRACT_DEPS = ['react', 'react-dom/client']\n\n/** Extensions an import-style source path may omit, in resolution order. */\nconst SOURCE_EXTENSIONS = ['.tsx', '.ts', '.jsx', '.js', '.mjs', '.cjs']\n\n/**\n * Resolve an import-style source path to the file on disk. The app `entry`\n * defaults to the extensionless `./src/App` (and a user may omit the extension\n * anywhere), which the runtime imports fine through Vite's resolver — but\n * `optimizeDeps.entries` is matched against the filesystem, so an extensionless\n * path never matches and its deps go unscanned. Try the path as-is, then the\n * common source extensions; fall back to the input so an already-resolved path\n * (or a genuinely missing one) passes through unchanged.\n */\nfunction resolveSourceFile(absPath: string): string {\n if (fs.existsSync(absPath) && fs.statSync(absPath).isFile()) return absPath\n for (const extension of SOURCE_EXTENSIONS) {\n if (fs.existsSync(`${absPath}${extension}`)) return `${absPath}${extension}`\n }\n return absPath\n}\n\n/**\n * Dep pre-bundling inputs for a workbench app's dev server.\n *\n * Vite's dep scanner crawls from the app's HTML entry, which reaches only the\n * app's `entry` (or a studio's config) — never the federation `exposes` (dock\n * views, worker services, media-library config fields), which the host loads\n * dynamically at runtime. So a dep imported only by an exposed module (e.g.\n * `sanity/workbench` in a service or view) escapes the startup scan; Vite\n * discovers it on first request, re-optimizes, and full-page reloads — which\n * flakes Playwright in e2e.\n *\n * Point `entries` at the source of every interface: the app `entry` (or, for a\n * studio, its config), plus each view, service, and installation-config source.\n * `entries` follows real import statements, so it covers whatever those sources\n * transitively use — correct subpaths and all — with no hand-maintained dep\n * list, and never crashes on an unresolvable name the way a bad `include` entry\n * does. Each source is resolved to its on-disk file so an extensionless path\n * (like the default `./src/App`) still matches `entries`' filesystem glob.\n *\n * @param cwd - Project root; `entries` are returned relative to it.\n * @param appSources - Absolute paths to the app's `entry` and/or studio config.\n * @param exposes - The app's declared views/services/config.\n * @internal\n */\nexport function workbenchOptimizeDeps(options: {\n appSources: readonly string[]\n cwd: string\n exposes?: WorkbenchExposes\n}): {entries: string[]; include: string[]} {\n const {appSources, cwd, exposes} = options\n\n const interfaceSources = [\n ...(exposes?.views ?? []).map((view) => view.src),\n ...(exposes?.services ?? []).map((service) => service.src),\n ...(exposes?.config?.fields ?? []).map((field) => field.src),\n ].map((src) => path.resolve(cwd, src))\n\n const entries = [...appSources, ...interfaceSources].map((absPath) => {\n const resolved = resolveSourceFile(absPath)\n return path.relative(cwd, resolved).split(path.sep).join('/')\n })\n\n return {\n entries: [...new Set(entries)],\n include: [...RENDER_CONTRACT_DEPS],\n }\n}\n"],"names":["fs","path","RENDER_CONTRACT_DEPS","SOURCE_EXTENSIONS","resolveSourceFile","absPath","existsSync","statSync","isFile","extension","workbenchOptimizeDeps","options","appSources","cwd","exposes","interfaceSources","views","map","view","src","services","service","config","fields","field","resolve","entries","resolved","relative","split","sep","join","Set","include"],"mappings":"AAAA,OAAOA,QAAQ,UAAS;AACxB,OAAOC,UAAU,YAAW;AAI5B;;;;;;;CAOC,GACD,MAAMC,uBAAuB;IAAC;IAAS;CAAmB;AAE1D,0EAA0E,GAC1E,MAAMC,oBAAoB;IAAC;IAAQ;IAAO;IAAQ;IAAO;IAAQ;CAAO;AAExE;;;;;;;;CAQC,GACD,SAASC,kBAAkBC,OAAe;IACxC,IAAIL,GAAGM,UAAU,CAACD,YAAYL,GAAGO,QAAQ,CAACF,SAASG,MAAM,IAAI,OAAOH;IACpE,KAAK,MAAMI,aAAaN,kBAAmB;QACzC,IAAIH,GAAGM,UAAU,CAAC,GAAGD,UAAUI,WAAW,GAAG,OAAO,GAAGJ,UAAUI,WAAW;IAC9E;IACA,OAAOJ;AACT;AAEA;;;;;;;;;;;;;;;;;;;;;;;CAuBC,GACD,OAAO,SAASK,sBAAsBC,OAIrC;IACC,MAAM,EAACC,UAAU,EAAEC,GAAG,EAAEC,OAAO,EAAC,GAAGH;IAEnC,MAAMI,mBAAmB;WACpB,AAACD,CAAAA,SAASE,SAAS,EAAE,AAAD,EAAGC,GAAG,CAAC,CAACC,OAASA,KAAKC,GAAG;WAC7C,AAACL,CAAAA,SAASM,YAAY,EAAE,AAAD,EAAGH,GAAG,CAAC,CAACI,UAAYA,QAAQF,GAAG;WACtD,AAACL,CAAAA,SAASQ,QAAQC,UAAU,EAAE,AAAD,EAAGN,GAAG,CAAC,CAACO,QAAUA,MAAML,GAAG;KAC5D,CAACF,GAAG,CAAC,CAACE,MAAQlB,KAAKwB,OAAO,CAACZ,KAAKM;IAEjC,MAAMO,UAAU;WAAId;WAAeG;KAAiB,CAACE,GAAG,CAAC,CAACZ;QACxD,MAAMsB,WAAWvB,kBAAkBC;QACnC,OAAOJ,KAAK2B,QAAQ,CAACf,KAAKc,UAAUE,KAAK,CAAC5B,KAAK6B,GAAG,EAAEC,IAAI,CAAC;IAC3D;IAEA,OAAO;QACLL,SAAS;eAAI,IAAIM,IAAIN;SAAS;QAC9BO,SAAS;eAAI/B;SAAqB;IACpC;AACF"}