@sanity/cli 7.2.3 → 7.3.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.
- package/bin/run.js +3 -12
- package/dist/actions/auth/authServer.js +37 -20
- package/dist/actions/auth/authServer.js.map +1 -1
- package/dist/actions/backup/assertDatasetExist.js +3 -3
- package/dist/actions/backup/assertDatasetExist.js.map +1 -1
- package/dist/actions/build/buildApp.js +15 -5
- package/dist/actions/build/buildApp.js.map +1 -1
- package/dist/actions/build/buildStaticFiles.js +57 -5
- package/dist/actions/build/buildStaticFiles.js.map +1 -1
- package/dist/actions/build/buildStudio.js +13 -5
- package/dist/actions/build/buildStudio.js.map +1 -1
- package/dist/actions/build/handlePrereleaseVersions.js +2 -2
- package/dist/actions/build/handlePrereleaseVersions.js.map +1 -1
- package/dist/actions/dataset/resolveDataset.js +2 -2
- package/dist/actions/dataset/resolveDataset.js.map +1 -1
- package/dist/actions/deploy/deployApp.js +43 -5
- package/dist/actions/deploy/deployApp.js.map +1 -1
- package/dist/actions/deploy/deployStudio.js +14 -2
- package/dist/actions/deploy/deployStudio.js.map +1 -1
- package/dist/actions/deploy/viewDeployment.js +32 -0
- package/dist/actions/deploy/viewDeployment.js.map +1 -0
- package/dist/actions/dev/devAction.js +219 -4
- package/dist/actions/dev/devAction.js.map +1 -1
- package/dist/actions/dev/registration/deriveInterfaces.js +46 -0
- package/dist/actions/dev/registration/deriveInterfaces.js.map +1 -0
- package/dist/actions/dev/registration/extractDevServerManifest.js +30 -0
- package/dist/actions/dev/registration/extractDevServerManifest.js.map +1 -0
- package/dist/actions/dev/registration/interfaceSetId.js +41 -0
- package/dist/actions/dev/registration/interfaceSetId.js.map +1 -0
- package/dist/actions/dev/registration/startDevManifestWatcher.js +104 -0
- package/dist/actions/dev/registration/startDevManifestWatcher.js.map +1 -0
- package/dist/actions/dev/registration/startDevServerRegistration.js +121 -0
- package/dist/actions/dev/registration/startDevServerRegistration.js.map +1 -0
- package/dist/actions/dev/servers/getDashboardAppUrl.js.map +1 -0
- package/dist/actions/dev/servers/getDevServerConfig.js +45 -0
- package/dist/actions/dev/servers/getDevServerConfig.js.map +1 -0
- package/dist/actions/dev/servers/startAppDevServer.js +78 -0
- package/dist/actions/dev/servers/startAppDevServer.js.map +1 -0
- package/dist/actions/dev/{startStudioDevServer.js → servers/startStudioDevServer.js} +20 -16
- package/dist/actions/dev/servers/startStudioDevServer.js.map +1 -0
- package/dist/actions/dev/types.js +7 -1
- package/dist/actions/dev/types.js.map +1 -1
- package/dist/actions/dev/workbench/startWorkbenchDevServer.js +276 -0
- package/dist/actions/dev/workbench/startWorkbenchDevServer.js.map +1 -0
- package/dist/actions/dev/workbench/writeWorkbenchRuntime.js +66 -0
- package/dist/actions/dev/workbench/writeWorkbenchRuntime.js.map +1 -0
- package/dist/actions/init/bootstrapLocalTemplate.js +15 -3
- package/dist/actions/init/bootstrapLocalTemplate.js.map +1 -1
- package/dist/actions/init/bootstrapTemplate.js +3 -2
- package/dist/actions/init/bootstrapTemplate.js.map +1 -1
- package/dist/actions/init/createAppCliConfig.js +5 -2
- package/dist/actions/init/createAppCliConfig.js.map +1 -1
- package/dist/actions/init/createCliConfig.js +5 -3
- package/dist/actions/init/createCliConfig.js.map +1 -1
- package/dist/actions/init/createStudioConfig.js.map +1 -1
- package/dist/actions/init/initAction.js +11 -4
- package/dist/actions/init/initAction.js.map +1 -1
- package/dist/actions/init/initApp.js +2 -1
- package/dist/actions/init/initApp.js.map +1 -1
- package/dist/actions/init/initStudio.js +2 -1
- package/dist/actions/init/initStudio.js.map +1 -1
- package/dist/actions/init/scaffoldTemplate.js +3 -2
- package/dist/actions/init/scaffoldTemplate.js.map +1 -1
- package/dist/actions/init/templates/pageBuilder.js +1 -1
- package/dist/actions/init/templates/pageBuilder.js.map +1 -1
- package/dist/actions/init/types.js +1 -0
- package/dist/actions/init/types.js.map +1 -1
- package/dist/actions/manifest/{extractAppManifest.js → extractCoreAppManifest.js} +30 -11
- package/dist/actions/manifest/extractCoreAppManifest.js.map +1 -0
- package/dist/actions/manifest/extractManifest.js +7 -7
- package/dist/actions/manifest/extractManifest.js.map +1 -1
- package/dist/actions/manifest/iconResolver.js +2 -3
- package/dist/actions/manifest/iconResolver.js.map +1 -1
- package/dist/actions/manifest/sanitizeIcon.js +13 -0
- package/dist/actions/manifest/sanitizeIcon.js.map +1 -0
- package/dist/actions/manifest/types.js +4 -9
- package/dist/actions/manifest/types.js.map +1 -1
- package/dist/actions/manifest/writeManifestFile.js +1 -1
- package/dist/actions/manifest/writeManifestFile.js.map +1 -1
- package/dist/actions/mcp/editorConfigs.js +26 -2
- package/dist/actions/mcp/editorConfigs.js.map +1 -1
- package/dist/actions/mcp/setupMCP.js +24 -25
- package/dist/actions/mcp/setupMCP.js.map +1 -1
- package/dist/actions/mcp/types.js.map +1 -1
- package/dist/actions/skills/configureSkills.js +49 -0
- package/dist/actions/skills/configureSkills.js.map +1 -0
- package/dist/actions/skills/readSkillState.js +40 -5
- package/dist/actions/skills/readSkillState.js.map +1 -1
- package/dist/actions/skills/setupSkills.js +47 -6
- package/dist/actions/skills/setupSkills.js.map +1 -1
- package/dist/actions/skills/skillCandidates.js +40 -0
- package/dist/actions/skills/skillCandidates.js.map +1 -0
- package/dist/actions/telemetry/telemetryDisclosure.js +2 -3
- package/dist/actions/telemetry/telemetryDisclosure.js.map +1 -1
- package/dist/actions/tokens/validateRole.js +3 -3
- package/dist/actions/tokens/validateRole.js.map +1 -1
- package/dist/commands/backups/disable.js +1 -1
- package/dist/commands/backups/disable.js.map +1 -1
- package/dist/commands/backups/download.js +1 -1
- package/dist/commands/backups/download.js.map +1 -1
- package/dist/commands/backups/enable.js +1 -1
- package/dist/commands/backups/enable.js.map +1 -1
- package/dist/commands/backups/list.js +1 -1
- package/dist/commands/backups/list.js.map +1 -1
- package/dist/commands/datasets/embeddings/disable.js +1 -0
- package/dist/commands/datasets/embeddings/disable.js.map +1 -1
- package/dist/commands/datasets/embeddings/enable.js +1 -0
- package/dist/commands/datasets/embeddings/enable.js.map +1 -1
- package/dist/commands/datasets/embeddings/status.js +1 -0
- package/dist/commands/datasets/embeddings/status.js.map +1 -1
- package/dist/commands/dev.js +11 -1
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/init.js +7 -0
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/manifest/extract.js +7 -2
- package/dist/commands/manifest/extract.js.map +1 -1
- package/dist/commands/mcp/configure.js +1 -0
- package/dist/commands/mcp/configure.js.map +1 -1
- package/dist/commands/skills/install.js +40 -0
- package/dist/commands/skills/install.js.map +1 -0
- package/dist/commands/tokens/add.js +1 -1
- package/dist/commands/tokens/add.js.map +1 -1
- package/dist/exports/index.d.ts +6 -0
- package/dist/exports/index.js +8 -0
- package/dist/exports/index.js.map +1 -1
- package/dist/exports/runtime.d.ts +41 -0
- package/dist/exports/runtime.js +13 -0
- package/dist/exports/runtime.js.map +1 -0
- package/dist/hooks/prerun/setupTelemetry.js +3 -1
- package/dist/hooks/prerun/setupTelemetry.js.map +1 -1
- package/dist/server/devServer.js +8 -3
- package/dist/server/devServer.js.map +1 -1
- package/dist/services/documents.js +0 -1
- package/dist/services/documents.js.map +1 -1
- package/dist/telemetry/skills.telemetry.js +8 -0
- package/dist/telemetry/skills.telemetry.js.map +1 -0
- package/dist/util/compareDependencyVersions.js +1 -1
- package/dist/util/compareDependencyVersions.js.map +1 -1
- package/dist/util/determineIsApp.js +12 -1
- package/dist/util/determineIsApp.js.map +1 -1
- package/dist/util/getSharedServerConfig.js +2 -1
- package/dist/util/getSharedServerConfig.js.map +1 -1
- package/dist/util/resolveReactStrictMode.js +11 -0
- package/dist/util/resolveReactStrictMode.js.map +1 -0
- package/oclif.config.js +2 -1
- package/oclif.manifest.json +146 -113
- package/package.json +26 -17
- package/templates/page-builder/schemaTypes/index.js +1 -1
- package/dist/actions/build/checkRequiredDependencies.js +0 -124
- package/dist/actions/build/checkRequiredDependencies.js.map +0 -1
- package/dist/actions/build/getAutoUpdatesImportMap.js +0 -66
- package/dist/actions/build/getAutoUpdatesImportMap.js.map +0 -1
- package/dist/actions/dev/getDashboardAppUrl.js.map +0 -1
- package/dist/actions/dev/getDevServerConfig.js +0 -32
- package/dist/actions/dev/getDevServerConfig.js.map +0 -1
- package/dist/actions/dev/startAppDevServer.js +0 -59
- package/dist/actions/dev/startAppDevServer.js.map +0 -1
- package/dist/actions/dev/startStudioDevServer.js.map +0 -1
- package/dist/actions/manifest/extractAppManifest.js.map +0 -1
- /package/dist/actions/dev/{getDashboardAppUrl.js → servers/getDashboardAppUrl.js} +0 -0
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
import { SANITY_CACHE_DIR } from '@sanity/cli-build/_internal/build';
|
|
2
|
+
import { isWorkbenchApp, resolveLocalPackage } from '@sanity/cli-core';
|
|
3
|
+
import { acquireWorkbenchLock, getRegisteredServers, readWorkbenchLock, watchRegistry } from '@sanity/workbench-cli/dev';
|
|
4
|
+
import viteReact from '@vitejs/plugin-react';
|
|
5
|
+
import { createServer } from 'vite';
|
|
6
|
+
import { z } from 'zod/mini';
|
|
7
|
+
import { resolveReactStrictMode } from '../../../util/resolveReactStrictMode.js';
|
|
8
|
+
import { devDebug } from '../devDebug.js';
|
|
9
|
+
import { interfaceSetId } from '../registration/interfaceSetId.js';
|
|
10
|
+
import { writeWorkbenchRuntime } from './writeWorkbenchRuntime.js';
|
|
11
|
+
const noop = async ()=>{};
|
|
12
|
+
/** Stable per-app key for the registry-watch interface diff. */ const serverKey = (s)=>`${s.id ?? ''}@${s.host ?? ''}:${s.port}`;
|
|
13
|
+
const toApplicationsPayload = (servers)=>({
|
|
14
|
+
applications: servers.map(({ host, id, interfaces, manifest, port, projectId, type })=>({
|
|
15
|
+
host,
|
|
16
|
+
id,
|
|
17
|
+
interfaces,
|
|
18
|
+
manifest,
|
|
19
|
+
port,
|
|
20
|
+
projectId,
|
|
21
|
+
type
|
|
22
|
+
}))
|
|
23
|
+
});
|
|
24
|
+
/**
|
|
25
|
+
* Start the workbench dev server when federation is enabled and the workbench
|
|
26
|
+
* package is available. If the desired port is already taken — by another
|
|
27
|
+
* workbench instance or an unrelated process — fall back to running without a
|
|
28
|
+
* workbench and let the app/studio dev server claim the configured port.
|
|
29
|
+
*/ export async function startWorkbenchDevServer(options) {
|
|
30
|
+
const { cliConfig, httpHost, httpPort: workbenchPort, output, workDir } = options;
|
|
31
|
+
// Workbench is opted into solely by calling `unstable_defineApp`.
|
|
32
|
+
if (!isWorkbenchApp(cliConfig?.app)) {
|
|
33
|
+
devDebug('Not a workbench app, skipping workbench dev server');
|
|
34
|
+
return {
|
|
35
|
+
close: noop,
|
|
36
|
+
httpHost,
|
|
37
|
+
workbenchAvailable: false,
|
|
38
|
+
workbenchPort
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
let workbenchAvailable = false;
|
|
42
|
+
try {
|
|
43
|
+
await resolveLocalPackage('sanity/workbench', workDir);
|
|
44
|
+
workbenchAvailable = true;
|
|
45
|
+
} catch {
|
|
46
|
+
devDebug('Workbench not available, skipping workbench dev server');
|
|
47
|
+
}
|
|
48
|
+
if (!workbenchAvailable) {
|
|
49
|
+
return {
|
|
50
|
+
close: noop,
|
|
51
|
+
httpHost,
|
|
52
|
+
workbenchAvailable,
|
|
53
|
+
workbenchPort
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
// Acquire an exclusive lock — only one workbench per machine.
|
|
57
|
+
// Uses O_EXCL which is atomic at the OS level, preventing races when
|
|
58
|
+
// multiple `sanity dev` processes start simultaneously (e.g. via turbo).
|
|
59
|
+
const workbenchLock = acquireWorkbenchLock({
|
|
60
|
+
host: httpHost || 'localhost',
|
|
61
|
+
port: workbenchPort
|
|
62
|
+
});
|
|
63
|
+
if (!workbenchLock) {
|
|
64
|
+
const existing = readWorkbenchLock();
|
|
65
|
+
devDebug('Workbench already running at pid %d on port %d, skipping', existing?.pid, existing?.port);
|
|
66
|
+
return {
|
|
67
|
+
close: noop,
|
|
68
|
+
httpHost: existing?.host ?? httpHost,
|
|
69
|
+
workbenchAvailable: true,
|
|
70
|
+
workbenchPort: existing?.port ?? workbenchPort
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
// The lock is already held; an exception here (runtime-file write failure,
|
|
74
|
+
// invalid remote URL) would otherwise leak it until the next acquire prunes
|
|
75
|
+
// the stale PID.
|
|
76
|
+
let result;
|
|
77
|
+
try {
|
|
78
|
+
result = await createWorkbenchViteServer({
|
|
79
|
+
cliConfig,
|
|
80
|
+
httpHost,
|
|
81
|
+
output,
|
|
82
|
+
workbenchPort,
|
|
83
|
+
workDir
|
|
84
|
+
});
|
|
85
|
+
} catch (err) {
|
|
86
|
+
workbenchLock.release();
|
|
87
|
+
throw err;
|
|
88
|
+
}
|
|
89
|
+
if (!result) {
|
|
90
|
+
workbenchLock.release();
|
|
91
|
+
return {
|
|
92
|
+
close: noop,
|
|
93
|
+
httpHost,
|
|
94
|
+
workbenchAvailable: false,
|
|
95
|
+
workbenchPort
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
const { actualPort, close } = result;
|
|
99
|
+
workbenchLock.updatePort(actualPort);
|
|
100
|
+
return {
|
|
101
|
+
close: async ()=>{
|
|
102
|
+
workbenchLock.release();
|
|
103
|
+
await close();
|
|
104
|
+
},
|
|
105
|
+
httpHost,
|
|
106
|
+
workbenchAvailable,
|
|
107
|
+
workbenchPort: actualPort
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
async function createWorkbenchViteServer(options) {
|
|
111
|
+
const { cliConfig, httpHost, output, workbenchPort, workDir } = options;
|
|
112
|
+
const remoteUrl = parseRemoteUrl(process.env.SANITY_INTERNAL_WORKBENCH_REMOTE_URL);
|
|
113
|
+
// The workbench runtime template needs a concrete boolean (it has no studio
|
|
114
|
+
// default to defer to), so collapse an unset config to off.
|
|
115
|
+
const reactStrictMode = resolveReactStrictMode(cliConfig) ?? false;
|
|
116
|
+
const organizationId = resolveOrganizationId(cliConfig);
|
|
117
|
+
devDebug('Writing workbench runtime files');
|
|
118
|
+
const root = await writeWorkbenchRuntime({
|
|
119
|
+
cwd: workDir,
|
|
120
|
+
organizationId,
|
|
121
|
+
reactStrictMode,
|
|
122
|
+
remoteUrl
|
|
123
|
+
});
|
|
124
|
+
const viteConfig = {
|
|
125
|
+
// Custom cache directory so sanity's vite cache doesn't conflict with local vite projects
|
|
126
|
+
cacheDir: `${SANITY_CACHE_DIR}/vite`,
|
|
127
|
+
configFile: false,
|
|
128
|
+
define: {
|
|
129
|
+
__SANITY_STAGING__: process.env.SANITY_INTERNAL_ENV === 'staging',
|
|
130
|
+
'import.meta.env.SANITY_INTERNAL_WORKBENCH_REMOTE_URL': JSON.stringify(remoteUrl)
|
|
131
|
+
},
|
|
132
|
+
logLevel: 'warn',
|
|
133
|
+
mode: 'development',
|
|
134
|
+
optimizeDeps: {
|
|
135
|
+
// Exclude sanity/workbench (and its transitive dep @sanity/workbench)
|
|
136
|
+
// from dep pre-bundling so that `import.meta.hot` is available at
|
|
137
|
+
// runtime — pre-bundled modules do not receive Vite's HMR client
|
|
138
|
+
// injection, which causes the custom HMR events for local application
|
|
139
|
+
// discovery to silently not fire.
|
|
140
|
+
exclude: [
|
|
141
|
+
'sanity',
|
|
142
|
+
'@sanity/workbench'
|
|
143
|
+
]
|
|
144
|
+
},
|
|
145
|
+
// viteReact looks inert here — it transforms none of the host's own modules —
|
|
146
|
+
// but it's load-bearing for the remotes. It serves the Fast Refresh runtime at
|
|
147
|
+
// /@react-refresh and injects the preamble that defines window.$RefreshReg$. The
|
|
148
|
+
// federated remotes loaded into this page are react-refresh transformed, so
|
|
149
|
+
// without the preamble they throw "can't detect preamble", and without the
|
|
150
|
+
// runtime their /@react-refresh import (wired by @module-federation/vite's
|
|
151
|
+
// remoteHmr) fails. Dropping it as dead code broke every panel; see #1262.
|
|
152
|
+
plugins: [
|
|
153
|
+
viteReact(),
|
|
154
|
+
...remoteUrl ? [
|
|
155
|
+
remoteManifestPreloadHeaderPlugin(remoteUrl)
|
|
156
|
+
] : []
|
|
157
|
+
],
|
|
158
|
+
resolve: {
|
|
159
|
+
dedupe: [
|
|
160
|
+
'react',
|
|
161
|
+
'react-dom'
|
|
162
|
+
]
|
|
163
|
+
},
|
|
164
|
+
root,
|
|
165
|
+
server: {
|
|
166
|
+
host: httpHost,
|
|
167
|
+
port: workbenchPort,
|
|
168
|
+
strictPort: false,
|
|
169
|
+
warmup: {
|
|
170
|
+
clientFiles: [
|
|
171
|
+
'./workbench.js'
|
|
172
|
+
]
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
devDebug('Creating workbench vite server');
|
|
177
|
+
const server = await createServer(viteConfig);
|
|
178
|
+
try {
|
|
179
|
+
await server.listen();
|
|
180
|
+
} catch (err) {
|
|
181
|
+
await server.close();
|
|
182
|
+
output.warn(`Workbench dev server failed to start: ${err instanceof Error ? err.message : String(err)}`);
|
|
183
|
+
return undefined;
|
|
184
|
+
}
|
|
185
|
+
// Vite may have picked a different port if the desired one was occupied
|
|
186
|
+
const addr = server.httpServer?.address();
|
|
187
|
+
const actualPort = typeof addr === 'object' && addr ? addr.port : workbenchPort;
|
|
188
|
+
// Fire-and-forget: warm the workbench remote's Vite transform pipeline so
|
|
189
|
+
// the first browser request hits a pre-populated module graph.
|
|
190
|
+
if (remoteUrl) {
|
|
191
|
+
fetch(remoteUrl).then((r)=>r.body?.cancel()).catch(()=>{});
|
|
192
|
+
devDebug('Warming workbench remote at %s', remoteUrl);
|
|
193
|
+
}
|
|
194
|
+
server.ws.on('sanity:workbench:get-local-applications', (_, client)=>{
|
|
195
|
+
client.send('sanity:workbench:local-applications', toApplicationsPayload(getRegisteredServers()));
|
|
196
|
+
});
|
|
197
|
+
// A running app's declared interface set changing (a view/service added or
|
|
198
|
+
// removed in `sanity.cli.ts`) means its remote was rebuilt with new exposes.
|
|
199
|
+
// Module federation has the old remote-entry cached, so an in-place reconcile
|
|
200
|
+
// would load a stale remote (empty panel / no worker) — the page must reload
|
|
201
|
+
// to re-fetch it. A new/removed app, or a manifest-only edit (title/icon),
|
|
202
|
+
// reconciles softly as before. Source-file edits don't change the set, so they
|
|
203
|
+
// stay on the HMR path and never trip a reload here.
|
|
204
|
+
let knownInterfaces = new Map();
|
|
205
|
+
const registryWatcher = watchRegistry((servers)=>{
|
|
206
|
+
const rebuiltApp = servers.some((s)=>{
|
|
207
|
+
const key = serverKey(s);
|
|
208
|
+
return knownInterfaces.has(key) && knownInterfaces.get(key) !== interfaceSetId(s.interfaces);
|
|
209
|
+
});
|
|
210
|
+
knownInterfaces = new Map(servers.map((s)=>[
|
|
211
|
+
serverKey(s),
|
|
212
|
+
interfaceSetId(s.interfaces)
|
|
213
|
+
]));
|
|
214
|
+
if (rebuiltApp) {
|
|
215
|
+
server.ws.send({
|
|
216
|
+
type: 'full-reload'
|
|
217
|
+
});
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
server.ws.send('sanity:workbench:local-applications', toApplicationsPayload(servers));
|
|
221
|
+
});
|
|
222
|
+
return {
|
|
223
|
+
actualPort,
|
|
224
|
+
close: async ()=>{
|
|
225
|
+
registryWatcher.close();
|
|
226
|
+
await server.close();
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
// Workbench is opted into via `unstable_defineApp`, which carries the
|
|
231
|
+
// organization ID. Deliberately no fallback (e.g. resolving it from the
|
|
232
|
+
// configured project): the lookup would need an authenticated user and an
|
|
233
|
+
// API round-trip on every startup for something the opt-in already declares.
|
|
234
|
+
const resolveOrganizationId = (cliConfig)=>{
|
|
235
|
+
if (cliConfig.app?.organizationId) {
|
|
236
|
+
return cliConfig.app.organizationId;
|
|
237
|
+
}
|
|
238
|
+
throw new Error('Workbench requires an organization ID. Pass "organizationId" to unstable_defineApp() in sanity.cli.ts.');
|
|
239
|
+
};
|
|
240
|
+
// Restricts protocol to http(s) so the URL is safe to interpolate into HTML
|
|
241
|
+
// attributes and Link headers downstream.
|
|
242
|
+
const remoteUrlSchema = z.url({
|
|
243
|
+
normalize: true,
|
|
244
|
+
protocol: /^https?$/
|
|
245
|
+
});
|
|
246
|
+
function parseRemoteUrl(value) {
|
|
247
|
+
if (!value) return undefined;
|
|
248
|
+
const result = remoteUrlSchema.safeParse(value);
|
|
249
|
+
if (!result.success) {
|
|
250
|
+
throw new Error(`Invalid SANITY_INTERNAL_WORKBENCH_REMOTE_URL: ${value} (must be an http(s) URL)`);
|
|
251
|
+
}
|
|
252
|
+
return result.data;
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Sets a `Link: <remoteUrl>; rel=preload; as=fetch; crossorigin` response header
|
|
256
|
+
* on the index document so the browser can start fetching the Module Federation
|
|
257
|
+
* manifest as soon as response headers arrive — before HTML parsing reaches the
|
|
258
|
+
* in-head preconnect hint. `as=fetch` matches how the federation runtime later
|
|
259
|
+
* retrieves the JSON manifest, allowing the preload entry to satisfy that fetch.
|
|
260
|
+
*/ function remoteManifestPreloadHeaderPlugin(remoteUrl) {
|
|
261
|
+
return {
|
|
262
|
+
apply: 'serve',
|
|
263
|
+
configureServer (server) {
|
|
264
|
+
server.middlewares.use((req, res, next)=>{
|
|
265
|
+
const pathname = (req.url || '/').split('?')[0];
|
|
266
|
+
if (pathname === '/' || pathname === '/index.html') {
|
|
267
|
+
res.setHeader('Link', `<${remoteUrl}>; rel=preload; as=fetch; crossorigin`);
|
|
268
|
+
}
|
|
269
|
+
next();
|
|
270
|
+
});
|
|
271
|
+
},
|
|
272
|
+
name: 'sanity:workbench-remote-preload-header'
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
//# sourceMappingURL=startWorkbenchDevServer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/actions/dev/workbench/startWorkbenchDevServer.ts"],"sourcesContent":["import {SANITY_CACHE_DIR} from '@sanity/cli-build/_internal/build'\nimport {isWorkbenchApp, resolveLocalPackage} from '@sanity/cli-core'\nimport {\n acquireWorkbenchLock,\n type DevServerManifest,\n getRegisteredServers,\n readWorkbenchLock,\n watchRegistry,\n} from '@sanity/workbench-cli/dev'\nimport viteReact from '@vitejs/plugin-react'\nimport {createServer, type InlineConfig, type Plugin} from 'vite'\nimport {z} from 'zod/mini'\n\nimport {resolveReactStrictMode} from '../../../util/resolveReactStrictMode.js'\nimport {devDebug} from '../devDebug.js'\nimport {interfaceSetId} from '../registration/interfaceSetId.js'\nimport {type DevActionOptions} from '../types.js'\nimport {writeWorkbenchRuntime} from './writeWorkbenchRuntime.js'\n\nconst noop = async () => {}\n\n/** Stable per-app key for the registry-watch interface diff. */\nconst serverKey = (s: DevServerManifest) => `${s.id ?? ''}@${s.host ?? ''}:${s.port}`\n\nconst toApplicationsPayload = (servers: DevServerManifest[]) => ({\n applications: servers.map(({host, id, interfaces, manifest, port, projectId, type}) => ({\n host,\n id,\n interfaces,\n manifest,\n port,\n projectId,\n type,\n })),\n})\n\ninterface WorkbenchDevServerResult {\n close: () => Promise<void>\n httpHost: string | undefined\n workbenchAvailable: boolean\n workbenchPort: number\n}\n\nexport interface StartWorkbenchOptions extends DevActionOptions {\n httpHost: string | undefined\n httpPort: number\n}\n\n/**\n * Start the workbench dev server when federation is enabled and the workbench\n * package is available. If the desired port is already taken — by another\n * workbench instance or an unrelated process — fall back to running without a\n * workbench and let the app/studio dev server claim the configured port.\n */\nexport async function startWorkbenchDevServer(\n options: StartWorkbenchOptions,\n): Promise<WorkbenchDevServerResult> {\n const {cliConfig, httpHost, httpPort: workbenchPort, output, workDir} = options\n\n // Workbench is opted into solely by calling `unstable_defineApp`.\n if (!isWorkbenchApp(cliConfig?.app)) {\n devDebug('Not a workbench app, skipping workbench dev server')\n return {close: noop, httpHost, workbenchAvailable: false, workbenchPort}\n }\n\n let workbenchAvailable = false\n\n try {\n await resolveLocalPackage('sanity/workbench', workDir)\n workbenchAvailable = true\n } catch {\n devDebug('Workbench not available, skipping workbench dev server')\n }\n\n if (!workbenchAvailable) {\n return {close: noop, httpHost, workbenchAvailable, workbenchPort}\n }\n\n // Acquire an exclusive lock — only one workbench per machine.\n // Uses O_EXCL which is atomic at the OS level, preventing races when\n // multiple `sanity dev` processes start simultaneously (e.g. via turbo).\n const workbenchLock = acquireWorkbenchLock({host: httpHost || 'localhost', port: workbenchPort})\n if (!workbenchLock) {\n const existing = readWorkbenchLock()\n devDebug(\n 'Workbench already running at pid %d on port %d, skipping',\n existing?.pid,\n existing?.port,\n )\n return {\n close: noop,\n httpHost: existing?.host ?? httpHost,\n workbenchAvailable: true,\n workbenchPort: existing?.port ?? workbenchPort,\n }\n }\n\n // The lock is already held; an exception here (runtime-file write failure,\n // invalid remote URL) would otherwise leak it until the next acquire prunes\n // the stale PID.\n let result: Awaited<ReturnType<typeof createWorkbenchViteServer>>\n try {\n result = await createWorkbenchViteServer({\n cliConfig,\n httpHost,\n output,\n workbenchPort,\n workDir,\n })\n } catch (err) {\n workbenchLock.release()\n throw err\n }\n\n if (!result) {\n workbenchLock.release()\n return {close: noop, httpHost, workbenchAvailable: false, workbenchPort}\n }\n\n const {actualPort, close} = result\n workbenchLock.updatePort(actualPort)\n\n return {\n close: async () => {\n workbenchLock.release()\n await close()\n },\n httpHost,\n workbenchAvailable,\n workbenchPort: actualPort,\n }\n}\n\ninterface CreateWorkbenchViteServerOptions {\n cliConfig: DevActionOptions['cliConfig']\n httpHost: string | undefined\n output: DevActionOptions['output']\n workbenchPort: number\n workDir: string\n}\n\ninterface CreateWorkbenchViteServerResult {\n actualPort: number\n close: () => Promise<void>\n}\n\nasync function createWorkbenchViteServer(\n options: CreateWorkbenchViteServerOptions,\n): Promise<CreateWorkbenchViteServerResult | undefined> {\n const {cliConfig, httpHost, output, workbenchPort, workDir} = options\n\n const remoteUrl = parseRemoteUrl(process.env.SANITY_INTERNAL_WORKBENCH_REMOTE_URL)\n // The workbench runtime template needs a concrete boolean (it has no studio\n // default to defer to), so collapse an unset config to off.\n const reactStrictMode = resolveReactStrictMode(cliConfig) ?? false\n\n const organizationId = resolveOrganizationId(cliConfig)\n\n devDebug('Writing workbench runtime files')\n const root = await writeWorkbenchRuntime({\n cwd: workDir,\n organizationId,\n reactStrictMode,\n remoteUrl,\n })\n\n const viteConfig: InlineConfig = {\n // Custom cache directory so sanity's vite cache doesn't conflict with local vite projects\n cacheDir: `${SANITY_CACHE_DIR}/vite`,\n configFile: false,\n define: {\n __SANITY_STAGING__: process.env.SANITY_INTERNAL_ENV === 'staging',\n 'import.meta.env.SANITY_INTERNAL_WORKBENCH_REMOTE_URL': JSON.stringify(remoteUrl),\n },\n logLevel: 'warn',\n mode: 'development',\n optimizeDeps: {\n // Exclude sanity/workbench (and its transitive dep @sanity/workbench)\n // from dep pre-bundling so that `import.meta.hot` is available at\n // runtime — pre-bundled modules do not receive Vite's HMR client\n // injection, which causes the custom HMR events for local application\n // discovery to silently not fire.\n exclude: ['sanity', '@sanity/workbench'],\n },\n // viteReact looks inert here — it transforms none of the host's own modules —\n // but it's load-bearing for the remotes. It serves the Fast Refresh runtime at\n // /@react-refresh and injects the preamble that defines window.$RefreshReg$. The\n // federated remotes loaded into this page are react-refresh transformed, so\n // without the preamble they throw \"can't detect preamble\", and without the\n // runtime their /@react-refresh import (wired by @module-federation/vite's\n // remoteHmr) fails. Dropping it as dead code broke every panel; see #1262.\n plugins: [viteReact(), ...(remoteUrl ? [remoteManifestPreloadHeaderPlugin(remoteUrl)] : [])],\n resolve: {dedupe: ['react', 'react-dom']},\n root,\n server: {\n host: httpHost,\n port: workbenchPort,\n strictPort: false,\n warmup: {\n clientFiles: ['./workbench.js'],\n },\n },\n }\n\n devDebug('Creating workbench vite server')\n const server = await createServer(viteConfig)\n try {\n await server.listen()\n } catch (err) {\n await server.close()\n output.warn(\n `Workbench dev server failed to start: ${err instanceof Error ? err.message : String(err)}`,\n )\n return undefined\n }\n\n // Vite may have picked a different port if the desired one was occupied\n const addr = server.httpServer?.address()\n const actualPort = typeof addr === 'object' && addr ? addr.port : workbenchPort\n\n // Fire-and-forget: warm the workbench remote's Vite transform pipeline so\n // the first browser request hits a pre-populated module graph.\n if (remoteUrl) {\n fetch(remoteUrl)\n .then((r) => r.body?.cancel())\n .catch(() => {})\n devDebug('Warming workbench remote at %s', remoteUrl)\n }\n\n server.ws.on('sanity:workbench:get-local-applications', (_, client) => {\n client.send(\n 'sanity:workbench:local-applications',\n toApplicationsPayload(getRegisteredServers()),\n )\n })\n\n // A running app's declared interface set changing (a view/service added or\n // removed in `sanity.cli.ts`) means its remote was rebuilt with new exposes.\n // Module federation has the old remote-entry cached, so an in-place reconcile\n // would load a stale remote (empty panel / no worker) — the page must reload\n // to re-fetch it. A new/removed app, or a manifest-only edit (title/icon),\n // reconciles softly as before. Source-file edits don't change the set, so they\n // stay on the HMR path and never trip a reload here.\n let knownInterfaces = new Map<string, string>()\n const registryWatcher = watchRegistry((servers) => {\n const rebuiltApp = servers.some((s) => {\n const key = serverKey(s)\n return knownInterfaces.has(key) && knownInterfaces.get(key) !== interfaceSetId(s.interfaces)\n })\n knownInterfaces = new Map(servers.map((s) => [serverKey(s), interfaceSetId(s.interfaces)]))\n\n if (rebuiltApp) {\n server.ws.send({type: 'full-reload'})\n return\n }\n server.ws.send('sanity:workbench:local-applications', toApplicationsPayload(servers))\n })\n\n return {\n actualPort,\n close: async () => {\n registryWatcher.close()\n await server.close()\n },\n }\n}\n\n// Workbench is opted into via `unstable_defineApp`, which carries the\n// organization ID. Deliberately no fallback (e.g. resolving it from the\n// configured project): the lookup would need an authenticated user and an\n// API round-trip on every startup for something the opt-in already declares.\nconst resolveOrganizationId = (cliConfig: DevActionOptions['cliConfig']): string => {\n if (cliConfig.app?.organizationId) {\n return cliConfig.app.organizationId\n }\n\n throw new Error(\n 'Workbench requires an organization ID. Pass \"organizationId\" to unstable_defineApp() in sanity.cli.ts.',\n )\n}\n\n// Restricts protocol to http(s) so the URL is safe to interpolate into HTML\n// attributes and Link headers downstream.\nconst remoteUrlSchema = z.url({normalize: true, protocol: /^https?$/})\n\nfunction parseRemoteUrl(value: string | undefined): string | undefined {\n if (!value) return undefined\n\n const result = remoteUrlSchema.safeParse(value)\n\n if (!result.success) {\n throw new Error(\n `Invalid SANITY_INTERNAL_WORKBENCH_REMOTE_URL: ${value} (must be an http(s) URL)`,\n )\n }\n\n return result.data\n}\n\n/**\n * Sets a `Link: <remoteUrl>; rel=preload; as=fetch; crossorigin` response header\n * on the index document so the browser can start fetching the Module Federation\n * manifest as soon as response headers arrive — before HTML parsing reaches the\n * in-head preconnect hint. `as=fetch` matches how the federation runtime later\n * retrieves the JSON manifest, allowing the preload entry to satisfy that fetch.\n */\nfunction remoteManifestPreloadHeaderPlugin(remoteUrl: string): Plugin {\n return {\n apply: 'serve',\n configureServer(server) {\n server.middlewares.use((req, res, next) => {\n const pathname = (req.url || '/').split('?')[0]\n if (pathname === '/' || pathname === '/index.html') {\n res.setHeader('Link', `<${remoteUrl}>; rel=preload; as=fetch; crossorigin`)\n }\n next()\n })\n },\n name: 'sanity:workbench-remote-preload-header',\n }\n}\n"],"names":["SANITY_CACHE_DIR","isWorkbenchApp","resolveLocalPackage","acquireWorkbenchLock","getRegisteredServers","readWorkbenchLock","watchRegistry","viteReact","createServer","z","resolveReactStrictMode","devDebug","interfaceSetId","writeWorkbenchRuntime","noop","serverKey","s","id","host","port","toApplicationsPayload","servers","applications","map","interfaces","manifest","projectId","type","startWorkbenchDevServer","options","cliConfig","httpHost","httpPort","workbenchPort","output","workDir","app","close","workbenchAvailable","workbenchLock","existing","pid","result","createWorkbenchViteServer","err","release","actualPort","updatePort","remoteUrl","parseRemoteUrl","process","env","SANITY_INTERNAL_WORKBENCH_REMOTE_URL","reactStrictMode","organizationId","resolveOrganizationId","root","cwd","viteConfig","cacheDir","configFile","define","__SANITY_STAGING__","SANITY_INTERNAL_ENV","JSON","stringify","logLevel","mode","optimizeDeps","exclude","plugins","remoteManifestPreloadHeaderPlugin","resolve","dedupe","server","strictPort","warmup","clientFiles","listen","warn","Error","message","String","undefined","addr","httpServer","address","fetch","then","r","body","cancel","catch","ws","on","_","client","send","knownInterfaces","Map","registryWatcher","rebuiltApp","some","key","has","get","remoteUrlSchema","url","normalize","protocol","value","safeParse","success","data","apply","configureServer","middlewares","use","req","res","next","pathname","split","setHeader","name"],"mappings":"AAAA,SAAQA,gBAAgB,QAAO,oCAAmC;AAClE,SAAQC,cAAc,EAAEC,mBAAmB,QAAO,mBAAkB;AACpE,SACEC,oBAAoB,EAEpBC,oBAAoB,EACpBC,iBAAiB,EACjBC,aAAa,QACR,4BAA2B;AAClC,OAAOC,eAAe,uBAAsB;AAC5C,SAAQC,YAAY,QAAuC,OAAM;AACjE,SAAQC,CAAC,QAAO,WAAU;AAE1B,SAAQC,sBAAsB,QAAO,0CAAyC;AAC9E,SAAQC,QAAQ,QAAO,iBAAgB;AACvC,SAAQC,cAAc,QAAO,oCAAmC;AAEhE,SAAQC,qBAAqB,QAAO,6BAA4B;AAEhE,MAAMC,OAAO,WAAa;AAE1B,8DAA8D,GAC9D,MAAMC,YAAY,CAACC,IAAyB,GAAGA,EAAEC,EAAE,IAAI,GAAG,CAAC,EAAED,EAAEE,IAAI,IAAI,GAAG,CAAC,EAAEF,EAAEG,IAAI,EAAE;AAErF,MAAMC,wBAAwB,CAACC,UAAkC,CAAA;QAC/DC,cAAcD,QAAQE,GAAG,CAAC,CAAC,EAACL,IAAI,EAAED,EAAE,EAAEO,UAAU,EAAEC,QAAQ,EAAEN,IAAI,EAAEO,SAAS,EAAEC,IAAI,EAAC,GAAM,CAAA;gBACtFT;gBACAD;gBACAO;gBACAC;gBACAN;gBACAO;gBACAC;YACF,CAAA;IACF,CAAA;AAcA;;;;;CAKC,GACD,OAAO,eAAeC,wBACpBC,OAA8B;IAE9B,MAAM,EAACC,SAAS,EAAEC,QAAQ,EAAEC,UAAUC,aAAa,EAAEC,MAAM,EAAEC,OAAO,EAAC,GAAGN;IAExE,kEAAkE;IAClE,IAAI,CAAC5B,eAAe6B,WAAWM,MAAM;QACnCzB,SAAS;QACT,OAAO;YAAC0B,OAAOvB;YAAMiB;YAAUO,oBAAoB;YAAOL;QAAa;IACzE;IAEA,IAAIK,qBAAqB;IAEzB,IAAI;QACF,MAAMpC,oBAAoB,oBAAoBiC;QAC9CG,qBAAqB;IACvB,EAAE,OAAM;QACN3B,SAAS;IACX;IAEA,IAAI,CAAC2B,oBAAoB;QACvB,OAAO;YAACD,OAAOvB;YAAMiB;YAAUO;YAAoBL;QAAa;IAClE;IAEA,8DAA8D;IAC9D,qEAAqE;IACrE,yEAAyE;IACzE,MAAMM,gBAAgBpC,qBAAqB;QAACe,MAAMa,YAAY;QAAaZ,MAAMc;IAAa;IAC9F,IAAI,CAACM,eAAe;QAClB,MAAMC,WAAWnC;QACjBM,SACE,4DACA6B,UAAUC,KACVD,UAAUrB;QAEZ,OAAO;YACLkB,OAAOvB;YACPiB,UAAUS,UAAUtB,QAAQa;YAC5BO,oBAAoB;YACpBL,eAAeO,UAAUrB,QAAQc;QACnC;IACF;IAEA,2EAA2E;IAC3E,4EAA4E;IAC5E,iBAAiB;IACjB,IAAIS;IACJ,IAAI;QACFA,SAAS,MAAMC,0BAA0B;YACvCb;YACAC;YACAG;YACAD;YACAE;QACF;IACF,EAAE,OAAOS,KAAK;QACZL,cAAcM,OAAO;QACrB,MAAMD;IACR;IAEA,IAAI,CAACF,QAAQ;QACXH,cAAcM,OAAO;QACrB,OAAO;YAACR,OAAOvB;YAAMiB;YAAUO,oBAAoB;YAAOL;QAAa;IACzE;IAEA,MAAM,EAACa,UAAU,EAAET,KAAK,EAAC,GAAGK;IAC5BH,cAAcQ,UAAU,CAACD;IAEzB,OAAO;QACLT,OAAO;YACLE,cAAcM,OAAO;YACrB,MAAMR;QACR;QACAN;QACAO;QACAL,eAAea;IACjB;AACF;AAeA,eAAeH,0BACbd,OAAyC;IAEzC,MAAM,EAACC,SAAS,EAAEC,QAAQ,EAAEG,MAAM,EAAED,aAAa,EAAEE,OAAO,EAAC,GAAGN;IAE9D,MAAMmB,YAAYC,eAAeC,QAAQC,GAAG,CAACC,oCAAoC;IACjF,4EAA4E;IAC5E,4DAA4D;IAC5D,MAAMC,kBAAkB3C,uBAAuBoB,cAAc;IAE7D,MAAMwB,iBAAiBC,sBAAsBzB;IAE7CnB,SAAS;IACT,MAAM6C,OAAO,MAAM3C,sBAAsB;QACvC4C,KAAKtB;QACLmB;QACAD;QACAL;IACF;IAEA,MAAMU,aAA2B;QAC/B,0FAA0F;QAC1FC,UAAU,GAAG3D,iBAAiB,KAAK,CAAC;QACpC4D,YAAY;QACZC,QAAQ;YACNC,oBAAoBZ,QAAQC,GAAG,CAACY,mBAAmB,KAAK;YACxD,wDAAwDC,KAAKC,SAAS,CAACjB;QACzE;QACAkB,UAAU;QACVC,MAAM;QACNC,cAAc;YACZ,sEAAsE;YACtE,kEAAkE;YAClE,iEAAiE;YACjE,sEAAsE;YACtE,kCAAkC;YAClCC,SAAS;gBAAC;gBAAU;aAAoB;QAC1C;QACA,8EAA8E;QAC9E,+EAA+E;QAC/E,iFAAiF;QACjF,4EAA4E;QAC5E,2EAA2E;QAC3E,2EAA2E;QAC3E,2EAA2E;QAC3EC,SAAS;YAAC/D;eAAiByC,YAAY;gBAACuB,kCAAkCvB;aAAW,GAAG,EAAE;SAAE;QAC5FwB,SAAS;YAACC,QAAQ;gBAAC;gBAAS;aAAY;QAAA;QACxCjB;QACAkB,QAAQ;YACNxD,MAAMa;YACNZ,MAAMc;YACN0C,YAAY;YACZC,QAAQ;gBACNC,aAAa;oBAAC;iBAAiB;YACjC;QACF;IACF;IAEAlE,SAAS;IACT,MAAM+D,SAAS,MAAMlE,aAAakD;IAClC,IAAI;QACF,MAAMgB,OAAOI,MAAM;IACrB,EAAE,OAAOlC,KAAK;QACZ,MAAM8B,OAAOrC,KAAK;QAClBH,OAAO6C,IAAI,CACT,CAAC,sCAAsC,EAAEnC,eAAeoC,QAAQpC,IAAIqC,OAAO,GAAGC,OAAOtC,MAAM;QAE7F,OAAOuC;IACT;IAEA,wEAAwE;IACxE,MAAMC,OAAOV,OAAOW,UAAU,EAAEC;IAChC,MAAMxC,aAAa,OAAOsC,SAAS,YAAYA,OAAOA,KAAKjE,IAAI,GAAGc;IAElE,0EAA0E;IAC1E,+DAA+D;IAC/D,IAAIe,WAAW;QACbuC,MAAMvC,WACHwC,IAAI,CAAC,CAACC,IAAMA,EAAEC,IAAI,EAAEC,UACpBC,KAAK,CAAC,KAAO;QAChBjF,SAAS,kCAAkCqC;IAC7C;IAEA0B,OAAOmB,EAAE,CAACC,EAAE,CAAC,2CAA2C,CAACC,GAAGC;QAC1DA,OAAOC,IAAI,CACT,uCACA7E,sBAAsBhB;IAE1B;IAEA,2EAA2E;IAC3E,6EAA6E;IAC7E,8EAA8E;IAC9E,6EAA6E;IAC7E,2EAA2E;IAC3E,+EAA+E;IAC/E,qDAAqD;IACrD,IAAI8F,kBAAkB,IAAIC;IAC1B,MAAMC,kBAAkB9F,cAAc,CAACe;QACrC,MAAMgF,aAAahF,QAAQiF,IAAI,CAAC,CAACtF;YAC/B,MAAMuF,MAAMxF,UAAUC;YACtB,OAAOkF,gBAAgBM,GAAG,CAACD,QAAQL,gBAAgBO,GAAG,CAACF,SAAS3F,eAAeI,EAAEQ,UAAU;QAC7F;QACA0E,kBAAkB,IAAIC,IAAI9E,QAAQE,GAAG,CAAC,CAACP,IAAM;gBAACD,UAAUC;gBAAIJ,eAAeI,EAAEQ,UAAU;aAAE;QAEzF,IAAI6E,YAAY;YACd3B,OAAOmB,EAAE,CAACI,IAAI,CAAC;gBAACtE,MAAM;YAAa;YACnC;QACF;QACA+C,OAAOmB,EAAE,CAACI,IAAI,CAAC,uCAAuC7E,sBAAsBC;IAC9E;IAEA,OAAO;QACLyB;QACAT,OAAO;YACL+D,gBAAgB/D,KAAK;YACrB,MAAMqC,OAAOrC,KAAK;QACpB;IACF;AACF;AAEA,sEAAsE;AACtE,wEAAwE;AACxE,0EAA0E;AAC1E,6EAA6E;AAC7E,MAAMkB,wBAAwB,CAACzB;IAC7B,IAAIA,UAAUM,GAAG,EAAEkB,gBAAgB;QACjC,OAAOxB,UAAUM,GAAG,CAACkB,cAAc;IACrC;IAEA,MAAM,IAAI0B,MACR;AAEJ;AAEA,4EAA4E;AAC5E,0CAA0C;AAC1C,MAAM0B,kBAAkBjG,EAAEkG,GAAG,CAAC;IAACC,WAAW;IAAMC,UAAU;AAAU;AAEpE,SAAS5D,eAAe6D,KAAyB;IAC/C,IAAI,CAACA,OAAO,OAAO3B;IAEnB,MAAMzC,SAASgE,gBAAgBK,SAAS,CAACD;IAEzC,IAAI,CAACpE,OAAOsE,OAAO,EAAE;QACnB,MAAM,IAAIhC,MACR,CAAC,8CAA8C,EAAE8B,MAAM,yBAAyB,CAAC;IAErF;IAEA,OAAOpE,OAAOuE,IAAI;AACpB;AAEA;;;;;;CAMC,GACD,SAAS1C,kCAAkCvB,SAAiB;IAC1D,OAAO;QACLkE,OAAO;QACPC,iBAAgBzC,MAAM;YACpBA,OAAO0C,WAAW,CAACC,GAAG,CAAC,CAACC,KAAKC,KAAKC;gBAChC,MAAMC,WAAW,AAACH,CAAAA,IAAIX,GAAG,IAAI,GAAE,EAAGe,KAAK,CAAC,IAAI,CAAC,EAAE;gBAC/C,IAAID,aAAa,OAAOA,aAAa,eAAe;oBAClDF,IAAII,SAAS,CAAC,QAAQ,CAAC,CAAC,EAAE3E,UAAU,qCAAqC,CAAC;gBAC5E;gBACAwE;YACF;QACF;QACAI,MAAM;IACR;AACF"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { devDebug } from '../devDebug.js';
|
|
4
|
+
const workbenchJsTemplate = `\
|
|
5
|
+
// This file is auto-generated on 'sanity dev'
|
|
6
|
+
// Modifications to this file are automatically discarded
|
|
7
|
+
import {renderWorkbench} from "sanity/workbench"
|
|
8
|
+
|
|
9
|
+
renderWorkbench(
|
|
10
|
+
document.getElementById("workbench"),
|
|
11
|
+
{organizationId: %SANITY_WORKBENCH_ORGANIZATION_ID%},
|
|
12
|
+
{reactStrictMode: %SANITY_WORKBENCH_REACT_STRICT_MODE%}
|
|
13
|
+
)
|
|
14
|
+
`;
|
|
15
|
+
const indexHtmlTemplate = `\
|
|
16
|
+
<!DOCTYPE html>
|
|
17
|
+
<!-- This file is auto-generated on 'sanity dev' -->
|
|
18
|
+
<!-- Modifications to this file are automatically discarded -->
|
|
19
|
+
<html>
|
|
20
|
+
<head>
|
|
21
|
+
<meta charset="UTF-8" />
|
|
22
|
+
%SANITY_WORKBENCH_PREFETCH_HINTS%
|
|
23
|
+
</head>
|
|
24
|
+
<body>
|
|
25
|
+
<div id="workbench"></div>
|
|
26
|
+
<script type="module" src="./workbench.js"></script>
|
|
27
|
+
</body>
|
|
28
|
+
</html>
|
|
29
|
+
`;
|
|
30
|
+
/**
|
|
31
|
+
* Generates the `.sanity/workbench` directory with static entry files for
|
|
32
|
+
* the workbench Vite dev server.
|
|
33
|
+
*
|
|
34
|
+
* @param cwd - Current working directory (Sanity root dir)
|
|
35
|
+
* @returns The absolute path to the written workbench runtime directory
|
|
36
|
+
* @internal
|
|
37
|
+
*/ export async function writeWorkbenchRuntime(options) {
|
|
38
|
+
const { cwd, organizationId, reactStrictMode, remoteUrl } = options;
|
|
39
|
+
const workbenchDir = path.join(cwd, '.sanity', 'workbench');
|
|
40
|
+
const workbenchJs = workbenchJsTemplate.replace(/%SANITY_WORKBENCH_ORGANIZATION_ID%/, organizationId === undefined ? 'undefined' : JSON.stringify(organizationId)).replace(/%SANITY_WORKBENCH_REACT_STRICT_MODE%/, JSON.stringify(reactStrictMode));
|
|
41
|
+
const prefetchHints = buildPrefetchHints(remoteUrl);
|
|
42
|
+
const indexHtml = indexHtmlTemplate.replace(/%SANITY_WORKBENCH_PREFETCH_HINTS%/, prefetchHints);
|
|
43
|
+
devDebug('Making workbench runtime directory');
|
|
44
|
+
await fs.mkdir(workbenchDir, {
|
|
45
|
+
recursive: true
|
|
46
|
+
});
|
|
47
|
+
devDebug('Writing workbench.js to workbench runtime directory');
|
|
48
|
+
await fs.writeFile(path.join(workbenchDir, 'workbench.js'), workbenchJs);
|
|
49
|
+
devDebug('Writing index.html to workbench runtime directory');
|
|
50
|
+
await fs.writeFile(path.join(workbenchDir, 'index.html'), indexHtml);
|
|
51
|
+
return workbenchDir;
|
|
52
|
+
}
|
|
53
|
+
function buildPrefetchHints(remoteUrl) {
|
|
54
|
+
if (!remoteUrl) return '';
|
|
55
|
+
try {
|
|
56
|
+
const url = new URL(remoteUrl);
|
|
57
|
+
return [
|
|
58
|
+
` <link rel="preconnect" href="${url.origin}" />`,
|
|
59
|
+
` <link rel="preload" as="fetch" href="${url.toString()}" crossorigin />`
|
|
60
|
+
].join('\n');
|
|
61
|
+
} catch {
|
|
62
|
+
return '';
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
//# sourceMappingURL=writeWorkbenchRuntime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/actions/dev/workbench/writeWorkbenchRuntime.ts"],"sourcesContent":["import fs from 'node:fs/promises'\nimport path from 'node:path'\n\nimport {devDebug} from '../devDebug.js'\n\nconst workbenchJsTemplate = `\\\n// This file is auto-generated on 'sanity dev'\n// Modifications to this file are automatically discarded\nimport {renderWorkbench} from \"sanity/workbench\"\n\nrenderWorkbench(\n document.getElementById(\"workbench\"),\n {organizationId: %SANITY_WORKBENCH_ORGANIZATION_ID%},\n {reactStrictMode: %SANITY_WORKBENCH_REACT_STRICT_MODE%}\n)\n`\n\nconst indexHtmlTemplate = `\\\n<!DOCTYPE html>\n<!-- This file is auto-generated on 'sanity dev' -->\n<!-- Modifications to this file are automatically discarded -->\n<html>\n <head>\n <meta charset=\"UTF-8\" />\n%SANITY_WORKBENCH_PREFETCH_HINTS%\n </head>\n <body>\n <div id=\"workbench\"></div>\n <script type=\"module\" src=\"./workbench.js\"></script>\n </body>\n</html>\n`\n\n/**\n * Generates the `.sanity/workbench` directory with static entry files for\n * the workbench Vite dev server.\n *\n * @param cwd - Current working directory (Sanity root dir)\n * @returns The absolute path to the written workbench runtime directory\n * @internal\n */\nexport async function writeWorkbenchRuntime(options: {\n cwd: string\n organizationId?: string\n reactStrictMode: boolean\n remoteUrl?: string\n}): Promise<string> {\n const {cwd, organizationId, reactStrictMode, remoteUrl} = options\n const workbenchDir = path.join(cwd, '.sanity', 'workbench')\n\n const workbenchJs = workbenchJsTemplate\n .replace(\n /%SANITY_WORKBENCH_ORGANIZATION_ID%/,\n organizationId === undefined ? 'undefined' : JSON.stringify(organizationId),\n )\n .replace(/%SANITY_WORKBENCH_REACT_STRICT_MODE%/, JSON.stringify(reactStrictMode))\n\n const prefetchHints = buildPrefetchHints(remoteUrl)\n\n const indexHtml = indexHtmlTemplate.replace(/%SANITY_WORKBENCH_PREFETCH_HINTS%/, prefetchHints)\n\n devDebug('Making workbench runtime directory')\n await fs.mkdir(workbenchDir, {recursive: true})\n\n devDebug('Writing workbench.js to workbench runtime directory')\n await fs.writeFile(path.join(workbenchDir, 'workbench.js'), workbenchJs)\n\n devDebug('Writing index.html to workbench runtime directory')\n await fs.writeFile(path.join(workbenchDir, 'index.html'), indexHtml)\n\n return workbenchDir\n}\n\nfunction buildPrefetchHints(remoteUrl: string | undefined): string {\n if (!remoteUrl) return ''\n\n try {\n const url = new URL(remoteUrl)\n return [\n ` <link rel=\"preconnect\" href=\"${url.origin}\" />`,\n ` <link rel=\"preload\" as=\"fetch\" href=\"${url.toString()}\" crossorigin />`,\n ].join('\\n')\n } catch {\n return ''\n }\n}\n"],"names":["fs","path","devDebug","workbenchJsTemplate","indexHtmlTemplate","writeWorkbenchRuntime","options","cwd","organizationId","reactStrictMode","remoteUrl","workbenchDir","join","workbenchJs","replace","undefined","JSON","stringify","prefetchHints","buildPrefetchHints","indexHtml","mkdir","recursive","writeFile","url","URL","origin","toString"],"mappings":"AAAA,OAAOA,QAAQ,mBAAkB;AACjC,OAAOC,UAAU,YAAW;AAE5B,SAAQC,QAAQ,QAAO,iBAAgB;AAEvC,MAAMC,sBAAsB,CAAC;;;;;;;;;;AAU7B,CAAC;AAED,MAAMC,oBAAoB,CAAC;;;;;;;;;;;;;;AAc3B,CAAC;AAED;;;;;;;CAOC,GACD,OAAO,eAAeC,sBAAsBC,OAK3C;IACC,MAAM,EAACC,GAAG,EAAEC,cAAc,EAAEC,eAAe,EAAEC,SAAS,EAAC,GAAGJ;IAC1D,MAAMK,eAAeV,KAAKW,IAAI,CAACL,KAAK,WAAW;IAE/C,MAAMM,cAAcV,oBACjBW,OAAO,CACN,sCACAN,mBAAmBO,YAAY,cAAcC,KAAKC,SAAS,CAACT,iBAE7DM,OAAO,CAAC,wCAAwCE,KAAKC,SAAS,CAACR;IAElE,MAAMS,gBAAgBC,mBAAmBT;IAEzC,MAAMU,YAAYhB,kBAAkBU,OAAO,CAAC,qCAAqCI;IAEjFhB,SAAS;IACT,MAAMF,GAAGqB,KAAK,CAACV,cAAc;QAACW,WAAW;IAAI;IAE7CpB,SAAS;IACT,MAAMF,GAAGuB,SAAS,CAACtB,KAAKW,IAAI,CAACD,cAAc,iBAAiBE;IAE5DX,SAAS;IACT,MAAMF,GAAGuB,SAAS,CAACtB,KAAKW,IAAI,CAACD,cAAc,eAAeS;IAE1D,OAAOT;AACT;AAEA,SAASQ,mBAAmBT,SAA6B;IACvD,IAAI,CAACA,WAAW,OAAO;IAEvB,IAAI;QACF,MAAMc,MAAM,IAAIC,IAAIf;QACpB,OAAO;YACL,CAAC,iCAAiC,EAAEc,IAAIE,MAAM,CAAC,IAAI,CAAC;YACpD,CAAC,yCAAyC,EAAEF,IAAIG,QAAQ,GAAG,gBAAgB,CAAC;SAC7E,CAACf,IAAI,CAAC;IACT,EAAE,OAAM;QACN,OAAO;IACT;AACF"}
|
|
@@ -64,7 +64,12 @@ export async function bootstrapLocalTemplate(opts) {
|
|
|
64
64
|
...isAppTemplate ? sdkAppDependencies.dependencies : studioDependencies.dependencies,
|
|
65
65
|
...isAppTemplate ? sdkAppDependencies.devDependencies : studioDependencies.devDependencies,
|
|
66
66
|
...template.dependencies,
|
|
67
|
-
...template.devDependencies
|
|
67
|
+
...template.devDependencies,
|
|
68
|
+
// `unstable_defineApp` (re-exported via `sanity/cli`) only exists on the
|
|
69
|
+
// workbench dist-tag of `sanity`.
|
|
70
|
+
...variables.workbench && {
|
|
71
|
+
sanity: 'workbench'
|
|
72
|
+
}
|
|
68
73
|
});
|
|
69
74
|
spin.succeed();
|
|
70
75
|
// Use the resolved version for the given dependency
|
|
@@ -106,11 +111,18 @@ export async function bootstrapLocalTemplate(opts) {
|
|
|
106
111
|
// ...and a CLI config (`sanity.cli.[ts|js]`)
|
|
107
112
|
const cliConfig = isAppTemplate ? createAppCliConfig({
|
|
108
113
|
entry: template.entry,
|
|
109
|
-
|
|
114
|
+
isWorkbenchApp: variables.workbench,
|
|
115
|
+
name: packageJsonName,
|
|
116
|
+
organizationId: variables.organizationId,
|
|
117
|
+
title: variables.projectName || packageJsonName
|
|
110
118
|
}) : createCliConfig({
|
|
111
119
|
autoUpdates: variables.autoUpdates,
|
|
112
120
|
dataset: variables.dataset,
|
|
113
|
-
|
|
121
|
+
isWorkbenchApp: variables.workbench,
|
|
122
|
+
name: packageJsonName,
|
|
123
|
+
organizationId: variables.organizationId,
|
|
124
|
+
projectId: variables.projectId,
|
|
125
|
+
title: variables.projectName || packageJsonName
|
|
114
126
|
});
|
|
115
127
|
// Write non-template files to disc
|
|
116
128
|
const codeExt = useTypeScript ? 'ts' : 'js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/init/bootstrapLocalTemplate.ts"],"sourcesContent":["import fs from 'node:fs/promises'\nimport path from 'node:path'\nimport {styleText} from 'node:util'\n\nimport {Output, subdebug} from '@sanity/cli-core'\nimport {spinner} from '@sanity/cli-core/ux'\nimport deburr from 'lodash-es/deburr.js'\n\nimport {copy} from '../../util/copy.js'\nimport {resolveLatestVersions} from '../../util/resolveLatestVersions.js'\nimport {createAppCliConfig} from './createAppCliConfig.js'\nimport {createCliConfig} from './createCliConfig.js'\nimport {createPackageManifest} from './createPackageManifest.js'\nimport {createStudioConfig, type GenerateConfigOptions} from './createStudioConfig.js'\nimport {determineAppTemplate} from './determineAppTemplate.js'\nimport {processTemplate} from './processTemplate.js'\nimport {sdkAppDependencies} from './sdkAppDependencies.js'\nimport {studioDependencies} from './studioDependencies.js'\nimport templates from './templates/index.js'\nimport {type ProjectTemplate} from './types.js'\nimport {updateInitialTemplateMetadata} from './updateInitialTemplateMetadata.js'\n\nconst debug = subdebug('init:bootstrapRemoteTemplate')\n\ninterface BootstrapLocalOptions {\n output: Output\n outputPath: string\n packageName: string\n templateName: string\n useTypeScript: boolean\n variables: GenerateConfigOptions['variables']\n\n overwriteFiles?: boolean\n}\n\nexport async function bootstrapLocalTemplate(\n opts: BootstrapLocalOptions,\n): Promise<ProjectTemplate> {\n const {output, outputPath, packageName, templateName, useTypeScript, variables} = opts\n // packages/@sanity/cli/src/actions/init/ -> packages/@sanity/cli/src/action -> packages/@sanity/cli/src/\n const cliRoot = path.resolve(import.meta.dirname, '../../..')\n const templatesDir = path.join(cliRoot, 'templates')\n const sourceDir = path.join(templatesDir, templateName)\n const sharedDir = path.join(templatesDir, 'shared')\n const isAppTemplate = determineAppTemplate(templateName)\n\n // Check that we have a template info file (dependencies, plugins etc)\n const template = templates[templateName]\n if (!template) {\n throw new Error(`Template \"${templateName}\" not defined`)\n }\n\n // Copy template files\n debug('Copying files from template \"%s\" to \"%s\"', templateName, outputPath)\n let spin = spinner('Bootstrapping files from template').start()\n\n debug(`Copying template from : ${sourceDir}`)\n await copy(sourceDir, outputPath, {\n rename: useTypeScript ? toTypeScriptPath : undefined,\n })\n debug(`Copying shared template code from : ${sharedDir}`)\n await copy(path.join(sharedDir, 'gitignore.txt'), outputPath, {rename: () => '.gitignore'})\n\n if (useTypeScript) {\n await fs.copyFile(path.join(sharedDir, 'tsconfig.json'), path.join(outputPath, 'tsconfig.json'))\n }\n\n spin.succeed()\n\n if (isAppTemplate) {\n const appEntryPath = path.join(outputPath, 'src', 'App.tsx')\n const raw = await fs.readFile(appEntryPath, 'utf8')\n const rendered = processTemplate({\n template: raw,\n variables: {\n dataset: variables.dataset ?? '',\n projectId: variables.projectId ?? '',\n },\n })\n await fs.writeFile(appEntryPath, rendered)\n }\n\n // Merge global and template-specific plugins and dependencies\n\n // Resolve latest versions of Sanity-dependencies\n spin = spinner('Resolving latest module versions').start()\n const dependencyVersions = await resolveLatestVersions({\n ...(isAppTemplate ? sdkAppDependencies.dependencies : studioDependencies.dependencies),\n ...(isAppTemplate ? sdkAppDependencies.devDependencies : studioDependencies.devDependencies),\n ...template.dependencies,\n ...template.devDependencies,\n })\n spin.succeed()\n\n // Use the resolved version for the given dependency\n const dependencies: Record<string, string> = {}\n for (const dependency of Object.keys({\n ...(isAppTemplate ? sdkAppDependencies.dependencies : studioDependencies.dependencies),\n ...template.dependencies,\n })) {\n dependencies[dependency] = dependencyVersions[dependency]\n }\n\n const devDependencies: Record<string, string> = {}\n for (const dependency of Object.keys({\n ...(isAppTemplate ? sdkAppDependencies.devDependencies : studioDependencies.devDependencies),\n ...template.devDependencies,\n })) {\n devDependencies[dependency] = dependencyVersions[dependency]\n }\n\n let packageJsonName: string = packageName\n\n /**\n * Currently app init doesn't ask for a name, so we use the last part of the path\n */\n if (isAppTemplate) {\n packageJsonName = deburr(path.basename(outputPath).toLowerCase())\n .replaceAll(/\\s+/g, '-')\n .replaceAll(/[^a-z0-9-]/g, '')\n }\n\n // Now create a package manifest (`package.json`) with the merged dependencies\n spin = spinner('Creating default project files').start()\n const packageManifest = createPackageManifest({\n dependencies,\n devDependencies,\n isAppTemplate,\n name: packageJsonName,\n scripts: template.scripts,\n type: template.type,\n })\n\n // ...and a studio config (`sanity.config.[ts|js]`)\n const studioConfig = createStudioConfig({\n template: template.configTemplate,\n variables,\n })\n\n // ...and a CLI config (`sanity.cli.[ts|js]`)\n const cliConfig = isAppTemplate\n ? createAppCliConfig({\n entry: template.entry!,\n organizationId: variables.organizationId,\n })\n : createCliConfig({\n autoUpdates: variables.autoUpdates,\n dataset: variables.dataset,\n projectId: variables.projectId,\n })\n\n // Write non-template files to disc\n const codeExt = useTypeScript ? 'ts' : 'js'\n await Promise.all(\n [\n isAppTemplate\n ? Promise.resolve(null)\n : writeFileIfNotExists(`sanity.config.${codeExt}`, studioConfig),\n writeFileIfNotExists(`sanity.cli.${codeExt}`, cliConfig),\n writeFileIfNotExists('package.json', packageManifest),\n\n writeFileIfNotExists(\n 'eslint.config.mjs',\n `import studio from '@sanity/eslint-config-studio'\\n\\nexport default [...studio]\\n`,\n ),\n ].filter(Boolean),\n )\n\n debug('Updating initial template metadata')\n if (variables.projectId) {\n await updateInitialTemplateMetadata(variables.projectId, `cli-${templateName}`)\n }\n\n // Finish up by providing init process with template-specific info\n spin.succeed()\n return template\n\n async function writeFileIfNotExists(fileName: string, content: string): Promise<void> {\n const filePath = path.join(outputPath, fileName)\n\n if (opts.overwriteFiles) {\n // If overwrite is enabled, just write the file\n await fs.writeFile(filePath, content)\n return\n }\n\n try {\n await fs.writeFile(filePath, content, {flag: 'wx'})\n } catch (err) {\n if (err.code === 'EEXIST') {\n output.warn(`\\n${styleText('yellow', '⚠')} File \"${filePath}\" already exists, skipping`)\n } else {\n throw err\n }\n }\n }\n}\n\nfunction toTypeScriptPath(originalPath: string): string {\n return originalPath.replace(/\\.js$/, '.ts')\n}\n"],"names":["fs","path","styleText","subdebug","spinner","deburr","copy","resolveLatestVersions","createAppCliConfig","createCliConfig","createPackageManifest","createStudioConfig","determineAppTemplate","processTemplate","sdkAppDependencies","studioDependencies","templates","updateInitialTemplateMetadata","debug","bootstrapLocalTemplate","opts","output","outputPath","packageName","templateName","useTypeScript","variables","cliRoot","resolve","dirname","templatesDir","join","sourceDir","sharedDir","isAppTemplate","template","Error","spin","start","rename","toTypeScriptPath","undefined","copyFile","succeed","appEntryPath","raw","readFile","rendered","dataset","projectId","writeFile","dependencyVersions","dependencies","devDependencies","dependency","Object","keys","packageJsonName","basename","toLowerCase","replaceAll","packageManifest","name","scripts","type","studioConfig","configTemplate","cliConfig","entry","organizationId","autoUpdates","codeExt","Promise","all","writeFileIfNotExists","filter","Boolean","fileName","content","filePath","overwriteFiles","flag","err","code","warn","originalPath","replace"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/init/bootstrapLocalTemplate.ts"],"sourcesContent":["import fs from 'node:fs/promises'\nimport path from 'node:path'\nimport {styleText} from 'node:util'\n\nimport {Output, subdebug} from '@sanity/cli-core'\nimport {spinner} from '@sanity/cli-core/ux'\nimport deburr from 'lodash-es/deburr.js'\n\nimport {copy} from '../../util/copy.js'\nimport {resolveLatestVersions} from '../../util/resolveLatestVersions.js'\nimport {createAppCliConfig} from './createAppCliConfig.js'\nimport {createCliConfig} from './createCliConfig.js'\nimport {createPackageManifest} from './createPackageManifest.js'\nimport {createStudioConfig, type GenerateConfigOptions} from './createStudioConfig.js'\nimport {determineAppTemplate} from './determineAppTemplate.js'\nimport {processTemplate} from './processTemplate.js'\nimport {sdkAppDependencies} from './sdkAppDependencies.js'\nimport {studioDependencies} from './studioDependencies.js'\nimport templates from './templates/index.js'\nimport {type ProjectTemplate} from './types.js'\nimport {updateInitialTemplateMetadata} from './updateInitialTemplateMetadata.js'\n\nconst debug = subdebug('init:bootstrapRemoteTemplate')\n\ninterface BootstrapLocalOptions {\n output: Output\n outputPath: string\n packageName: string\n templateName: string\n useTypeScript: boolean\n variables: GenerateConfigOptions['variables']\n\n overwriteFiles?: boolean\n}\n\nexport async function bootstrapLocalTemplate(\n opts: BootstrapLocalOptions,\n): Promise<ProjectTemplate> {\n const {output, outputPath, packageName, templateName, useTypeScript, variables} = opts\n // packages/@sanity/cli/src/actions/init/ -> packages/@sanity/cli/src/action -> packages/@sanity/cli/src/\n const cliRoot = path.resolve(import.meta.dirname, '../../..')\n const templatesDir = path.join(cliRoot, 'templates')\n const sourceDir = path.join(templatesDir, templateName)\n const sharedDir = path.join(templatesDir, 'shared')\n const isAppTemplate = determineAppTemplate(templateName)\n\n // Check that we have a template info file (dependencies, plugins etc)\n const template = templates[templateName]\n if (!template) {\n throw new Error(`Template \"${templateName}\" not defined`)\n }\n\n // Copy template files\n debug('Copying files from template \"%s\" to \"%s\"', templateName, outputPath)\n let spin = spinner('Bootstrapping files from template').start()\n\n debug(`Copying template from : ${sourceDir}`)\n await copy(sourceDir, outputPath, {\n rename: useTypeScript ? toTypeScriptPath : undefined,\n })\n debug(`Copying shared template code from : ${sharedDir}`)\n await copy(path.join(sharedDir, 'gitignore.txt'), outputPath, {rename: () => '.gitignore'})\n\n if (useTypeScript) {\n await fs.copyFile(path.join(sharedDir, 'tsconfig.json'), path.join(outputPath, 'tsconfig.json'))\n }\n\n spin.succeed()\n\n if (isAppTemplate) {\n const appEntryPath = path.join(outputPath, 'src', 'App.tsx')\n const raw = await fs.readFile(appEntryPath, 'utf8')\n const rendered = processTemplate({\n template: raw,\n variables: {\n dataset: variables.dataset ?? '',\n projectId: variables.projectId ?? '',\n },\n })\n await fs.writeFile(appEntryPath, rendered)\n }\n\n // Merge global and template-specific plugins and dependencies\n\n // Resolve latest versions of Sanity-dependencies\n spin = spinner('Resolving latest module versions').start()\n const dependencyVersions = await resolveLatestVersions({\n ...(isAppTemplate ? sdkAppDependencies.dependencies : studioDependencies.dependencies),\n ...(isAppTemplate ? sdkAppDependencies.devDependencies : studioDependencies.devDependencies),\n ...template.dependencies,\n ...template.devDependencies,\n // `unstable_defineApp` (re-exported via `sanity/cli`) only exists on the\n // workbench dist-tag of `sanity`.\n ...(variables.workbench && {sanity: 'workbench'}),\n })\n spin.succeed()\n\n // Use the resolved version for the given dependency\n const dependencies: Record<string, string> = {}\n for (const dependency of Object.keys({\n ...(isAppTemplate ? sdkAppDependencies.dependencies : studioDependencies.dependencies),\n ...template.dependencies,\n })) {\n dependencies[dependency] = dependencyVersions[dependency]\n }\n\n const devDependencies: Record<string, string> = {}\n for (const dependency of Object.keys({\n ...(isAppTemplate ? sdkAppDependencies.devDependencies : studioDependencies.devDependencies),\n ...template.devDependencies,\n })) {\n devDependencies[dependency] = dependencyVersions[dependency]\n }\n\n let packageJsonName: string = packageName\n\n /**\n * Currently app init doesn't ask for a name, so we use the last part of the path\n */\n if (isAppTemplate) {\n packageJsonName = deburr(path.basename(outputPath).toLowerCase())\n .replaceAll(/\\s+/g, '-')\n .replaceAll(/[^a-z0-9-]/g, '')\n }\n\n // Now create a package manifest (`package.json`) with the merged dependencies\n spin = spinner('Creating default project files').start()\n const packageManifest = createPackageManifest({\n dependencies,\n devDependencies,\n isAppTemplate,\n name: packageJsonName,\n scripts: template.scripts,\n type: template.type,\n })\n\n // ...and a studio config (`sanity.config.[ts|js]`)\n const studioConfig = createStudioConfig({\n template: template.configTemplate,\n variables,\n })\n\n // ...and a CLI config (`sanity.cli.[ts|js]`)\n const cliConfig = isAppTemplate\n ? createAppCliConfig({\n entry: template.entry!,\n isWorkbenchApp: variables.workbench,\n name: packageJsonName,\n organizationId: variables.organizationId,\n title: variables.projectName || packageJsonName,\n })\n : createCliConfig({\n autoUpdates: variables.autoUpdates,\n dataset: variables.dataset,\n isWorkbenchApp: variables.workbench,\n name: packageJsonName,\n organizationId: variables.organizationId,\n projectId: variables.projectId,\n title: variables.projectName || packageJsonName,\n })\n\n // Write non-template files to disc\n const codeExt = useTypeScript ? 'ts' : 'js'\n await Promise.all(\n [\n isAppTemplate\n ? Promise.resolve(null)\n : writeFileIfNotExists(`sanity.config.${codeExt}`, studioConfig),\n writeFileIfNotExists(`sanity.cli.${codeExt}`, cliConfig),\n writeFileIfNotExists('package.json', packageManifest),\n\n writeFileIfNotExists(\n 'eslint.config.mjs',\n `import studio from '@sanity/eslint-config-studio'\\n\\nexport default [...studio]\\n`,\n ),\n ].filter(Boolean),\n )\n\n debug('Updating initial template metadata')\n if (variables.projectId) {\n await updateInitialTemplateMetadata(variables.projectId, `cli-${templateName}`)\n }\n\n // Finish up by providing init process with template-specific info\n spin.succeed()\n return template\n\n async function writeFileIfNotExists(fileName: string, content: string): Promise<void> {\n const filePath = path.join(outputPath, fileName)\n\n if (opts.overwriteFiles) {\n // If overwrite is enabled, just write the file\n await fs.writeFile(filePath, content)\n return\n }\n\n try {\n await fs.writeFile(filePath, content, {flag: 'wx'})\n } catch (err) {\n if (err.code === 'EEXIST') {\n output.warn(`\\n${styleText('yellow', '⚠')} File \"${filePath}\" already exists, skipping`)\n } else {\n throw err\n }\n }\n }\n}\n\nfunction toTypeScriptPath(originalPath: string): string {\n return originalPath.replace(/\\.js$/, '.ts')\n}\n"],"names":["fs","path","styleText","subdebug","spinner","deburr","copy","resolveLatestVersions","createAppCliConfig","createCliConfig","createPackageManifest","createStudioConfig","determineAppTemplate","processTemplate","sdkAppDependencies","studioDependencies","templates","updateInitialTemplateMetadata","debug","bootstrapLocalTemplate","opts","output","outputPath","packageName","templateName","useTypeScript","variables","cliRoot","resolve","dirname","templatesDir","join","sourceDir","sharedDir","isAppTemplate","template","Error","spin","start","rename","toTypeScriptPath","undefined","copyFile","succeed","appEntryPath","raw","readFile","rendered","dataset","projectId","writeFile","dependencyVersions","dependencies","devDependencies","workbench","sanity","dependency","Object","keys","packageJsonName","basename","toLowerCase","replaceAll","packageManifest","name","scripts","type","studioConfig","configTemplate","cliConfig","entry","isWorkbenchApp","organizationId","title","projectName","autoUpdates","codeExt","Promise","all","writeFileIfNotExists","filter","Boolean","fileName","content","filePath","overwriteFiles","flag","err","code","warn","originalPath","replace"],"mappings":"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"}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { bootstrapLocalTemplate } from './bootstrapLocalTemplate.js';
|
|
2
2
|
import { bootstrapRemoteTemplate } from './bootstrapRemoteTemplate.js';
|
|
3
|
-
export async function bootstrapTemplate({ autoUpdates, bearerToken, dataset, organizationId, output, outputPath, overwriteFiles, packageName, projectId, projectName, remoteTemplateInfo, templateName, useTypeScript }) {
|
|
3
|
+
export async function bootstrapTemplate({ autoUpdates, bearerToken, dataset, organizationId, output, outputPath, overwriteFiles, packageName, projectId, projectName, remoteTemplateInfo, templateName, useTypeScript, workbench }) {
|
|
4
4
|
const bootstrapVariables = {
|
|
5
5
|
autoUpdates,
|
|
6
6
|
dataset,
|
|
7
7
|
organizationId,
|
|
8
8
|
projectId,
|
|
9
|
-
projectName
|
|
9
|
+
projectName,
|
|
10
|
+
workbench
|
|
10
11
|
};
|
|
11
12
|
if (remoteTemplateInfo) {
|
|
12
13
|
return bootstrapRemoteTemplate({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/init/bootstrapTemplate.ts"],"sourcesContent":["import {Output} from '@sanity/cli-core'\n\nimport {bootstrapLocalTemplate} from './bootstrapLocalTemplate.js'\nimport {bootstrapRemoteTemplate} from './bootstrapRemoteTemplate.js'\nimport {type GenerateConfigOptions} from './createStudioConfig.js'\nimport {type RepoInfo} from './remoteTemplate.js'\n\ninterface BootstrapTemplateOptions {\n autoUpdates: boolean\n bearerToken: string | undefined\n dataset: string\n organizationId: string | undefined\n output: Output\n outputPath: string\n packageName: string\n projectId: string\n projectName: string\n remoteTemplateInfo: RepoInfo | undefined\n templateName: string\n\n useTypeScript: boolean\n\n overwriteFiles?: boolean\n}\n\nexport async function bootstrapTemplate({\n autoUpdates,\n bearerToken,\n dataset,\n organizationId,\n output,\n outputPath,\n overwriteFiles,\n packageName,\n projectId,\n projectName,\n remoteTemplateInfo,\n templateName,\n useTypeScript,\n}: BootstrapTemplateOptions) {\n const bootstrapVariables: GenerateConfigOptions['variables'] = {\n autoUpdates,\n dataset,\n organizationId,\n projectId,\n projectName,\n }\n\n if (remoteTemplateInfo) {\n return bootstrapRemoteTemplate({\n bearerToken,\n output,\n outputPath,\n packageName,\n repoInfo: remoteTemplateInfo,\n variables: bootstrapVariables,\n })\n }\n\n return bootstrapLocalTemplate({\n output,\n outputPath,\n overwriteFiles,\n packageName,\n templateName,\n useTypeScript,\n variables: bootstrapVariables,\n })\n}\n"],"names":["bootstrapLocalTemplate","bootstrapRemoteTemplate","bootstrapTemplate","autoUpdates","bearerToken","dataset","organizationId","output","outputPath","overwriteFiles","packageName","projectId","projectName","remoteTemplateInfo","templateName","useTypeScript","bootstrapVariables","repoInfo","variables"],"mappings":"AAEA,SAAQA,sBAAsB,QAAO,8BAA6B;AAClE,SAAQC,uBAAuB,QAAO,+BAA8B;
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/init/bootstrapTemplate.ts"],"sourcesContent":["import {Output} from '@sanity/cli-core'\n\nimport {bootstrapLocalTemplate} from './bootstrapLocalTemplate.js'\nimport {bootstrapRemoteTemplate} from './bootstrapRemoteTemplate.js'\nimport {type GenerateConfigOptions} from './createStudioConfig.js'\nimport {type RepoInfo} from './remoteTemplate.js'\n\ninterface BootstrapTemplateOptions {\n autoUpdates: boolean\n bearerToken: string | undefined\n dataset: string\n organizationId: string | undefined\n output: Output\n outputPath: string\n packageName: string\n projectId: string\n projectName: string\n remoteTemplateInfo: RepoInfo | undefined\n templateName: string\n\n useTypeScript: boolean\n workbench: boolean\n\n overwriteFiles?: boolean\n}\n\nexport async function bootstrapTemplate({\n autoUpdates,\n bearerToken,\n dataset,\n organizationId,\n output,\n outputPath,\n overwriteFiles,\n packageName,\n projectId,\n projectName,\n remoteTemplateInfo,\n templateName,\n useTypeScript,\n workbench,\n}: BootstrapTemplateOptions) {\n const bootstrapVariables: GenerateConfigOptions['variables'] = {\n autoUpdates,\n dataset,\n organizationId,\n projectId,\n projectName,\n workbench,\n }\n\n if (remoteTemplateInfo) {\n return bootstrapRemoteTemplate({\n bearerToken,\n output,\n outputPath,\n packageName,\n repoInfo: remoteTemplateInfo,\n variables: bootstrapVariables,\n })\n }\n\n return bootstrapLocalTemplate({\n output,\n outputPath,\n overwriteFiles,\n packageName,\n templateName,\n useTypeScript,\n variables: bootstrapVariables,\n })\n}\n"],"names":["bootstrapLocalTemplate","bootstrapRemoteTemplate","bootstrapTemplate","autoUpdates","bearerToken","dataset","organizationId","output","outputPath","overwriteFiles","packageName","projectId","projectName","remoteTemplateInfo","templateName","useTypeScript","workbench","bootstrapVariables","repoInfo","variables"],"mappings":"AAEA,SAAQA,sBAAsB,QAAO,8BAA6B;AAClE,SAAQC,uBAAuB,QAAO,+BAA8B;AAuBpE,OAAO,eAAeC,kBAAkB,EACtCC,WAAW,EACXC,WAAW,EACXC,OAAO,EACPC,cAAc,EACdC,MAAM,EACNC,UAAU,EACVC,cAAc,EACdC,WAAW,EACXC,SAAS,EACTC,WAAW,EACXC,kBAAkB,EAClBC,YAAY,EACZC,aAAa,EACbC,SAAS,EACgB;IACzB,MAAMC,qBAAyD;QAC7Dd;QACAE;QACAC;QACAK;QACAC;QACAI;IACF;IAEA,IAAIH,oBAAoB;QACtB,OAAOZ,wBAAwB;YAC7BG;YACAG;YACAC;YACAE;YACAQ,UAAUL;YACVM,WAAWF;QACb;IACF;IAEA,OAAOjB,uBAAuB;QAC5BO;QACAC;QACAC;QACAC;QACAI;QACAC;QACAI,WAAWF;IACb;AACF"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { workbenchAppConfigTemplate } from '@sanity/workbench-cli/init';
|
|
1
2
|
import { processTemplate } from './processTemplate.js';
|
|
2
3
|
const defaultAppTemplate = `
|
|
3
4
|
import {defineCliConfig} from 'sanity/cli'
|
|
@@ -10,9 +11,11 @@ export default defineCliConfig({
|
|
|
10
11
|
})
|
|
11
12
|
`;
|
|
12
13
|
export function createAppCliConfig(options) {
|
|
14
|
+
const { isWorkbenchApp, ...variables } = options;
|
|
13
15
|
return processTemplate({
|
|
14
|
-
|
|
15
|
-
|
|
16
|
+
includeBooleanTransform: true,
|
|
17
|
+
template: isWorkbenchApp ? workbenchAppConfigTemplate : defaultAppTemplate,
|
|
18
|
+
variables
|
|
16
19
|
});
|
|
17
20
|
}
|
|
18
21
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/init/createAppCliConfig.ts"],"sourcesContent":["import {processTemplate} from './processTemplate.js'\n\nconst defaultAppTemplate = `\nimport {defineCliConfig} from 'sanity/cli'\n\nexport default defineCliConfig({\n app: {\n organizationId: '%organizationId%',\n entry: '%entry%',\n },\n})\n`\n\ninterface GenerateCliConfigOptions {\n entry: string\n\n organizationId?: string\n}\n\nexport function createAppCliConfig(options: GenerateCliConfigOptions): string {\n return processTemplate({\n template: defaultAppTemplate,\n variables
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/init/createAppCliConfig.ts"],"sourcesContent":["import {workbenchAppConfigTemplate} from '@sanity/workbench-cli/init'\n\nimport {processTemplate} from './processTemplate.js'\n\nconst defaultAppTemplate = `\nimport {defineCliConfig} from 'sanity/cli'\n\nexport default defineCliConfig({\n app: {\n organizationId: '%organizationId%',\n entry: '%entry%',\n },\n})\n`\n\ninterface GenerateCliConfigOptions {\n entry: string\n isWorkbenchApp: boolean\n name: string\n title: string\n\n organizationId?: string\n}\n\nexport function createAppCliConfig(options: GenerateCliConfigOptions): string {\n const {isWorkbenchApp, ...variables} = options\n return processTemplate({\n includeBooleanTransform: true,\n template: isWorkbenchApp ? workbenchAppConfigTemplate : defaultAppTemplate,\n variables,\n })\n}\n"],"names":["workbenchAppConfigTemplate","processTemplate","defaultAppTemplate","createAppCliConfig","options","isWorkbenchApp","variables","includeBooleanTransform","template"],"mappings":"AAAA,SAAQA,0BAA0B,QAAO,6BAA4B;AAErE,SAAQC,eAAe,QAAO,uBAAsB;AAEpD,MAAMC,qBAAqB,CAAC;;;;;;;;;AAS5B,CAAC;AAWD,OAAO,SAASC,mBAAmBC,OAAiC;IAClE,MAAM,EAACC,cAAc,EAAE,GAAGC,WAAU,GAAGF;IACvC,OAAOH,gBAAgB;QACrBM,yBAAyB;QACzBC,UAAUH,iBAAiBL,6BAA6BE;QACxDI;IACF;AACF"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { workbenchStudioConfigTemplate } from '@sanity/workbench-cli/init';
|
|
1
2
|
import { processTemplate } from './processTemplate.js';
|
|
2
3
|
const defaultTemplate = `
|
|
3
4
|
import {defineCliConfig} from 'sanity/cli'
|
|
@@ -13,14 +14,15 @@ export default defineCliConfig({
|
|
|
13
14
|
* Learn more at https://www.sanity.io/docs/studio/latest-version-of-sanity#k47faf43faf56
|
|
14
15
|
*/
|
|
15
16
|
autoUpdates: __BOOL__autoUpdates__,
|
|
16
|
-
}
|
|
17
|
+
},
|
|
17
18
|
})
|
|
18
19
|
`;
|
|
19
20
|
export function createCliConfig(options) {
|
|
21
|
+
const { isWorkbenchApp, ...variables } = options;
|
|
20
22
|
return processTemplate({
|
|
21
23
|
includeBooleanTransform: true,
|
|
22
|
-
template: defaultTemplate,
|
|
23
|
-
variables
|
|
24
|
+
template: isWorkbenchApp ? workbenchStudioConfigTemplate : defaultTemplate,
|
|
25
|
+
variables
|
|
24
26
|
});
|
|
25
27
|
}
|
|
26
28
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/init/createCliConfig.ts"],"sourcesContent":["import {processTemplate} from './processTemplate.js'\n\nconst defaultTemplate = `\nimport {defineCliConfig} from 'sanity/cli'\n\nexport default defineCliConfig({\n api: {\n projectId: '%projectId%',\n dataset: '%dataset%'\n },\n deployment: {\n /**\n * Enable auto-updates for studios.\n * Learn more at https://www.sanity.io/docs/studio/latest-version-of-sanity#k47faf43faf56\n */\n autoUpdates: __BOOL__autoUpdates__,\n }
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/init/createCliConfig.ts"],"sourcesContent":["import {workbenchStudioConfigTemplate} from '@sanity/workbench-cli/init'\n\nimport {processTemplate} from './processTemplate.js'\n\nconst defaultTemplate = `\nimport {defineCliConfig} from 'sanity/cli'\n\nexport default defineCliConfig({\n api: {\n projectId: '%projectId%',\n dataset: '%dataset%'\n },\n deployment: {\n /**\n * Enable auto-updates for studios.\n * Learn more at https://www.sanity.io/docs/studio/latest-version-of-sanity#k47faf43faf56\n */\n autoUpdates: __BOOL__autoUpdates__,\n },\n})\n`\n\ninterface GenerateCliConfigOptions {\n autoUpdates: boolean\n dataset: string\n isWorkbenchApp: boolean\n name: string\n projectId: string\n title: string\n\n organizationId?: string\n}\n\nexport function createCliConfig(options: GenerateCliConfigOptions): string {\n const {isWorkbenchApp, ...variables} = options\n return processTemplate({\n includeBooleanTransform: true,\n template: isWorkbenchApp ? workbenchStudioConfigTemplate : defaultTemplate,\n variables,\n })\n}\n"],"names":["workbenchStudioConfigTemplate","processTemplate","defaultTemplate","createCliConfig","options","isWorkbenchApp","variables","includeBooleanTransform","template"],"mappings":"AAAA,SAAQA,6BAA6B,QAAO,6BAA4B;AAExE,SAAQC,eAAe,QAAO,uBAAsB;AAEpD,MAAMC,kBAAkB,CAAC;;;;;;;;;;;;;;;;AAgBzB,CAAC;AAaD,OAAO,SAASC,gBAAgBC,OAAiC;IAC/D,MAAM,EAACC,cAAc,EAAE,GAAGC,WAAU,GAAGF;IACvC,OAAOH,gBAAgB;QACrBM,yBAAyB;QACzBC,UAAUH,iBAAiBL,gCAAgCE;QAC3DI;IACF;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/init/createStudioConfig.ts"],"sourcesContent":["import {processTemplate} from './processTemplate.js'\n\nconst defaultTemplate = `\nimport {defineConfig} from 'sanity'\nimport {structureTool} from 'sanity/structure'\nimport {visionTool} from '@sanity/vision'\nimport {schemaTypes} from './schemaTypes'\n\nexport default defineConfig({\n name: '%sourceName%',\n title: '%projectName%',\n\n projectId: '%projectId%',\n dataset: '%dataset%',\n\n plugins: [structureTool(), visionTool()],\n\n schema: {\n types: schemaTypes,\n },\n})\n`\n\nconst defaultVariables = {\n projectName: 'Sanity Studio',\n sourceName: 'default',\n sourceTitle: 'Default',\n}\n\nexport interface GenerateConfigOptions {\n variables: {\n autoUpdates: boolean\n dataset: string\n organizationId?: string\n projectId: string\n projectName?: string\n sourceName?: string\n sourceTitle?: string\n }\n\n template?: ((variables: GenerateConfigOptions['variables']) => string) | string\n}\n\nexport function createStudioConfig(options: GenerateConfigOptions): string {\n const variables = {...defaultVariables, ...options.variables}\n if (typeof options.template === 'function') {\n return options.template(variables).trimStart()\n }\n\n return processTemplate({\n template: options.template || defaultTemplate,\n variables,\n })\n}\n"],"names":["processTemplate","defaultTemplate","defaultVariables","projectName","sourceName","sourceTitle","createStudioConfig","options","variables","template","trimStart"],"mappings":"AAAA,SAAQA,eAAe,QAAO,uBAAsB;AAEpD,MAAMC,kBAAkB,CAAC;;;;;;;;;;;;;;;;;;;AAmBzB,CAAC;AAED,MAAMC,mBAAmB;IACvBC,aAAa;IACbC,YAAY;IACZC,aAAa;AACf;
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/init/createStudioConfig.ts"],"sourcesContent":["import {processTemplate} from './processTemplate.js'\n\nconst defaultTemplate = `\nimport {defineConfig} from 'sanity'\nimport {structureTool} from 'sanity/structure'\nimport {visionTool} from '@sanity/vision'\nimport {schemaTypes} from './schemaTypes'\n\nexport default defineConfig({\n name: '%sourceName%',\n title: '%projectName%',\n\n projectId: '%projectId%',\n dataset: '%dataset%',\n\n plugins: [structureTool(), visionTool()],\n\n schema: {\n types: schemaTypes,\n },\n})\n`\n\nconst defaultVariables = {\n projectName: 'Sanity Studio',\n sourceName: 'default',\n sourceTitle: 'Default',\n}\n\nexport interface GenerateConfigOptions {\n variables: {\n autoUpdates: boolean\n dataset: string\n organizationId?: string\n projectId: string\n projectName?: string\n sourceName?: string\n sourceTitle?: string\n workbench: boolean\n }\n\n template?: ((variables: GenerateConfigOptions['variables']) => string) | string\n}\n\nexport function createStudioConfig(options: GenerateConfigOptions): string {\n const variables = {...defaultVariables, ...options.variables}\n if (typeof options.template === 'function') {\n return options.template(variables).trimStart()\n }\n\n return processTemplate({\n template: options.template || defaultTemplate,\n variables,\n })\n}\n"],"names":["processTemplate","defaultTemplate","defaultVariables","projectName","sourceName","sourceTitle","createStudioConfig","options","variables","template","trimStart"],"mappings":"AAAA,SAAQA,eAAe,QAAO,uBAAsB;AAEpD,MAAMC,kBAAkB,CAAC;;;;;;;;;;;;;;;;;;;AAmBzB,CAAC;AAED,MAAMC,mBAAmB;IACvBC,aAAa;IACbC,YAAY;IACZC,aAAa;AACf;AAiBA,OAAO,SAASC,mBAAmBC,OAA8B;IAC/D,MAAMC,YAAY;QAAC,GAAGN,gBAAgB;QAAE,GAAGK,QAAQC,SAAS;IAAA;IAC5D,IAAI,OAAOD,QAAQE,QAAQ,KAAK,YAAY;QAC1C,OAAOF,QAAQE,QAAQ,CAACD,WAAWE,SAAS;IAC9C;IAEA,OAAOV,gBAAgB;QACrBS,UAAUF,QAAQE,QAAQ,IAAIR;QAC9BO;IACF;AACF"}
|