@sanity/cli 7.4.0 → 7.4.2

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 +25 -1
  2. package/dist/actions/build/buildApp.js +20 -17
  3. package/dist/actions/build/buildApp.js.map +1 -1
  4. package/dist/actions/build/buildStudio.js +23 -21
  5. package/dist/actions/build/buildStudio.js.map +1 -1
  6. package/dist/actions/dev/devAction.js +46 -197
  7. package/dist/actions/dev/devAction.js.map +1 -1
  8. package/dist/actions/dev/servers/getDevServerConfig.js +1 -1
  9. package/dist/actions/dev/servers/getDevServerConfig.js.map +1 -1
  10. package/dist/actions/dev/servers/startAppDevServer.js +18 -9
  11. package/dist/actions/dev/servers/startAppDevServer.js.map +1 -1
  12. package/dist/actions/dev/servers/startStudioDevServer.js +2 -2
  13. package/dist/actions/dev/servers/startStudioDevServer.js.map +1 -1
  14. package/dist/actions/dev/types.js.map +1 -1
  15. package/dist/actions/{dev/registration/extractDevServerManifest.js → manifest/extractStudioManifest.js} +3 -3
  16. package/dist/actions/manifest/extractStudioManifest.js.map +1 -0
  17. package/dist/actions/mcp/editorConfigs.js +8 -4
  18. package/dist/actions/mcp/editorConfigs.js.map +1 -1
  19. package/dist/commands/datasets/copy.js +17 -19
  20. package/dist/commands/datasets/copy.js.map +1 -1
  21. package/dist/commands/datasets/import.js +11 -15
  22. package/dist/commands/datasets/import.js.map +1 -1
  23. package/dist/commands/doctor.js +9 -9
  24. package/dist/commands/doctor.js.map +1 -1
  25. package/dist/commands/telemetry/disable.js +3 -3
  26. package/dist/commands/telemetry/disable.js.map +1 -1
  27. package/dist/commands/telemetry/enable.js +3 -3
  28. package/dist/commands/telemetry/enable.js.map +1 -1
  29. package/dist/commands/telemetry/status.js +2 -2
  30. package/dist/commands/telemetry/status.js.map +1 -1
  31. package/dist/exports/_internal.d.ts +4 -47
  32. package/dist/exports/_internal.js +1 -1
  33. package/dist/exports/_internal.js.map +1 -1
  34. package/dist/server/devServer.js +1 -1
  35. package/dist/server/devServer.js.map +1 -1
  36. package/dist/util/compareDependencyVersions.js.map +1 -1
  37. package/oclif.manifest.json +1 -1
  38. package/package.json +9 -8
  39. package/dist/actions/build/buildStaticFiles.js +0 -144
  40. package/dist/actions/build/buildStaticFiles.js.map +0 -1
  41. package/dist/actions/build/getEnvironmentVariables.js +0 -54
  42. package/dist/actions/build/getEnvironmentVariables.js.map +0 -1
  43. package/dist/actions/dev/registration/deriveInterfaces.js +0 -46
  44. package/dist/actions/dev/registration/deriveInterfaces.js.map +0 -1
  45. package/dist/actions/dev/registration/extractDevServerManifest.js.map +0 -1
  46. package/dist/actions/dev/registration/interfaceSetId.js +0 -41
  47. package/dist/actions/dev/registration/interfaceSetId.js.map +0 -1
  48. package/dist/actions/dev/registration/startDevManifestWatcher.js +0 -104
  49. package/dist/actions/dev/registration/startDevManifestWatcher.js.map +0 -1
  50. package/dist/actions/dev/registration/startDevServerRegistration.js +0 -121
  51. package/dist/actions/dev/registration/startDevServerRegistration.js.map +0 -1
  52. package/dist/actions/dev/workbench/startWorkbenchDevServer.js +0 -276
  53. package/dist/actions/dev/workbench/startWorkbenchDevServer.js.map +0 -1
  54. package/dist/actions/dev/workbench/writeWorkbenchRuntime.js +0 -66
  55. package/dist/actions/dev/workbench/writeWorkbenchRuntime.js.map +0 -1
  56. package/dist/util/formatSize.js +0 -10
  57. package/dist/util/formatSize.js.map +0 -1
  58. package/dist/util/moduleFormatUtils.js +0 -18
  59. package/dist/util/moduleFormatUtils.js.map +0 -1
@@ -1,34 +1,20 @@
1
- import { styleText } from 'node:util';
2
- import { getCliConfigUncached, isWorkbenchApp } from '@sanity/cli-core';
1
+ import { SANITY_CACHE_DIR } from '@sanity/cli-build/_internal/build';
2
+ import { isWorkbenchApp } from '@sanity/cli-core';
3
+ import { checkForDeprecatedAppId, getAppId } from '../../util/appId.js';
3
4
  import { getSharedServerConfig } from '../../util/getSharedServerConfig.js';
4
- import { startDevServerRegistration } from './registration/startDevServerRegistration.js';
5
+ import { resolveReactStrictMode } from '../../util/resolveReactStrictMode.js';
6
+ import { extractCoreAppManifest } from '../manifest/extractCoreAppManifest.js';
7
+ import { extractStudioManifest } from '../manifest/extractStudioManifest.js';
5
8
  import { startAppDevServer } from './servers/startAppDevServer.js';
6
9
  import { startStudioDevServer } from './servers/startStudioDevServer.js';
7
- import { startWorkbenchDevServer } from './workbench/startWorkbenchDevServer.js';
8
10
  const noop = async ()=>{};
