@sanity/cli-build 1.1.1 → 1.1.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.
- package/dist/_exports/_internal/env.d.ts +63 -0
- package/dist/_exports/_internal/env.js +3 -0
- package/dist/_exports/_internal/env.js.map +1 -0
- package/dist/actions/build/getEnvironmentVariables.js +54 -0
- package/dist/actions/build/getEnvironmentVariables.js.map +1 -0
- package/dist/actions/build/renderDocumentWorker/addTimestampImportMapScriptToHtml.js +1 -37
- package/dist/actions/build/renderDocumentWorker/addTimestampImportMapScriptToHtml.js.map +1 -1
- package/dist/actions/build/writeSanityRuntime.js +4 -1
- package/dist/actions/build/writeSanityRuntime.js.map +1 -1
- package/package.json +6 -2
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get environment variables prefixed with SANITY_APP_, as an object.
|
|
3
|
+
*
|
|
4
|
+
* @param options - Options for the environment variable loading
|
|
5
|
+
* {@link StudioEnvVariablesOptions}
|
|
6
|
+
* @returns Object of app environment variables
|
|
7
|
+
*
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
export declare function getAppEnvironmentVariables(
|
|
11
|
+
options?: StudioEnvVariablesOptions,
|
|
12
|
+
): Record<string, string>;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Get environment variables prefixed with SANITY_STUDIO_, as an object.
|
|
16
|
+
*
|
|
17
|
+
* @param options - Options for the environment variable loading
|
|
18
|
+
* {@link StudioEnvVariablesOptions}
|
|
19
|
+
* @returns Object of studio environment variables
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```tsx
|
|
23
|
+
* getStudioEnvironmentVariables({prefix: 'process.env.', jsonEncode: true})
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* @public
|
|
27
|
+
*/
|
|
28
|
+
export declare function getStudioEnvironmentVariables(
|
|
29
|
+
options?: StudioEnvVariablesOptions,
|
|
30
|
+
): Record<string, string>;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* The params for the `getStudioEnvironmentVariables` and `getAppEnvironmentVariables` function
|
|
34
|
+
* that gets Studio/App-focused environment variables.
|
|
35
|
+
*
|
|
36
|
+
* @public
|
|
37
|
+
*/
|
|
38
|
+
export declare interface StudioEnvVariablesOptions {
|
|
39
|
+
/**
|
|
40
|
+
* When specified includes environment variables from dotenv files (`.env`), in the same way the studio does.
|
|
41
|
+
* A `mode` must be specified, usually `development`
|
|
42
|
+
* or `production`, which will load the corresponding `.env.development` or `.env.production`.
|
|
43
|
+
* To specify where to look for the dotenv files, specify `options.envFile.envDir`.
|
|
44
|
+
*/
|
|
45
|
+
envFile?:
|
|
46
|
+
| false
|
|
47
|
+
| {
|
|
48
|
+
envDir?: string;
|
|
49
|
+
mode: string;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* When specified, JSON-encodes the values, which is handy if you want to pass
|
|
53
|
+
* this to a bundlers hardcoded defines, such as Vite's `define` or Webpack's `DefinePlugin`.
|
|
54
|
+
*/
|
|
55
|
+
jsonEncode?: boolean;
|
|
56
|
+
/**
|
|
57
|
+
* When specified adds a prefix to the environment variable keys,
|
|
58
|
+
* eg: `getStudioEnvironmentVariables({prefix: 'process.env.'})`
|
|
59
|
+
*/
|
|
60
|
+
prefix?: string;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/_exports/_internal/env.ts"],"sourcesContent":["export {\n getAppEnvironmentVariables,\n getStudioEnvironmentVariables,\n type StudioEnvVariablesOptions,\n} from '../../actions/build/getEnvironmentVariables.js'\n"],"names":["getAppEnvironmentVariables","getStudioEnvironmentVariables"],"mappings":"AAAA,SACEA,0BAA0B,EAC1BC,6BAA6B,QAExB,iDAAgD"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { loadEnv } from 'vite';
|
|
2
|
+
const appEnvPrefix = 'SANITY_APP_';
|
|
3
|
+
const studioEnvPrefix = 'SANITY_STUDIO_';
|
|
4
|
+
/**
|
|
5
|
+
* Get environment variables prefixed with SANITY_STUDIO_, as an object.
|
|
6
|
+
*
|
|
7
|
+
* @param options - Options for the environment variable loading
|
|
8
|
+
* {@link StudioEnvVariablesOptions}
|
|
9
|
+
* @returns Object of studio environment variables
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```tsx
|
|
13
|
+
* getStudioEnvironmentVariables({prefix: 'process.env.', jsonEncode: true})
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* @public
|
|
17
|
+
*/ export function getStudioEnvironmentVariables(options = {}) {
|
|
18
|
+
return getEnvironmentVariables({
|
|
19
|
+
...options,
|
|
20
|
+
varTypePrefix: studioEnvPrefix
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Get environment variables prefixed with SANITY_APP_, as an object.
|
|
25
|
+
*
|
|
26
|
+
* @param options - Options for the environment variable loading
|
|
27
|
+
* {@link StudioEnvVariablesOptions}
|
|
28
|
+
* @returns Object of app environment variables
|
|
29
|
+
*
|
|
30
|
+
* @internal
|
|
31
|
+
*/ export function getAppEnvironmentVariables(options = {}) {
|
|
32
|
+
return getEnvironmentVariables({
|
|
33
|
+
...options,
|
|
34
|
+
varTypePrefix: appEnvPrefix
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
function getEnvironmentVariables(options) {
|
|
38
|
+
const { envFile = false, jsonEncode = false, prefix = '', varTypePrefix } = options;
|
|
39
|
+
const fullEnv = envFile ? {
|
|
40
|
+
...process.env,
|
|
41
|
+
...loadEnv(envFile.mode, envFile.envDir || process.cwd(), [
|
|
42
|
+
varTypePrefix
|
|
43
|
+
])
|
|
44
|
+
} : process.env;
|
|
45
|
+
const appEnv = {};
|
|
46
|
+
for(const key in fullEnv){
|
|
47
|
+
if (key.startsWith(varTypePrefix)) {
|
|
48
|
+
appEnv[`${prefix}${key}`] = jsonEncode ? JSON.stringify(fullEnv[key] || '') : fullEnv[key] || '';
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return appEnv;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
//# sourceMappingURL=getEnvironmentVariables.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/build/getEnvironmentVariables.ts"],"sourcesContent":["import {loadEnv} from 'vite'\n\nconst appEnvPrefix = 'SANITY_APP_'\nconst studioEnvPrefix = 'SANITY_STUDIO_'\n\n/**\n * The params for the `getStudioEnvironmentVariables` and `getAppEnvironmentVariables` function\n * that gets Studio/App-focused environment variables.\n *\n * @public\n */\nexport interface StudioEnvVariablesOptions {\n /**\n * When specified includes environment variables from dotenv files (`.env`), in the same way the studio does.\n * A `mode` must be specified, usually `development`\n * or `production`, which will load the corresponding `.env.development` or `.env.production`.\n * To specify where to look for the dotenv files, specify `options.envFile.envDir`.\n */\n envFile?: false | {envDir?: string; mode: string}\n /**\n * When specified, JSON-encodes the values, which is handy if you want to pass\n * this to a bundlers hardcoded defines, such as Vite's `define` or Webpack's `DefinePlugin`.\n */\n jsonEncode?: boolean\n /**\n * When specified adds a prefix to the environment variable keys,\n * eg: `getStudioEnvironmentVariables({prefix: 'process.env.'})`\n */\n prefix?: string\n}\n\n/**\n * Get environment variables prefixed with SANITY_STUDIO_, as an object.\n *\n * @param options - Options for the environment variable loading\n * {@link StudioEnvVariablesOptions}\n * @returns Object of studio environment variables\n *\n * @example\n * ```tsx\n * getStudioEnvironmentVariables({prefix: 'process.env.', jsonEncode: true})\n * ```\n *\n * @public\n */\nexport function getStudioEnvironmentVariables(\n options: StudioEnvVariablesOptions = {},\n): Record<string, string> {\n return getEnvironmentVariables({...options, varTypePrefix: studioEnvPrefix})\n}\n\n/**\n * Get environment variables prefixed with SANITY_APP_, as an object.\n *\n * @param options - Options for the environment variable loading\n * {@link StudioEnvVariablesOptions}\n * @returns Object of app environment variables\n *\n * @internal\n */\nexport function getAppEnvironmentVariables(\n options: StudioEnvVariablesOptions = {},\n): Record<string, string> {\n return getEnvironmentVariables({...options, varTypePrefix: appEnvPrefix})\n}\n\nfunction getEnvironmentVariables(\n options: StudioEnvVariablesOptions & {varTypePrefix: string},\n): Record<string, string> {\n const {envFile = false, jsonEncode = false, prefix = '', varTypePrefix} = options\n const fullEnv = envFile\n ? {...process.env, ...loadEnv(envFile.mode, envFile.envDir || process.cwd(), [varTypePrefix])}\n : process.env\n\n const appEnv: Record<string, string> = {}\n for (const key in fullEnv) {\n if (key.startsWith(varTypePrefix)) {\n appEnv[`${prefix}${key}`] = jsonEncode\n ? JSON.stringify(fullEnv[key] || '')\n : fullEnv[key] || ''\n }\n }\n return appEnv\n}\n"],"names":["loadEnv","appEnvPrefix","studioEnvPrefix","getStudioEnvironmentVariables","options","getEnvironmentVariables","varTypePrefix","getAppEnvironmentVariables","envFile","jsonEncode","prefix","fullEnv","process","env","mode","envDir","cwd","appEnv","key","startsWith","JSON","stringify"],"mappings":"AAAA,SAAQA,OAAO,QAAO,OAAM;AAE5B,MAAMC,eAAe;AACrB,MAAMC,kBAAkB;AA4BxB;;;;;;;;;;;;;CAaC,GACD,OAAO,SAASC,8BACdC,UAAqC,CAAC,CAAC;IAEvC,OAAOC,wBAAwB;QAAC,GAAGD,OAAO;QAAEE,eAAeJ;IAAe;AAC5E;AAEA;;;;;;;;CAQC,GACD,OAAO,SAASK,2BACdH,UAAqC,CAAC,CAAC;IAEvC,OAAOC,wBAAwB;QAAC,GAAGD,OAAO;QAAEE,eAAeL;IAAY;AACzE;AAEA,SAASI,wBACPD,OAA4D;IAE5D,MAAM,EAACI,UAAU,KAAK,EAAEC,aAAa,KAAK,EAAEC,SAAS,EAAE,EAAEJ,aAAa,EAAC,GAAGF;IAC1E,MAAMO,UAAUH,UACZ;QAAC,GAAGI,QAAQC,GAAG;QAAE,GAAGb,QAAQQ,QAAQM,IAAI,EAAEN,QAAQO,MAAM,IAAIH,QAAQI,GAAG,IAAI;YAACV;SAAc,CAAC;IAAA,IAC3FM,QAAQC,GAAG;IAEf,MAAMI,SAAiC,CAAC;IACxC,IAAK,MAAMC,OAAOP,QAAS;QACzB,IAAIO,IAAIC,UAAU,CAACb,gBAAgB;YACjCW,MAAM,CAAC,GAAGP,SAASQ,KAAK,CAAC,GAAGT,aACxBW,KAAKC,SAAS,CAACV,OAAO,CAACO,IAAI,IAAI,MAC/BP,OAAO,CAACO,IAAI,IAAI;QACtB;IACF;IACA,OAAOD;AACT"}
|
|
@@ -23,7 +23,7 @@ import { parse as parseHtml } from 'node-html-parser';
|
|
|
23
23
|
function replaceTimestamp(urlStr) {
|
|
24
24
|
try {
|
|
25
25
|
const url = new URL(urlStr);
|
|
26
|
-
if (
|
|
26
|
+
if (/^sanity-cdn\\.[a-zA-Z]+$/.test(url.hostname)) {
|
|
27
27
|
url.pathname = url.pathname.replace(/\\/t\\d+/, newTimestamp);
|
|
28
28
|
}
|
|
29
29
|
return url.toString();
|
|
@@ -32,14 +32,6 @@ import { parse as parseHtml } from 'node-html-parser';
|
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
function isSanityCdnUrl(urlStr) {
|
|
36
|
-
try {
|
|
37
|
-
return /^sanity-cdn\\.[a-zA-Z]+$/.test(new URL(urlStr).hostname);
|
|
38
|
-
} catch {
|
|
39
|
-
return false;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
35
|
importMapEl.textContent = JSON.stringify({
|
|
44
36
|
imports: Object.fromEntries(
|
|
45
37
|
Object.entries(imports).map(([specifier, path]) => [specifier, replaceTimestamp(path)])
|
|
@@ -55,34 +47,6 @@ import { parse as parseHtml } from 'node-html-parser';
|
|
|
55
47
|
linkEl.href = replaceTimestamp(cssUrl);
|
|
56
48
|
document.head.appendChild(linkEl);
|
|
57
49
|
}
|
|
58
|
-
|
|
59
|
-
// Warm the CDN module connection during head parse so the cross-origin
|
|
60
|
-
// \`sanity\` fetch can start before the entry script discovers the import.
|
|
61
|
-
const firstCdnImport = Object.values(imports).find(isSanityCdnUrl);
|
|
62
|
-
|
|
63
|
-
if (firstCdnImport) {
|
|
64
|
-
const preconnectEl = document.createElement('link');
|
|
65
|
-
preconnectEl.rel = 'preconnect';
|
|
66
|
-
preconnectEl.href = new URL(firstCdnImport).origin;
|
|
67
|
-
// Module fetches are CORS; without crossorigin the warmed socket is not reused.
|
|
68
|
-
preconnectEl.crossOrigin = 'anonymous';
|
|
69
|
-
document.head.appendChild(preconnectEl);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// Start downloading the timestamped \`sanity\` module during head parse. The
|
|
73
|
-
// href reuses replaceTimestamp so it matches the importmap entry exactly —
|
|
74
|
-
// a stale timestamp here would double-fetch the largest chunk.
|
|
75
|
-
const sanityModuleUrl = imports['sanity'];
|
|
76
|
-
if (typeof sanityModuleUrl === 'string' && isSanityCdnUrl(sanityModuleUrl)) {
|
|
77
|
-
const preloadEl = document.createElement('link');
|
|
78
|
-
preloadEl.rel = 'modulepreload';
|
|
79
|
-
preloadEl.href = replaceTimestamp(sanityModuleUrl);
|
|
80
|
-
// Must match the preconnect's credentials mode, otherwise the browser
|
|
81
|
-
// treats them as separate connections and the warmed cross-origin socket
|
|
82
|
-
// is not reused for this fetch.
|
|
83
|
-
preloadEl.crossOrigin = 'anonymous';
|
|
84
|
-
document.head.appendChild(preloadEl);
|
|
85
|
-
}
|
|
86
50
|
</script>`;
|
|
87
51
|
/**
|
|
88
52
|
* @internal
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/actions/build/renderDocumentWorker/addTimestampImportMapScriptToHtml.ts"],"sourcesContent":["import {parse as parseHtml} from 'node-html-parser'\n\n/**\n * This script takes the import map from the `#__imports` script tag,\n * modifies relevant URLs that match the sanity-cdn hostname by replacing\n * the existing timestamp in the sanity-cdn URLs with a new runtime timestamp,\n * and injects the modified import map back into the HTML.\n *\n * It also synchronously creates `<link rel=\"stylesheet\">` tags for each CDN\n * CSS URL with a fresh timestamp.\n *\n * This will be injected into the HTML of the user's bundle.\n *\n * Note that this is in a separate constants file to prevent \"Cannot access\n * before initialization\" errors.\n */\nconst TIMESTAMPED_IMPORTMAP_INJECTOR_SCRIPT = `<script>\n // auto-generated script to add import map with timestamp\n const importsJson = document.getElementById('__imports')?.textContent;\n const { imports = {}, css = [], ...rest } = importsJson ? JSON.parse(importsJson) : {};\n const importMapEl = document.createElement('script');\n importMapEl.type = 'importmap';\n const newTimestamp = \\`/t\\${Math.floor(Date.now() / 1000)}\\`;\n\n function replaceTimestamp(urlStr) {\n try {\n const url = new URL(urlStr);\n if (
|
|
1
|
+
{"version":3,"sources":["../../../../src/actions/build/renderDocumentWorker/addTimestampImportMapScriptToHtml.ts"],"sourcesContent":["import {parse as parseHtml} from 'node-html-parser'\n\n/**\n * This script takes the import map from the `#__imports` script tag,\n * modifies relevant URLs that match the sanity-cdn hostname by replacing\n * the existing timestamp in the sanity-cdn URLs with a new runtime timestamp,\n * and injects the modified import map back into the HTML.\n *\n * It also synchronously creates `<link rel=\"stylesheet\">` tags for each CDN\n * CSS URL with a fresh timestamp.\n *\n * This will be injected into the HTML of the user's bundle.\n *\n * Note that this is in a separate constants file to prevent \"Cannot access\n * before initialization\" errors.\n */\nconst TIMESTAMPED_IMPORTMAP_INJECTOR_SCRIPT = `<script>\n // auto-generated script to add import map with timestamp\n const importsJson = document.getElementById('__imports')?.textContent;\n const { imports = {}, css = [], ...rest } = importsJson ? JSON.parse(importsJson) : {};\n const importMapEl = document.createElement('script');\n importMapEl.type = 'importmap';\n const newTimestamp = \\`/t\\${Math.floor(Date.now() / 1000)}\\`;\n\n function replaceTimestamp(urlStr) {\n try {\n const url = new URL(urlStr);\n if (/^sanity-cdn\\\\.[a-zA-Z]+$/.test(url.hostname)) {\n url.pathname = url.pathname.replace(/\\\\/t\\\\d+/, newTimestamp);\n }\n return url.toString();\n } catch {\n return urlStr;\n }\n }\n\n importMapEl.textContent = JSON.stringify({\n imports: Object.fromEntries(\n Object.entries(imports).map(([specifier, path]) => [specifier, replaceTimestamp(path)])\n ),\n ...rest,\n });\n document.head.appendChild(importMapEl);\n\n // Creates <link rel=\"stylesheet\"> tags with fresh timestamps.\n for (const cssUrl of css) {\n const linkEl = document.createElement('link');\n linkEl.rel = 'stylesheet';\n linkEl.href = replaceTimestamp(cssUrl);\n document.head.appendChild(linkEl);\n }\n</script>`\n\n/**\n * @internal\n */\nexport function addTimestampedImportMapScriptToHtml(\n html: string,\n importMap?: {imports?: Record<string, string>},\n autoUpdatesCssUrls?: string[],\n): string {\n if (!importMap) return html\n\n let root = parseHtml(html)\n let htmlEl = root.querySelector('html')\n if (!htmlEl) {\n const oldRoot = root\n root = parseHtml('<html></html>')\n htmlEl = root.querySelector('html')!\n htmlEl.append(oldRoot)\n }\n\n let headEl = htmlEl.querySelector('head')\n\n if (!headEl) {\n htmlEl.insertAdjacentHTML('afterbegin', '<head></head>')\n headEl = root.querySelector('head')!\n }\n\n // Include CSS URLs in the __imports JSON so the runtime script can create\n // <link> tags with fresh timestamps synchronously during head parsing.\n const importMapWithCss =\n autoUpdatesCssUrls && autoUpdatesCssUrls.length > 0\n ? {...importMap, css: autoUpdatesCssUrls}\n : importMap\n\n headEl.insertAdjacentHTML(\n 'beforeend',\n `<script type=\"application/json\" id=\"__imports\">${JSON.stringify(importMapWithCss)}</script>`,\n )\n\n headEl.insertAdjacentHTML('beforeend', TIMESTAMPED_IMPORTMAP_INJECTOR_SCRIPT)\n return root.outerHTML\n}\n"],"names":["parse","parseHtml","TIMESTAMPED_IMPORTMAP_INJECTOR_SCRIPT","addTimestampedImportMapScriptToHtml","html","importMap","autoUpdatesCssUrls","root","htmlEl","querySelector","oldRoot","append","headEl","insertAdjacentHTML","importMapWithCss","length","css","JSON","stringify","outerHTML"],"mappings":"AAAA,SAAQA,SAASC,SAAS,QAAO,mBAAkB;AAEnD;;;;;;;;;;;;;CAaC,GACD,MAAMC,wCAAwC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;SAmCtC,CAAC;AAEV;;CAEC,GACD,OAAO,SAASC,oCACdC,IAAY,EACZC,SAA8C,EAC9CC,kBAA6B;IAE7B,IAAI,CAACD,WAAW,OAAOD;IAEvB,IAAIG,OAAON,UAAUG;IACrB,IAAII,SAASD,KAAKE,aAAa,CAAC;IAChC,IAAI,CAACD,QAAQ;QACX,MAAME,UAAUH;QAChBA,OAAON,UAAU;QACjBO,SAASD,KAAKE,aAAa,CAAC;QAC5BD,OAAOG,MAAM,CAACD;IAChB;IAEA,IAAIE,SAASJ,OAAOC,aAAa,CAAC;IAElC,IAAI,CAACG,QAAQ;QACXJ,OAAOK,kBAAkB,CAAC,cAAc;QACxCD,SAASL,KAAKE,aAAa,CAAC;IAC9B;IAEA,0EAA0E;IAC1E,uEAAuE;IACvE,MAAMK,mBACJR,sBAAsBA,mBAAmBS,MAAM,GAAG,IAC9C;QAAC,GAAGV,SAAS;QAAEW,KAAKV;IAAkB,IACtCD;IAENO,OAAOC,kBAAkB,CACvB,aACA,CAAC,+CAA+C,EAAEI,KAAKC,SAAS,CAACJ,kBAAkB,SAAS,CAAC;IAG/FF,OAAOC,kBAAkB,CAAC,aAAaX;IACvC,OAAOK,KAAKY,SAAS;AACvB"}
|
|
@@ -39,7 +39,10 @@ import { renderDocument } from './renderDocument.js';
|
|
|
39
39
|
}
|
|
40
40
|
let watcher;
|
|
41
41
|
if (watch) {
|
|
42
|
-
|
|
42
|
+
// Skip the initial scan; the explicit renderAndWriteDocument() below handles first generation.
|
|
43
|
+
watcher = chokidarWatch(getPossibleDocumentComponentLocations(cwd), {
|
|
44
|
+
ignoreInitial: true
|
|
45
|
+
}).on('all', ()=>renderAndWriteDocument());
|
|
43
46
|
}
|
|
44
47
|
await renderAndWriteDocument();
|
|
45
48
|
buildDebug('Writing app.js to runtime directory');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/build/writeSanityRuntime.ts"],"sourcesContent":["import fs from 'node:fs/promises'\nimport path from 'node:path'\n\nimport {tryFindStudioConfigPath} from '@sanity/cli-core'\nimport {watch as chokidarWatch, type FSWatcher} from 'chokidar'\n\nimport {buildDebug} from './buildDebug.js'\nimport {decorateIndexWithAutoGeneratedWarning} from './decorateIndexWithAutoGeneratedWarning.js'\nimport {decorateIndexWithBridgeScript} from './decorateIndexWithBridgeScript.js'\nimport {decorateIndexWithStagingScript} from './decorateIndexWithStagingScript.js'\nimport {getEntryModule} from './getEntryModule.js'\nimport {getPossibleDocumentComponentLocations} from './getPossibleDocumentComponentLocations.js'\nimport {renderDocument} from './renderDocument.js'\n\ninterface RuntimeOptions {\n cwd: string\n reactStrictMode: boolean | undefined\n watch: boolean\n\n appTitle?: string\n basePath?: string\n entry?: string\n isApp?: boolean\n isWorkbenchApp?: boolean\n}\n\n/**\n * Generates the `.sanity/runtime` directory, and optionally watches for custom\n * document files, rebuilding when they change\n *\n * @param options - Current working directory (Sanity root dir), and whether or not to watch\n * @returns A watcher instance if watch is enabled, undefined otherwise\n * @internal\n */\nexport async function writeSanityRuntime(options: RuntimeOptions): Promise<{\n entries: {relativeConfigLocation: string | null; relativeEntry: string | null}\n watcher: FSWatcher | undefined\n}> {\n const {appTitle, basePath, cwd, entry, isApp, isWorkbenchApp, reactStrictMode, watch} = options\n const runtimeDir = path.join(cwd, '.sanity', 'runtime')\n\n buildDebug('Making runtime directory')\n await fs.mkdir(runtimeDir, {recursive: true})\n\n async function renderAndWriteDocument() {\n buildDebug('Rendering document template')\n const indexHtml = decorateIndexWithStagingScript(\n decorateIndexWithBridgeScript(\n decorateIndexWithAutoGeneratedWarning(\n await renderDocument({\n isApp,\n props: {\n basePath: basePath || '/',\n entryPath: `/${toForwardSlashes(path.relative(cwd, path.join(runtimeDir, 'app.js')))}`,\n title: appTitle,\n },\n studioRootPath: cwd,\n }),\n ),\n ),\n )\n\n buildDebug('Writing index.html to runtime directory')\n await fs.writeFile(path.join(runtimeDir, 'index.html'), indexHtml)\n }\n\n let watcher: FSWatcher | undefined\n\n if (watch) {\n watcher = chokidarWatch(getPossibleDocumentComponentLocations(cwd)).on('all'
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/build/writeSanityRuntime.ts"],"sourcesContent":["import fs from 'node:fs/promises'\nimport path from 'node:path'\n\nimport {tryFindStudioConfigPath} from '@sanity/cli-core'\nimport {watch as chokidarWatch, type FSWatcher} from 'chokidar'\n\nimport {buildDebug} from './buildDebug.js'\nimport {decorateIndexWithAutoGeneratedWarning} from './decorateIndexWithAutoGeneratedWarning.js'\nimport {decorateIndexWithBridgeScript} from './decorateIndexWithBridgeScript.js'\nimport {decorateIndexWithStagingScript} from './decorateIndexWithStagingScript.js'\nimport {getEntryModule} from './getEntryModule.js'\nimport {getPossibleDocumentComponentLocations} from './getPossibleDocumentComponentLocations.js'\nimport {renderDocument} from './renderDocument.js'\n\ninterface RuntimeOptions {\n cwd: string\n reactStrictMode: boolean | undefined\n watch: boolean\n\n appTitle?: string\n basePath?: string\n entry?: string\n isApp?: boolean\n isWorkbenchApp?: boolean\n}\n\n/**\n * Generates the `.sanity/runtime` directory, and optionally watches for custom\n * document files, rebuilding when they change\n *\n * @param options - Current working directory (Sanity root dir), and whether or not to watch\n * @returns A watcher instance if watch is enabled, undefined otherwise\n * @internal\n */\nexport async function writeSanityRuntime(options: RuntimeOptions): Promise<{\n entries: {relativeConfigLocation: string | null; relativeEntry: string | null}\n watcher: FSWatcher | undefined\n}> {\n const {appTitle, basePath, cwd, entry, isApp, isWorkbenchApp, reactStrictMode, watch} = options\n const runtimeDir = path.join(cwd, '.sanity', 'runtime')\n\n buildDebug('Making runtime directory')\n await fs.mkdir(runtimeDir, {recursive: true})\n\n async function renderAndWriteDocument() {\n buildDebug('Rendering document template')\n const indexHtml = decorateIndexWithStagingScript(\n decorateIndexWithBridgeScript(\n decorateIndexWithAutoGeneratedWarning(\n await renderDocument({\n isApp,\n props: {\n basePath: basePath || '/',\n entryPath: `/${toForwardSlashes(path.relative(cwd, path.join(runtimeDir, 'app.js')))}`,\n title: appTitle,\n },\n studioRootPath: cwd,\n }),\n ),\n ),\n )\n\n buildDebug('Writing index.html to runtime directory')\n await fs.writeFile(path.join(runtimeDir, 'index.html'), indexHtml)\n }\n\n let watcher: FSWatcher | undefined\n\n if (watch) {\n // Skip the initial scan; the explicit renderAndWriteDocument() below handles first generation.\n watcher = chokidarWatch(getPossibleDocumentComponentLocations(cwd), {ignoreInitial: true}).on(\n 'all',\n () => renderAndWriteDocument(),\n )\n }\n\n await renderAndWriteDocument()\n\n buildDebug('Writing app.js to runtime directory')\n const {relativeConfigLocation, relativeEntry} = await resolveEntries({\n cwd,\n entry,\n isApp,\n isWorkbenchApp,\n runtimeDir,\n })\n const appJsContent = getEntryModule({\n basePath,\n entry: relativeEntry ?? undefined,\n isApp,\n reactStrictMode,\n relativeConfigLocation,\n })\n await fs.writeFile(path.join(runtimeDir, 'app.js'), appJsContent)\n\n return {\n entries: {\n relativeConfigLocation,\n relativeEntry,\n },\n watcher,\n }\n}\n\n/**\n * Resolves the relative entry paths for a Sanity project without writing any\n * runtime files to disk. Used by federation builds that skip the full runtime\n * generation but still need entry metadata for the vite plugin.\n */\nexport async function resolveEntries(options: {\n cwd: string\n entry?: string\n isApp?: boolean\n isWorkbenchApp?: boolean\n runtimeDir?: string\n}): Promise<{relativeConfigLocation: string | null; relativeEntry: string | null}> {\n const {cwd, entry, isApp, isWorkbenchApp} = options\n const runtimeDir = options.runtimeDir ?? path.join(cwd, '.sanity', 'runtime')\n\n let relativeConfigLocation: string | null = null\n if (!isApp) {\n const studioConfigPath = await tryFindStudioConfigPath(cwd)\n relativeConfigLocation = studioConfigPath\n ? toForwardSlashes(path.relative(runtimeDir, studioConfigPath))\n : null\n }\n\n // Only a *branded* app (`unstable_defineApp`) that declares no `entry` has no\n // navigable app view (sanity-io/workbench spec 002-workbench-extension-api,\n // US5): `null` entry tells the runtime/federation to skip the `./App` render\n // path. Non-branded (legacy SDK) apps keep the historical `./src/App` default,\n // and studios ignore `relativeEntry` — so gating on `isApp` here would regress\n // non-opted-in apps to the dock-only stub.\n const relativeEntry =\n isWorkbenchApp && !entry\n ? null\n : toForwardSlashes(path.relative(runtimeDir, path.resolve(cwd, entry || './src/App')))\n\n return {relativeConfigLocation, relativeEntry}\n}\n\nfunction toForwardSlashes(filePath: string): string {\n return filePath.replaceAll('\\\\', '/')\n}\n"],"names":["fs","path","tryFindStudioConfigPath","watch","chokidarWatch","buildDebug","decorateIndexWithAutoGeneratedWarning","decorateIndexWithBridgeScript","decorateIndexWithStagingScript","getEntryModule","getPossibleDocumentComponentLocations","renderDocument","writeSanityRuntime","options","appTitle","basePath","cwd","entry","isApp","isWorkbenchApp","reactStrictMode","runtimeDir","join","mkdir","recursive","renderAndWriteDocument","indexHtml","props","entryPath","toForwardSlashes","relative","title","studioRootPath","writeFile","watcher","ignoreInitial","on","relativeConfigLocation","relativeEntry","resolveEntries","appJsContent","undefined","entries","studioConfigPath","resolve","filePath","replaceAll"],"mappings":"AAAA,OAAOA,QAAQ,mBAAkB;AACjC,OAAOC,UAAU,YAAW;AAE5B,SAAQC,uBAAuB,QAAO,mBAAkB;AACxD,SAAQC,SAASC,aAAa,QAAuB,WAAU;AAE/D,SAAQC,UAAU,QAAO,kBAAiB;AAC1C,SAAQC,qCAAqC,QAAO,6CAA4C;AAChG,SAAQC,6BAA6B,QAAO,qCAAoC;AAChF,SAAQC,8BAA8B,QAAO,sCAAqC;AAClF,SAAQC,cAAc,QAAO,sBAAqB;AAClD,SAAQC,qCAAqC,QAAO,6CAA4C;AAChG,SAAQC,cAAc,QAAO,sBAAqB;AAclD;;;;;;;CAOC,GACD,OAAO,eAAeC,mBAAmBC,OAAuB;IAI9D,MAAM,EAACC,QAAQ,EAAEC,QAAQ,EAAEC,GAAG,EAAEC,KAAK,EAAEC,KAAK,EAAEC,cAAc,EAAEC,eAAe,EAAEjB,KAAK,EAAC,GAAGU;IACxF,MAAMQ,aAAapB,KAAKqB,IAAI,CAACN,KAAK,WAAW;IAE7CX,WAAW;IACX,MAAML,GAAGuB,KAAK,CAACF,YAAY;QAACG,WAAW;IAAI;IAE3C,eAAeC;QACbpB,WAAW;QACX,MAAMqB,YAAYlB,+BAChBD,8BACED,sCACE,MAAMK,eAAe;YACnBO;YACAS,OAAO;gBACLZ,UAAUA,YAAY;gBACtBa,WAAW,CAAC,CAAC,EAAEC,iBAAiB5B,KAAK6B,QAAQ,CAACd,KAAKf,KAAKqB,IAAI,CAACD,YAAY,aAAa;gBACtFU,OAAOjB;YACT;YACAkB,gBAAgBhB;QAClB;QAKNX,WAAW;QACX,MAAML,GAAGiC,SAAS,CAAChC,KAAKqB,IAAI,CAACD,YAAY,eAAeK;IAC1D;IAEA,IAAIQ;IAEJ,IAAI/B,OAAO;QACT,+FAA+F;QAC/F+B,UAAU9B,cAAcM,sCAAsCM,MAAM;YAACmB,eAAe;QAAI,GAAGC,EAAE,CAC3F,OACA,IAAMX;IAEV;IAEA,MAAMA;IAENpB,WAAW;IACX,MAAM,EAACgC,sBAAsB,EAAEC,aAAa,EAAC,GAAG,MAAMC,eAAe;QACnEvB;QACAC;QACAC;QACAC;QACAE;IACF;IACA,MAAMmB,eAAe/B,eAAe;QAClCM;QACAE,OAAOqB,iBAAiBG;QACxBvB;QACAE;QACAiB;IACF;IACA,MAAMrC,GAAGiC,SAAS,CAAChC,KAAKqB,IAAI,CAACD,YAAY,WAAWmB;IAEpD,OAAO;QACLE,SAAS;YACPL;YACAC;QACF;QACAJ;IACF;AACF;AAEA;;;;CAIC,GACD,OAAO,eAAeK,eAAe1B,OAMpC;IACC,MAAM,EAACG,GAAG,EAAEC,KAAK,EAAEC,KAAK,EAAEC,cAAc,EAAC,GAAGN;IAC5C,MAAMQ,aAAaR,QAAQQ,UAAU,IAAIpB,KAAKqB,IAAI,CAACN,KAAK,WAAW;IAEnE,IAAIqB,yBAAwC;IAC5C,IAAI,CAACnB,OAAO;QACV,MAAMyB,mBAAmB,MAAMzC,wBAAwBc;QACvDqB,yBAAyBM,mBACrBd,iBAAiB5B,KAAK6B,QAAQ,CAACT,YAAYsB,qBAC3C;IACN;IAEA,8EAA8E;IAC9E,4EAA4E;IAC5E,6EAA6E;IAC7E,+EAA+E;IAC/E,+EAA+E;IAC/E,2CAA2C;IAC3C,MAAML,gBACJnB,kBAAkB,CAACF,QACf,OACAY,iBAAiB5B,KAAK6B,QAAQ,CAACT,YAAYpB,KAAK2C,OAAO,CAAC5B,KAAKC,SAAS;IAE5E,OAAO;QAACoB;QAAwBC;IAAa;AAC/C;AAEA,SAAST,iBAAiBgB,QAAgB;IACxC,OAAOA,SAASC,UAAU,CAAC,MAAM;AACnC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sanity/cli-build",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"description": "Internal Sanity package for building studios and apps",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
@@ -32,6 +32,10 @@
|
|
|
32
32
|
"source": "./src/_exports/_internal/build.ts",
|
|
33
33
|
"default": "./dist/_exports/_internal/build.js"
|
|
34
34
|
},
|
|
35
|
+
"./_internal/env": {
|
|
36
|
+
"source": "./src/_exports/_internal/env.ts",
|
|
37
|
+
"default": "./dist/_exports/_internal/env.js"
|
|
38
|
+
},
|
|
35
39
|
"./_internal/extract": {
|
|
36
40
|
"source": "./src/_exports/_internal/extract.ts",
|
|
37
41
|
"default": "./dist/_exports/_internal/extract.js"
|
|
@@ -63,7 +67,7 @@
|
|
|
63
67
|
"vite": "^8.1.0",
|
|
64
68
|
"zod": "^4.4.3",
|
|
65
69
|
"@sanity/cli-core": "^2.1.1",
|
|
66
|
-
"@sanity/workbench-cli": "^1.1.
|
|
70
|
+
"@sanity/workbench-cli": "^1.1.1"
|
|
67
71
|
},
|
|
68
72
|
"devDependencies": {
|
|
69
73
|
"@eslint/compat": "^2.1.0",
|