9
11
  /**
10
- * How long a signal-triggered teardown may run before the process force-exits
11
- * by re-raising the signal generous enough for Vite servers and watchers to
12
- * close, short enough not to strand a backgrounded process holding the ports.
13
- */ const SHUTDOWN_GRACE_MS = 5000;
14
- // Bind-only addresses ('0.0.0.0', '::') aren't routable URLs in every
15
- // browser (notably on Windows), so the displayed URL falls back to
16
- // localhost. The bind address itself is untouched — listening and the
17
- // lock file keep whatever the user configured.
18
- function toDisplayHost(host) {
19
- if (!host || host === '0.0.0.0' || host === '::' || host === '[::]') {
20
- return 'localhost';
21
- }
22
- return host;
23
- }
24
- /**
25
- * Orchestrates the dev servers required by the process. It will attempt to run a workbench
26
- * dev-server and, if successful, will run the app/studio dev server on the next available port.
27
- * If the workbench dev-server fails to start for an expected reason, e.g. because there is already
28
- * a workbench instance running or the workbench package is unavailable, it will run the app/studio
29
- * dev server on the configured port.
12
+ * Entry point for `sanity dev`. A plain studio/app starts a single dev server, as
13
+ * before workbench existed. A workbench app (via `unstable_defineApp`) delegates to
14
+ * `@sanity/workbench-cli`, injecting the CLI-domain pieces (app server, manifest
15
+ * extraction, app id) and loading the package lazily so plain projects never do.
30
16
  */ export async function devAction(options) {
31
- const { cliConfig, flags, output, workDir } = options;
17
+ const { cliConfig, flags, isApp, output, workDir } = options;
32
18
  const { httpHost, httpPort } = getSharedServerConfig({
33
19
  cliConfig,
34
20
  flags: {
@@ -37,185 +23,48 @@ function toDisplayHost(host) {
37
23
  },
38
24
  workDir
39
25
  });
40
- /**
41
- * The workbench remote is the app that renders "workbench ready" apps, thereby it can't render itself.
42
- * But it still wants to be deployed as a singleton in the sanity ecosystem. Therefore, this internal flag
43
- * allows us to develop the workbench remote correctly – as a standalone app.
44
- */ const isWorkbenchRemote = isWorkbenchApp(cliConfig?.app) && process.env.SANITY_INTERNAL_IS_WORKBENCH_REMOTE === 'true';
45
- const { close: closeWorkbenchServer, httpHost: workbenchHost, workbenchAvailable, workbenchPort } = isWorkbenchRemote ? {
46
- close: noop,
47
- httpHost,
48
- workbenchAvailable: false,
49
- workbenchPort: httpPort
50
- } : await startWorkbenchDevServer({
51
- ...options,
52
- httpHost,
53
- httpPort
54
- });
55
- // A running workbench claims the configured port, so the app server binds the
56
- // next one — passed explicitly rather than by rewriting the shared flags.
57
- // Without a workbench the app server resolves its port from flags/env/config
58
- // downstream, exactly as it did before workbench existed.
59
- const appOptions = workbenchAvailable ? {
60
- ...options,
61
- httpPort: workbenchPort + 1,
62
- workbenchAvailable
63
- } : {
64
- ...options,
65
- workbenchAvailable
66
- };
67
- let closeAppDevServer = noop;
68
- // Takes the config as a param so a rebuild can feed a freshly-loaded one.
69
- const startApp = async (config)=>{
70
- const result = options.isApp ? await startAppDevServer({
71
- ...appOptions,
72
- cliConfig: config
73
- }) : await startStudioDevServer({
74
- ...appOptions,
75
- cliConfig: config
26
+ // The app/studio server, parameterized per call; `announceUrl` is false when
27
+ // the workbench announces the URL on its behalf.
28
+ const startAppServer = (params)=>(isApp ? startAppDevServer : startStudioDevServer)({
29
+ ...options,
30
+ announceUrl: params.announceUrl,
31
+ cliConfig: params.cliConfig,
32
+ httpPort: params.httpPort
76
33
  });
77
- closeAppDevServer = result.started ? result.close : noop;
78
- return result;
79
- };
80
- let initial;
81
- try {
82
- initial = await startApp(cliConfig);
83
- } catch (err) {
84
- await closeWorkbenchServer();
85
- throw err;
86
- }
87
- if (!initial.started) {
88
- // The server has already reported why (e.g. missing organization ID).
89
- return {
90
- close: closeWorkbenchServer
91
- };
92
- }
93
- const { server } = initial;
94
- // Adding/removing a view or service in `sanity.cli.ts` during dev requires
95
- // rebuilding the federation remote: its module-federation `exposes` map +
96
- // codegen artifacts are computed once at server start, so a newly-declared
97
- // interface has no expose until the server is recreated. `server.restart()`
98
- // can't do it — it re-uses the inline config — so we tear the app server
99
- // down and bring it back up with a freshly-loaded config. The workbench page
100
- // then reloads (driven by the registry watch in the workbench server) to
101
- // re-fetch the rebuilt remote. A view/service *source* edit doesn't change
102
- // the interface set, so it stays on the HMR path untouched. Studios declare
103
- // views/services the same way (only `entry` is rejected, FR-026), so they
104
- // get the same rebuild. The returned-server / thrown-failed-restart contract
105
- // is documented on `onInterfaceSetChange` in startDevServerRegistration.
106
- // Declared ahead of `runRebuild`, which the watcher's initial background
107
- // extraction can invoke before the statements below it have run.
108
- let closed = false;
109
- const runRebuild = async ()=>{
110
- // The watcher only learns about shutdown when its own close runs, late in
111
- // the teardown sequence — refuse here so a config save during shutdown
112
- // can't boot a replacement server nobody owns. Checked before the first
113
- // await so a rebuild can't start after close() has read `rebuildInFlight`.
114
- if (closed) {
115
- throw new Error('Dev server is shutting down');
116
- }
117
- const freshConfig = await getCliConfigUncached(workDir);
118
- await closeAppDevServer();
119
- const result = await startApp(freshConfig);
120
- if (!result.started) {
121
- // The server already reported why (e.g. organizationId was removed).
122
- throw new Error('Dev server did not restart after the view/service change');
123
- }
124
- return result.server;
125
- };
126
- // `closeAppDevServer` is repointed at the replacement server only after
127
- // `startApp` resolves — a close() racing a rebuild would tear down the old
128
- // (already-closed) server and leave the replacement running with no owner,
129
- // so close() waits on the rebuild in flight. Rejections are owned by the
130
- // watcher (warn + retry on next save); the tracked copy swallows them so
131
- // close() can't reject.
132
- let rebuildInFlight = Promise.resolve();
133
- const onInterfaceSetChange = ()=>{
134
- const rebuild = runRebuild();
135
- rebuildInFlight = rebuild.catch(()=>{});
136
- return rebuild;
137
- };
138
- // Workbench is opted into solely by calling `unstable_defineApp` — its
139
- // branded identity is the only signal. The workbench remote is the exception:
140
- // it's the shell itself, not a dock app, so it never registers into the
141
- // shared workbench registry.
142
- let registration;
143
- try {
144
- registration = isWorkbenchApp(cliConfig?.app) && !isWorkbenchRemote ? await startDevServerRegistration({
34
+ if (isWorkbenchApp(cliConfig?.app)) {
35
+ // Lazy so a non-workbench `sanity dev` never loads the package. `doImport`
36
+ // is path-based and doesn't apply to a bare specifier.
37
+ // eslint-disable-next-line no-restricted-syntax
38
+ const { startWorkbenchDev } = await import('@sanity/workbench-cli/dev');
39
+ return startWorkbenchDev({
40
+ appId: getAppId(cliConfig),
41
+ cacheDir: `${SANITY_CACHE_DIR}/vite`,
42
+ checkForDeprecatedAppId: ()=>checkForDeprecatedAppId({
43
+ cliConfig,
44
+ output
45
+ }),
145
46
  cliConfig,
146
- isApp: options.isApp,
147
- onInterfaceSetChange,
47
+ extractManifest: isApp ? ({ workDir: wd })=>extractCoreAppManifest({
48
+ workDir: wd
49
+ }) : (params)=>extractStudioManifest(params),
50
+ httpHost,
51
+ httpPort,
52
+ isApp,
148
53
  output,
149
- server,
54
+ // Runtime template needs a concrete boolean; collapse an unset config to off.
55
+ reactStrictMode: resolveReactStrictMode(cliConfig) ?? false,
56
+ startAppServer,
150
57
  workDir
151
- }) : undefined;
152
- } catch (err) {
153
- // Registration runs only after both servers are already up. If it throws
154
- // (e.g. `deriveInterfaces` rejects), tear them down before rethrowing —
155
- // otherwise the workbench lock and dev servers leak until the next run.
156
- await Promise.allSettled([
157
- closeWorkbenchServer(),
158
- closeAppDevServer()
159
- ]);
160
- throw err;
161
- }
162
- if (workbenchAvailable) {
163
- const workbenchUrl = `http://${toDisplayHost(workbenchHost)}:${workbenchPort}`;
164
- const addr = server.httpServer?.address();
165
- const appPort = typeof addr === 'object' && addr ? addr.port : server.config.server.port;
166
- output.log(`Workbench dev server started at ${styleText([
167
- 'blue',
168
- 'underline'
169
- ], workbenchUrl)} (app on port ${appPort})`);
170
- }
171
- // Single-flight: SIGINT followed by SIGTERM (each signal has its own `once`
172
- // handler), or a signal racing the caller's own close(), must share one
173
- // teardown instead of double-closing every server.
174
- let closing;
175
- const close = ()=>{
176
- closing ??= (async ()=>{
177
- closed = true;
178
- process.off('SIGINT', onSignal);
179
- process.off('SIGTERM', onSignal);
180
- await rebuildInFlight;
181
- await Promise.allSettled([
182
- registration?.close(),
183
- closeWorkbenchServer(),
184
- closeAppDevServer()
185
- ]);
186
- })();
187
- return closing;
188
- };
189
- // Ensure the workbench lock file and registry entries are cleaned up on
190
- // abrupt shutdown. The registry is self-healing (stale PIDs are pruned on
191
- // next read), but eager cleanup avoids the detect-prune-retry cycle.
192
- // Plain projects have no lock or registry entry, so they keep the default
193
- // signal handling (and exit codes) they had before workbench existed.
194
- //
195
- // Trapping the signal disables Node's default exit, and a finished teardown
196
- // doesn't guarantee an empty event loop (keep-alive sockets, an extraction
197
- // worker mid-run) — without an explicit exit the process lingers, holding
198
- // its ports, while the shell prompt returns. Re-raising after teardown
199
- // restores the default termination (the `once` handler is gone by then),
200
- // with conventional signal exit semantics.
201
- const onSignal = (signal)=>{
202
- // Backstop for a teardown that never settles (a wedged socket or watcher):
203
- // force the exit once the grace period elapses. Cleared on the normal path
204
- // so the re-raise fires exactly once; `unref` keeps the timer from holding
205
- // the process open by itself.
206
- const graceTimer = setTimeout(()=>process.kill(process.pid, signal), SHUTDOWN_GRACE_MS);
207
- graceTimer.unref();
208
- void close().finally(()=>{
209
- clearTimeout(graceTimer);
210
- process.kill(process.pid, signal);
211
58
  });
212
- };
213
- if (workbenchAvailable || registration) {
214
- process.once('SIGINT', onSignal);
215
- process.once('SIGTERM', onSignal);
216
59
  }
60
+ // Plain non-workbench studio/app: one dev server announcing its own URL.
61
+ const result = await startAppServer({
62
+ announceUrl: true,
63
+ cliConfig,
64
+ httpPort
65
+ });
217
66
  return {
218
- close
67
+ close: result.started ? result.close : noop
219
68
  };
220
69
  }
221
70
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/dev/devAction.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {getCliConfigUncached, isWorkbenchApp} from '@sanity/cli-core'\nimport {type ViteDevServer} from 'vite'\n\nimport {getSharedServerConfig} from '../../util/getSharedServerConfig.js'\nimport {startDevServerRegistration} from './registration/startDevServerRegistration.js'\nimport {startAppDevServer} from './servers/startAppDevServer.js'\nimport {startStudioDevServer} from './servers/startStudioDevServer.js'\nimport {type DevActionOptions, type StartDevServerResult} from './types.js'\nimport {startWorkbenchDevServer} from './workbench/startWorkbenchDevServer.js'\n\nconst noop = async () => {}\n\n/**\n * How long a signal-triggered teardown may run before the process force-exits\n * by re-raising the signal — generous enough for Vite servers and watchers to\n * close, short enough not to strand a backgrounded process holding the ports.\n */\nconst SHUTDOWN_GRACE_MS = 5000\n\n// Bind-only addresses ('0.0.0.0', '::') aren't routable URLs in every\n// browser (notably on Windows), so the displayed URL falls back to\n// localhost. The bind address itself is untouched — listening and the\n// lock file keep whatever the user configured.\nfunction toDisplayHost(host: string | undefined): string {\n if (!host || host === '0.0.0.0' || host === '::' || host === '[::]') {\n return 'localhost'\n }\n return host\n}\n\n/**\n * Orchestrates the dev servers required by the process. It will attempt to run a workbench\n * dev-server and, if successful, will run the app/studio dev server on the next available port.\n * If the workbench dev-server fails to start for an expected reason, e.g. because there is already\n * a workbench instance running or the workbench package is unavailable, it will run the app/studio\n * dev server on the configured port.\n */\nexport async function devAction(options: DevActionOptions): Promise<{close: () => Promise<void>}> {\n const {cliConfig, flags, output, workDir} = options\n\n const {httpHost, httpPort} = getSharedServerConfig({\n cliConfig,\n flags: {host: flags.host, port: flags.port},\n workDir,\n })\n\n /**\n * The workbench remote is the app that renders \"workbench ready\" apps, thereby it can't render itself.\n * But it still wants to be deployed as a singleton in the sanity ecosystem. Therefore, this internal flag\n * allows us to develop the workbench remote correctly – as a standalone app.\n */\n const isWorkbenchRemote =\n isWorkbenchApp(cliConfig?.app) && process.env.SANITY_INTERNAL_IS_WORKBENCH_REMOTE === 'true'\n\n const {\n close: closeWorkbenchServer,\n httpHost: workbenchHost,\n workbenchAvailable,\n workbenchPort,\n } = isWorkbenchRemote\n ? {close: noop, httpHost, workbenchAvailable: false, workbenchPort: httpPort}\n : await startWorkbenchDevServer({...options, httpHost, httpPort})\n\n // A running workbench claims the configured port, so the app server binds the\n // next one — passed explicitly rather than by rewriting the shared flags.\n // Without a workbench the app server resolves its port from flags/env/config\n // downstream, exactly as it did before workbench existed.\n const appOptions: DevActionOptions = workbenchAvailable\n ? {...options, httpPort: workbenchPort + 1, workbenchAvailable}\n : {...options, workbenchAvailable}\n\n let closeAppDevServer: () => Promise<void> = noop\n\n // Takes the config as a param so a rebuild can feed a freshly-loaded one.\n const startApp = async (config: DevActionOptions['cliConfig']): Promise<StartDevServerResult> => {\n const result = options.isApp\n ? await startAppDevServer({...appOptions, cliConfig: config})\n : await startStudioDevServer({...appOptions, cliConfig: config})\n closeAppDevServer = result.started ? result.close : noop\n return result\n }\n\n let initial: StartDevServerResult\n try {\n initial = await startApp(cliConfig)\n } catch (err) {\n await closeWorkbenchServer()\n throw err\n }\n\n if (!initial.started) {\n // The server has already reported why (e.g. missing organization ID).\n return {close: closeWorkbenchServer}\n }\n const {server} = initial\n\n // Adding/removing a view or service in `sanity.cli.ts` during dev requires\n // rebuilding the federation remote: its module-federation `exposes` map +\n // codegen artifacts are computed once at server start, so a newly-declared\n // interface has no expose until the server is recreated. `server.restart()`\n // can't do it — it re-uses the inline config — so we tear the app server\n // down and bring it back up with a freshly-loaded config. The workbench page\n // then reloads (driven by the registry watch in the workbench server) to\n // re-fetch the rebuilt remote. A view/service *source* edit doesn't change\n // the interface set, so it stays on the HMR path untouched. Studios declare\n // views/services the same way (only `entry` is rejected, FR-026), so they\n // get the same rebuild. The returned-server / thrown-failed-restart contract\n // is documented on `onInterfaceSetChange` in startDevServerRegistration.\n\n // Declared ahead of `runRebuild`, which the watcher's initial background\n // extraction can invoke before the statements below it have run.\n let closed = false\n\n const runRebuild = async (): Promise<ViteDevServer> => {\n // The watcher only learns about shutdown when its own close runs, late in\n // the teardown sequence — refuse here so a config save during shutdown\n // can't boot a replacement server nobody owns. Checked before the first\n // await so a rebuild can't start after close() has read `rebuildInFlight`.\n if (closed) {\n throw new Error('Dev server is shutting down')\n }\n const freshConfig = await getCliConfigUncached(workDir)\n await closeAppDevServer()\n const result = await startApp(freshConfig)\n if (!result.started) {\n // The server already reported why (e.g. organizationId was removed).\n throw new Error('Dev server did not restart after the view/service change')\n }\n return result.server\n }\n\n // `closeAppDevServer` is repointed at the replacement server only after\n // `startApp` resolves — a close() racing a rebuild would tear down the old\n // (already-closed) server and leave the replacement running with no owner,\n // so close() waits on the rebuild in flight. Rejections are owned by the\n // watcher (warn + retry on next save); the tracked copy swallows them so\n // close() can't reject.\n let rebuildInFlight: Promise<unknown> = Promise.resolve()\n const onInterfaceSetChange = (): Promise<ViteDevServer> => {\n const rebuild = runRebuild()\n rebuildInFlight = rebuild.catch(() => {})\n return rebuild\n }\n\n // Workbench is opted into solely by calling `unstable_defineApp` — its\n // branded identity is the only signal. The workbench remote is the exception:\n // it's the shell itself, not a dock app, so it never registers into the\n // shared workbench registry.\n let registration: Awaited<ReturnType<typeof startDevServerRegistration>> | undefined\n try {\n registration =\n isWorkbenchApp(cliConfig?.app) && !isWorkbenchRemote\n ? await startDevServerRegistration({\n cliConfig,\n isApp: options.isApp,\n onInterfaceSetChange,\n output,\n server,\n workDir,\n })\n : undefined\n } catch (err) {\n // Registration runs only after both servers are already up. If it throws\n // (e.g. `deriveInterfaces` rejects), tear them down before rethrowing —\n // otherwise the workbench lock and dev servers leak until the next run.\n await Promise.allSettled([closeWorkbenchServer(), closeAppDevServer()])\n throw err\n }\n\n if (workbenchAvailable) {\n const workbenchUrl = `http://${toDisplayHost(workbenchHost)}:${workbenchPort}`\n const addr = server.httpServer?.address()\n const appPort = typeof addr === 'object' && addr ? addr.port : server.config.server.port\n output.log(\n `Workbench dev server started at ${styleText(['blue', 'underline'], workbenchUrl)} (app on port ${appPort})`,\n )\n }\n\n // Single-flight: SIGINT followed by SIGTERM (each signal has its own `once`\n // handler), or a signal racing the caller's own close(), must share one\n // teardown instead of double-closing every server.\n let closing: Promise<void> | undefined\n const close = () => {\n closing ??= (async () => {\n closed = true\n process.off('SIGINT', onSignal)\n process.off('SIGTERM', onSignal)\n await rebuildInFlight\n await Promise.allSettled([registration?.close(), closeWorkbenchServer(), closeAppDevServer()])\n })()\n return closing\n }\n\n // Ensure the workbench lock file and registry entries are cleaned up on\n // abrupt shutdown. The registry is self-healing (stale PIDs are pruned on\n // next read), but eager cleanup avoids the detect-prune-retry cycle.\n // Plain projects have no lock or registry entry, so they keep the default\n // signal handling (and exit codes) they had before workbench existed.\n //\n // Trapping the signal disables Node's default exit, and a finished teardown\n // doesn't guarantee an empty event loop (keep-alive sockets, an extraction\n // worker mid-run) — without an explicit exit the process lingers, holding\n // its ports, while the shell prompt returns. Re-raising after teardown\n // restores the default termination (the `once` handler is gone by then),\n // with conventional signal exit semantics.\n const onSignal = (signal: NodeJS.Signals) => {\n // Backstop for a teardown that never settles (a wedged socket or watcher):\n // force the exit once the grace period elapses. Cleared on the normal path\n // so the re-raise fires exactly once; `unref` keeps the timer from holding\n // the process open by itself.\n const graceTimer = setTimeout(() => process.kill(process.pid, signal), SHUTDOWN_GRACE_MS)\n graceTimer.unref()\n void close().finally(() => {\n clearTimeout(graceTimer)\n process.kill(process.pid, signal)\n })\n }\n if (workbenchAvailable || registration) {\n process.once('SIGINT', onSignal)\n process.once('SIGTERM', onSignal)\n }\n\n return {close}\n}\n"],"names":["styleText","getCliConfigUncached","isWorkbenchApp","getSharedServerConfig","startDevServerRegistration","startAppDevServer","startStudioDevServer","startWorkbenchDevServer","noop","SHUTDOWN_GRACE_MS","toDisplayHost","host","devAction","options","cliConfig","flags","output","workDir","httpHost","httpPort","port","isWorkbenchRemote","app","process","env","SANITY_INTERNAL_IS_WORKBENCH_REMOTE","close","closeWorkbenchServer","workbenchHost","workbenchAvailable","workbenchPort","appOptions","closeAppDevServer","startApp","config","result","isApp","started","initial","err","server","closed","runRebuild","Error","freshConfig","rebuildInFlight","Promise","resolve","onInterfaceSetChange","rebuild","catch","registration","undefined","allSettled","workbenchUrl","addr","httpServer","address","appPort","log","closing","off","onSignal","signal","graceTimer","setTimeout","kill","pid","unref","finally","clearTimeout","once"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/actions/dev/devAction.ts"],"sourcesContent":["import {SANITY_CACHE_DIR} from '@sanity/cli-build/_internal/build'\nimport {type CliConfig, isWorkbenchApp} from '@sanity/cli-core'\n\nimport {checkForDeprecatedAppId, getAppId} from '../../util/appId.js'\nimport {getSharedServerConfig} from '../../util/getSharedServerConfig.js'\nimport {resolveReactStrictMode} from '../../util/resolveReactStrictMode.js'\nimport {extractCoreAppManifest} from '../manifest/extractCoreAppManifest.js'\nimport {extractStudioManifest} from '../manifest/extractStudioManifest.js'\nimport {startAppDevServer} from './servers/startAppDevServer.js'\nimport {startStudioDevServer} from './servers/startStudioDevServer.js'\nimport {type DevActionOptions} from './types.js'\n\nconst noop = async () => {}\n\n/**\n * Entry point for `sanity dev`. A plain studio/app starts a single dev server, as\n * before workbench existed. A workbench app (via `unstable_defineApp`) delegates to\n * `@sanity/workbench-cli`, injecting the CLI-domain pieces (app server, manifest\n * extraction, app id) and loading the package lazily so plain projects never do.\n */\nexport async function devAction(options: DevActionOptions): Promise<{close: () => Promise<void>}> {\n const {cliConfig, flags, isApp, output, workDir} = options\n\n const {httpHost, httpPort} = getSharedServerConfig({\n cliConfig,\n flags: {host: flags.host, port: flags.port},\n workDir,\n })\n\n // The app/studio server, parameterized per call; `announceUrl` is false when\n // the workbench announces the URL on its behalf.\n const startAppServer = (params: {announceUrl: boolean; cliConfig: CliConfig; httpPort: number}) =>\n (isApp ? startAppDevServer : startStudioDevServer)({\n ...options,\n announceUrl: params.announceUrl,\n cliConfig: params.cliConfig,\n httpPort: params.httpPort,\n })\n\n if (isWorkbenchApp(cliConfig?.app)) {\n // Lazy so a non-workbench `sanity dev` never loads the package. `doImport`\n // is path-based and doesn't apply to a bare specifier.\n // eslint-disable-next-line no-restricted-syntax\n const {startWorkbenchDev} = await import('@sanity/workbench-cli/dev')\n return startWorkbenchDev({\n appId: getAppId(cliConfig),\n cacheDir: `${SANITY_CACHE_DIR}/vite`,\n checkForDeprecatedAppId: () => checkForDeprecatedAppId({cliConfig, output}),\n cliConfig,\n extractManifest: isApp\n ? ({workDir: wd}) => extractCoreAppManifest({workDir: wd})\n : (params) => extractStudioManifest(params),\n httpHost,\n httpPort,\n isApp,\n output,\n // Runtime template needs a concrete boolean; collapse an unset config to off.\n reactStrictMode: resolveReactStrictMode(cliConfig) ?? false,\n startAppServer,\n workDir,\n })\n }\n\n // Plain non-workbench studio/app: one dev server announcing its own URL.\n const result = await startAppServer({announceUrl: true, cliConfig, httpPort})\n return {close: result.started ? result.close : noop}\n}\n"],"names":["SANITY_CACHE_DIR","isWorkbenchApp","checkForDeprecatedAppId","getAppId","getSharedServerConfig","resolveReactStrictMode","extractCoreAppManifest","extractStudioManifest","startAppDevServer","startStudioDevServer","noop","devAction","options","cliConfig","flags","isApp","output","workDir","httpHost","httpPort","host","port","startAppServer","params","announceUrl","app","startWorkbenchDev","appId","cacheDir","extractManifest","wd","reactStrictMode","result","close","started"],"mappings":"AAAA,SAAQA,gBAAgB,QAAO,oCAAmC;AAClE,SAAwBC,cAAc,QAAO,mBAAkB;AAE/D,SAAQC,uBAAuB,EAAEC,QAAQ,QAAO,sBAAqB;AACrE,SAAQC,qBAAqB,QAAO,sCAAqC;AACzE,SAAQC,sBAAsB,QAAO,uCAAsC;AAC3E,SAAQC,sBAAsB,QAAO,wCAAuC;AAC5E,SAAQC,qBAAqB,QAAO,uCAAsC;AAC1E,SAAQC,iBAAiB,QAAO,iCAAgC;AAChE,SAAQC,oBAAoB,QAAO,oCAAmC;AAGtE,MAAMC,OAAO,WAAa;AAE1B;;;;;CAKC,GACD,OAAO,eAAeC,UAAUC,OAAyB;IACvD,MAAM,EAACC,SAAS,EAAEC,KAAK,EAAEC,KAAK,EAAEC,MAAM,EAAEC,OAAO,EAAC,GAAGL;IAEnD,MAAM,EAACM,QAAQ,EAAEC,QAAQ,EAAC,GAAGf,sBAAsB;QACjDS;QACAC,OAAO;YAACM,MAAMN,MAAMM,IAAI;YAAEC,MAAMP,MAAMO,IAAI;QAAA;QAC1CJ;IACF;IAEA,6EAA6E;IAC7E,iDAAiD;IACjD,MAAMK,iBAAiB,CAACC,SACtB,AAACR,CAAAA,QAAQP,oBAAoBC,oBAAmB,EAAG;YACjD,GAAGG,OAAO;YACVY,aAAaD,OAAOC,WAAW;YAC/BX,WAAWU,OAAOV,SAAS;YAC3BM,UAAUI,OAAOJ,QAAQ;QAC3B;IAEF,IAAIlB,eAAeY,WAAWY,MAAM;QAClC,2EAA2E;QAC3E,uDAAuD;QACvD,gDAAgD;QAChD,MAAM,EAACC,iBAAiB,EAAC,GAAG,MAAM,MAAM,CAAC;QACzC,OAAOA,kBAAkB;YACvBC,OAAOxB,SAASU;YAChBe,UAAU,GAAG5B,iBAAiB,KAAK,CAAC;YACpCE,yBAAyB,IAAMA,wBAAwB;oBAACW;oBAAWG;gBAAM;YACzEH;YACAgB,iBAAiBd,QACb,CAAC,EAACE,SAASa,EAAE,EAAC,GAAKxB,uBAAuB;oBAACW,SAASa;gBAAE,KACtD,CAACP,SAAWhB,sBAAsBgB;YACtCL;YACAC;YACAJ;YACAC;YACA,8EAA8E;YAC9Ee,iBAAiB1B,uBAAuBQ,cAAc;YACtDS;YACAL;QACF;IACF;IAEA,yEAAyE;IACzE,MAAMe,SAAS,MAAMV,eAAe;QAACE,aAAa;QAAMX;QAAWM;IAAQ;IAC3E,OAAO;QAACc,OAAOD,OAAOE,OAAO,GAAGF,OAAOC,KAAK,GAAGvB;IAAI;AACrD"}
@@ -27,7 +27,7 @@ export function getDevServerConfig({ cliConfig, flags, httpPort, output, workDir
27
27
  return {
28
28
  ...baseConfig,
29
29
  // The app's navigable entry. A branded app that omits `entry` has no app
30
- // view (sanity-io/workbench spec 002-workbench-extension-api, US5): the runtime/federation skip the `./App` render path entirely.
30
+ // view: the runtime/federation skip the `./App` render path entirely.
31
31
  entry: app?.entry,
32
32
  // `devAction` passes an explicit port when a running workbench claimed the
33
33
  // configured one; otherwise the shared resolution stands.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/actions/dev/servers/getDevServerConfig.ts"],"sourcesContent":["import path from 'node:path'\n\nimport {type CliConfig, getSanityEnvVar, isWorkbenchApp, type Output} from '@sanity/cli-core'\nimport {spinner} from '@sanity/cli-core/ux'\n\nimport {type DevServerOptions} from '../../../server/devServer.js'\nimport {determineIsApp} from '../../../util/determineIsApp.js'\nimport {getSharedServerConfig} from '../../../util/getSharedServerConfig.js'\nimport {resolveReactStrictMode} from '../../../util/resolveReactStrictMode.js'\nimport {type DevFlags} from '../types.js'\n\nexport function getDevServerConfig({\n cliConfig,\n flags,\n httpPort,\n output,\n workDir,\n}: {\n cliConfig?: CliConfig\n flags: DevFlags\n httpPort?: number\n output: Output\n workDir: string\n}): Omit<DevServerOptions, 'spinner'> {\n const configSpinner = spinner('Checking configuration files...')\n\n const baseConfig = getSharedServerConfig({\n cliConfig,\n flags: {\n host: flags.host,\n port: flags.port,\n },\n workDir,\n })\n\n configSpinner.succeed()\n\n const isApp = cliConfig ? determineIsApp(cliConfig) : false\n const reactStrictMode = resolveReactStrictMode(cliConfig)\n // `views` is declared via `unstable_defineApp`, so read it off the branded\n // app result rather than the legacy `app` config type.\n const app = cliConfig?.app\n\n const envBasePath = getSanityEnvVar('BASEPATH', isApp ?? false)\n if (envBasePath && cliConfig?.project?.basePath) {\n output.warn(\n `Overriding configured base path (${cliConfig.project.basePath}) with value from environment variable (${envBasePath})`,\n )\n }\n\n return {\n ...baseConfig,\n // The app's navigable entry. A branded app that omits `entry` has no app\n // view (sanity-io/workbench spec 002-workbench-extension-api, US5): the runtime/federation skip the `./App` render path entirely.\n entry: app?.entry,\n // `devAction` passes an explicit port when a running workbench claimed the\n // configured one; otherwise the shared resolution stands.\n httpPort: httpPort ?? baseConfig.httpPort,\n isWorkbenchApp: isWorkbenchApp(app),\n reactCompiler: cliConfig && 'reactCompiler' in cliConfig ? cliConfig.reactCompiler : undefined,\n reactStrictMode,\n services: isWorkbenchApp(app) ? app.services : undefined,\n staticPath: path.join(workDir, 'static'),\n typegen: cliConfig?.typegen,\n views: isWorkbenchApp(app) ? app.views : undefined,\n }\n}\n"],"names":["path","getSanityEnvVar","isWorkbenchApp","spinner","determineIsApp","getSharedServerConfig","resolveReactStrictMode","getDevServerConfig","cliConfig","flags","httpPort","output","workDir","configSpinner","baseConfig","host","port","succeed","isApp","reactStrictMode","app","envBasePath","project","basePath","warn","entry","reactCompiler","undefined","services","staticPath","join","typegen","views"],"mappings":"AAAA,OAAOA,UAAU,YAAW;AAE5B,SAAwBC,eAAe,EAAEC,cAAc,QAAoB,mBAAkB;AAC7F,SAAQC,OAAO,QAAO,sBAAqB;AAG3C,SAAQC,cAAc,QAAO,kCAAiC;AAC9D,SAAQC,qBAAqB,QAAO,yCAAwC;AAC5E,SAAQC,sBAAsB,QAAO,0CAAyC;AAG9E,OAAO,SAASC,mBAAmB,EACjCC,SAAS,EACTC,KAAK,EACLC,QAAQ,EACRC,MAAM,EACNC,OAAO,EAOR;IACC,MAAMC,gBAAgBV,QAAQ;IAE9B,MAAMW,aAAaT,sBAAsB;QACvCG;QACAC,OAAO;YACLM,MAAMN,MAAMM,IAAI;YAChBC,MAAMP,MAAMO,IAAI;QAClB;QACAJ;IACF;IAEAC,cAAcI,OAAO;IAErB,MAAMC,QAAQV,YAAYJ,eAAeI,aAAa;IACtD,MAAMW,kBAAkBb,uBAAuBE;IAC/C,2EAA2E;IAC3E,uDAAuD;IACvD,MAAMY,MAAMZ,WAAWY;IAEvB,MAAMC,cAAcpB,gBAAgB,YAAYiB,SAAS;IACzD,IAAIG,eAAeb,WAAWc,SAASC,UAAU;QAC/CZ,OAAOa,IAAI,CACT,CAAC,iCAAiC,EAAEhB,UAAUc,OAAO,CAACC,QAAQ,CAAC,wCAAwC,EAAEF,YAAY,CAAC,CAAC;IAE3H;IAEA,OAAO;QACL,GAAGP,UAAU;QACb,yEAAyE;QACzE,kIAAkI;QAClIW,OAAOL,KAAKK;QACZ,2EAA2E;QAC3E,0DAA0D;QAC1Df,UAAUA,YAAYI,WAAWJ,QAAQ;QACzCR,gBAAgBA,eAAekB;QAC/BM,eAAelB,aAAa,mBAAmBA,YAAYA,UAAUkB,aAAa,GAAGC;QACrFR;QACAS,UAAU1B,eAAekB,OAAOA,IAAIQ,QAAQ,GAAGD;QAC/CE,YAAY7B,KAAK8B,IAAI,CAAClB,SAAS;QAC/BmB,SAASvB,WAAWuB;QACpBC,OAAO9B,eAAekB,OAAOA,IAAIY,KAAK,GAAGL;IAC3C;AACF"}
1
+ {"version":3,"sources":["../../../../src/actions/dev/servers/getDevServerConfig.ts"],"sourcesContent":["import path from 'node:path'\n\nimport {type CliConfig, getSanityEnvVar, isWorkbenchApp, type Output} from '@sanity/cli-core'\nimport {spinner} from '@sanity/cli-core/ux'\n\nimport {type DevServerOptions} from '../../../server/devServer.js'\nimport {determineIsApp} from '../../../util/determineIsApp.js'\nimport {getSharedServerConfig} from '../../../util/getSharedServerConfig.js'\nimport {resolveReactStrictMode} from '../../../util/resolveReactStrictMode.js'\nimport {type DevFlags} from '../types.js'\n\nexport function getDevServerConfig({\n cliConfig,\n flags,\n httpPort,\n output,\n workDir,\n}: {\n cliConfig?: CliConfig\n flags: DevFlags\n httpPort?: number\n output: Output\n workDir: string\n}): Omit<DevServerOptions, 'spinner'> {\n const configSpinner = spinner('Checking configuration files...')\n\n const baseConfig = getSharedServerConfig({\n cliConfig,\n flags: {\n host: flags.host,\n port: flags.port,\n },\n workDir,\n })\n\n configSpinner.succeed()\n\n const isApp = cliConfig ? determineIsApp(cliConfig) : false\n const reactStrictMode = resolveReactStrictMode(cliConfig)\n // `views` is declared via `unstable_defineApp`, so read it off the branded\n // app result rather than the legacy `app` config type.\n const app = cliConfig?.app\n\n const envBasePath = getSanityEnvVar('BASEPATH', isApp ?? false)\n if (envBasePath && cliConfig?.project?.basePath) {\n output.warn(\n `Overriding configured base path (${cliConfig.project.basePath}) with value from environment variable (${envBasePath})`,\n )\n }\n\n return {\n ...baseConfig,\n // The app's navigable entry. A branded app that omits `entry` has no app\n // view: the runtime/federation skip the `./App` render path entirely.\n entry: app?.entry,\n // `devAction` passes an explicit port when a running workbench claimed the\n // configured one; otherwise the shared resolution stands.\n httpPort: httpPort ?? baseConfig.httpPort,\n isWorkbenchApp: isWorkbenchApp(app),\n reactCompiler: cliConfig && 'reactCompiler' in cliConfig ? cliConfig.reactCompiler : undefined,\n reactStrictMode,\n services: isWorkbenchApp(app) ? app.services : undefined,\n staticPath: path.join(workDir, 'static'),\n typegen: cliConfig?.typegen,\n views: isWorkbenchApp(app) ? app.views : undefined,\n }\n}\n"],"names":["path","getSanityEnvVar","isWorkbenchApp","spinner","determineIsApp","getSharedServerConfig","resolveReactStrictMode","getDevServerConfig","cliConfig","flags","httpPort","output","workDir","configSpinner","baseConfig","host","port","succeed","isApp","reactStrictMode","app","envBasePath","project","basePath","warn","entry","reactCompiler","undefined","services","staticPath","join","typegen","views"],"mappings":"AAAA,OAAOA,UAAU,YAAW;AAE5B,SAAwBC,eAAe,EAAEC,cAAc,QAAoB,mBAAkB;AAC7F,SAAQC,OAAO,QAAO,sBAAqB;AAG3C,SAAQC,cAAc,QAAO,kCAAiC;AAC9D,SAAQC,qBAAqB,QAAO,yCAAwC;AAC5E,SAAQC,sBAAsB,QAAO,0CAAyC;AAG9E,OAAO,SAASC,mBAAmB,EACjCC,SAAS,EACTC,KAAK,EACLC,QAAQ,EACRC,MAAM,EACNC,OAAO,EAOR;IACC,MAAMC,gBAAgBV,QAAQ;IAE9B,MAAMW,aAAaT,sBAAsB;QACvCG;QACAC,OAAO;YACLM,MAAMN,MAAMM,IAAI;YAChBC,MAAMP,MAAMO,IAAI;QAClB;QACAJ;IACF;IAEAC,cAAcI,OAAO;IAErB,MAAMC,QAAQV,YAAYJ,eAAeI,aAAa;IACtD,MAAMW,kBAAkBb,uBAAuBE;IAC/C,2EAA2E;IAC3E,uDAAuD;IACvD,MAAMY,MAAMZ,WAAWY;IAEvB,MAAMC,cAAcpB,gBAAgB,YAAYiB,SAAS;IACzD,IAAIG,eAAeb,WAAWc,SAASC,UAAU;QAC/CZ,OAAOa,IAAI,CACT,CAAC,iCAAiC,EAAEhB,UAAUc,OAAO,CAACC,QAAQ,CAAC,wCAAwC,EAAEF,YAAY,CAAC,CAAC;IAE3H;IAEA,OAAO;QACL,GAAGP,UAAU;QACb,yEAAyE;QACzE,sEAAsE;QACtEW,OAAOL,KAAKK;QACZ,2EAA2E;QAC3E,0DAA0D;QAC1Df,UAAUA,YAAYI,WAAWJ,QAAQ;QACzCR,gBAAgBA,eAAekB;QAC/BM,eAAelB,aAAa,mBAAmBA,YAAYA,UAAUkB,aAAa,GAAGC;QACrFR;QACAS,UAAU1B,eAAekB,OAAOA,IAAIQ,QAAQ,GAAGD;QAC/CE,YAAY7B,KAAK8B,IAAI,CAAClB,SAAS;QAC/BmB,SAASvB,WAAWuB;QACpBC,OAAO9B,eAAekB,OAAOA,IAAIY,KAAK,GAAGL;IAC3C;AACF"}
@@ -5,8 +5,16 @@ import { gracefulServerDeath } from '../../../server/gracefulServerDeath.js';
5
5
  import { devDebug } from '../devDebug.js';
6
6
  import { getDashboardAppURL } from './getDashboardAppUrl.js';
7
7
  import { getDevServerConfig } from './getDevServerConfig.js';
8
+ // Bind-only addresses ('0.0.0.0', '::') aren't routable in every browser; the
9
+ // displayed URL falls back to localhost. The bind address itself is untouched.
10
+ function toDisplayHost(host) {
11
+ if (!host || host === '0.0.0.0' || host === '::' || host === '[::]') {
12
+ return 'localhost';
13
+ }
14
+ return host;
15
+ }
8
16
  export async function startAppDevServer(options) {
9
- const { cliConfig, flags, httpPort, output, workbenchAvailable, workDir } = options;
17
+ const { announceUrl = true, cliConfig, flags, httpPort, output, workDir } = options;
10
18
  const isWorkbenchApp = determineIsWorkbenchApp(cliConfig?.app);
11
19
  // Workbench apps don't load through the dashboard, so the flag has no
12
20
  // meaning for them and is ignored.
@@ -43,14 +51,15 @@ export async function startAppDevServer(options) {
43
51
  isApp: true
44
52
  });
45
53
  const { port } = server.config.server;
46
- if (isWorkbenchApp) {
47
- // Federated apps surface through the workbench, so the dashboard URL is
48
- // meaningless for them. When the workbench runs, devAction announces its
49
- // URL instead — only the package-unavailable fallback logs from here.
50
- if (!workbenchAvailable) {
51
- output.log(`App dev server started on port ${port}`);
52
- }
53
- } else {
54
+ // Federated apps surface through the workbench, which announces the URL;
55
+ // only the package-unavailable fallback announces from here.
56
+ if (isWorkbenchApp && announceUrl) {
57
+ const url = `http://${toDisplayHost(config.httpHost)}:${port}`;
58
+ output.log(`App dev server started at ${styleText([
59
+ 'blue',
60
+ 'underline'
61
+ ], url)}`);
62
+ } else if (!isWorkbenchApp) {
54
63
  const httpHost = config.httpHost || 'localhost';
55
64
  const dashboardAppUrl = await getDashboardAppURL({
56
65
  httpHost,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/actions/dev/servers/startAppDevServer.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {isWorkbenchApp as determineIsWorkbenchApp} from '@sanity/cli-core'\n\nimport {startDevServer} from '../../../server/devServer.js'\nimport {gracefulServerDeath} from '../../../server/gracefulServerDeath.js'\nimport {devDebug} from '../devDebug.js'\nimport {type DevActionOptions, type StartDevServerResult} from '../types.js'\nimport {getDashboardAppURL} from './getDashboardAppUrl.js'\nimport {getDevServerConfig} from './getDevServerConfig.js'\n\nexport async function startAppDevServer(options: DevActionOptions): Promise<StartDevServerResult> {\n const {cliConfig, flags, httpPort, output, workbenchAvailable, workDir} = options\n\n const isWorkbenchApp = determineIsWorkbenchApp(cliConfig?.app)\n\n // Workbench apps don't load through the dashboard, so the flag has no\n // meaning for them and is ignored.\n if (!isWorkbenchApp && !flags['load-in-dashboard']) {\n output.warn(`Apps cannot run without the Sanity dashboard`)\n output.warn(`Starting dev server with the --load-in-dashboard flag set to true`)\n }\n\n let organizationId: string | undefined\n if (cliConfig && 'app' in cliConfig && cliConfig.app?.organizationId) {\n organizationId = cliConfig.app.organizationId\n }\n\n if (!organizationId) {\n output.error(`Apps require an organization ID (orgId) specified in your sanity.cli.ts file`, {\n exit: 1,\n })\n return {reason: 'missing-organization-id', started: false}\n }\n\n const config = getDevServerConfig({cliConfig, flags, httpPort, output, workDir})\n\n try {\n output.log('Starting dev server')\n\n const appTitle = cliConfig && 'app' in cliConfig ? cliConfig.app?.title : undefined\n const {close, server} = await startDevServer({\n ...config,\n appTitle,\n isApp: true,\n })\n\n const {port} = server.config.server\n\n if (isWorkbenchApp) {\n // Federated apps surface through the workbench, so the dashboard URL is\n // meaningless for them. When the workbench runs, devAction announces its\n // URL instead — only the package-unavailable fallback logs from here.\n if (!workbenchAvailable) {\n output.log(`App dev server started on port ${port}`)\n }\n } else {\n const httpHost = config.httpHost || 'localhost'\n\n const dashboardAppUrl = await getDashboardAppURL({\n httpHost,\n httpPort: port,\n organizationId,\n })\n output.log(`Dev server started on port ${port}`)\n output.log(`View your app in the Sanity dashboard here:`)\n output.log(styleText(['blue', 'underline'], dashboardAppUrl))\n }\n\n return {close, server, started: true}\n } catch (err) {\n devDebug('Error starting app dev server', err)\n throw gracefulServerDeath('dev', config.httpHost, config.httpPort, err)\n }\n}\n"],"names":["styleText","isWorkbenchApp","determineIsWorkbenchApp","startDevServer","gracefulServerDeath","devDebug","getDashboardAppURL","getDevServerConfig","startAppDevServer","options","cliConfig","flags","httpPort","output","workbenchAvailable","workDir","app","warn","organizationId","error","exit","reason","started","config","log","appTitle","title","undefined","close","server","isApp","port","httpHost","dashboardAppUrl","err"],"mappings":"AAAA,SAAQA,SAAS,QAAO,YAAW;AAEnC,SAAQC,kBAAkBC,uBAAuB,QAAO,mBAAkB;AAE1E,SAAQC,cAAc,QAAO,+BAA8B;AAC3D,SAAQC,mBAAmB,QAAO,yCAAwC;AAC1E,SAAQC,QAAQ,QAAO,iBAAgB;AAEvC,SAAQC,kBAAkB,QAAO,0BAAyB;AAC1D,SAAQC,kBAAkB,QAAO,0BAAyB;AAE1D,OAAO,eAAeC,kBAAkBC,OAAyB;IAC/D,MAAM,EAACC,SAAS,EAAEC,KAAK,EAAEC,QAAQ,EAAEC,MAAM,EAAEC,kBAAkB,EAAEC,OAAO,EAAC,GAAGN;IAE1E,MAAMR,iBAAiBC,wBAAwBQ,WAAWM;IAE1D,sEAAsE;IACtE,mCAAmC;IACnC,IAAI,CAACf,kBAAkB,CAACU,KAAK,CAAC,oBAAoB,EAAE;QAClDE,OAAOI,IAAI,CAAC,CAAC,4CAA4C,CAAC;QAC1DJ,OAAOI,IAAI,CAAC,CAAC,iEAAiE,CAAC;IACjF;IAEA,IAAIC;IACJ,IAAIR,aAAa,SAASA,aAAaA,UAAUM,GAAG,EAAEE,gBAAgB;QACpEA,iBAAiBR,UAAUM,GAAG,CAACE,cAAc;IAC/C;IAEA,IAAI,CAACA,gBAAgB;QACnBL,OAAOM,KAAK,CAAC,CAAC,4EAA4E,CAAC,EAAE;YAC3FC,MAAM;QACR;QACA,OAAO;YAACC,QAAQ;YAA2BC,SAAS;QAAK;IAC3D;IAEA,MAAMC,SAAShB,mBAAmB;QAACG;QAAWC;QAAOC;QAAUC;QAAQE;IAAO;IAE9E,IAAI;QACFF,OAAOW,GAAG,CAAC;QAEX,MAAMC,WAAWf,aAAa,SAASA,YAAYA,UAAUM,GAAG,EAAEU,QAAQC;QAC1E,MAAM,EAACC,KAAK,EAAEC,MAAM,EAAC,GAAG,MAAM1B,eAAe;YAC3C,GAAGoB,MAAM;YACTE;YACAK,OAAO;QACT;QAEA,MAAM,EAACC,IAAI,EAAC,GAAGF,OAAON,MAAM,CAACM,MAAM;QAEnC,IAAI5B,gBAAgB;YAClB,wEAAwE;YACxE,yEAAyE;YACzE,sEAAsE;YACtE,IAAI,CAACa,oBAAoB;gBACvBD,OAAOW,GAAG,CAAC,CAAC,+BAA+B,EAAEO,MAAM;YACrD;QACF,OAAO;YACL,MAAMC,WAAWT,OAAOS,QAAQ,IAAI;YAEpC,MAAMC,kBAAkB,MAAM3B,mBAAmB;gBAC/C0B;gBACApB,UAAUmB;gBACVb;YACF;YACAL,OAAOW,GAAG,CAAC,CAAC,2BAA2B,EAAEO,MAAM;YAC/ClB,OAAOW,GAAG,CAAC,CAAC,2CAA2C,CAAC;YACxDX,OAAOW,GAAG,CAACxB,UAAU;gBAAC;gBAAQ;aAAY,EAAEiC;QAC9C;QAEA,OAAO;YAACL;YAAOC;YAAQP,SAAS;QAAI;IACtC,EAAE,OAAOY,KAAK;QACZ7B,SAAS,iCAAiC6B;QAC1C,MAAM9B,oBAAoB,OAAOmB,OAAOS,QAAQ,EAAET,OAAOX,QAAQ,EAAEsB;IACrE;AACF"}
1
+ {"version":3,"sources":["../../../../src/actions/dev/servers/startAppDevServer.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {isWorkbenchApp as determineIsWorkbenchApp} from '@sanity/cli-core'\n\nimport {startDevServer} from '../../../server/devServer.js'\nimport {gracefulServerDeath} from '../../../server/gracefulServerDeath.js'\nimport {devDebug} from '../devDebug.js'\nimport {type DevActionOptions, type StartDevServerResult} from '../types.js'\nimport {getDashboardAppURL} from './getDashboardAppUrl.js'\nimport {getDevServerConfig} from './getDevServerConfig.js'\n\n// Bind-only addresses ('0.0.0.0', '::') aren't routable in every browser; the\n// displayed URL falls back to localhost. The bind address itself is untouched.\nfunction toDisplayHost(host: string | undefined): string {\n if (!host || host === '0.0.0.0' || host === '::' || host === '[::]') {\n return 'localhost'\n }\n return host\n}\n\nexport async function startAppDevServer(options: DevActionOptions): Promise<StartDevServerResult> {\n const {announceUrl = true, cliConfig, flags, httpPort, output, workDir} = options\n\n const isWorkbenchApp = determineIsWorkbenchApp(cliConfig?.app)\n\n // Workbench apps don't load through the dashboard, so the flag has no\n // meaning for them and is ignored.\n if (!isWorkbenchApp && !flags['load-in-dashboard']) {\n output.warn(`Apps cannot run without the Sanity dashboard`)\n output.warn(`Starting dev server with the --load-in-dashboard flag set to true`)\n }\n\n let organizationId: string | undefined\n if (cliConfig && 'app' in cliConfig && cliConfig.app?.organizationId) {\n organizationId = cliConfig.app.organizationId\n }\n\n if (!organizationId) {\n output.error(`Apps require an organization ID (orgId) specified in your sanity.cli.ts file`, {\n exit: 1,\n })\n return {reason: 'missing-organization-id', started: false}\n }\n\n const config = getDevServerConfig({cliConfig, flags, httpPort, output, workDir})\n\n try {\n output.log('Starting dev server')\n\n const appTitle = cliConfig && 'app' in cliConfig ? cliConfig.app?.title : undefined\n const {close, server} = await startDevServer({\n ...config,\n appTitle,\n isApp: true,\n })\n\n const {port} = server.config.server\n\n // Federated apps surface through the workbench, which announces the URL;\n // only the package-unavailable fallback announces from here.\n if (isWorkbenchApp && announceUrl) {\n const url = `http://${toDisplayHost(config.httpHost)}:${port}`\n output.log(`App dev server started at ${styleText(['blue', 'underline'], url)}`)\n } else if (!isWorkbenchApp) {\n const httpHost = config.httpHost || 'localhost'\n\n const dashboardAppUrl = await getDashboardAppURL({\n httpHost,\n httpPort: port,\n organizationId,\n })\n output.log(`Dev server started on port ${port}`)\n output.log(`View your app in the Sanity dashboard here:`)\n output.log(styleText(['blue', 'underline'], dashboardAppUrl))\n }\n\n return {close, server, started: true}\n } catch (err) {\n devDebug('Error starting app dev server', err)\n throw gracefulServerDeath('dev', config.httpHost, config.httpPort, err)\n }\n}\n"],"names":["styleText","isWorkbenchApp","determineIsWorkbenchApp","startDevServer","gracefulServerDeath","devDebug","getDashboardAppURL","getDevServerConfig","toDisplayHost","host","startAppDevServer","options","announceUrl","cliConfig","flags","httpPort","output","workDir","app","warn","organizationId","error","exit","reason","started","config","log","appTitle","title","undefined","close","server","isApp","port","url","httpHost","dashboardAppUrl","err"],"mappings":"AAAA,SAAQA,SAAS,QAAO,YAAW;AAEnC,SAAQC,kBAAkBC,uBAAuB,QAAO,mBAAkB;AAE1E,SAAQC,cAAc,QAAO,+BAA8B;AAC3D,SAAQC,mBAAmB,QAAO,yCAAwC;AAC1E,SAAQC,QAAQ,QAAO,iBAAgB;AAEvC,SAAQC,kBAAkB,QAAO,0BAAyB;AAC1D,SAAQC,kBAAkB,QAAO,0BAAyB;AAE1D,8EAA8E;AAC9E,+EAA+E;AAC/E,SAASC,cAAcC,IAAwB;IAC7C,IAAI,CAACA,QAAQA,SAAS,aAAaA,SAAS,QAAQA,SAAS,QAAQ;QACnE,OAAO;IACT;IACA,OAAOA;AACT;AAEA,OAAO,eAAeC,kBAAkBC,OAAyB;IAC/D,MAAM,EAACC,cAAc,IAAI,EAAEC,SAAS,EAAEC,KAAK,EAAEC,QAAQ,EAAEC,MAAM,EAAEC,OAAO,EAAC,GAAGN;IAE1E,MAAMV,iBAAiBC,wBAAwBW,WAAWK;IAE1D,sEAAsE;IACtE,mCAAmC;IACnC,IAAI,CAACjB,kBAAkB,CAACa,KAAK,CAAC,oBAAoB,EAAE;QAClDE,OAAOG,IAAI,CAAC,CAAC,4CAA4C,CAAC;QAC1DH,OAAOG,IAAI,CAAC,CAAC,iEAAiE,CAAC;IACjF;IAEA,IAAIC;IACJ,IAAIP,aAAa,SAASA,aAAaA,UAAUK,GAAG,EAAEE,gBAAgB;QACpEA,iBAAiBP,UAAUK,GAAG,CAACE,cAAc;IAC/C;IAEA,IAAI,CAACA,gBAAgB;QACnBJ,OAAOK,KAAK,CAAC,CAAC,4EAA4E,CAAC,EAAE;YAC3FC,MAAM;QACR;QACA,OAAO;YAACC,QAAQ;YAA2BC,SAAS;QAAK;IAC3D;IAEA,MAAMC,SAASlB,mBAAmB;QAACM;QAAWC;QAAOC;QAAUC;QAAQC;IAAO;IAE9E,IAAI;QACFD,OAAOU,GAAG,CAAC;QAEX,MAAMC,WAAWd,aAAa,SAASA,YAAYA,UAAUK,GAAG,EAAEU,QAAQC;QAC1E,MAAM,EAACC,KAAK,EAAEC,MAAM,EAAC,GAAG,MAAM5B,eAAe;YAC3C,GAAGsB,MAAM;YACTE;YACAK,OAAO;QACT;QAEA,MAAM,EAACC,IAAI,EAAC,GAAGF,OAAON,MAAM,CAACM,MAAM;QAEnC,yEAAyE;QACzE,6DAA6D;QAC7D,IAAI9B,kBAAkBW,aAAa;YACjC,MAAMsB,MAAM,CAAC,OAAO,EAAE1B,cAAciB,OAAOU,QAAQ,EAAE,CAAC,EAAEF,MAAM;YAC9DjB,OAAOU,GAAG,CAAC,CAAC,0BAA0B,EAAE1B,UAAU;gBAAC;gBAAQ;aAAY,EAAEkC,MAAM;QACjF,OAAO,IAAI,CAACjC,gBAAgB;YAC1B,MAAMkC,WAAWV,OAAOU,QAAQ,IAAI;YAEpC,MAAMC,kBAAkB,MAAM9B,mBAAmB;gBAC/C6B;gBACApB,UAAUkB;gBACVb;YACF;YACAJ,OAAOU,GAAG,CAAC,CAAC,2BAA2B,EAAEO,MAAM;YAC/CjB,OAAOU,GAAG,CAAC,CAAC,2CAA2C,CAAC;YACxDV,OAAOU,GAAG,CAAC1B,UAAU;gBAAC;gBAAQ;aAAY,EAAEoC;QAC9C;QAEA,OAAO;YAACN;YAAOC;YAAQP,SAAS;QAAI;IACtC,EAAE,OAAOa,KAAK;QACZhC,SAAS,iCAAiCgC;QAC1C,MAAMjC,oBAAoB,OAAOqB,OAAOU,QAAQ,EAAEV,OAAOV,QAAQ,EAAEsB;IACrE;AACF"}
@@ -15,7 +15,7 @@ import { devDebug } from '../devDebug.js';
15
15
  import { getDashboardAppURL } from './getDashboardAppUrl.js';
16
16
  import { getDevServerConfig } from './getDevServerConfig.js';
17
17
  export async function startStudioDevServer(options) {
18
- const { cliConfig, flags, httpPort, output, workbenchAvailable, workDir } = options;
18
+ const { announceUrl = true, cliConfig, flags, httpPort, output, workDir } = options;
19
19
  const projectId = cliConfig?.api?.projectId;
20
20
  let organizationId;
21
21
  // Workbench apps don't load through the dashboard, so the flag has no
@@ -141,7 +141,7 @@ export async function startStudioDevServer(options) {
141
141
  const appType = 'Sanity Studio';
142
142
  const viteVersion = await getLocalPackageVersion('vite', import.meta.url);
143
143
  spin.succeed();
144
- loggerInfo(`${appType} ` + `using ${styleText('cyan', `vite@${viteVersion}`)} ` + `ready in ${styleText('cyan', `${Math.ceil(startupDuration)}ms`)}` + (workbenchAvailable ? '' : ` and running at ${styleText('cyan', url)}`));
144
+ loggerInfo(`${appType} ` + `using ${styleText('cyan', `vite@${viteVersion}`)} ` + `ready in ${styleText('cyan', `${Math.ceil(startupDuration)}ms`)}` + (announceUrl ? ` and running at ${styleText('cyan', url)}` : ''));
145
145
  }
146
146
  return {
147
147
  close,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/actions/dev/servers/startStudioDevServer.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {\n checkRequiredDependencies,\n checkStudioDependencyVersions,\n} from '@sanity/cli-build/_internal/build'\nimport {getLocalPackageVersion, isInteractive, isWorkbenchApp} from '@sanity/cli-core'\nimport {confirm, logSymbols, spinner} from '@sanity/cli-core/ux'\nimport {parse as semverParse} from 'semver'\n\nimport {startDevServer} from '../../../server/devServer.js'\nimport {gracefulServerDeath} from '../../../server/gracefulServerDeath.js'\nimport {getProjectById} from '../../../services/projects.js'\nimport {getAppId} from '../../../util/appId.js'\nimport {compareDependencyVersions} from '../../../util/compareDependencyVersions.js'\nimport {getPackageManagerChoice} from '../../../util/packageManager/packageManagerChoice.js'\nimport {upgradePackages} from '../../../util/packageManager/upgradePackages.js'\nimport {shouldAutoUpdate} from '../../build/shouldAutoUpdate.js'\nimport {devDebug} from '../devDebug.js'\nimport {type DevActionOptions, type StartDevServerResult} from '../types.js'\nimport {getDashboardAppURL} from './getDashboardAppUrl.js'\nimport {getDevServerConfig} from './getDevServerConfig.js'\n\nexport async function startStudioDevServer(\n options: DevActionOptions,\n): Promise<StartDevServerResult> {\n const {cliConfig, flags, httpPort, output, workbenchAvailable, workDir} = options\n const projectId = cliConfig?.api?.projectId\n let organizationId: string | undefined\n\n // Workbench apps don't load through the dashboard, so the flag has no\n // meaning for them and is ignored.\n const loadInDashboard = flags['load-in-dashboard'] && !isWorkbenchApp(cliConfig?.app)\n\n // Check studio dependency versions\n await checkStudioDependencyVersions(workDir, output)\n\n const {installedSanityVersion} = await checkRequiredDependencies(options)\n\n // Check if auto-updates are enabled\n const autoUpdatesEnabled = shouldAutoUpdate({cliConfig, flags, output})\n\n if (autoUpdatesEnabled) {\n // Get the clean version without build metadata: https://semver.org/#spec-item-10\n const cleanSanityVersion = semverParse(installedSanityVersion)?.version\n if (!cleanSanityVersion) {\n throw new Error(`Failed to parse installed Sanity version: ${installedSanityVersion}`)\n }\n\n const sanityDependencies = [\n {name: 'sanity', version: cleanSanityVersion},\n {name: '@sanity/vision', version: cleanSanityVersion},\n ]\n\n output.log(`${logSymbols.info} Running with auto-updates enabled`)\n\n // Check local versions against deployed versions\n let result: Awaited<ReturnType<typeof compareDependencyVersions>> | undefined\n\n const appId = getAppId(cliConfig)\n\n try {\n result = await compareDependencyVersions(sanityDependencies, workDir, {appId})\n } catch (err) {\n output.warn(`Failed to compare local versions against auto-updating versions: ${err}`)\n }\n\n if (result?.unresolvedPrerelease.length) {\n for (const mod of result.unresolvedPrerelease) {\n output.warn(\n `Your local version of ${mod.pkg} (${mod.version}) is a prerelease not available on the auto-updates CDN. The locally installed version will be used.`,\n )\n }\n }\n\n // mismatch between local and auto-updating dependencies\n if (result?.mismatched.length) {\n const message =\n `The following local package versions are different from the versions currently served at runtime.\\n` +\n `When using auto updates, we recommend that you run with the same versions locally as will be used when deploying.\\n\\n` +\n `${result.mismatched.map((mod) => ` - ${mod.pkg} (local version: ${mod.installed}, runtime version: ${mod.remote})`).join('\\n')}\\n\\n`\n\n if (isInteractive()) {\n const shouldUpgrade = await confirm({\n default: true,\n message: styleText('yellow', `${message}Do you want to upgrade local versions?`),\n })\n if (shouldUpgrade) {\n await upgradePackages(\n {\n packageManager: (await getPackageManagerChoice(workDir, {interactive: false})).chosen,\n packages: result.mismatched.map((res) => [res.pkg, res.remote]),\n },\n {output, workDir},\n )\n }\n } else {\n // In this case we warn the user but we don't ask them if they want to upgrade because it's not interactive.\n output.log(styleText('yellow', message))\n }\n }\n }\n\n if (cliConfig?.schemaExtraction?.enabled) {\n output.log(`${logSymbols.info} Running dev server with schema extraction enabled`)\n }\n\n const config = getDevServerConfig({cliConfig, flags, httpPort, output, workDir})\n\n if (loadInDashboard) {\n if (!projectId) {\n output.error('Project Id is required to load in dashboard', {exit: 1})\n }\n\n try {\n const project = await getProjectById(projectId!)\n organizationId = project.organizationId!\n } catch (error) {\n devDebug('Error getting organization id from project id', error)\n output.error('Failed to get organization id from project id', {exit: 1})\n }\n }\n\n try {\n const startTime = Date.now()\n const spin = spinner('Starting dev server').start()\n const {close, server} = await startDevServer(config)\n\n const {info: loggerInfo} = server.config.logger\n const {port} = server.config.server\n const httpHost = config.httpHost || 'localhost'\n\n if (loadInDashboard) {\n spin.succeed()\n\n output.log(`Dev server started on port ${port}`)\n output.log(`View your studio in the Sanity dashboard here:`)\n output.log(\n styleText(\n ['blue', 'underline'],\n await getDashboardAppURL({\n httpHost,\n httpPort: port,\n organizationId: organizationId!,\n }),\n ),\n )\n } else {\n const startupDuration = Date.now() - startTime\n const url = `http://${httpHost || 'localhost'}:${port}${config.basePath}`\n const appType = 'Sanity Studio'\n\n const viteVersion = await getLocalPackageVersion('vite', import.meta.url)\n spin.succeed()\n\n loggerInfo(\n `${appType} ` +\n `using ${styleText('cyan', `vite@${viteVersion}`)} ` +\n `ready in ${styleText('cyan', `${Math.ceil(startupDuration)}ms`)}` +\n (workbenchAvailable ? '' : ` and running at ${styleText('cyan', url)}`),\n )\n }\n\n return {close, server, started: true}\n } catch (err) {\n devDebug('Error starting studio dev server', err)\n throw gracefulServerDeath('dev', config.httpHost, config.httpPort, err)\n }\n}\n"],"names":["styleText","checkRequiredDependencies","checkStudioDependencyVersions","getLocalPackageVersion","isInteractive","isWorkbenchApp","confirm","logSymbols","spinner","parse","semverParse","startDevServer","gracefulServerDeath","getProjectById","getAppId","compareDependencyVersions","getPackageManagerChoice","upgradePackages","shouldAutoUpdate","devDebug","getDashboardAppURL","getDevServerConfig","startStudioDevServer","options","cliConfig","flags","httpPort","output","workbenchAvailable","workDir","projectId","api","organizationId","loadInDashboard","app","installedSanityVersion","autoUpdatesEnabled","cleanSanityVersion","version","Error","sanityDependencies","name","log","info","result","appId","err","warn","unresolvedPrerelease","length","mod","pkg","mismatched","message","map","installed","remote","join","shouldUpgrade","default","packageManager","interactive","chosen","packages","res","schemaExtraction","enabled","config","error","exit","project","startTime","Date","now","spin","start","close","server","loggerInfo","logger","port","httpHost","succeed","startupDuration","url","basePath","appType","viteVersion","Math","ceil","started"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../src/actions/dev/servers/startStudioDevServer.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {\n checkRequiredDependencies,\n checkStudioDependencyVersions,\n} from '@sanity/cli-build/_internal/build'\nimport {getLocalPackageVersion, isInteractive, isWorkbenchApp} from '@sanity/cli-core'\nimport {confirm, logSymbols, spinner} from '@sanity/cli-core/ux'\nimport {parse as semverParse} from 'semver'\n\nimport {startDevServer} from '../../../server/devServer.js'\nimport {gracefulServerDeath} from '../../../server/gracefulServerDeath.js'\nimport {getProjectById} from '../../../services/projects.js'\nimport {getAppId} from '../../../util/appId.js'\nimport {compareDependencyVersions} from '../../../util/compareDependencyVersions.js'\nimport {getPackageManagerChoice} from '../../../util/packageManager/packageManagerChoice.js'\nimport {upgradePackages} from '../../../util/packageManager/upgradePackages.js'\nimport {shouldAutoUpdate} from '../../build/shouldAutoUpdate.js'\nimport {devDebug} from '../devDebug.js'\nimport {type DevActionOptions, type StartDevServerResult} from '../types.js'\nimport {getDashboardAppURL} from './getDashboardAppUrl.js'\nimport {getDevServerConfig} from './getDevServerConfig.js'\n\nexport async function startStudioDevServer(\n options: DevActionOptions,\n): Promise<StartDevServerResult> {\n const {announceUrl = true, cliConfig, flags, httpPort, output, workDir} = options\n const projectId = cliConfig?.api?.projectId\n let organizationId: string | undefined\n\n // Workbench apps don't load through the dashboard, so the flag has no\n // meaning for them and is ignored.\n const loadInDashboard = flags['load-in-dashboard'] && !isWorkbenchApp(cliConfig?.app)\n\n // Check studio dependency versions\n await checkStudioDependencyVersions(workDir, output)\n\n const {installedSanityVersion} = await checkRequiredDependencies(options)\n\n // Check if auto-updates are enabled\n const autoUpdatesEnabled = shouldAutoUpdate({cliConfig, flags, output})\n\n if (autoUpdatesEnabled) {\n // Get the clean version without build metadata: https://semver.org/#spec-item-10\n const cleanSanityVersion = semverParse(installedSanityVersion)?.version\n if (!cleanSanityVersion) {\n throw new Error(`Failed to parse installed Sanity version: ${installedSanityVersion}`)\n }\n\n const sanityDependencies = [\n {name: 'sanity', version: cleanSanityVersion},\n {name: '@sanity/vision', version: cleanSanityVersion},\n ]\n\n output.log(`${logSymbols.info} Running with auto-updates enabled`)\n\n // Check local versions against deployed versions\n let result: Awaited<ReturnType<typeof compareDependencyVersions>> | undefined\n\n const appId = getAppId(cliConfig)\n\n try {\n result = await compareDependencyVersions(sanityDependencies, workDir, {appId})\n } catch (err) {\n output.warn(`Failed to compare local versions against auto-updating versions: ${err}`)\n }\n\n if (result?.unresolvedPrerelease.length) {\n for (const mod of result.unresolvedPrerelease) {\n output.warn(\n `Your local version of ${mod.pkg} (${mod.version}) is a prerelease not available on the auto-updates CDN. The locally installed version will be used.`,\n )\n }\n }\n\n // mismatch between local and auto-updating dependencies\n if (result?.mismatched.length) {\n const message =\n `The following local package versions are different from the versions currently served at runtime.\\n` +\n `When using auto updates, we recommend that you run with the same versions locally as will be used when deploying.\\n\\n` +\n `${result.mismatched.map((mod) => ` - ${mod.pkg} (local version: ${mod.installed}, runtime version: ${mod.remote})`).join('\\n')}\\n\\n`\n\n if (isInteractive()) {\n const shouldUpgrade = await confirm({\n default: true,\n message: styleText('yellow', `${message}Do you want to upgrade local versions?`),\n })\n if (shouldUpgrade) {\n await upgradePackages(\n {\n packageManager: (await getPackageManagerChoice(workDir, {interactive: false})).chosen,\n packages: result.mismatched.map((res) => [res.pkg, res.remote]),\n },\n {output, workDir},\n )\n }\n } else {\n // In this case we warn the user but we don't ask them if they want to upgrade because it's not interactive.\n output.log(styleText('yellow', message))\n }\n }\n }\n\n if (cliConfig?.schemaExtraction?.enabled) {\n output.log(`${logSymbols.info} Running dev server with schema extraction enabled`)\n }\n\n const config = getDevServerConfig({cliConfig, flags, httpPort, output, workDir})\n\n if (loadInDashboard) {\n if (!projectId) {\n output.error('Project Id is required to load in dashboard', {exit: 1})\n }\n\n try {\n const project = await getProjectById(projectId!)\n organizationId = project.organizationId!\n } catch (error) {\n devDebug('Error getting organization id from project id', error)\n output.error('Failed to get organization id from project id', {exit: 1})\n }\n }\n\n try {\n const startTime = Date.now()\n const spin = spinner('Starting dev server').start()\n const {close, server} = await startDevServer(config)\n\n const {info: loggerInfo} = server.config.logger\n const {port} = server.config.server\n const httpHost = config.httpHost || 'localhost'\n\n if (loadInDashboard) {\n spin.succeed()\n\n output.log(`Dev server started on port ${port}`)\n output.log(`View your studio in the Sanity dashboard here:`)\n output.log(\n styleText(\n ['blue', 'underline'],\n await getDashboardAppURL({\n httpHost,\n httpPort: port,\n organizationId: organizationId!,\n }),\n ),\n )\n } else {\n const startupDuration = Date.now() - startTime\n const url = `http://${httpHost || 'localhost'}:${port}${config.basePath}`\n const appType = 'Sanity Studio'\n\n const viteVersion = await getLocalPackageVersion('vite', import.meta.url)\n spin.succeed()\n\n loggerInfo(\n `${appType} ` +\n `using ${styleText('cyan', `vite@${viteVersion}`)} ` +\n `ready in ${styleText('cyan', `${Math.ceil(startupDuration)}ms`)}` +\n (announceUrl ? ` and running at ${styleText('cyan', url)}` : ''),\n )\n }\n\n return {close, server, started: true}\n } catch (err) {\n devDebug('Error starting studio dev server', err)\n throw gracefulServerDeath('dev', config.httpHost, config.httpPort, err)\n }\n}\n"],"names":["styleText","checkRequiredDependencies","checkStudioDependencyVersions","getLocalPackageVersion","isInteractive","isWorkbenchApp","confirm","logSymbols","spinner","parse","semverParse","startDevServer","gracefulServerDeath","getProjectById","getAppId","compareDependencyVersions","getPackageManagerChoice","upgradePackages","shouldAutoUpdate","devDebug","getDashboardAppURL","getDevServerConfig","startStudioDevServer","options","announceUrl","cliConfig","flags","httpPort","output","workDir","projectId","api","organizationId","loadInDashboard","app","installedSanityVersion","autoUpdatesEnabled","cleanSanityVersion","version","Error","sanityDependencies","name","log","info","result","appId","err","warn","unresolvedPrerelease","length","mod","pkg","mismatched","message","map","installed","remote","join","shouldUpgrade","default","packageManager","interactive","chosen","packages","res","schemaExtraction","enabled","config","error","exit","project","startTime","Date","now","spin","start","close","server","loggerInfo","logger","port","httpHost","succeed","startupDuration","url","basePath","appType","viteVersion","Math","ceil","started"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/dev/types.ts"],"sourcesContent":["import {type CliConfig, type Output} from '@sanity/cli-core'\nimport {type ViteDevServer} from 'vite'\n\nimport {type DevCommand} from '../../commands/dev.js'\n\nexport type DevFlags = DevCommand['flags']\n\nexport interface DevActionOptions {\n cliConfig: CliConfig\n flags: DevFlags\n isApp: boolean\n output: Output\n workDir: string\n\n /**\n * Port the app/studio dev server should bind. `devAction` sets it when a\n * running workbench has claimed the configured port; otherwise it stays\n * absent and the server resolves its port from flags/env/config.\n */\n httpPort?: number\n\n workbenchAvailable?: boolean\n}\n\n/**\n * Result of starting an app/studio dev server. Discriminated on `started` so\n * callers handle the didn't-start case explicitly instead of null-checking\n * optional fields. A server that fails to *boot* still throws — the\n * not-started arm is reserved for expected early exits the server has\n * already reported to the user.\n */\nexport type StartDevServerResult =\n | {close: () => Promise<void>; server: ViteDevServer; started: true}\n | {reason: 'missing-organization-id'; started: false}\n"],"names":[],"mappings":"AAwBA;;;;;;CAMC,GACD,WAEuD"}
1
+ {"version":3,"sources":["../../../src/actions/dev/types.ts"],"sourcesContent":["import {type CliConfig, type Output} from '@sanity/cli-core'\nimport {type ViteDevServer} from 'vite'\n\nimport {type DevCommand} from '../../commands/dev.js'\n\nexport type DevFlags = DevCommand['flags']\n\nexport interface DevActionOptions {\n cliConfig: CliConfig\n flags: DevFlags\n isApp: boolean\n output: Output\n workDir: string\n\n /** Announce the server's own URL on startup; `false` when the workbench announces it instead (default `true`). */\n announceUrl?: boolean\n\n /**\n * Port the app/studio dev server should bind. `devAction` sets it when a\n * running workbench has claimed the configured port; otherwise it stays\n * absent and the server resolves its port from flags/env/config.\n */\n httpPort?: number\n}\n\n/**\n * Result of starting an app/studio dev server. Discriminated on `started` so\n * callers handle the didn't-start case explicitly instead of null-checking\n * optional fields. A server that fails to *boot* still throws — the\n * not-started arm is reserved for expected early exits the server has\n * already reported to the user.\n */\nexport type StartDevServerResult =\n | {close: () => Promise<void>; server: ViteDevServer; started: true}\n | {reason: 'missing-organization-id'; started: false}\n"],"names":[],"mappings":"AAyBA;;;;;;CAMC,GACD,WAEuD"}
@@ -1,8 +1,8 @@
1
1
  import { readFile } from 'node:fs/promises';
2
2
  import { join, resolve } from 'node:path';
3
3
  import { SANITY_CACHE_DIR } from '@sanity/cli-build/_internal/build';
4
- import { extractManifest } from '../../manifest/extractManifest.js';
5
- import { MANIFEST_FILENAME } from '../../manifest/writeManifestFile.js';
4
+ import { extractManifest } from './extractManifest.js';
5
+ import { MANIFEST_FILENAME } from './writeManifestFile.js';
6
6
  /**
7
7
  * Dev-time manifest output directory, relative to the studio working
8
8
  * directory. Sibling of Vite's `cacheDir` so it stays out of `dist` and is
@@ -27,4 +27,4 @@ import { MANIFEST_FILENAME } from '../../manifest/writeManifestFile.js';
27
27
  return JSON.parse(raw);
28
28
  }
29
29
 
30
- //# sourceMappingURL=extractDevServerManifest.js.map
30
+ //# sourceMappingURL=extractStudioManifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/actions/manifest/extractStudioManifest.ts"],"sourcesContent":["import {readFile} from 'node:fs/promises'\nimport {join, resolve} from 'node:path'\n\nimport {SANITY_CACHE_DIR} from '@sanity/cli-build/_internal/build'\n\nimport {extractManifest} from './extractManifest.js'\nimport {type StudioManifest} from './types.js'\nimport {MANIFEST_FILENAME} from './writeManifestFile.js'\n\n/**\n * Dev-time manifest output directory, relative to the studio working\n * directory. Sibling of Vite's `cacheDir` so it stays out of `dist` and is\n * ignored by default in typical `.gitignore` files.\n */\nconst MANIFEST_DIR = `${SANITY_CACHE_DIR}/manifest`\n\n/**\n * Run the worker-based studio schema extraction, write the resulting manifest\n * to `MANIFEST_DIR`, then read it back so the caller can inline it into the\n * registry.\n *\n * `configPath` must be the resolved `sanity.config.(ts|js)` path — passing it\n * in (e.g. from `findProjectRoot`) avoids re-traversing the filesystem on\n * every call.\n */\nexport async function extractStudioManifest(options: {\n configPath: string\n workDir: string\n}): Promise<StudioManifest | undefined> {\n const outPath = resolve(options.workDir, MANIFEST_DIR)\n await extractManifest({outPath, path: options.configPath, workDir: options.workDir})\n const raw = await readFile(join(outPath, MANIFEST_FILENAME), 'utf8')\n return JSON.parse(raw)\n}\n"],"names":["readFile","join","resolve","SANITY_CACHE_DIR","extractManifest","MANIFEST_FILENAME","MANIFEST_DIR","extractStudioManifest","options","outPath","workDir","path","configPath","raw","JSON","parse"],"mappings":"AAAA,SAAQA,QAAQ,QAAO,mBAAkB;AACzC,SAAQC,IAAI,EAAEC,OAAO,QAAO,YAAW;AAEvC,SAAQC,gBAAgB,QAAO,oCAAmC;AAElE,SAAQC,eAAe,QAAO,uBAAsB;AAEpD,SAAQC,iBAAiB,QAAO,yBAAwB;AAExD;;;;CAIC,GACD,MAAMC,eAAe,GAAGH,iBAAiB,SAAS,CAAC;AAEnD;;;;;;;;CAQC,GACD,OAAO,eAAeI,sBAAsBC,OAG3C;IACC,MAAMC,UAAUP,QAAQM,QAAQE,OAAO,EAAEJ;IACzC,MAAMF,gBAAgB;QAACK;QAASE,MAAMH,QAAQI,UAAU;QAAEF,SAASF,QAAQE,OAAO;IAAA;IAClF,MAAMG,MAAM,MAAMb,SAASC,KAAKQ,SAASJ,oBAAoB;IAC7D,OAAOS,KAAKC,KAAK,CAACF;AACpB"}
@@ -188,13 +188,16 @@ function buildClineServerConfig(token) {
188
188
  };
189
189
  }
190
190
  function buildCodexCliServerConfig(token) {
191
- return {
192
- http_headers: {
193
- Authorization: `Bearer ${token}`
194
- },
191
+ const config = {
195
192
  type: 'http',
196
193
  url: MCP_SERVER_URL
197
194
  };
195
+ if (token) {
196
+ config.http_headers = {
197
+ Authorization: `Bearer ${token}`
198
+ };
199
+ }
200
+ return config;
198
201
  }
199
202
  function buildGitHubCopilotCliServerConfig(token) {
200
203
  return {
@@ -274,6 +277,7 @@ function buildZedServerConfig(token) {
274
277
  configKey: 'mcp_servers',
275
278
  detect: detectCodexCli,
276
279
  format: 'toml',
280
+ oauthOnly: true,
277
281
  readToken: readTokenFromHttpHeaders,
278
282
  skillsCliAgent: 'codex'
279
283
  },