@sanity/cli-build 7.1.1 → 7.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/build.d.ts +19 -5
- package/dist/_exports/_internal/build.js +1 -1
- package/dist/_exports/_internal/build.js.map +1 -1
- package/dist/actions/build/buildApp.js +5 -1
- package/dist/actions/build/buildApp.js.map +1 -1
- package/dist/actions/build/buildStudio.js +5 -1
- package/dist/actions/build/buildStudio.js.map +1 -1
- package/dist/actions/build/decorateIndexWithAuthHashScript.js +42 -0
- package/dist/actions/build/decorateIndexWithAuthHashScript.js.map +1 -0
- package/dist/actions/build/vite/plugin-sanity-build-entries.js +4 -1
- package/dist/actions/build/vite/plugin-sanity-build-entries.js.map +1 -1
- package/dist/actions/build/writeSanityRuntime.js +5 -1
- package/dist/actions/build/writeSanityRuntime.js.map +1 -1
- package/dist/actions/schema/buildStudioSchemasAndManifestsWorker.js +25 -74
- package/dist/actions/schema/buildStudioSchemasAndManifestsWorker.js.map +1 -1
- package/dist/util/compareDependencyVersions.js +84 -43
- package/dist/util/compareDependencyVersions.js.map +1 -1
- package/package.json +6 -6
|
@@ -11,9 +11,18 @@ interface UnresolvedPrerelease {
|
|
|
11
11
|
pkg: string;
|
|
12
12
|
version: string;
|
|
13
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* A package whose runtime version Module Server did not report, because of a network error,
|
|
16
|
+
* a timeout or a 5xx.
|
|
17
|
+
*/
|
|
18
|
+
interface UnavailableDependencyVersion {
|
|
19
|
+
pkg: string;
|
|
20
|
+
reason: string;
|
|
21
|
+
}
|
|
14
22
|
interface CompareDependencyVersionsResult {
|
|
15
23
|
mismatched: Array<CompareDependencyVersions>;
|
|
16
24
|
unresolvedPrerelease: Array<UnresolvedPrerelease>;
|
|
25
|
+
unavailable?: Array<UnavailableDependencyVersion>;
|
|
17
26
|
}
|
|
18
27
|
interface CompareDependencyVersionsOptions {
|
|
19
28
|
/** When provided, uses the app-specific module endpoint instead of the default endpoint. */
|
|
@@ -35,16 +44,21 @@ interface CompareDependencyVersionsOptions {
|
|
|
35
44
|
* @param workDir - The path to the working directory containing the package.json file.
|
|
36
45
|
* @param options - Optional configuration for version comparison.
|
|
37
46
|
*
|
|
38
|
-
* @returns A promise that resolves to an object containing `mismatched` (packages whose local and remote versions differ)
|
|
39
|
-
*
|
|
47
|
+
* @returns A promise that resolves to an object containing `mismatched` (packages whose local and remote versions differ),
|
|
48
|
+
* `unresolvedPrerelease` (packages with prerelease versions that could not be resolved remotely) and `unavailable`
|
|
49
|
+
* (packages Module Server did not answer for, because of a network error, a timeout or a 5xx).
|
|
40
50
|
*
|
|
41
|
-
* @throws Throws an error if
|
|
42
|
-
* of a package cannot be parsed.
|
|
51
|
+
* @throws Throws an error if a non-prerelease package is not found remotely, if Module Server answers with an unexpected
|
|
52
|
+
* response, or if the local version of a package cannot be parsed.
|
|
43
53
|
*/
|
|
44
54
|
declare function compareDependencyVersions(packages: {
|
|
45
55
|
name: string;
|
|
46
56
|
version: string;
|
|
47
57
|
}[], workDir: string, { appId }?: CompareDependencyVersionsOptions): Promise<CompareDependencyVersionsResult>;
|
|
58
|
+
/**
|
|
59
|
+
* @internal
|
|
60
|
+
*/
|
|
61
|
+
declare function getUnavailableVersionsWarning(unavailable: UnavailableDependencyVersion[]): string;
|
|
48
62
|
type MessageFunc = ({ message }: {
|
|
49
63
|
message: string;
|
|
50
64
|
}) => void;
|
|
@@ -397,5 +411,5 @@ declare function writeSanityRuntime(options: RuntimeOptions): Promise<{
|
|
|
397
411
|
* ignored by default in typical `.gitignore` files.
|
|
398
412
|
*/
|
|
399
413
|
declare const SANITY_CACHE_DIR = "node_modules/.sanity";
|
|
400
|
-
export { type BuildAppEventListener, type BuildStudioEventListener, type CompareDependencyVersions, type CompareDependencyVersionsResult, SANITY_CACHE_DIR, type UnresolvedPrerelease, buildApp, buildStaticFiles, buildStudio, checkRequiredDependencies, checkStudioDependencyVersions, compareDependencyVersions, extendViteConfigWithUserConfig, getViteConfig, resolveVendorBuildConfig, writeSanityRuntime };
|
|
414
|
+
export { type BuildAppEventListener, type BuildStudioEventListener, type CompareDependencyVersions, type CompareDependencyVersionsResult, SANITY_CACHE_DIR, type UnavailableDependencyVersion, type UnresolvedPrerelease, buildApp, buildStaticFiles, buildStudio, checkRequiredDependencies, checkStudioDependencyVersions, compareDependencyVersions, extendViteConfigWithUserConfig, getUnavailableVersionsWarning, getViteConfig, resolveVendorBuildConfig, writeSanityRuntime };
|
|
401
415
|
//# sourceMappingURL=build.d.ts.map
|
|
@@ -7,6 +7,6 @@ export { extendViteConfigWithUserConfig, getViteConfig } from '../../actions/bui
|
|
|
7
7
|
export { resolveVendorBuildConfig } from '../../actions/build/resolveVendorBuildConfig.js';
|
|
8
8
|
export { writeSanityRuntime } from '../../actions/build/writeSanityRuntime.js';
|
|
9
9
|
export { SANITY_CACHE_DIR } from '../../constants.js';
|
|
10
|
-
export { compareDependencyVersions } from '../../util/compareDependencyVersions.js';
|
|
10
|
+
export { compareDependencyVersions, getUnavailableVersionsWarning } from '../../util/compareDependencyVersions.js';
|
|
11
11
|
|
|
12
12
|
//# sourceMappingURL=build.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/_exports/_internal/build.ts"],"sourcesContent":["export {buildApp, type BuildAppEventListener} from '../../actions/build/buildApp.js'\nexport {buildStaticFiles} from '../../actions/build/buildStaticFiles.js'\nexport {buildStudio, type BuildStudioEventListener} from '../../actions/build/buildStudio.js'\nexport {checkRequiredDependencies} from '../../actions/build/checkRequiredDependencies.js'\nexport {checkStudioDependencyVersions} from '../../actions/build/checkStudioDependencyVersions.js'\nexport {extendViteConfigWithUserConfig, getViteConfig} from '../../actions/build/getViteConfig.js'\nexport {resolveVendorBuildConfig} from '../../actions/build/resolveVendorBuildConfig.js'\nexport {writeSanityRuntime} from '../../actions/build/writeSanityRuntime.js'\nexport {SANITY_CACHE_DIR} from '../../constants.js'\nexport {\n compareDependencyVersions,\n type CompareDependencyVersions,\n type CompareDependencyVersionsResult,\n type UnresolvedPrerelease,\n} from '../../util/compareDependencyVersions.js'\n"],"names":["buildApp","buildStaticFiles","buildStudio","checkRequiredDependencies","checkStudioDependencyVersions","extendViteConfigWithUserConfig","getViteConfig","resolveVendorBuildConfig","writeSanityRuntime","SANITY_CACHE_DIR","compareDependencyVersions"],"mappings":"AAAA,SAAQA,QAAQ,QAAmC,kCAAiC;AACpF,SAAQC,gBAAgB,QAAO,0CAAyC;AACxE,SAAQC,WAAW,QAAsC,qCAAoC;AAC7F,SAAQC,yBAAyB,QAAO,mDAAkD;AAC1F,SAAQC,6BAA6B,QAAO,uDAAsD;AAClG,SAAQC,8BAA8B,EAAEC,aAAa,QAAO,uCAAsC;AAClG,SAAQC,wBAAwB,QAAO,kDAAiD;AACxF,SAAQC,kBAAkB,QAAO,4CAA2C;AAC5E,SAAQC,gBAAgB,QAAO,qBAAoB;AACnD,SACEC,yBAAyB,
|
|
1
|
+
{"version":3,"sources":["../../../src/_exports/_internal/build.ts"],"sourcesContent":["export {buildApp, type BuildAppEventListener} from '../../actions/build/buildApp.js'\nexport {buildStaticFiles} from '../../actions/build/buildStaticFiles.js'\nexport {buildStudio, type BuildStudioEventListener} from '../../actions/build/buildStudio.js'\nexport {checkRequiredDependencies} from '../../actions/build/checkRequiredDependencies.js'\nexport {checkStudioDependencyVersions} from '../../actions/build/checkStudioDependencyVersions.js'\nexport {extendViteConfigWithUserConfig, getViteConfig} from '../../actions/build/getViteConfig.js'\nexport {resolveVendorBuildConfig} from '../../actions/build/resolveVendorBuildConfig.js'\nexport {writeSanityRuntime} from '../../actions/build/writeSanityRuntime.js'\nexport {SANITY_CACHE_DIR} from '../../constants.js'\nexport {\n compareDependencyVersions,\n type CompareDependencyVersions,\n type CompareDependencyVersionsResult,\n getUnavailableVersionsWarning,\n type UnavailableDependencyVersion,\n type UnresolvedPrerelease,\n} from '../../util/compareDependencyVersions.js'\n"],"names":["buildApp","buildStaticFiles","buildStudio","checkRequiredDependencies","checkStudioDependencyVersions","extendViteConfigWithUserConfig","getViteConfig","resolveVendorBuildConfig","writeSanityRuntime","SANITY_CACHE_DIR","compareDependencyVersions","getUnavailableVersionsWarning"],"mappings":"AAAA,SAAQA,QAAQ,QAAmC,kCAAiC;AACpF,SAAQC,gBAAgB,QAAO,0CAAyC;AACxE,SAAQC,WAAW,QAAsC,qCAAoC;AAC7F,SAAQC,yBAAyB,QAAO,mDAAkD;AAC1F,SAAQC,6BAA6B,QAAO,uDAAsD;AAClG,SAAQC,8BAA8B,EAAEC,aAAa,QAAO,uCAAsC;AAClG,SAAQC,wBAAwB,QAAO,kDAAiD;AACxF,SAAQC,kBAAkB,QAAO,4CAA2C;AAC5E,SAAQC,gBAAgB,QAAO,qBAAoB;AACnD,SACEC,yBAAyB,EAGzBC,6BAA6B,QAGxB,0CAAyC"}
|
|
@@ -9,6 +9,7 @@ import { confirm, getTimer, logSymbols, spinner } from '@sanity/cli-core/ux';
|
|
|
9
9
|
import { readBuiltManifest } from '@sanity/workbench-cli/build';
|
|
10
10
|
import { parse as semverParse } from 'semver';
|
|
11
11
|
import { AppBuildTrace } from '../../telemetry/build.telemetry.js';
|
|
12
|
+
import { getUnavailableVersionsWarning } from '../../util/compareDependencyVersions.js';
|
|
12
13
|
import { formatModuleSizes, sortModulesBySize } from '../../util/moduleFormatUtils.js';
|
|
13
14
|
import { buildDebug } from './buildDebug.js';
|
|
14
15
|
import { buildStaticFiles } from './buildStaticFiles.js';
|
|
@@ -93,7 +94,10 @@ import { resolveVendorBuildConfig } from './resolveVendorBuildConfig.js';
|
|
|
93
94
|
// Warn if auto updates enabled but no appId configured.
|
|
94
95
|
options.checkAppId();
|
|
95
96
|
// Check the versions
|
|
96
|
-
const { mismatched, unresolvedPrerelease } = await options.compareDependencyVersions(autoUpdatedPackages);
|
|
97
|
+
const { mismatched, unavailable = [], unresolvedPrerelease } = await options.compareDependencyVersions(autoUpdatedPackages);
|
|
98
|
+
if (unavailable.length > 0) {
|
|
99
|
+
output.warn(getUnavailableVersionsWarning(unavailable));
|
|
100
|
+
}
|
|
97
101
|
if (unresolvedPrerelease.length > 0) {
|
|
98
102
|
await handlePrereleaseVersions({
|
|
99
103
|
onPreReleaseInInteractiveAutoUpdate: eventListener.onPreReleaseInInteractiveAutoUpdate,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/build/buildApp.ts"],"sourcesContent":["import {rm} from 'node:fs/promises'\nimport path from 'node:path'\nimport {styleText} from 'node:util'\n\nimport {exitCodes} from '@sanity/cli-core/ExitCodes'\nimport {getLocalPackageVersion} from '@sanity/cli-core/package-manager'\nimport {getCliTelemetry} from '@sanity/cli-core/telemetry'\nimport {type CliConfig, type Output, type UserViteConfig} from '@sanity/cli-core/types'\nimport {isInteractive} from '@sanity/cli-core/util'\nimport {confirm, getTimer, logSymbols, spinner, type SpinnerInstance} from '@sanity/cli-core/ux'\nimport {readBuiltManifest, type WorkbenchExposes} from '@sanity/workbench-cli/build'\nimport {parse as semverParse} from 'semver'\n\nimport {AppBuildTrace} from '../../telemetry/build.telemetry.js'\nimport {CompareDependencyVersionsResult} from '../../util/compareDependencyVersions.js'\nimport {formatModuleSizes, sortModulesBySize} from '../../util/moduleFormatUtils.js'\nimport {buildDebug} from './buildDebug.js'\nimport {buildStaticFiles} from './buildStaticFiles.js'\nimport {BuildEventListener} from './eventListener.js'\nimport {getAutoUpdatesCssUrls, getAutoUpdatesImportMap} from './getAutoUpdatesImportMap.js'\nimport {getAppEnvironmentVariables} from './getEnvironmentVariables.js'\nimport {handlePrereleaseVersions} from './handlePrereleaseVersions.js'\nimport {resolveVendorBuildConfig} from './resolveVendorBuildConfig.js'\n\nexport type BuildAppEventListener = BuildEventListener\nexport interface BuildOptions {\n appId: string | undefined\n appTitle: string | undefined\n autoUpdatesEnabled: boolean\n checkAppId: () => void\n compareDependencyVersions: (\n packages: {name: string; version: string}[],\n ) => Promise<CompareDependencyVersionsResult>\n determineBasePath: () => string\n entry: string | undefined\n eventListener: Partial<BuildAppEventListener>\n isWorkbenchApp: boolean\n minify: boolean\n outDir: string | undefined\n output: Output\n reactCompiler: CliConfig['reactCompiler']\n schemaExtraction: CliConfig['schemaExtraction']\n sourceMap: boolean\n stats: boolean\n unattendedMode: boolean\n vite: UserViteConfig | undefined\n workDir: string\n\n exposes?: WorkbenchExposes\n /**\n * The build is running under Sanity Blueprints (invoked programmatically by\n * `@sanity/runtime-cli`), so emit the statically-imported resource-bindings\n * module Brett rewrites at deploy. Defaults to `false`, so a normal\n * `sanity build`/`dev`/`preview` never emits it.\n */\n isBlueprints?: boolean\n\n /** The workbench app's bus identity (`__SANITY_APP_ID__`). */\n workbenchAppId?: string\n}\n\n/**\n * Internal build app that avoids depending on flags for CLI config.\n * @param options - options for the build\n */\nexport async function buildApp(\n options: BuildOptions,\n): Promise<{mfManifest: Record<string, unknown> | undefined}> {\n buildDebug(`Building app`)\n\n const {appId, determineBasePath, eventListener, outDir, output, workDir} = options\n let {autoUpdatesEnabled} = options\n const unattendedMode = options.unattendedMode\n\n const timer = getTimer()\n\n const defaultOutputDir = path.resolve(path.join(workDir, 'dist'))\n const outputDir = path.resolve(outDir || defaultOutputDir)\n\n const installedSdkVersion = await getLocalPackageVersion('@sanity/sdk-react', workDir)\n const installedSanityVersion = await getLocalPackageVersion('sanity', workDir)\n\n // A Media Library config ships no SDK app — its inputs are island-rendered\n // by `sanity`, so verify that instead and skip the SDK auto-update\n // machinery. Checked via the `appType` discriminator, not the mere presence\n // of a config: a future `ConfigSchema` member must not inherit these\n // media-library build semantics by default.\n const isMediaLibraryConfigBuild = options.exposes?.config?.appType === 'media-library'\n\n if (!installedSdkVersion && !isMediaLibraryConfigBuild) {\n output.error(`Failed to find installed @sanity/sdk-react version`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n return {mfManifest: undefined}\n }\n\n if (isMediaLibraryConfigBuild && !installedSanityVersion) {\n output.error(`Failed to find installed sanity version`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n return {mfManifest: undefined}\n }\n\n let autoUpdatesImports = {}\n let autoUpdatesCssUrls: string[] = []\n\n if (autoUpdatesEnabled && !isMediaLibraryConfigBuild) {\n // Get the clean version without build metadata: https://semver.org/#spec-item-10\n const cleanSDKVersion = semverParse(installedSdkVersion)?.version\n if (!cleanSDKVersion) {\n output.error(`Failed to parse installed SDK version: ${installedSdkVersion}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n return {mfManifest: undefined}\n }\n\n // Sanity might not be installed, but if it is, we want to auto update it.\n const cleanSanityVersion = semverParse(installedSanityVersion)?.version\n\n const autoUpdatedPackages = [\n {name: '@sanity/sdk', version: cleanSDKVersion},\n {name: '@sanity/sdk-react', version: cleanSDKVersion},\n ...(cleanSanityVersion\n ? [{cssFile: 'index.css', name: 'sanity' as const, version: cleanSanityVersion}]\n : []),\n ]\n autoUpdatesImports = getAutoUpdatesImportMap(autoUpdatedPackages, {appId})\n autoUpdatesCssUrls = getAutoUpdatesCssUrls(autoUpdatedPackages, {appId})\n\n output.log(`${logSymbols.info} Building with auto-updates enabled`)\n\n // Warn if auto updates enabled but no appId configured.\n options.checkAppId()\n\n // Check the versions\n const {mismatched, unresolvedPrerelease} =\n await options.compareDependencyVersions(autoUpdatedPackages)\n\n if (unresolvedPrerelease.length > 0) {\n await handlePrereleaseVersions({\n onPreReleaseInInteractiveAutoUpdate: eventListener.onPreReleaseInInteractiveAutoUpdate,\n onPreReleaseInNonInteractiveAutoUpdate:\n eventListener.onPreReleaseInNonInteractiveAutoUpdate,\n unattendedMode,\n unresolvedPrerelease,\n })\n autoUpdatesImports = {}\n autoUpdatesCssUrls = []\n autoUpdatesEnabled = false\n }\n\n if (mismatched.length > 0 && autoUpdatesEnabled) {\n const versionMismatchWarning =\n `The following local package versions are different from the versions currently served at runtime.\\n` +\n `When using auto updates, we recommend that you test locally with the same versions before deploying. \\n\\n` +\n `${mismatched.map((mod) => ` - ${mod.pkg} (local version: ${mod.installed}, runtime version: ${mod.remote})`).join('\\n')}`\n\n // If it is non-interactive or in unattended mode, we don't want to prompt\n if (isInteractive() && !unattendedMode) {\n const shouldContinue = await confirm({\n default: false,\n message: styleText('yellow', `${versionMismatchWarning} \\n\\nContinue anyway?`),\n })\n\n if (!shouldContinue) {\n output.error('Declined to continue with build', {exit: exitCodes.RUNTIME_ERROR})\n return {mfManifest: undefined}\n }\n } else {\n // if non-interactive or unattended, just show the warning\n output.warn(versionMismatchWarning)\n }\n }\n }\n\n const envVarKeys = Object.keys(getAppEnvironmentVariables())\n if (envVarKeys.length > 0) {\n output.log('\\nIncluding the following environment variables as part of the JavaScript bundle:')\n for (const key of envVarKeys) output.log(`- ${key}`)\n output.log('')\n }\n\n let shouldClean = true\n if (outputDir !== defaultOutputDir && !unattendedMode && isInteractive()) {\n shouldClean = await confirm({\n default: true,\n message: `Do you want to delete the existing directory (${outputDir}) first?`,\n })\n }\n\n const basePath = determineBasePath()\n\n let spin: SpinnerInstance\n if (shouldClean) {\n timer.start('cleanOutputFolder')\n spin = spinner('Clean output folder').start()\n await rm(outputDir, {force: true, recursive: true})\n const cleanDuration = timer.end('cleanOutputFolder')\n spin.text = `Clean output folder (${cleanDuration.toFixed(0)}ms)`\n spin.succeed()\n }\n\n spin = spinner(`Building Sanity application`).start()\n\n const trace = getCliTelemetry().trace(AppBuildTrace)\n trace.start()\n\n let autoUpdates\n if (autoUpdatesEnabled && !isMediaLibraryConfigBuild) {\n autoUpdates = {\n cssUrls: autoUpdatesCssUrls,\n imports: autoUpdatesImports,\n // Module server `sanity` imports `styled-components` by name, so the app provides it when it has it.\n vendor: await resolveVendorBuildConfig({\n cwd: workDir,\n isApp: !(await getLocalPackageVersion('styled-components', workDir)),\n }),\n }\n }\n\n try {\n timer.start('bundleStudio')\n\n const bundle = await buildStaticFiles({\n appTitle: options.appTitle,\n autoUpdates,\n basePath,\n cwd: workDir,\n entry: options.entry,\n exposes: options.exposes,\n isApp: true,\n isBlueprints: options.isBlueprints,\n isWorkbenchApp: options.isWorkbenchApp,\n minify: options.minify,\n outputDir,\n reactCompiler: options.reactCompiler,\n schemaExtraction: options.schemaExtraction,\n sourceMap: options.sourceMap,\n vite: options.vite,\n workbenchAppId: options.workbenchAppId,\n })\n const mfManifest = options.isWorkbenchApp ? await readBuiltManifest(outputDir) : undefined\n\n trace.log({\n outputSize: bundle.chunks\n .flatMap((chunk) => chunk.modules.flatMap((mod) => mod.renderedLength))\n .reduce((sum, n) => sum + n, 0),\n })\n const buildDuration = timer.end('bundleStudio')\n\n spin.text = `Build Sanity application (${buildDuration.toFixed(0)}ms)`\n spin.succeed()\n\n if (options.stats) {\n output.log('\\nLargest module files:')\n output.log(formatModuleSizes(sortModulesBySize(bundle.chunks).slice(0, 15)))\n }\n\n trace.complete()\n return {mfManifest}\n } catch (error) {\n spin.fail()\n trace.error(error)\n const message = error instanceof Error ? error.message : String(error)\n buildDebug(`Failed to build Sanity application`, {error})\n output.error(`Failed to build Sanity application: ${message}`, {exit: exitCodes.RUNTIME_ERROR})\n return {mfManifest: undefined}\n }\n}\n"],"names":["rm","path","styleText","exitCodes","getLocalPackageVersion","getCliTelemetry","isInteractive","confirm","getTimer","logSymbols","spinner","readBuiltManifest","parse","semverParse","AppBuildTrace","formatModuleSizes","sortModulesBySize","buildDebug","buildStaticFiles","getAutoUpdatesCssUrls","getAutoUpdatesImportMap","getAppEnvironmentVariables","handlePrereleaseVersions","resolveVendorBuildConfig","buildApp","options","appId","determineBasePath","eventListener","outDir","output","workDir","autoUpdatesEnabled","unattendedMode","timer","defaultOutputDir","resolve","join","outputDir","installedSdkVersion","installedSanityVersion","isMediaLibraryConfigBuild","exposes","config","appType","error","exit","RUNTIME_ERROR","mfManifest","undefined","autoUpdatesImports","autoUpdatesCssUrls","cleanSDKVersion","version","cleanSanityVersion","autoUpdatedPackages","name","cssFile","log","info","checkAppId","mismatched","unresolvedPrerelease","compareDependencyVersions","length","onPreReleaseInInteractiveAutoUpdate","onPreReleaseInNonInteractiveAutoUpdate","versionMismatchWarning","map","mod","pkg","installed","remote","shouldContinue","default","message","warn","envVarKeys","Object","keys","key","shouldClean","basePath","spin","start","force","recursive","cleanDuration","end","text","toFixed","succeed","trace","autoUpdates","cssUrls","imports","vendor","cwd","isApp","bundle","appTitle","entry","isBlueprints","isWorkbenchApp","minify","reactCompiler","schemaExtraction","sourceMap","vite","workbenchAppId","outputSize","chunks","flatMap","chunk","modules","renderedLength","reduce","sum","n","buildDuration","stats","slice","complete","fail","Error","String"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/build/buildApp.ts"],"sourcesContent":["import {rm} from 'node:fs/promises'\nimport path from 'node:path'\nimport {styleText} from 'node:util'\n\nimport {exitCodes} from '@sanity/cli-core/ExitCodes'\nimport {getLocalPackageVersion} from '@sanity/cli-core/package-manager'\nimport {getCliTelemetry} from '@sanity/cli-core/telemetry'\nimport {type CliConfig, type Output, type UserViteConfig} from '@sanity/cli-core/types'\nimport {isInteractive} from '@sanity/cli-core/util'\nimport {confirm, getTimer, logSymbols, spinner, type SpinnerInstance} from '@sanity/cli-core/ux'\nimport {readBuiltManifest, type WorkbenchExposes} from '@sanity/workbench-cli/build'\nimport {parse as semverParse} from 'semver'\n\nimport {AppBuildTrace} from '../../telemetry/build.telemetry.js'\nimport {\n CompareDependencyVersionsResult,\n getUnavailableVersionsWarning,\n} from '../../util/compareDependencyVersions.js'\nimport {formatModuleSizes, sortModulesBySize} from '../../util/moduleFormatUtils.js'\nimport {buildDebug} from './buildDebug.js'\nimport {buildStaticFiles} from './buildStaticFiles.js'\nimport {BuildEventListener} from './eventListener.js'\nimport {getAutoUpdatesCssUrls, getAutoUpdatesImportMap} from './getAutoUpdatesImportMap.js'\nimport {getAppEnvironmentVariables} from './getEnvironmentVariables.js'\nimport {handlePrereleaseVersions} from './handlePrereleaseVersions.js'\nimport {resolveVendorBuildConfig} from './resolveVendorBuildConfig.js'\n\nexport type BuildAppEventListener = BuildEventListener\nexport interface BuildOptions {\n appId: string | undefined\n appTitle: string | undefined\n autoUpdatesEnabled: boolean\n checkAppId: () => void\n compareDependencyVersions: (\n packages: {name: string; version: string}[],\n ) => Promise<CompareDependencyVersionsResult>\n determineBasePath: () => string\n entry: string | undefined\n eventListener: Partial<BuildAppEventListener>\n isWorkbenchApp: boolean\n minify: boolean\n outDir: string | undefined\n output: Output\n reactCompiler: CliConfig['reactCompiler']\n schemaExtraction: CliConfig['schemaExtraction']\n sourceMap: boolean\n stats: boolean\n unattendedMode: boolean\n vite: UserViteConfig | undefined\n workDir: string\n\n exposes?: WorkbenchExposes\n /**\n * The build is running under Sanity Blueprints (invoked programmatically by\n * `@sanity/runtime-cli`), so emit the statically-imported resource-bindings\n * module Brett rewrites at deploy. Defaults to `false`, so a normal\n * `sanity build`/`dev`/`preview` never emits it.\n */\n isBlueprints?: boolean\n\n /** The workbench app's bus identity (`__SANITY_APP_ID__`). */\n workbenchAppId?: string\n}\n\n/**\n * Internal build app that avoids depending on flags for CLI config.\n * @param options - options for the build\n */\nexport async function buildApp(\n options: BuildOptions,\n): Promise<{mfManifest: Record<string, unknown> | undefined}> {\n buildDebug(`Building app`)\n\n const {appId, determineBasePath, eventListener, outDir, output, workDir} = options\n let {autoUpdatesEnabled} = options\n const unattendedMode = options.unattendedMode\n\n const timer = getTimer()\n\n const defaultOutputDir = path.resolve(path.join(workDir, 'dist'))\n const outputDir = path.resolve(outDir || defaultOutputDir)\n\n const installedSdkVersion = await getLocalPackageVersion('@sanity/sdk-react', workDir)\n const installedSanityVersion = await getLocalPackageVersion('sanity', workDir)\n\n // A Media Library config ships no SDK app — its inputs are island-rendered\n // by `sanity`, so verify that instead and skip the SDK auto-update\n // machinery. Checked via the `appType` discriminator, not the mere presence\n // of a config: a future `ConfigSchema` member must not inherit these\n // media-library build semantics by default.\n const isMediaLibraryConfigBuild = options.exposes?.config?.appType === 'media-library'\n\n if (!installedSdkVersion && !isMediaLibraryConfigBuild) {\n output.error(`Failed to find installed @sanity/sdk-react version`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n return {mfManifest: undefined}\n }\n\n if (isMediaLibraryConfigBuild && !installedSanityVersion) {\n output.error(`Failed to find installed sanity version`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n return {mfManifest: undefined}\n }\n\n let autoUpdatesImports = {}\n let autoUpdatesCssUrls: string[] = []\n\n if (autoUpdatesEnabled && !isMediaLibraryConfigBuild) {\n // Get the clean version without build metadata: https://semver.org/#spec-item-10\n const cleanSDKVersion = semverParse(installedSdkVersion)?.version\n if (!cleanSDKVersion) {\n output.error(`Failed to parse installed SDK version: ${installedSdkVersion}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n return {mfManifest: undefined}\n }\n\n // Sanity might not be installed, but if it is, we want to auto update it.\n const cleanSanityVersion = semverParse(installedSanityVersion)?.version\n\n const autoUpdatedPackages = [\n {name: '@sanity/sdk', version: cleanSDKVersion},\n {name: '@sanity/sdk-react', version: cleanSDKVersion},\n ...(cleanSanityVersion\n ? [{cssFile: 'index.css', name: 'sanity' as const, version: cleanSanityVersion}]\n : []),\n ]\n autoUpdatesImports = getAutoUpdatesImportMap(autoUpdatedPackages, {appId})\n autoUpdatesCssUrls = getAutoUpdatesCssUrls(autoUpdatedPackages, {appId})\n\n output.log(`${logSymbols.info} Building with auto-updates enabled`)\n\n // Warn if auto updates enabled but no appId configured.\n options.checkAppId()\n\n // Check the versions\n const {\n mismatched,\n unavailable = [],\n unresolvedPrerelease,\n } = await options.compareDependencyVersions(autoUpdatedPackages)\n\n if (unavailable.length > 0) {\n output.warn(getUnavailableVersionsWarning(unavailable))\n }\n\n if (unresolvedPrerelease.length > 0) {\n await handlePrereleaseVersions({\n onPreReleaseInInteractiveAutoUpdate: eventListener.onPreReleaseInInteractiveAutoUpdate,\n onPreReleaseInNonInteractiveAutoUpdate:\n eventListener.onPreReleaseInNonInteractiveAutoUpdate,\n unattendedMode,\n unresolvedPrerelease,\n })\n autoUpdatesImports = {}\n autoUpdatesCssUrls = []\n autoUpdatesEnabled = false\n }\n\n if (mismatched.length > 0 && autoUpdatesEnabled) {\n const versionMismatchWarning =\n `The following local package versions are different from the versions currently served at runtime.\\n` +\n `When using auto updates, we recommend that you test locally with the same versions before deploying. \\n\\n` +\n `${mismatched.map((mod) => ` - ${mod.pkg} (local version: ${mod.installed}, runtime version: ${mod.remote})`).join('\\n')}`\n\n // If it is non-interactive or in unattended mode, we don't want to prompt\n if (isInteractive() && !unattendedMode) {\n const shouldContinue = await confirm({\n default: false,\n message: styleText('yellow', `${versionMismatchWarning} \\n\\nContinue anyway?`),\n })\n\n if (!shouldContinue) {\n output.error('Declined to continue with build', {exit: exitCodes.RUNTIME_ERROR})\n return {mfManifest: undefined}\n }\n } else {\n // if non-interactive or unattended, just show the warning\n output.warn(versionMismatchWarning)\n }\n }\n }\n\n const envVarKeys = Object.keys(getAppEnvironmentVariables())\n if (envVarKeys.length > 0) {\n output.log('\\nIncluding the following environment variables as part of the JavaScript bundle:')\n for (const key of envVarKeys) output.log(`- ${key}`)\n output.log('')\n }\n\n let shouldClean = true\n if (outputDir !== defaultOutputDir && !unattendedMode && isInteractive()) {\n shouldClean = await confirm({\n default: true,\n message: `Do you want to delete the existing directory (${outputDir}) first?`,\n })\n }\n\n const basePath = determineBasePath()\n\n let spin: SpinnerInstance\n if (shouldClean) {\n timer.start('cleanOutputFolder')\n spin = spinner('Clean output folder').start()\n await rm(outputDir, {force: true, recursive: true})\n const cleanDuration = timer.end('cleanOutputFolder')\n spin.text = `Clean output folder (${cleanDuration.toFixed(0)}ms)`\n spin.succeed()\n }\n\n spin = spinner(`Building Sanity application`).start()\n\n const trace = getCliTelemetry().trace(AppBuildTrace)\n trace.start()\n\n let autoUpdates\n if (autoUpdatesEnabled && !isMediaLibraryConfigBuild) {\n autoUpdates = {\n cssUrls: autoUpdatesCssUrls,\n imports: autoUpdatesImports,\n // Module server `sanity` imports `styled-components` by name, so the app provides it when it has it.\n vendor: await resolveVendorBuildConfig({\n cwd: workDir,\n isApp: !(await getLocalPackageVersion('styled-components', workDir)),\n }),\n }\n }\n\n try {\n timer.start('bundleStudio')\n\n const bundle = await buildStaticFiles({\n appTitle: options.appTitle,\n autoUpdates,\n basePath,\n cwd: workDir,\n entry: options.entry,\n exposes: options.exposes,\n isApp: true,\n isBlueprints: options.isBlueprints,\n isWorkbenchApp: options.isWorkbenchApp,\n minify: options.minify,\n outputDir,\n reactCompiler: options.reactCompiler,\n schemaExtraction: options.schemaExtraction,\n sourceMap: options.sourceMap,\n vite: options.vite,\n workbenchAppId: options.workbenchAppId,\n })\n const mfManifest = options.isWorkbenchApp ? await readBuiltManifest(outputDir) : undefined\n\n trace.log({\n outputSize: bundle.chunks\n .flatMap((chunk) => chunk.modules.flatMap((mod) => mod.renderedLength))\n .reduce((sum, n) => sum + n, 0),\n })\n const buildDuration = timer.end('bundleStudio')\n\n spin.text = `Build Sanity application (${buildDuration.toFixed(0)}ms)`\n spin.succeed()\n\n if (options.stats) {\n output.log('\\nLargest module files:')\n output.log(formatModuleSizes(sortModulesBySize(bundle.chunks).slice(0, 15)))\n }\n\n trace.complete()\n return {mfManifest}\n } catch (error) {\n spin.fail()\n trace.error(error)\n const message = error instanceof Error ? error.message : String(error)\n buildDebug(`Failed to build Sanity application`, {error})\n output.error(`Failed to build Sanity application: ${message}`, {exit: exitCodes.RUNTIME_ERROR})\n return {mfManifest: undefined}\n }\n}\n"],"names":["rm","path","styleText","exitCodes","getLocalPackageVersion","getCliTelemetry","isInteractive","confirm","getTimer","logSymbols","spinner","readBuiltManifest","parse","semverParse","AppBuildTrace","getUnavailableVersionsWarning","formatModuleSizes","sortModulesBySize","buildDebug","buildStaticFiles","getAutoUpdatesCssUrls","getAutoUpdatesImportMap","getAppEnvironmentVariables","handlePrereleaseVersions","resolveVendorBuildConfig","buildApp","options","appId","determineBasePath","eventListener","outDir","output","workDir","autoUpdatesEnabled","unattendedMode","timer","defaultOutputDir","resolve","join","outputDir","installedSdkVersion","installedSanityVersion","isMediaLibraryConfigBuild","exposes","config","appType","error","exit","RUNTIME_ERROR","mfManifest","undefined","autoUpdatesImports","autoUpdatesCssUrls","cleanSDKVersion","version","cleanSanityVersion","autoUpdatedPackages","name","cssFile","log","info","checkAppId","mismatched","unavailable","unresolvedPrerelease","compareDependencyVersions","length","warn","onPreReleaseInInteractiveAutoUpdate","onPreReleaseInNonInteractiveAutoUpdate","versionMismatchWarning","map","mod","pkg","installed","remote","shouldContinue","default","message","envVarKeys","Object","keys","key","shouldClean","basePath","spin","start","force","recursive","cleanDuration","end","text","toFixed","succeed","trace","autoUpdates","cssUrls","imports","vendor","cwd","isApp","bundle","appTitle","entry","isBlueprints","isWorkbenchApp","minify","reactCompiler","schemaExtraction","sourceMap","vite","workbenchAppId","outputSize","chunks","flatMap","chunk","modules","renderedLength","reduce","sum","n","buildDuration","stats","slice","complete","fail","Error","String"],"mappings":"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"}
|
|
@@ -7,6 +7,7 @@ import { getTimer, logSymbols } from '@sanity/cli-core/ux';
|
|
|
7
7
|
import { readBuiltManifest } from '@sanity/workbench-cli/build';
|
|
8
8
|
import { parse as semverParse } from 'semver';
|
|
9
9
|
import { StudioBuildTrace } from '../../telemetry/build.telemetry.js';
|
|
10
|
+
import { getUnavailableVersionsWarning } from '../../util/compareDependencyVersions.js';
|
|
10
11
|
import { formatModuleSizes, sortModulesBySize } from '../../util/moduleFormatUtils.js';
|
|
11
12
|
import { buildDebug } from './buildDebug.js';
|
|
12
13
|
import { buildStaticFiles } from './buildStaticFiles.js';
|
|
@@ -73,7 +74,10 @@ import { resolveVendorBuildConfig } from './resolveVendorBuildConfig.js';
|
|
|
73
74
|
appId
|
|
74
75
|
});
|
|
75
76
|
// Check the versions
|
|
76
|
-
const { mismatched, unresolvedPrerelease } = await options.compareDependencyVersions(sanityDependencies);
|
|
77
|
+
const { mismatched, unavailable = [], unresolvedPrerelease } = await options.compareDependencyVersions(sanityDependencies);
|
|
78
|
+
if (unavailable.length > 0) {
|
|
79
|
+
output.warn(getUnavailableVersionsWarning(unavailable));
|
|
80
|
+
}
|
|
77
81
|
if (unresolvedPrerelease.length > 0) {
|
|
78
82
|
await handlePrereleaseVersions({
|
|
79
83
|
unattendedMode,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/build/buildStudio.ts"],"sourcesContent":["import {rm} from 'node:fs/promises'\nimport path from 'node:path'\n\nimport {getLocalPackageVersion} from '@sanity/cli-core/package-manager'\nimport {getCliTelemetry} from '@sanity/cli-core/telemetry'\nimport {type CliConfig, type Output, type UserViteConfig} from '@sanity/cli-core/types'\nimport {isInteractive} from '@sanity/cli-core/util'\nimport {getTimer, logSymbols} from '@sanity/cli-core/ux'\nimport {readBuiltManifest, type WorkbenchExposes} from '@sanity/workbench-cli/build'\nimport {parse as semverParse} from 'semver'\n\nimport {StudioBuildTrace} from '../../telemetry/build.telemetry.js'\nimport {\n CompareDependencyVersions,\n CompareDependencyVersionsResult,\n} from '../../util/compareDependencyVersions.js'\nimport {formatModuleSizes, sortModulesBySize} from '../../util/moduleFormatUtils.js'\nimport {buildDebug} from './buildDebug.js'\nimport {buildStaticFiles} from './buildStaticFiles.js'\nimport {checkRequiredDependencies} from './checkRequiredDependencies.js'\nimport {checkStudioDependencyVersions} from './checkStudioDependencyVersions.js'\nimport {type BuildEventListener, type MessageFunc} from './eventListener.js'\nimport {getAutoUpdatesCssUrls, getAutoUpdatesImportMap} from './getAutoUpdatesImportMap.js'\nimport {getStudioEnvironmentVariables} from './getEnvironmentVariables.js'\nimport {handlePrereleaseVersions} from './handlePrereleaseVersions.js'\nimport {resolveVendorBuildConfig} from './resolveVendorBuildConfig.js'\n\nexport interface BuildStudioEventListener extends BuildEventListener {\n onBuildEnd: MessageFunc\n onBuildFail: MessageFunc\n onBuildStart: MessageFunc\n onCleanOutputDirEnd: MessageFunc\n onCleanOutputDirStart: MessageFunc\n onIncompatibleDeclaredStyledComponentsVersionRange: MessageFunc\n onIncompatibleInstalledStyledComponentsVersionRange: MessageFunc\n onInteractiveNonDefaultOutputDir({message}: {message: string}): Promise<{shouldClean: boolean}>\n onInvalidStyledComponentsVersionRange: MessageFunc\n onNoDeclaredStyledComponentsVersion: MessageFunc\n onNoInstalledSanityVersion: MessageFunc\n onNoInstalledStyledComponentsVersion: MessageFunc\n onVersionMismatchInInteractiveAutoUpdate(params: {\n mismatched: CompareDependencyVersions[]\n versionMismatchWarning: string\n }): Promise<{stopBuild: boolean}>\n onVersionMismatchInNonInteractiveAutoUpdate(params: {versionMismatchWarning: string}): void\n}\n\nexport interface BuildOptions {\n appId: string | undefined\n autoUpdatesEnabled: boolean\n checkAppId: () => void\n compareDependencyVersions: (\n packages: {name: string; version: string}[],\n ) => Promise<CompareDependencyVersionsResult>\n determineBasePath: () => string\n eventListener: Partial<BuildStudioEventListener>\n isApp: boolean\n isWorkbenchApp: boolean\n minify: boolean\n outDir: string | undefined\n output: Output\n reactCompiler: boolean | CliConfig['reactCompiler'] | undefined\n schemaExtraction: CliConfig['schemaExtraction']\n sourceMap: boolean\n stats: boolean\n unattendedMode: boolean\n vite: UserViteConfig | undefined\n workDir: string\n\n exposes?: WorkbenchExposes\n /**\n * The build is running under Sanity Blueprints (invoked programmatically by\n * `@sanity/runtime-cli`), so emit the statically-imported resource-bindings\n * module Brett rewrites at deploy. Defaults to `false`, so a normal\n * `sanity build`/`dev`/`preview` never emits it.\n */\n isBlueprints?: boolean\n\n /** The workbench app's bus identity (`__SANITY_APP_ID__`). */\n workbenchAppId?: string\n}\n\n/**\n * Internal build studio that avoids depending on flags for CLI config.\n * @param options - options for the build\n */\nexport async function buildStudio(\n options: BuildOptions,\n): Promise<{mfManifest: Record<string, unknown> | undefined}> {\n buildDebug(`Building studio`)\n\n const timer = getTimer()\n const {\n appId,\n determineBasePath,\n eventListener,\n exposes,\n isApp,\n minify,\n outDir,\n output,\n reactCompiler,\n schemaExtraction,\n sourceMap,\n stats,\n unattendedMode,\n vite,\n workDir,\n } = options\n const defaultOutputDir = path.resolve(path.join(workDir, 'dist'))\n const outputDir = path.resolve(outDir || defaultOutputDir)\n\n await checkStudioDependencyVersions(workDir, output)\n\n // If the check resulted in a dependency install, the CLI command will be re-run,\n // thus we want to exit early\n const {installedSanityVersion} = await checkRequiredDependencies({\n isApp,\n workDir,\n\n ...eventListener,\n })\n\n let autoUpdatesEnabled = options.autoUpdatesEnabled\n\n let autoUpdatesImports = {}\n let autoUpdatesCssUrls: string[] = []\n\n if (autoUpdatesEnabled) {\n // Get the clean version without build metadata: https://semver.org/#spec-item-10\n const cleanSanityVersion = semverParse(installedSanityVersion)?.version\n if (!cleanSanityVersion) {\n throw new Error(`Failed to parse installed Sanity version: ${installedSanityVersion}`)\n }\n\n output.log(`${logSymbols.info} Building with auto-updates enabled`)\n\n // Warn if auto updates enabled but no appId configured\n options.checkAppId()\n\n const installedVisionVersion = await getLocalPackageVersion('@sanity/vision', workDir)\n const cleanVisionVersion = installedVisionVersion\n ? semverParse(installedVisionVersion)?.version\n : undefined\n\n const sanityDependencies = [\n {cssFile: 'index.css', name: 'sanity', version: cleanSanityVersion},\n ...(cleanVisionVersion\n ? [{cssFile: 'index.css', name: '@sanity/vision' as const, version: cleanVisionVersion}]\n : [{name: '@sanity/vision' as const, version: cleanSanityVersion}]),\n ]\n autoUpdatesImports = getAutoUpdatesImportMap(sanityDependencies, {appId})\n\n autoUpdatesCssUrls = getAutoUpdatesCssUrls(sanityDependencies, {appId})\n\n // Check the versions\n const {mismatched, unresolvedPrerelease} =\n await options.compareDependencyVersions(sanityDependencies)\n\n if (unresolvedPrerelease.length > 0) {\n await handlePrereleaseVersions({\n unattendedMode,\n unresolvedPrerelease,\n\n ...eventListener,\n })\n autoUpdatesImports = {}\n autoUpdatesCssUrls = []\n autoUpdatesEnabled = false\n }\n\n if (mismatched.length > 0 && autoUpdatesEnabled) {\n const versionMismatchWarning =\n `The following local package versions are different from the versions currently served at runtime.\\n` +\n `When using auto updates, we recommend that you test locally with the same versions before deploying. \\n\\n` +\n `${mismatched.map((mod) => ` - ${mod.pkg} (local version: ${mod.installed}, runtime version: ${mod.remote})`).join('\\n')}`\n\n const {\n onVersionMismatchInInteractiveAutoUpdate = () => ({stopBuild: true}),\n onVersionMismatchInNonInteractiveAutoUpdate = () => {},\n } = eventListener\n\n // If it is non-interactive or in unattended mode, we don't want to prompt\n if (isInteractive() && !unattendedMode) {\n const {stopBuild} = await onVersionMismatchInInteractiveAutoUpdate({\n mismatched,\n versionMismatchWarning,\n })\n if (stopBuild) return {mfManifest: undefined}\n } else {\n // if non-interactive or unattended, just show the warning\n onVersionMismatchInNonInteractiveAutoUpdate({versionMismatchWarning})\n }\n }\n }\n\n const envVarKeys = Object.keys(getStudioEnvironmentVariables())\n if (envVarKeys.length > 0) {\n output.log('\\nIncluding the following environment variables as part of the JavaScript bundle:')\n for (const key of envVarKeys) {\n output.log(`- ${key}`)\n }\n output.log('')\n }\n\n let shouldClean = true\n if (outputDir !== defaultOutputDir && !unattendedMode && isInteractive()) {\n const {onInteractiveNonDefaultOutputDir = () => ({shouldClean: true})} = eventListener\n ;({shouldClean} = await onInteractiveNonDefaultOutputDir({\n message: `Do you want to delete the existing directory (${outputDir}) first?`,\n }))\n }\n\n // Determine base path for built studio\n const basePath = determineBasePath()\n\n if (schemaExtraction?.enabled) {\n output.log(`${logSymbols.info} Building with schema extraction enabled`)\n }\n\n if (shouldClean) {\n const {onCleanOutputDirEnd = () => {}, onCleanOutputDirStart = () => {}} = eventListener\n timer.start('cleanOutputFolder')\n onCleanOutputDirStart({message: 'Clean output folder'})\n\n await rm(outputDir, {force: true, recursive: true})\n const cleanDuration = timer.end('cleanOutputFolder')\n\n onCleanOutputDirEnd({\n message: `Clean output folder (${cleanDuration.toFixed(0)}ms)`,\n })\n }\n\n const {onBuildEnd = () => {}, onBuildFail = () => {}, onBuildStart = () => {}} = eventListener\n\n onBuildStart({message: `Build Sanity Studio`})\n\n const trace = getCliTelemetry().trace(StudioBuildTrace)\n trace.start()\n\n let autoUpdates\n if (autoUpdatesEnabled) {\n autoUpdates = {\n cssUrls: autoUpdatesCssUrls,\n imports: autoUpdatesImports,\n vendor: await resolveVendorBuildConfig({cwd: workDir, isApp: false}),\n }\n }\n\n try {\n timer.start('bundleStudio')\n\n const bundle = await buildStaticFiles({\n autoUpdates,\n basePath,\n cwd: workDir,\n exposes,\n isBlueprints: options.isBlueprints,\n isWorkbenchApp: options.isWorkbenchApp,\n minify,\n outputDir,\n reactCompiler,\n schemaExtraction,\n sourceMap,\n vite,\n workbenchAppId: options.workbenchAppId,\n })\n const mfManifest = options.isWorkbenchApp ? await readBuiltManifest(outputDir) : undefined\n\n trace.log({\n outputSize: bundle.chunks\n .flatMap((chunk) => chunk.modules.flatMap((mod) => mod.renderedLength))\n .reduce((sum, n) => sum + n, 0),\n })\n const buildDuration = timer.end('bundleStudio')\n\n onBuildEnd({message: `Build Sanity Studio (${buildDuration.toFixed(0)}ms)`})\n\n trace.complete()\n if (stats) {\n output.log('\\nLargest module files:')\n output.log(formatModuleSizes(sortModulesBySize(bundle.chunks).slice(0, 15)))\n }\n return {mfManifest}\n } catch (error) {\n trace.error(error)\n const message = error instanceof Error ? error.message : String(error)\n buildDebug(`Failed to build Sanity Studio`, {error})\n onBuildFail({message: `Failed to build Sanity Studio: ${message}`})\n return {mfManifest: undefined}\n }\n}\n"],"names":["rm","path","getLocalPackageVersion","getCliTelemetry","isInteractive","getTimer","logSymbols","readBuiltManifest","parse","semverParse","StudioBuildTrace","formatModuleSizes","sortModulesBySize","buildDebug","buildStaticFiles","checkRequiredDependencies","checkStudioDependencyVersions","getAutoUpdatesCssUrls","getAutoUpdatesImportMap","getStudioEnvironmentVariables","handlePrereleaseVersions","resolveVendorBuildConfig","buildStudio","options","timer","appId","determineBasePath","eventListener","exposes","isApp","minify","outDir","output","reactCompiler","schemaExtraction","sourceMap","stats","unattendedMode","vite","workDir","defaultOutputDir","resolve","join","outputDir","installedSanityVersion","autoUpdatesEnabled","autoUpdatesImports","autoUpdatesCssUrls","cleanSanityVersion","version","Error","log","info","checkAppId","installedVisionVersion","cleanVisionVersion","undefined","sanityDependencies","cssFile","name","mismatched","unresolvedPrerelease","compareDependencyVersions","length","versionMismatchWarning","map","mod","pkg","installed","remote","onVersionMismatchInInteractiveAutoUpdate","stopBuild","onVersionMismatchInNonInteractiveAutoUpdate","mfManifest","envVarKeys","Object","keys","key","shouldClean","onInteractiveNonDefaultOutputDir","message","basePath","enabled","onCleanOutputDirEnd","onCleanOutputDirStart","start","force","recursive","cleanDuration","end","toFixed","onBuildEnd","onBuildFail","onBuildStart","trace","autoUpdates","cssUrls","imports","vendor","cwd","bundle","isBlueprints","isWorkbenchApp","workbenchAppId","outputSize","chunks","flatMap","chunk","modules","renderedLength","reduce","sum","n","buildDuration","complete","slice","error","String"],"mappings":"AAAA,SAAQA,EAAE,QAAO,mBAAkB;AACnC,OAAOC,UAAU,YAAW;AAE5B,SAAQC,sBAAsB,QAAO,mCAAkC;AACvE,SAAQC,eAAe,QAAO,6BAA4B;AAE1D,SAAQC,aAAa,QAAO,wBAAuB;AACnD,SAAQC,QAAQ,EAAEC,UAAU,QAAO,sBAAqB;AACxD,SAAQC,iBAAiB,QAA8B,8BAA6B;AACpF,SAAQC,SAASC,WAAW,QAAO,SAAQ;AAE3C,SAAQC,gBAAgB,QAAO,qCAAoC;AAKnE,SAAQC,iBAAiB,EAAEC,iBAAiB,QAAO,kCAAiC;AACpF,SAAQC,UAAU,QAAO,kBAAiB;AAC1C,SAAQC,gBAAgB,QAAO,wBAAuB;AACtD,SAAQC,yBAAyB,QAAO,iCAAgC;AACxE,SAAQC,6BAA6B,QAAO,qCAAoC;AAEhF,SAAQC,qBAAqB,EAAEC,uBAAuB,QAAO,+BAA8B;AAC3F,SAAQC,6BAA6B,QAAO,+BAA8B;AAC1E,SAAQC,wBAAwB,QAAO,gCAA+B;AACtE,SAAQC,wBAAwB,QAAO,gCAA+B;AAyDtE;;;CAGC,GACD,OAAO,eAAeC,YACpBC,OAAqB;IAErBV,WAAW,CAAC,eAAe,CAAC;IAE5B,MAAMW,QAAQnB;IACd,MAAM,EACJoB,KAAK,EACLC,iBAAiB,EACjBC,aAAa,EACbC,OAAO,EACPC,KAAK,EACLC,MAAM,EACNC,MAAM,EACNC,MAAM,EACNC,aAAa,EACbC,gBAAgB,EAChBC,SAAS,EACTC,KAAK,EACLC,cAAc,EACdC,IAAI,EACJC,OAAO,EACR,GAAGhB;IACJ,MAAMiB,mBAAmBvC,KAAKwC,OAAO,CAACxC,KAAKyC,IAAI,CAACH,SAAS;IACzD,MAAMI,YAAY1C,KAAKwC,OAAO,CAACV,UAAUS;IAEzC,MAAMxB,8BAA8BuB,SAASP;IAE7C,iFAAiF;IACjF,6BAA6B;IAC7B,MAAM,EAACY,sBAAsB,EAAC,GAAG,MAAM7B,0BAA0B;QAC/Dc;QACAU;QAEA,GAAGZ,aAAa;IAClB;IAEA,IAAIkB,qBAAqBtB,QAAQsB,kBAAkB;IAEnD,IAAIC,qBAAqB,CAAC;IAC1B,IAAIC,qBAA+B,EAAE;IAErC,IAAIF,oBAAoB;QACtB,iFAAiF;QACjF,MAAMG,qBAAqBvC,YAAYmC,yBAAyBK;QAChE,IAAI,CAACD,oBAAoB;YACvB,MAAM,IAAIE,MAAM,CAAC,0CAA0C,EAAEN,wBAAwB;QACvF;QAEAZ,OAAOmB,GAAG,CAAC,GAAG7C,WAAW8C,IAAI,CAAC,mCAAmC,CAAC;QAElE,uDAAuD;QACvD7B,QAAQ8B,UAAU;QAElB,MAAMC,yBAAyB,MAAMpD,uBAAuB,kBAAkBqC;QAC9E,MAAMgB,qBAAqBD,yBACvB7C,YAAY6C,yBAAyBL,UACrCO;QAEJ,MAAMC,qBAAqB;YACzB;gBAACC,SAAS;gBAAaC,MAAM;gBAAUV,SAASD;YAAkB;eAC9DO,qBACA;gBAAC;oBAACG,SAAS;oBAAaC,MAAM;oBAA2BV,SAASM;gBAAkB;aAAE,GACtF;gBAAC;oBAACI,MAAM;oBAA2BV,SAASD;gBAAkB;aAAE;SACrE;QACDF,qBAAqB5B,wBAAwBuC,oBAAoB;YAAChC;QAAK;QAEvEsB,qBAAqB9B,sBAAsBwC,oBAAoB;YAAChC;QAAK;QAErE,qBAAqB;QACrB,MAAM,EAACmC,UAAU,EAAEC,oBAAoB,EAAC,GACtC,MAAMtC,QAAQuC,yBAAyB,CAACL;QAE1C,IAAII,qBAAqBE,MAAM,GAAG,GAAG;YACnC,MAAM3C,yBAAyB;gBAC7BiB;gBACAwB;gBAEA,GAAGlC,aAAa;YAClB;YACAmB,qBAAqB,CAAC;YACtBC,qBAAqB,EAAE;YACvBF,qBAAqB;QACvB;QAEA,IAAIe,WAAWG,MAAM,GAAG,KAAKlB,oBAAoB;YAC/C,MAAMmB,yBACJ,CAAC,mGAAmG,CAAC,GACrG,CAAC,yGAAyG,CAAC,GAC3G,GAAGJ,WAAWK,GAAG,CAAC,CAACC,MAAQ,CAAC,GAAG,EAAEA,IAAIC,GAAG,CAAC,iBAAiB,EAAED,IAAIE,SAAS,CAAC,mBAAmB,EAAEF,IAAIG,MAAM,CAAC,CAAC,CAAC,EAAE3B,IAAI,CAAC,OAAO;YAE5H,MAAM,EACJ4B,2CAA2C,IAAO,CAAA;oBAACC,WAAW;gBAAI,CAAA,CAAE,EACpEC,8CAA8C,KAAO,CAAC,EACvD,GAAG7C;YAEJ,0EAA0E;YAC1E,IAAIvB,mBAAmB,CAACiC,gBAAgB;gBACtC,MAAM,EAACkC,SAAS,EAAC,GAAG,MAAMD,yCAAyC;oBACjEV;oBACAI;gBACF;gBACA,IAAIO,WAAW,OAAO;oBAACE,YAAYjB;gBAAS;YAC9C,OAAO;gBACL,0DAA0D;gBAC1DgB,4CAA4C;oBAACR;gBAAsB;YACrE;QACF;IACF;IAEA,MAAMU,aAAaC,OAAOC,IAAI,CAACzD;IAC/B,IAAIuD,WAAWX,MAAM,GAAG,GAAG;QACzB/B,OAAOmB,GAAG,CAAC;QACX,KAAK,MAAM0B,OAAOH,WAAY;YAC5B1C,OAAOmB,GAAG,CAAC,CAAC,EAAE,EAAE0B,KAAK;QACvB;QACA7C,OAAOmB,GAAG,CAAC;IACb;IAEA,IAAI2B,cAAc;IAClB,IAAInC,cAAcH,oBAAoB,CAACH,kBAAkBjC,iBAAiB;QACxE,MAAM,EAAC2E,mCAAmC,IAAO,CAAA;gBAACD,aAAa;YAAI,CAAA,CAAE,EAAC,GAAGnD;QACvE,CAAA,EAACmD,WAAW,EAAC,GAAG,MAAMC,iCAAiC;YACvDC,SAAS,CAAC,8CAA8C,EAAErC,UAAU,QAAQ,CAAC;QAC/E,EAAC;IACH;IAEA,uCAAuC;IACvC,MAAMsC,WAAWvD;IAEjB,IAAIQ,kBAAkBgD,SAAS;QAC7BlD,OAAOmB,GAAG,CAAC,GAAG7C,WAAW8C,IAAI,CAAC,wCAAwC,CAAC;IACzE;IAEA,IAAI0B,aAAa;QACf,MAAM,EAACK,sBAAsB,KAAO,CAAC,EAAEC,wBAAwB,KAAO,CAAC,EAAC,GAAGzD;QAC3EH,MAAM6D,KAAK,CAAC;QACZD,sBAAsB;YAACJ,SAAS;QAAqB;QAErD,MAAMhF,GAAG2C,WAAW;YAAC2C,OAAO;YAAMC,WAAW;QAAI;QACjD,MAAMC,gBAAgBhE,MAAMiE,GAAG,CAAC;QAEhCN,oBAAoB;YAClBH,SAAS,CAAC,qBAAqB,EAAEQ,cAAcE,OAAO,CAAC,GAAG,GAAG,CAAC;QAChE;IACF;IAEA,MAAM,EAACC,aAAa,KAAO,CAAC,EAAEC,cAAc,KAAO,CAAC,EAAEC,eAAe,KAAO,CAAC,EAAC,GAAGlE;IAEjFkE,aAAa;QAACb,SAAS,CAAC,mBAAmB,CAAC;IAAA;IAE5C,MAAMc,QAAQ3F,kBAAkB2F,KAAK,CAACpF;IACtCoF,MAAMT,KAAK;IAEX,IAAIU;IACJ,IAAIlD,oBAAoB;QACtBkD,cAAc;YACZC,SAASjD;YACTkD,SAASnD;YACToD,QAAQ,MAAM7E,yBAAyB;gBAAC8E,KAAK5D;gBAASV,OAAO;YAAK;QACpE;IACF;IAEA,IAAI;QACFL,MAAM6D,KAAK,CAAC;QAEZ,MAAMe,SAAS,MAAMtF,iBAAiB;YACpCiF;YACAd;YACAkB,KAAK5D;YACLX;YACAyE,cAAc9E,QAAQ8E,YAAY;YAClCC,gBAAgB/E,QAAQ+E,cAAc;YACtCxE;YACAa;YACAV;YACAC;YACAC;YACAG;YACAiE,gBAAgBhF,QAAQgF,cAAc;QACxC;QACA,MAAM9B,aAAalD,QAAQ+E,cAAc,GAAG,MAAM/F,kBAAkBoC,aAAaa;QAEjFsC,MAAM3C,GAAG,CAAC;YACRqD,YAAYJ,OAAOK,MAAM,CACtBC,OAAO,CAAC,CAACC,QAAUA,MAAMC,OAAO,CAACF,OAAO,CAAC,CAACxC,MAAQA,IAAI2C,cAAc,GACpEC,MAAM,CAAC,CAACC,KAAKC,IAAMD,MAAMC,GAAG;QACjC;QACA,MAAMC,gBAAgBzF,MAAMiE,GAAG,CAAC;QAEhCE,WAAW;YAACX,SAAS,CAAC,qBAAqB,EAAEiC,cAAcvB,OAAO,CAAC,GAAG,GAAG,CAAC;QAAA;QAE1EI,MAAMoB,QAAQ;QACd,IAAI9E,OAAO;YACTJ,OAAOmB,GAAG,CAAC;YACXnB,OAAOmB,GAAG,CAACxC,kBAAkBC,kBAAkBwF,OAAOK,MAAM,EAAEU,KAAK,CAAC,GAAG;QACzE;QACA,OAAO;YAAC1C;QAAU;IACpB,EAAE,OAAO2C,OAAO;QACdtB,MAAMsB,KAAK,CAACA;QACZ,MAAMpC,UAAUoC,iBAAiBlE,QAAQkE,MAAMpC,OAAO,GAAGqC,OAAOD;QAChEvG,WAAW,CAAC,6BAA6B,CAAC,EAAE;YAACuG;QAAK;QAClDxB,YAAY;YAACZ,SAAS,CAAC,+BAA+B,EAAEA,SAAS;QAAA;QACjE,OAAO;YAACP,YAAYjB;QAAS;IAC/B;AACF"}
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/build/buildStudio.ts"],"sourcesContent":["import {rm} from 'node:fs/promises'\nimport path from 'node:path'\n\nimport {getLocalPackageVersion} from '@sanity/cli-core/package-manager'\nimport {getCliTelemetry} from '@sanity/cli-core/telemetry'\nimport {type CliConfig, type Output, type UserViteConfig} from '@sanity/cli-core/types'\nimport {isInteractive} from '@sanity/cli-core/util'\nimport {getTimer, logSymbols} from '@sanity/cli-core/ux'\nimport {readBuiltManifest, type WorkbenchExposes} from '@sanity/workbench-cli/build'\nimport {parse as semverParse} from 'semver'\n\nimport {StudioBuildTrace} from '../../telemetry/build.telemetry.js'\nimport {\n CompareDependencyVersions,\n CompareDependencyVersionsResult,\n getUnavailableVersionsWarning,\n} from '../../util/compareDependencyVersions.js'\nimport {formatModuleSizes, sortModulesBySize} from '../../util/moduleFormatUtils.js'\nimport {buildDebug} from './buildDebug.js'\nimport {buildStaticFiles} from './buildStaticFiles.js'\nimport {checkRequiredDependencies} from './checkRequiredDependencies.js'\nimport {checkStudioDependencyVersions} from './checkStudioDependencyVersions.js'\nimport {type BuildEventListener, type MessageFunc} from './eventListener.js'\nimport {getAutoUpdatesCssUrls, getAutoUpdatesImportMap} from './getAutoUpdatesImportMap.js'\nimport {getStudioEnvironmentVariables} from './getEnvironmentVariables.js'\nimport {handlePrereleaseVersions} from './handlePrereleaseVersions.js'\nimport {resolveVendorBuildConfig} from './resolveVendorBuildConfig.js'\n\nexport interface BuildStudioEventListener extends BuildEventListener {\n onBuildEnd: MessageFunc\n onBuildFail: MessageFunc\n onBuildStart: MessageFunc\n onCleanOutputDirEnd: MessageFunc\n onCleanOutputDirStart: MessageFunc\n onIncompatibleDeclaredStyledComponentsVersionRange: MessageFunc\n onIncompatibleInstalledStyledComponentsVersionRange: MessageFunc\n onInteractiveNonDefaultOutputDir({message}: {message: string}): Promise<{shouldClean: boolean}>\n onInvalidStyledComponentsVersionRange: MessageFunc\n onNoDeclaredStyledComponentsVersion: MessageFunc\n onNoInstalledSanityVersion: MessageFunc\n onNoInstalledStyledComponentsVersion: MessageFunc\n onVersionMismatchInInteractiveAutoUpdate(params: {\n mismatched: CompareDependencyVersions[]\n versionMismatchWarning: string\n }): Promise<{stopBuild: boolean}>\n onVersionMismatchInNonInteractiveAutoUpdate(params: {versionMismatchWarning: string}): void\n}\n\nexport interface BuildOptions {\n appId: string | undefined\n autoUpdatesEnabled: boolean\n checkAppId: () => void\n compareDependencyVersions: (\n packages: {name: string; version: string}[],\n ) => Promise<CompareDependencyVersionsResult>\n determineBasePath: () => string\n eventListener: Partial<BuildStudioEventListener>\n isApp: boolean\n isWorkbenchApp: boolean\n minify: boolean\n outDir: string | undefined\n output: Output\n reactCompiler: boolean | CliConfig['reactCompiler'] | undefined\n schemaExtraction: CliConfig['schemaExtraction']\n sourceMap: boolean\n stats: boolean\n unattendedMode: boolean\n vite: UserViteConfig | undefined\n workDir: string\n\n exposes?: WorkbenchExposes\n /**\n * The build is running under Sanity Blueprints (invoked programmatically by\n * `@sanity/runtime-cli`), so emit the statically-imported resource-bindings\n * module Brett rewrites at deploy. Defaults to `false`, so a normal\n * `sanity build`/`dev`/`preview` never emits it.\n */\n isBlueprints?: boolean\n\n /** The workbench app's bus identity (`__SANITY_APP_ID__`). */\n workbenchAppId?: string\n}\n\n/**\n * Internal build studio that avoids depending on flags for CLI config.\n * @param options - options for the build\n */\nexport async function buildStudio(\n options: BuildOptions,\n): Promise<{mfManifest: Record<string, unknown> | undefined}> {\n buildDebug(`Building studio`)\n\n const timer = getTimer()\n const {\n appId,\n determineBasePath,\n eventListener,\n exposes,\n isApp,\n minify,\n outDir,\n output,\n reactCompiler,\n schemaExtraction,\n sourceMap,\n stats,\n unattendedMode,\n vite,\n workDir,\n } = options\n const defaultOutputDir = path.resolve(path.join(workDir, 'dist'))\n const outputDir = path.resolve(outDir || defaultOutputDir)\n\n await checkStudioDependencyVersions(workDir, output)\n\n // If the check resulted in a dependency install, the CLI command will be re-run,\n // thus we want to exit early\n const {installedSanityVersion} = await checkRequiredDependencies({\n isApp,\n workDir,\n\n ...eventListener,\n })\n\n let autoUpdatesEnabled = options.autoUpdatesEnabled\n\n let autoUpdatesImports = {}\n let autoUpdatesCssUrls: string[] = []\n\n if (autoUpdatesEnabled) {\n // Get the clean version without build metadata: https://semver.org/#spec-item-10\n const cleanSanityVersion = semverParse(installedSanityVersion)?.version\n if (!cleanSanityVersion) {\n throw new Error(`Failed to parse installed Sanity version: ${installedSanityVersion}`)\n }\n\n output.log(`${logSymbols.info} Building with auto-updates enabled`)\n\n // Warn if auto updates enabled but no appId configured\n options.checkAppId()\n\n const installedVisionVersion = await getLocalPackageVersion('@sanity/vision', workDir)\n const cleanVisionVersion = installedVisionVersion\n ? semverParse(installedVisionVersion)?.version\n : undefined\n\n const sanityDependencies = [\n {cssFile: 'index.css', name: 'sanity', version: cleanSanityVersion},\n ...(cleanVisionVersion\n ? [{cssFile: 'index.css', name: '@sanity/vision' as const, version: cleanVisionVersion}]\n : [{name: '@sanity/vision' as const, version: cleanSanityVersion}]),\n ]\n autoUpdatesImports = getAutoUpdatesImportMap(sanityDependencies, {appId})\n\n autoUpdatesCssUrls = getAutoUpdatesCssUrls(sanityDependencies, {appId})\n\n // Check the versions\n const {\n mismatched,\n unavailable = [],\n unresolvedPrerelease,\n } = await options.compareDependencyVersions(sanityDependencies)\n\n if (unavailable.length > 0) {\n output.warn(getUnavailableVersionsWarning(unavailable))\n }\n\n if (unresolvedPrerelease.length > 0) {\n await handlePrereleaseVersions({\n unattendedMode,\n unresolvedPrerelease,\n\n ...eventListener,\n })\n autoUpdatesImports = {}\n autoUpdatesCssUrls = []\n autoUpdatesEnabled = false\n }\n\n if (mismatched.length > 0 && autoUpdatesEnabled) {\n const versionMismatchWarning =\n `The following local package versions are different from the versions currently served at runtime.\\n` +\n `When using auto updates, we recommend that you test locally with the same versions before deploying. \\n\\n` +\n `${mismatched.map((mod) => ` - ${mod.pkg} (local version: ${mod.installed}, runtime version: ${mod.remote})`).join('\\n')}`\n\n const {\n onVersionMismatchInInteractiveAutoUpdate = () => ({stopBuild: true}),\n onVersionMismatchInNonInteractiveAutoUpdate = () => {},\n } = eventListener\n\n // If it is non-interactive or in unattended mode, we don't want to prompt\n if (isInteractive() && !unattendedMode) {\n const {stopBuild} = await onVersionMismatchInInteractiveAutoUpdate({\n mismatched,\n versionMismatchWarning,\n })\n if (stopBuild) return {mfManifest: undefined}\n } else {\n // if non-interactive or unattended, just show the warning\n onVersionMismatchInNonInteractiveAutoUpdate({versionMismatchWarning})\n }\n }\n }\n\n const envVarKeys = Object.keys(getStudioEnvironmentVariables())\n if (envVarKeys.length > 0) {\n output.log('\\nIncluding the following environment variables as part of the JavaScript bundle:')\n for (const key of envVarKeys) {\n output.log(`- ${key}`)\n }\n output.log('')\n }\n\n let shouldClean = true\n if (outputDir !== defaultOutputDir && !unattendedMode && isInteractive()) {\n const {onInteractiveNonDefaultOutputDir = () => ({shouldClean: true})} = eventListener\n ;({shouldClean} = await onInteractiveNonDefaultOutputDir({\n message: `Do you want to delete the existing directory (${outputDir}) first?`,\n }))\n }\n\n // Determine base path for built studio\n const basePath = determineBasePath()\n\n if (schemaExtraction?.enabled) {\n output.log(`${logSymbols.info} Building with schema extraction enabled`)\n }\n\n if (shouldClean) {\n const {onCleanOutputDirEnd = () => {}, onCleanOutputDirStart = () => {}} = eventListener\n timer.start('cleanOutputFolder')\n onCleanOutputDirStart({message: 'Clean output folder'})\n\n await rm(outputDir, {force: true, recursive: true})\n const cleanDuration = timer.end('cleanOutputFolder')\n\n onCleanOutputDirEnd({\n message: `Clean output folder (${cleanDuration.toFixed(0)}ms)`,\n })\n }\n\n const {onBuildEnd = () => {}, onBuildFail = () => {}, onBuildStart = () => {}} = eventListener\n\n onBuildStart({message: `Build Sanity Studio`})\n\n const trace = getCliTelemetry().trace(StudioBuildTrace)\n trace.start()\n\n let autoUpdates\n if (autoUpdatesEnabled) {\n autoUpdates = {\n cssUrls: autoUpdatesCssUrls,\n imports: autoUpdatesImports,\n vendor: await resolveVendorBuildConfig({cwd: workDir, isApp: false}),\n }\n }\n\n try {\n timer.start('bundleStudio')\n\n const bundle = await buildStaticFiles({\n autoUpdates,\n basePath,\n cwd: workDir,\n exposes,\n isBlueprints: options.isBlueprints,\n isWorkbenchApp: options.isWorkbenchApp,\n minify,\n outputDir,\n reactCompiler,\n schemaExtraction,\n sourceMap,\n vite,\n workbenchAppId: options.workbenchAppId,\n })\n const mfManifest = options.isWorkbenchApp ? await readBuiltManifest(outputDir) : undefined\n\n trace.log({\n outputSize: bundle.chunks\n .flatMap((chunk) => chunk.modules.flatMap((mod) => mod.renderedLength))\n .reduce((sum, n) => sum + n, 0),\n })\n const buildDuration = timer.end('bundleStudio')\n\n onBuildEnd({message: `Build Sanity Studio (${buildDuration.toFixed(0)}ms)`})\n\n trace.complete()\n if (stats) {\n output.log('\\nLargest module files:')\n output.log(formatModuleSizes(sortModulesBySize(bundle.chunks).slice(0, 15)))\n }\n return {mfManifest}\n } catch (error) {\n trace.error(error)\n const message = error instanceof Error ? error.message : String(error)\n buildDebug(`Failed to build Sanity Studio`, {error})\n onBuildFail({message: `Failed to build Sanity Studio: ${message}`})\n return {mfManifest: undefined}\n }\n}\n"],"names":["rm","path","getLocalPackageVersion","getCliTelemetry","isInteractive","getTimer","logSymbols","readBuiltManifest","parse","semverParse","StudioBuildTrace","getUnavailableVersionsWarning","formatModuleSizes","sortModulesBySize","buildDebug","buildStaticFiles","checkRequiredDependencies","checkStudioDependencyVersions","getAutoUpdatesCssUrls","getAutoUpdatesImportMap","getStudioEnvironmentVariables","handlePrereleaseVersions","resolveVendorBuildConfig","buildStudio","options","timer","appId","determineBasePath","eventListener","exposes","isApp","minify","outDir","output","reactCompiler","schemaExtraction","sourceMap","stats","unattendedMode","vite","workDir","defaultOutputDir","resolve","join","outputDir","installedSanityVersion","autoUpdatesEnabled","autoUpdatesImports","autoUpdatesCssUrls","cleanSanityVersion","version","Error","log","info","checkAppId","installedVisionVersion","cleanVisionVersion","undefined","sanityDependencies","cssFile","name","mismatched","unavailable","unresolvedPrerelease","compareDependencyVersions","length","warn","versionMismatchWarning","map","mod","pkg","installed","remote","onVersionMismatchInInteractiveAutoUpdate","stopBuild","onVersionMismatchInNonInteractiveAutoUpdate","mfManifest","envVarKeys","Object","keys","key","shouldClean","onInteractiveNonDefaultOutputDir","message","basePath","enabled","onCleanOutputDirEnd","onCleanOutputDirStart","start","force","recursive","cleanDuration","end","toFixed","onBuildEnd","onBuildFail","onBuildStart","trace","autoUpdates","cssUrls","imports","vendor","cwd","bundle","isBlueprints","isWorkbenchApp","workbenchAppId","outputSize","chunks","flatMap","chunk","modules","renderedLength","reduce","sum","n","buildDuration","complete","slice","error","String"],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { gte, parse } from 'semver';
|
|
2
|
+
/**
|
|
3
|
+
* The first `sanity` release that reads `globalThis.__SANITY_AUTH_HASH_PARAMS__`
|
|
4
|
+
* (sanity-io/sanity#15337). Older studios only read the URL hash, so stripping the params
|
|
5
|
+
* would break their login. Must match the release that ships that PR.
|
|
6
|
+
*
|
|
7
|
+
* @internal
|
|
8
|
+
*/ export const MIN_SANITY_VERSION_READING_AUTH_HASH_STASH = '6.22.0';
|
|
9
|
+
/**
|
|
10
|
+
* Removes the `sid`, `token` and `claim` params from the URL hash and stores their raw values
|
|
11
|
+
* on `globalThis.__SANITY_AUTH_HASH_PARAMS__`, where the studio reads them. Running this before
|
|
12
|
+
* the bundle means the secrets are gone from the address bar even if the bundle fails to load.
|
|
13
|
+
*/ const authHashScript = `try {
|
|
14
|
+
const params = location.hash.slice(1).split('&');
|
|
15
|
+
const kept = params.filter(function (param) {
|
|
16
|
+
var match = /^(sid|token|claim)=(.*)$/.exec(param);
|
|
17
|
+
if (!match) return true;
|
|
18
|
+
var found = (globalThis.__SANITY_AUTH_HASH_PARAMS__ = globalThis.__SANITY_AUTH_HASH_PARAMS__ || {});
|
|
19
|
+
if (!(match[1] in found)) found[match[1]] = match[2];
|
|
20
|
+
return false;
|
|
21
|
+
});
|
|
22
|
+
if (kept.length !== params.length) {
|
|
23
|
+
history.replaceState(history.state, '', location.pathname + location.search + (kept.length ? '#' + kept.join('&') : ''));
|
|
24
|
+
}
|
|
25
|
+
} catch (err) {}`;
|
|
26
|
+
/**
|
|
27
|
+
* Decorates the given HTML template with a script tag that removes auth
|
|
28
|
+
* secrets from the URL hash. The script is injected as the first child
|
|
29
|
+
* of `<head>` so it runs before any other script. Studio documents only:
|
|
30
|
+
* apps rely on `@sanity/sdk` reading `sid` from the hash itself. Returns
|
|
31
|
+
* the template unchanged unless `sanityVersion` reads the stashed params.
|
|
32
|
+
*
|
|
33
|
+
* @internal
|
|
34
|
+
*/ export function decorateIndexWithAuthHashScript(template, sanityVersion) {
|
|
35
|
+
const parsed = sanityVersion ? parse(sanityVersion) : null;
|
|
36
|
+
if (!parsed || !gte(parsed, MIN_SANITY_VERSION_READING_AUTH_HASH_STASH)) {
|
|
37
|
+
return template;
|
|
38
|
+
}
|
|
39
|
+
return template.replace(/<head([^>]*)>/, (_, attributes)=>`<head${attributes}>\n<script>${authHashScript}</script>`);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
//# sourceMappingURL=decorateIndexWithAuthHashScript.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/build/decorateIndexWithAuthHashScript.ts"],"sourcesContent":["import {gte, parse} from 'semver'\n\n/**\n * The first `sanity` release that reads `globalThis.__SANITY_AUTH_HASH_PARAMS__`\n * (sanity-io/sanity#15337). Older studios only read the URL hash, so stripping the params\n * would break their login. Must match the release that ships that PR.\n *\n * @internal\n */\nexport const MIN_SANITY_VERSION_READING_AUTH_HASH_STASH = '6.22.0'\n\n/**\n * Removes the `sid`, `token` and `claim` params from the URL hash and stores their raw values\n * on `globalThis.__SANITY_AUTH_HASH_PARAMS__`, where the studio reads them. Running this before\n * the bundle means the secrets are gone from the address bar even if the bundle fails to load.\n */\nconst authHashScript = `try {\n const params = location.hash.slice(1).split('&');\n const kept = params.filter(function (param) {\n var match = /^(sid|token|claim)=(.*)$/.exec(param);\n if (!match) return true;\n var found = (globalThis.__SANITY_AUTH_HASH_PARAMS__ = globalThis.__SANITY_AUTH_HASH_PARAMS__ || {});\n if (!(match[1] in found)) found[match[1]] = match[2];\n return false;\n });\n if (kept.length !== params.length) {\n history.replaceState(history.state, '', location.pathname + location.search + (kept.length ? '#' + kept.join('&') : ''));\n }\n} catch (err) {}`\n\n/**\n * Decorates the given HTML template with a script tag that removes auth\n * secrets from the URL hash. The script is injected as the first child\n * of `<head>` so it runs before any other script. Studio documents only:\n * apps rely on `@sanity/sdk` reading `sid` from the hash itself. Returns\n * the template unchanged unless `sanityVersion` reads the stashed params.\n *\n * @internal\n */\nexport function decorateIndexWithAuthHashScript(\n template: string,\n sanityVersion: string | null,\n): string {\n const parsed = sanityVersion ? parse(sanityVersion) : null\n if (!parsed || !gte(parsed, MIN_SANITY_VERSION_READING_AUTH_HASH_STASH)) {\n return template\n }\n\n return template.replace(\n /<head([^>]*)>/,\n (_, attributes) => `<head${attributes}>\\n<script>${authHashScript}</script>`,\n )\n}\n"],"names":["gte","parse","MIN_SANITY_VERSION_READING_AUTH_HASH_STASH","authHashScript","decorateIndexWithAuthHashScript","template","sanityVersion","parsed","replace","_","attributes"],"mappings":"AAAA,SAAQA,GAAG,EAAEC,KAAK,QAAO,SAAQ;AAEjC;;;;;;CAMC,GACD,OAAO,MAAMC,6CAA6C,SAAQ;AAElE;;;;CAIC,GACD,MAAMC,iBAAiB,CAAC;;;;;;;;;;;;gBAYR,CAAC;AAEjB;;;;;;;;CAQC,GACD,OAAO,SAASC,gCACdC,QAAgB,EAChBC,aAA4B;IAE5B,MAAMC,SAASD,gBAAgBL,MAAMK,iBAAiB;IACtD,IAAI,CAACC,UAAU,CAACP,IAAIO,QAAQL,6CAA6C;QACvE,OAAOG;IACT;IAEA,OAAOA,SAASG,OAAO,CACrB,iBACA,CAACC,GAAGC,aAAe,CAAC,KAAK,EAAEA,WAAW,WAAW,EAAEP,eAAe,SAAS,CAAC;AAEhF"}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { getLocalPackageVersion } from '@sanity/cli-core/package-manager';
|
|
1
2
|
import { createVendorImportMapFromBundle } from '../createVendorImportMapFromBundle.js';
|
|
3
|
+
import { decorateIndexWithAuthHashScript } from '../decorateIndexWithAuthHashScript.js';
|
|
2
4
|
import { decorateIndexWithBridgeScript } from '../decorateIndexWithBridgeScript.js';
|
|
3
5
|
import { decorateIndexWithStagingScript } from '../decorateIndexWithStagingScript.js';
|
|
4
6
|
import { renderDocument } from '../renderDocument.js';
|
|
@@ -49,9 +51,10 @@ export function sanityBuildEntries(options) {
|
|
|
49
51
|
},
|
|
50
52
|
studioRootPath: cwd
|
|
51
53
|
});
|
|
54
|
+
const source = decorateIndexWithStagingScript(bridge ? decorateIndexWithBridgeScript(html) : html);
|
|
52
55
|
this.emitFile({
|
|
53
56
|
fileName: 'index.html',
|
|
54
|
-
source:
|
|
57
|
+
source: isApp ? source : decorateIndexWithAuthHashScript(source, await getLocalPackageVersion('sanity', cwd)),
|
|
55
58
|
type: 'asset'
|
|
56
59
|
});
|
|
57
60
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/actions/build/vite/plugin-sanity-build-entries.ts"],"sourcesContent":["import {type ChunkMetadata, type Plugin} from 'vite'\n\nimport {type AutoUpdatesBuildConfig} from '../autoUpdates.js'\nimport {createVendorImportMapFromBundle} from '../createVendorImportMapFromBundle.js'\nimport {decorateIndexWithBridgeScript} from '../decorateIndexWithBridgeScript.js'\nimport {decorateIndexWithStagingScript} from '../decorateIndexWithStagingScript.js'\nimport {renderDocument} from '../renderDocument.js'\n\ninterface ViteOutputBundle {\n [fileName: string]: ViteRenderedAsset | ViteRenderedChunk\n}\n\ninterface ViteRenderedAsset {\n type: 'asset'\n\n fileName?: string\n name?: string | null\n names?: string[]\n}\n\ninterface ViteRenderedChunk {\n code: string\n facadeModuleId: string | null\n fileName: string\n imports: string[]\n isEntry: boolean\n name: string\n type: 'chunk'\n\n /**\n * Populated by Vite when `build.cssCodeSplit` is true. Rolldown-based Vite\n * (Vite 7/8 and `rolldown-vite`) may omit it, or leave `importedCss` empty,\n * for the single stylesheet emitted when code splitting is disabled.\n */\n viteMetadata?: ChunkMetadata\n}\n\nconst entryChunkId = '.sanity/runtime/app.js'\n\n/**\n * Logical name Vite gives the single CSS asset emitted when\n * `build.cssCodeSplit` is false. `assetFileNames` can change the file written\n * to disk; `names` still carries this value.\n */\nconst CSS_BUNDLE_NAME = 'style.css'\n\nexport function sanityBuildEntries(options: {\n autoUpdates?: AutoUpdatesBuildConfig\n basePath: string\n /**\n * Injects the core-ui bridge script into the emitted `index.html`. Defaults to\n * `true`. Workbench remotes serve themselves standalone and pass `false`.\n */\n bridge?: boolean\n cwd: string\n isApp?: boolean\n}): Plugin {\n const {autoUpdates, basePath, bridge = true, cwd, isApp} = options\n // Vite's default. `configResolved` replaces this with the resolved value,\n // including a userland `vite` config that sets `build.cssCodeSplit: false`.\n let cssCodeSplit = true\n\n const generateBundle: Extract<Plugin['generateBundle'], {handler: unknown}> = {\n async handler(_options, outputBundle) {\n const bundle = outputBundle as unknown as ViteOutputBundle\n const entryFile = Object.values(bundle).find(\n (file) =>\n file.type === 'chunk' &&\n file.name === 'sanity' &&\n file.facadeModuleId?.endsWith(entryChunkId),\n )\n\n if (!entryFile) {\n throw new Error(`Failed to find entry file in bundle (${entryChunkId})`)\n }\n\n if (entryFile.type !== 'chunk') {\n throw new Error('Entry file is not a chunk')\n }\n\n const entryFileName = entryFile.fileName\n const entryPath = [basePath.replace(/\\/+$/, ''), entryFileName].join('/')\n const css = collectStylesheets(entryFile, bundle, cssCodeSplit)\n\n // For auto-updating studios/apps the import map combines the vendor\n // chunks emitted by this very build (hashed filenames, resolved from the\n // bundle) with the module-CDN imports for auto-updated packages.\n const importMap = autoUpdates\n ? {\n imports: {\n ...createVendorImportMapFromBundle(\n bundle,\n autoUpdates.vendor.specifiersByChunkName,\n basePath,\n ),\n ...autoUpdates.imports,\n },\n }\n : undefined\n\n const html = await renderDocument({\n autoUpdatesCssUrls: autoUpdates?.cssUrls,\n importMap,\n isApp,\n props: {\n basePath,\n css,\n entryPath,\n },\n studioRootPath: cwd,\n })\n\n this.emitFile({\n fileName: 'index.html',\n source: decorateIndexWithStagingScript(bridge ? decorateIndexWithBridgeScript(html) : html),\n type: 'asset',\n })\n },\n }\n\n return {\n apply: 'build',\n name: 'sanity/server/build-entries',\n\n configResolved(resolved) {\n cssCodeSplit = resolved.build.cssCodeSplit\n // `vite:css-post` emits the combined stylesheet during its own unordered\n // `generateBundle`, so with `cssCodeSplit: false` this hook has to run\n // after it. Default builds keep the normal order so user plugins with an\n // unordered `generateBundle` (HTML minifiers, SRI) still see `index.html`.\n generateBundle.order = cssCodeSplit ? undefined : 'post'\n },\n\n buildStart() {\n this.emitFile({\n id: entryChunkId,\n name: 'sanity',\n type: 'chunk',\n })\n },\n\n generateBundle,\n }\n}\n\n/**\n * Stylesheets the document should link.\n *\n * With CSS code splitting, Vite records each chunk's styles on\n * `viteMetadata.importedCss` (including the chunks the entry statically\n * imports). With `cssCodeSplit: false`, Vite emits one combined asset instead\n * and never adds it to `importedCss`. `vite:build-html` finds that asset by\n * its bundle name (`style.css`); mirror that. Other CSS assets (e.g. `?url`\n * imports) are not stylesheets for the document and must not be linked.\n */\nfunction collectStylesheets(\n entryFile: ViteRenderedChunk,\n bundle: ViteOutputBundle,\n cssCodeSplit: boolean,\n): string[] {\n const css = collectImportedCss(entryFile, bundle)\n if (cssCodeSplit) return css\n\n const seen = new Set(css)\n for (const fileName of collectCombinedStylesheets(bundle)) {\n if (seen.has(fileName)) continue\n seen.add(fileName)\n css.push(fileName)\n }\n return css\n}\n\nfunction collectImportedCss(entryFile: ViteRenderedChunk, bundle: ViteOutputBundle): string[] {\n const css = cssFilesFromChunk(entryFile)\n for (const key of entryFile.imports) {\n const imported = bundle[key]\n if (imported?.type === 'chunk') css.push(...cssFilesFromChunk(imported))\n }\n return css\n}\n\nfunction cssFilesFromChunk(chunk: ViteRenderedChunk): string[] {\n const imported = chunk.viteMetadata?.importedCss\n if (!imported) return []\n return [...imported]\n}\n\nfunction collectCombinedStylesheets(bundle: ViteOutputBundle): string[] {\n return Object.values(bundle).flatMap((file) =>\n file.type === 'asset' && file.fileName && isCombinedCssBundle(file) ? [file.fileName] : [],\n )\n}\n\nfunction isCombinedCssBundle(asset: ViteRenderedAsset): boolean {\n return asset.names ? asset.names.includes(CSS_BUNDLE_NAME) : asset.name === CSS_BUNDLE_NAME\n}\n"],"names":["createVendorImportMapFromBundle","decorateIndexWithBridgeScript","decorateIndexWithStagingScript","renderDocument","entryChunkId","CSS_BUNDLE_NAME","sanityBuildEntries","options","autoUpdates","basePath","bridge","cwd","isApp","cssCodeSplit","generateBundle","handler","_options","outputBundle","bundle","entryFile","Object","values","find","file","type","name","facadeModuleId","endsWith","Error","entryFileName","fileName","entryPath","replace","join","css","collectStylesheets","importMap","imports","vendor","specifiersByChunkName","undefined","html","autoUpdatesCssUrls","cssUrls","props","studioRootPath","emitFile","source","apply","configResolved","resolved","build","order","buildStart","id","collectImportedCss","seen","Set","collectCombinedStylesheets","has","add","push","cssFilesFromChunk","key","imported","chunk","viteMetadata","importedCss","flatMap","isCombinedCssBundle","asset","names","includes"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/actions/build/vite/plugin-sanity-build-entries.ts"],"sourcesContent":["import {getLocalPackageVersion} from '@sanity/cli-core/package-manager'\nimport {type ChunkMetadata, type Plugin} from 'vite'\n\nimport {type AutoUpdatesBuildConfig} from '../autoUpdates.js'\nimport {createVendorImportMapFromBundle} from '../createVendorImportMapFromBundle.js'\nimport {decorateIndexWithAuthHashScript} from '../decorateIndexWithAuthHashScript.js'\nimport {decorateIndexWithBridgeScript} from '../decorateIndexWithBridgeScript.js'\nimport {decorateIndexWithStagingScript} from '../decorateIndexWithStagingScript.js'\nimport {renderDocument} from '../renderDocument.js'\n\ninterface ViteOutputBundle {\n [fileName: string]: ViteRenderedAsset | ViteRenderedChunk\n}\n\ninterface ViteRenderedAsset {\n type: 'asset'\n\n fileName?: string\n name?: string | null\n names?: string[]\n}\n\ninterface ViteRenderedChunk {\n code: string\n facadeModuleId: string | null\n fileName: string\n imports: string[]\n isEntry: boolean\n name: string\n type: 'chunk'\n\n /**\n * Populated by Vite when `build.cssCodeSplit` is true. Rolldown-based Vite\n * (Vite 7/8 and `rolldown-vite`) may omit it, or leave `importedCss` empty,\n * for the single stylesheet emitted when code splitting is disabled.\n */\n viteMetadata?: ChunkMetadata\n}\n\nconst entryChunkId = '.sanity/runtime/app.js'\n\n/**\n * Logical name Vite gives the single CSS asset emitted when\n * `build.cssCodeSplit` is false. `assetFileNames` can change the file written\n * to disk; `names` still carries this value.\n */\nconst CSS_BUNDLE_NAME = 'style.css'\n\nexport function sanityBuildEntries(options: {\n autoUpdates?: AutoUpdatesBuildConfig\n basePath: string\n /**\n * Injects the core-ui bridge script into the emitted `index.html`. Defaults to\n * `true`. Workbench remotes serve themselves standalone and pass `false`.\n */\n bridge?: boolean\n cwd: string\n isApp?: boolean\n}): Plugin {\n const {autoUpdates, basePath, bridge = true, cwd, isApp} = options\n // Vite's default. `configResolved` replaces this with the resolved value,\n // including a userland `vite` config that sets `build.cssCodeSplit: false`.\n let cssCodeSplit = true\n\n const generateBundle: Extract<Plugin['generateBundle'], {handler: unknown}> = {\n async handler(_options, outputBundle) {\n const bundle = outputBundle as unknown as ViteOutputBundle\n const entryFile = Object.values(bundle).find(\n (file) =>\n file.type === 'chunk' &&\n file.name === 'sanity' &&\n file.facadeModuleId?.endsWith(entryChunkId),\n )\n\n if (!entryFile) {\n throw new Error(`Failed to find entry file in bundle (${entryChunkId})`)\n }\n\n if (entryFile.type !== 'chunk') {\n throw new Error('Entry file is not a chunk')\n }\n\n const entryFileName = entryFile.fileName\n const entryPath = [basePath.replace(/\\/+$/, ''), entryFileName].join('/')\n const css = collectStylesheets(entryFile, bundle, cssCodeSplit)\n\n // For auto-updating studios/apps the import map combines the vendor\n // chunks emitted by this very build (hashed filenames, resolved from the\n // bundle) with the module-CDN imports for auto-updated packages.\n const importMap = autoUpdates\n ? {\n imports: {\n ...createVendorImportMapFromBundle(\n bundle,\n autoUpdates.vendor.specifiersByChunkName,\n basePath,\n ),\n ...autoUpdates.imports,\n },\n }\n : undefined\n\n const html = await renderDocument({\n autoUpdatesCssUrls: autoUpdates?.cssUrls,\n importMap,\n isApp,\n props: {\n basePath,\n css,\n entryPath,\n },\n studioRootPath: cwd,\n })\n\n const source = decorateIndexWithStagingScript(\n bridge ? decorateIndexWithBridgeScript(html) : html,\n )\n\n this.emitFile({\n fileName: 'index.html',\n source: isApp\n ? source\n : decorateIndexWithAuthHashScript(source, await getLocalPackageVersion('sanity', cwd)),\n type: 'asset',\n })\n },\n }\n\n return {\n apply: 'build',\n name: 'sanity/server/build-entries',\n\n configResolved(resolved) {\n cssCodeSplit = resolved.build.cssCodeSplit\n // `vite:css-post` emits the combined stylesheet during its own unordered\n // `generateBundle`, so with `cssCodeSplit: false` this hook has to run\n // after it. Default builds keep the normal order so user plugins with an\n // unordered `generateBundle` (HTML minifiers, SRI) still see `index.html`.\n generateBundle.order = cssCodeSplit ? undefined : 'post'\n },\n\n buildStart() {\n this.emitFile({\n id: entryChunkId,\n name: 'sanity',\n type: 'chunk',\n })\n },\n\n generateBundle,\n }\n}\n\n/**\n * Stylesheets the document should link.\n *\n * With CSS code splitting, Vite records each chunk's styles on\n * `viteMetadata.importedCss` (including the chunks the entry statically\n * imports). With `cssCodeSplit: false`, Vite emits one combined asset instead\n * and never adds it to `importedCss`. `vite:build-html` finds that asset by\n * its bundle name (`style.css`); mirror that. Other CSS assets (e.g. `?url`\n * imports) are not stylesheets for the document and must not be linked.\n */\nfunction collectStylesheets(\n entryFile: ViteRenderedChunk,\n bundle: ViteOutputBundle,\n cssCodeSplit: boolean,\n): string[] {\n const css = collectImportedCss(entryFile, bundle)\n if (cssCodeSplit) return css\n\n const seen = new Set(css)\n for (const fileName of collectCombinedStylesheets(bundle)) {\n if (seen.has(fileName)) continue\n seen.add(fileName)\n css.push(fileName)\n }\n return css\n}\n\nfunction collectImportedCss(entryFile: ViteRenderedChunk, bundle: ViteOutputBundle): string[] {\n const css = cssFilesFromChunk(entryFile)\n for (const key of entryFile.imports) {\n const imported = bundle[key]\n if (imported?.type === 'chunk') css.push(...cssFilesFromChunk(imported))\n }\n return css\n}\n\nfunction cssFilesFromChunk(chunk: ViteRenderedChunk): string[] {\n const imported = chunk.viteMetadata?.importedCss\n if (!imported) return []\n return [...imported]\n}\n\nfunction collectCombinedStylesheets(bundle: ViteOutputBundle): string[] {\n return Object.values(bundle).flatMap((file) =>\n file.type === 'asset' && file.fileName && isCombinedCssBundle(file) ? [file.fileName] : [],\n )\n}\n\nfunction isCombinedCssBundle(asset: ViteRenderedAsset): boolean {\n return asset.names ? asset.names.includes(CSS_BUNDLE_NAME) : asset.name === CSS_BUNDLE_NAME\n}\n"],"names":["getLocalPackageVersion","createVendorImportMapFromBundle","decorateIndexWithAuthHashScript","decorateIndexWithBridgeScript","decorateIndexWithStagingScript","renderDocument","entryChunkId","CSS_BUNDLE_NAME","sanityBuildEntries","options","autoUpdates","basePath","bridge","cwd","isApp","cssCodeSplit","generateBundle","handler","_options","outputBundle","bundle","entryFile","Object","values","find","file","type","name","facadeModuleId","endsWith","Error","entryFileName","fileName","entryPath","replace","join","css","collectStylesheets","importMap","imports","vendor","specifiersByChunkName","undefined","html","autoUpdatesCssUrls","cssUrls","props","studioRootPath","source","emitFile","apply","configResolved","resolved","build","order","buildStart","id","collectImportedCss","seen","Set","collectCombinedStylesheets","has","add","push","cssFilesFromChunk","key","imported","chunk","viteMetadata","importedCss","flatMap","isCombinedCssBundle","asset","names","includes"],"mappings":"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"}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { mkdir, writeFile } from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { tryFindStudioConfigPath } from '@sanity/cli-core/config';
|
|
4
|
+
import { getLocalPackageVersion } from '@sanity/cli-core/package-manager';
|
|
4
5
|
import { RESOURCE_BINDINGS_FILENAME, RESOURCE_BINDINGS_MODULE_SOURCE } from '@sanity/workbench-cli/build';
|
|
5
6
|
import { watch as chokidarWatch } from 'chokidar';
|
|
6
7
|
import { buildDebug } from './buildDebug.js';
|
|
8
|
+
import { decorateIndexWithAuthHashScript } from './decorateIndexWithAuthHashScript.js';
|
|
7
9
|
import { decorateIndexWithAutoGeneratedWarning } from './decorateIndexWithAutoGeneratedWarning.js';
|
|
8
10
|
import { decorateIndexWithBridgeScript } from './decorateIndexWithBridgeScript.js';
|
|
9
11
|
import { decorateIndexWithStagingScript } from './decorateIndexWithStagingScript.js';
|
|
@@ -24,9 +26,10 @@ import { renderDocument } from './renderDocument.js';
|
|
|
24
26
|
await mkdir(runtimeDir, {
|
|
25
27
|
recursive: true
|
|
26
28
|
});
|
|
29
|
+
const sanityVersion = isApp ? null : await getLocalPackageVersion('sanity', cwd);
|
|
27
30
|
async function renderAndWriteDocument() {
|
|
28
31
|
buildDebug('Rendering document template');
|
|
29
|
-
const
|
|
32
|
+
const html = decorateIndexWithStagingScript(decorateIndexWithBridgeScript(decorateIndexWithAutoGeneratedWarning(await renderDocument({
|
|
30
33
|
isApp,
|
|
31
34
|
props: {
|
|
32
35
|
basePath: basePath || '/',
|
|
@@ -35,6 +38,7 @@ import { renderDocument } from './renderDocument.js';
|
|
|
35
38
|
},
|
|
36
39
|
studioRootPath: cwd
|
|
37
40
|
}))));
|
|
41
|
+
const indexHtml = isApp ? html : decorateIndexWithAuthHashScript(html, sanityVersion);
|
|
38
42
|
buildDebug('Writing index.html to runtime directory');
|
|
39
43
|
await writeFile(path.join(runtimeDir, 'index.html'), indexHtml);
|
|
40
44
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/build/writeSanityRuntime.ts"],"sourcesContent":["import {mkdir, writeFile} from 'node:fs/promises'\nimport path from 'node:path'\n\nimport {tryFindStudioConfigPath} from '@sanity/cli-core/config'\nimport {\n RESOURCE_BINDINGS_FILENAME,\n RESOURCE_BINDINGS_MODULE_SOURCE,\n} from '@sanity/workbench-cli/build'\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 /** Blueprints build (via `@sanity/runtime-cli`) — emit the resource-bindings module. */\n isBlueprints?: 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 {\n appTitle,\n basePath,\n cwd,\n entry,\n isApp,\n isBlueprints,\n isWorkbenchApp,\n reactStrictMode,\n watch,\n } = options\n const runtimeDir = path.join(cwd, '.sanity', 'runtime')\n\n buildDebug('Making runtime directory')\n await mkdir(runtimeDir, {recursive: true})\n\n async function renderAndWriteDocument() {\n buildDebug('Rendering document template')\n const
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/build/writeSanityRuntime.ts"],"sourcesContent":["import {mkdir, writeFile} from 'node:fs/promises'\nimport path from 'node:path'\n\nimport {tryFindStudioConfigPath} from '@sanity/cli-core/config'\nimport {getLocalPackageVersion} from '@sanity/cli-core/package-manager'\nimport {\n RESOURCE_BINDINGS_FILENAME,\n RESOURCE_BINDINGS_MODULE_SOURCE,\n} from '@sanity/workbench-cli/build'\nimport {watch as chokidarWatch, type FSWatcher} from 'chokidar'\n\nimport {buildDebug} from './buildDebug.js'\nimport {decorateIndexWithAuthHashScript} from './decorateIndexWithAuthHashScript.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 /** Blueprints build (via `@sanity/runtime-cli`) — emit the resource-bindings module. */\n isBlueprints?: 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 {\n appTitle,\n basePath,\n cwd,\n entry,\n isApp,\n isBlueprints,\n isWorkbenchApp,\n reactStrictMode,\n watch,\n } = options\n const runtimeDir = path.join(cwd, '.sanity', 'runtime')\n\n buildDebug('Making runtime directory')\n await mkdir(runtimeDir, {recursive: true})\n\n const sanityVersion = isApp ? null : await getLocalPackageVersion('sanity', cwd)\n\n async function renderAndWriteDocument() {\n buildDebug('Rendering document template')\n const html = 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 const indexHtml = isApp ? html : decorateIndexWithAuthHashScript(html, sanityVersion)\n\n buildDebug('Writing index.html to runtime directory')\n await 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 isBlueprints,\n reactStrictMode,\n relativeConfigLocation,\n })\n await writeFile(path.join(runtimeDir, 'app.js'), appJsContent)\n\n // Resource bindings ride in their own statically-imported module (see\n // resource-bindings.ts) so a federated host and a standalone studio resolve\n // them the same way. Brett bakes the resolved values in at deploy. Only a\n // Blueprints build emits it (and imports it — see getEntryModule); a normal\n // `sanity build`/`dev`/`preview` skips it entirely.\n if (isBlueprints) {\n buildDebug('Writing resource bindings module to runtime directory')\n await writeFile(\n path.join(runtimeDir, RESOURCE_BINDINGS_FILENAME),\n RESOURCE_BINDINGS_MODULE_SOURCE,\n )\n }\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 (`defineApplication`) 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":["mkdir","writeFile","path","tryFindStudioConfigPath","getLocalPackageVersion","RESOURCE_BINDINGS_FILENAME","RESOURCE_BINDINGS_MODULE_SOURCE","watch","chokidarWatch","buildDebug","decorateIndexWithAuthHashScript","decorateIndexWithAutoGeneratedWarning","decorateIndexWithBridgeScript","decorateIndexWithStagingScript","getEntryModule","getPossibleDocumentComponentLocations","renderDocument","writeSanityRuntime","options","appTitle","basePath","cwd","entry","isApp","isBlueprints","isWorkbenchApp","reactStrictMode","runtimeDir","join","recursive","sanityVersion","renderAndWriteDocument","html","props","entryPath","toForwardSlashes","relative","title","studioRootPath","indexHtml","watcher","ignoreInitial","on","relativeConfigLocation","relativeEntry","resolveEntries","appJsContent","undefined","entries","studioConfigPath","resolve","filePath","replaceAll"],"mappings":"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"}
|
|
@@ -22,89 +22,40 @@ const debug = subdebug('buildStudioSchemasAndManifests.worker');
|
|
|
22
22
|
// still live. Both writeWorkspaceToDist and updateWorkspacesSchemas consume the result.
|
|
23
23
|
const workspaceManifests = await extractWorkspaceManifest(workspaces, workDir);
|
|
24
24
|
debug('Handling build for %s', isExternal ? 'external' : 'internal');
|
|
25
|
-
|
|
26
|
-
if (!isExternal || schemaRequired) {
|
|
27
|
-
const schemaInputs = workspaceManifests.map((manifest)=>({
|
|
28
|
-
dataset: manifest.dataset,
|
|
29
|
-
manifestSchema: manifest.schema,
|
|
30
|
-
name: manifest.name,
|
|
31
|
-
projectId: manifest.projectId,
|
|
32
|
-
title: manifest.title
|
|
33
|
-
}));
|
|
34
|
-
if (workspaceSchemaHandler) {
|
|
35
|
-
await workspaceSchemaHandler(schemaInputs);
|
|
36
|
-
}
|
|
37
|
-
return schemaInputs;
|
|
38
|
-
}
|
|
39
|
-
return null;
|
|
40
|
-
}
|
|
41
|
-
const result = isExternal ? await handleExternalStudio({
|
|
25
|
+
const uploadToLexiconPromise = uploadSchemaToLexicon({
|
|
42
26
|
projectId,
|
|
43
27
|
verbose,
|
|
44
28
|
workDir,
|
|
45
|
-
workspaceManifests,
|
|
46
|
-
workspaceManifestsHandler,
|
|
47
29
|
workspaces
|
|
48
|
-
})
|
|
30
|
+
});
|
|
31
|
+
let writeManifestPromise;
|
|
32
|
+
if (!isExternal) writeManifestPromise = writeManifestFile({
|
|
49
33
|
outPath,
|
|
50
|
-
projectId,
|
|
51
|
-
verbose,
|
|
52
34
|
workDir,
|
|
53
|
-
workspaceManifests
|
|
54
|
-
workspaceManifestsHandler,
|
|
55
|
-
workspaces
|
|
35
|
+
workspaceManifests
|
|
56
36
|
});
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
workspaceManifestsHandler(workspaceManifests)
|
|
76
|
-
]);
|
|
77
|
-
return {
|
|
78
|
-
schemaInputs,
|
|
79
|
-
studioManifest
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
*
|
|
84
|
-
* Internal deployments:
|
|
85
|
-
* 1. Write the workspace manifests to the dist directory
|
|
86
|
-
* 2. Update the workspaces schemas to the /schemas endpoint
|
|
87
|
-
* 3. Call the workspace manifest handler if provided to update server-side schemas
|
|
88
|
-
*
|
|
89
|
-
* @param workspaces - The workspaces to deploy
|
|
90
|
-
*/ async function handleInternalStudio({ outPath, projectId, verbose, workDir, workspaceManifests, workspaceManifestsHandler, workspaces }) {
|
|
91
|
-
const [studioManifest, schemaInputs] = await Promise.all([
|
|
92
|
-
uploadSchemaToLexicon({
|
|
93
|
-
projectId,
|
|
94
|
-
verbose,
|
|
95
|
-
workDir,
|
|
96
|
-
workspaces
|
|
97
|
-
}),
|
|
98
|
-
workspaceManifestsHandler(workspaceManifests),
|
|
99
|
-
writeManifestFile({
|
|
100
|
-
outPath,
|
|
101
|
-
workDir,
|
|
102
|
-
workspaceManifests
|
|
103
|
-
})
|
|
104
|
-
]);
|
|
37
|
+
let schemaInputs = null;
|
|
38
|
+
let workspaceSchemaPromise;
|
|
39
|
+
if (!isExternal || schemaRequired) {
|
|
40
|
+
schemaInputs = workspaceManifests.map((manifest)=>({
|
|
41
|
+
dataset: manifest.dataset,
|
|
42
|
+
manifestSchema: manifest.schema,
|
|
43
|
+
name: manifest.name,
|
|
44
|
+
projectId: manifest.projectId,
|
|
45
|
+
title: manifest.title
|
|
46
|
+
}));
|
|
47
|
+
if (workspaceSchemaHandler) workspaceSchemaPromise = workspaceSchemaHandler(schemaInputs);
|
|
48
|
+
}
|
|
49
|
+
const promises = [
|
|
50
|
+
uploadToLexiconPromise
|
|
51
|
+
];
|
|
52
|
+
if (writeManifestPromise) promises.push(writeManifestPromise);
|
|
53
|
+
if (workspaceSchemaPromise) promises.push(workspaceSchemaPromise);
|
|
54
|
+
await Promise.all(promises);
|
|
105
55
|
return {
|
|
106
56
|
schemaInputs,
|
|
107
|
-
studioManifest
|
|
57
|
+
studioManifest: await uploadToLexiconPromise,
|
|
58
|
+
type: 'success'
|
|
108
59
|
};
|
|
109
60
|
}
|
|
110
61
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/schema/buildStudioSchemasAndManifestsWorker.ts"],"sourcesContent":["import {isMainThread} from 'node:worker_threads'\n\nimport {getStudioWorkspaces, subdebug} from '@sanity/cli-core'\
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/schema/buildStudioSchemasAndManifestsWorker.ts"],"sourcesContent":["import {isMainThread} from 'node:worker_threads'\n\nimport {getStudioWorkspaces, subdebug} from '@sanity/cli-core'\n\nimport {extractWorkspaceManifest} from '../manifest/extractWorkspaceManifest.js'\nimport {type WorkspaceSchemaInput} from '../manifest/types.js'\nimport {writeManifestFile} from '../manifest/writeManifestFile.js'\nimport {type BuildStudioSchemasAndManifestsWorkerSuccess} from './buildStudioSchemasAndManifests.js'\nimport {type BuildStudioSchemasAndManifestsWorkerData} from './types.js'\nimport {uploadSchemaToLexicon} from './uploadSchemaToLexicon.js'\n\nconst debug = subdebug('buildStudioSchemasAndManifests.worker')\n\n/**\n * This function must only be called from another worker process.\n * @param options - The worker options\n */\nexport async function workerBuildStudioSchemasAndManifests(\n options: BuildStudioSchemasAndManifestsWorkerData & {\n workspaceSchemaHandler?: (workspaces: WorkspaceSchemaInput[]) => Promise<void>\n },\n): Promise<BuildStudioSchemasAndManifestsWorkerSuccess> {\n if (isMainThread) {\n throw new Error(\n 'workerBuildStudioSchemasAndManifests should only be called from a worker thread',\n )\n }\n\n const {\n configPath,\n isExternal,\n outPath,\n projectId,\n schemaRequired,\n verbose,\n workDir,\n workspaceSchemaHandler,\n } = options\n\n debug('Building studio schemas and manifests from config path %s', configPath)\n const workspaces = await getStudioWorkspaces(configPath)\n debug('Workspaces %o', workspaces)\n\n if (workspaces.length === 0) {\n throw new Error('No workspaces found')\n }\n\n // Extract manifest data (including ManifestSchemaType[]) once, while Schema objects are\n // still live. Both writeWorkspaceToDist and updateWorkspacesSchemas consume the result.\n const workspaceManifests = await extractWorkspaceManifest(workspaces, workDir)\n\n debug('Handling build for %s', isExternal ? 'external' : 'internal')\n\n const uploadToLexiconPromise = uploadSchemaToLexicon({\n projectId,\n verbose,\n workDir,\n workspaces,\n })\n\n let writeManifestPromise: Promise<void> | undefined\n if (!isExternal) writeManifestPromise = writeManifestFile({outPath, workDir, workspaceManifests})\n\n let schemaInputs: WorkspaceSchemaInput[] | null = null\n let workspaceSchemaPromise: Promise<void> | undefined\n if (!isExternal || schemaRequired) {\n schemaInputs = workspaceManifests.map((manifest) => ({\n dataset: manifest.dataset,\n manifestSchema: manifest.schema,\n name: manifest.name,\n projectId: manifest.projectId,\n title: manifest.title,\n }))\n\n if (workspaceSchemaHandler) workspaceSchemaPromise = workspaceSchemaHandler(schemaInputs)\n }\n\n const promises: Promise<unknown>[] = [uploadToLexiconPromise]\n if (writeManifestPromise) promises.push(writeManifestPromise)\n if (workspaceSchemaPromise) promises.push(workspaceSchemaPromise)\n await Promise.all(promises)\n\n return {\n schemaInputs,\n studioManifest: await uploadToLexiconPromise,\n type: 'success',\n }\n}\n"],"names":["isMainThread","getStudioWorkspaces","subdebug","extractWorkspaceManifest","writeManifestFile","uploadSchemaToLexicon","debug","workerBuildStudioSchemasAndManifests","options","Error","configPath","isExternal","outPath","projectId","schemaRequired","verbose","workDir","workspaceSchemaHandler","workspaces","length","workspaceManifests","uploadToLexiconPromise","writeManifestPromise","schemaInputs","workspaceSchemaPromise","map","manifest","dataset","manifestSchema","schema","name","title","promises","push","Promise","all","studioManifest","type"],"mappings":"AAAA,SAAQA,YAAY,QAAO,sBAAqB;AAEhD,SAAQC,mBAAmB,EAAEC,QAAQ,QAAO,mBAAkB;AAE9D,SAAQC,wBAAwB,QAAO,0CAAyC;AAEhF,SAAQC,iBAAiB,QAAO,mCAAkC;AAGlE,SAAQC,qBAAqB,QAAO,6BAA4B;AAEhE,MAAMC,QAAQJ,SAAS;AAEvB;;;CAGC,GACD,OAAO,eAAeK,qCACpBC,OAEC;IAED,IAAIR,cAAc;QAChB,MAAM,IAAIS,MACR;IAEJ;IAEA,MAAM,EACJC,UAAU,EACVC,UAAU,EACVC,OAAO,EACPC,SAAS,EACTC,cAAc,EACdC,OAAO,EACPC,OAAO,EACPC,sBAAsB,EACvB,GAAGT;IAEJF,MAAM,6DAA6DI;IACnE,MAAMQ,aAAa,MAAMjB,oBAAoBS;IAC7CJ,MAAM,iBAAiBY;IAEvB,IAAIA,WAAWC,MAAM,KAAK,GAAG;QAC3B,MAAM,IAAIV,MAAM;IAClB;IAEA,wFAAwF;IACxF,wFAAwF;IACxF,MAAMW,qBAAqB,MAAMjB,yBAAyBe,YAAYF;IAEtEV,MAAM,yBAAyBK,aAAa,aAAa;IAEzD,MAAMU,yBAAyBhB,sBAAsB;QACnDQ;QACAE;QACAC;QACAE;IACF;IAEA,IAAII;IACJ,IAAI,CAACX,YAAYW,uBAAuBlB,kBAAkB;QAACQ;QAASI;QAASI;IAAkB;IAE/F,IAAIG,eAA8C;IAClD,IAAIC;IACJ,IAAI,CAACb,cAAcG,gBAAgB;QACjCS,eAAeH,mBAAmBK,GAAG,CAAC,CAACC,WAAc,CAAA;gBACnDC,SAASD,SAASC,OAAO;gBACzBC,gBAAgBF,SAASG,MAAM;gBAC/BC,MAAMJ,SAASI,IAAI;gBACnBjB,WAAWa,SAASb,SAAS;gBAC7BkB,OAAOL,SAASK,KAAK;YACvB,CAAA;QAEA,IAAId,wBAAwBO,yBAAyBP,uBAAuBM;IAC9E;IAEA,MAAMS,WAA+B;QAACX;KAAuB;IAC7D,IAAIC,sBAAsBU,SAASC,IAAI,CAACX;IACxC,IAAIE,wBAAwBQ,SAASC,IAAI,CAACT;IAC1C,MAAMU,QAAQC,GAAG,CAACH;IAElB,OAAO;QACLT;QACAa,gBAAgB,MAAMf;QACtBgB,MAAM;IACR;AACF"}
|
|
@@ -3,8 +3,10 @@ import { getLocalPackageVersion, readPackageJson } from '@sanity/cli-core';
|
|
|
3
3
|
import { createRequester } from '@sanity/cli-core/request';
|
|
4
4
|
import { coerce, eq, prerelease, parse as semverParse } from 'semver';
|
|
5
5
|
import { getModuleUrl } from '../actions/build/getAutoUpdatesImportMap.js';
|
|
6
|
+
const REMOTE_VERSION_TIMEOUT_MS = 5000;
|
|
6
7
|
const defaultRequester = createRequester({
|
|
7
|
-
httpErrors: false
|
|
8
|
+
httpErrors: false,
|
|
9
|
+
timeout: REMOTE_VERSION_TIMEOUT_MS
|
|
8
10
|
});
|
|
9
11
|
/**
|
|
10
12
|
* @internal
|
|
@@ -22,11 +24,12 @@ const defaultRequester = createRequester({
|
|
|
22
24
|
* @param workDir - The path to the working directory containing the package.json file.
|
|
23
25
|
* @param options - Optional configuration for version comparison.
|
|
24
26
|
*
|
|
25
|
-
* @returns A promise that resolves to an object containing `mismatched` (packages whose local and remote versions differ)
|
|
26
|
-
*
|
|
27
|
+
* @returns A promise that resolves to an object containing `mismatched` (packages whose local and remote versions differ),
|
|
28
|
+
* `unresolvedPrerelease` (packages with prerelease versions that could not be resolved remotely) and `unavailable`
|
|
29
|
+
* (packages Module Server did not answer for, because of a network error, a timeout or a 5xx).
|
|
27
30
|
*
|
|
28
|
-
* @throws Throws an error if
|
|
29
|
-
* of a package cannot be parsed.
|
|
31
|
+
* @throws Throws an error if a non-prerelease package is not found remotely, if Module Server answers with an unexpected
|
|
32
|
+
* response, or if the local version of a package cannot be parsed.
|
|
30
33
|
*/ export async function compareDependencyVersions(packages, workDir, { appId } = {}) {
|
|
31
34
|
const manifest = await readPackageJson(path.join(workDir, 'package.json'), {
|
|
32
35
|
skipSchemaValidation: true
|
|
@@ -35,43 +38,70 @@ const defaultRequester = createRequester({
|
|
|
35
38
|
...manifest?.dependencies,
|
|
36
39
|
...manifest?.devDependencies
|
|
37
40
|
};
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
41
|
+
const comparisons = await Promise.all(packages.filter((pkg)=>Boolean(dependencies[pkg.name])).map((pkg)=>comparePackageVersion(pkg, dependencies[pkg.name], {
|
|
42
|
+
appId,
|
|
43
|
+
workDir
|
|
44
|
+
})));
|
|
45
|
+
return {
|
|
46
|
+
mismatched: comparisons.flatMap((result)=>result.type === 'mismatched' ? [
|
|
47
|
+
result.mismatch
|
|
48
|
+
] : []),
|
|
49
|
+
unavailable: comparisons.flatMap((result)=>result.type === 'unavailable' ? [
|
|
50
|
+
result.unavailable
|
|
51
|
+
] : []),
|
|
52
|
+
unresolvedPrerelease: comparisons.flatMap((result)=>result.type === 'unresolvedPrerelease' ? [
|
|
53
|
+
result.prerelease
|
|
54
|
+
] : [])
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* @internal
|
|
59
|
+
*/ export function getUnavailableVersionsWarning(unavailable) {
|
|
60
|
+
const packageNames = unavailable.map((entry)=>entry.pkg).join(', ');
|
|
61
|
+
const reasons = [
|
|
62
|
+
...new Set(unavailable.map((entry)=>entry.reason))
|
|
63
|
+
].join('; ');
|
|
64
|
+
return `Could not check the runtime version of ${packageNames}: ` + `the Sanity module CDN request failed (${reasons}). Continuing without the check.`;
|
|
65
|
+
}
|
|
66
|
+
async function comparePackageVersion(pkg, manifestVersion, { appId, workDir }) {
|
|
67
|
+
const remote = await getRemoteResolvedVersion(getModuleUrl(pkg, {
|
|
68
|
+
appId
|
|
69
|
+
}));
|
|
70
|
+
if (remote.type !== 'found') {
|
|
71
|
+
if (prerelease(pkg.version)) {
|
|
72
|
+
return {
|
|
73
|
+
prerelease: {
|
|
51
74
|
pkg: pkg.name,
|
|
52
75
|
version: pkg.version
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
throw new Error(`Failed to resolve remote version for ${pkg.name}@${pkg.version}: package not found`);
|
|
76
|
+
},
|
|
77
|
+
type: 'unresolvedPrerelease'
|
|
78
|
+
};
|
|
57
79
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
installed: installed.version,
|
|
67
|
-
pkg: pkg.name,
|
|
68
|
-
remote: resolvedVersion
|
|
69
|
-
});
|
|
80
|
+
if (remote.type === 'unavailable') {
|
|
81
|
+
return {
|
|
82
|
+
type: 'unavailable',
|
|
83
|
+
unavailable: {
|
|
84
|
+
pkg: pkg.name,
|
|
85
|
+
reason: remote.reason
|
|
86
|
+
}
|
|
87
|
+
};
|
|
70
88
|
}
|
|
89
|
+
throw new Error(`Failed to resolve remote version for ${pkg.name}@${pkg.version}: package not found`);
|
|
71
90
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
91
|
+
const packageVersion = await getLocalPackageVersion(pkg.name, workDir);
|
|
92
|
+
const installed = coerce(packageVersion ? semverParse(packageVersion) : coerce(manifestVersion));
|
|
93
|
+
if (!installed) {
|
|
94
|
+
throw new Error(`Failed to parse installed version for ${pkg.name}`);
|
|
95
|
+
}
|
|
96
|
+
return eq(remote.version, installed.version) ? {
|
|
97
|
+
type: 'matched'
|
|
98
|
+
} : {
|
|
99
|
+
mismatch: {
|
|
100
|
+
installed: installed.version,
|
|
101
|
+
pkg: pkg.name,
|
|
102
|
+
remote: remote.version
|
|
103
|
+
},
|
|
104
|
+
type: 'mismatched'
|
|
75
105
|
};
|
|
76
106
|
}
|
|
77
107
|
async function getRemoteResolvedVersion(url) {
|
|
@@ -83,10 +113,10 @@ async function getRemoteResolvedVersion(url) {
|
|
|
83
113
|
url
|
|
84
114
|
});
|
|
85
115
|
} catch (err) {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
}
|
|
116
|
+
return {
|
|
117
|
+
reason: err instanceof Error ? err.message : String(err),
|
|
118
|
+
type: 'unavailable'
|
|
119
|
+
};
|
|
90
120
|
}
|
|
91
121
|
// 302 is expected, but lets also handle 2xx
|
|
92
122
|
if (response.status < 400) {
|
|
@@ -94,10 +124,21 @@ async function getRemoteResolvedVersion(url) {
|
|
|
94
124
|
if (!resolved) {
|
|
95
125
|
throw new Error(`Missing 'x-resolved-version' header on response from HEAD ${url}`);
|
|
96
126
|
}
|
|
97
|
-
return
|
|
127
|
+
return {
|
|
128
|
+
type: 'found',
|
|
129
|
+
version: resolved
|
|
130
|
+
};
|
|
98
131
|
}
|
|
99
132
|
if (response.status === 404) {
|
|
100
|
-
return
|
|
133
|
+
return {
|
|
134
|
+
type: 'not-found'
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
if (response.status === 429 || response.status >= 500) {
|
|
138
|
+
return {
|
|
139
|
+
reason: `HTTP ${response.status} ${response.statusText}`,
|
|
140
|
+
type: 'unavailable'
|
|
141
|
+
};
|
|
101
142
|
}
|
|
102
143
|
throw new Error(`Unexpected HTTP response: ${response.status} ${response.statusText}`);
|
|
103
144
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/util/compareDependencyVersions.ts"],"sourcesContent":["import path from 'node:path'\n\nimport {getLocalPackageVersion, readPackageJson} from '@sanity/cli-core'\nimport {createRequester} from '@sanity/cli-core/request'\nimport {coerce, eq, prerelease, parse as semverParse} from 'semver'\n\nimport {getModuleUrl} from '../actions/build/getAutoUpdatesImportMap.js'\n\nexport interface CompareDependencyVersions {\n installed: string\n pkg: string\n remote: string\n}\n\nexport interface UnresolvedPrerelease {\n pkg: string\n version: string\n}\n\nexport interface CompareDependencyVersionsResult {\n mismatched: Array<CompareDependencyVersions>\n unresolvedPrerelease: Array<UnresolvedPrerelease>\n}\n\nconst defaultRequester = createRequester({\n httpErrors: false,\n})\n\ninterface CompareDependencyVersionsOptions {\n /** When provided, uses the app-specific module endpoint instead of the default endpoint. */\n appId?: string\n}\n\n/**\n * @internal\n *\n * Compares the versions of dependencies in the studio or app with their remote versions.\n *\n * This function reads the package.json file in the provided working directory, and compares the versions of the dependencies\n * specified in the `autoUpdatesImports` parameter with their remote versions. If the versions do not match, the dependency is\n * added to a list of failed dependencies, which is returned by the function.\n *\n * The failed dependencies are anything that does not strictly match the remote version.\n * This means that if a version is lower or greater by even a patch it will be marked as failed.\n *\n * @param packages - An array of packages with their name and version to compare against remote.\n * @param workDir - The path to the working directory containing the package.json file.\n * @param options - Optional configuration for version comparison.\n *\n * @returns A promise that resolves to an object containing `mismatched` (packages whose local and remote versions differ)\n * and `unresolvedPrerelease` (packages with prerelease versions that could not be resolved remotely).\n *\n * @throws Throws an error if the remote version of a non-prerelease package cannot be fetched, or if the local version\n * of a package cannot be parsed.\n */\nexport async function compareDependencyVersions(\n packages: {name: string; version: string}[],\n workDir: string,\n {appId}: CompareDependencyVersionsOptions = {},\n): Promise<CompareDependencyVersionsResult> {\n const manifest = await readPackageJson(path.join(workDir, 'package.json'), {\n skipSchemaValidation: true,\n })\n const dependencies = {...manifest?.dependencies, ...manifest?.devDependencies}\n\n const mismatched: Array<CompareDependencyVersions> = []\n const unresolvedPrerelease: Array<UnresolvedPrerelease> = []\n\n for (const pkg of packages) {\n // Skip packages that are not declared in the local package.json\n if (!dependencies[pkg.name]) {\n continue\n }\n\n const resolvedVersion = await getRemoteResolvedVersion(getModuleUrl(pkg, {appId}))\n\n if (resolvedVersion === null) {\n if (prerelease(pkg.version)) {\n unresolvedPrerelease.push({pkg: pkg.name, version: pkg.version})\n continue\n }\n throw new Error(\n `Failed to resolve remote version for ${pkg.name}@${pkg.version}: package not found`,\n )\n }\n\n const packageVersion = await getLocalPackageVersion(pkg.name, workDir)\n\n const manifestVersion = dependencies[pkg.name]\n\n const installed = coerce(packageVersion ? semverParse(packageVersion) : coerce(manifestVersion))\n\n if (!installed) {\n throw new Error(`Failed to parse installed version for ${pkg.name}`)\n }\n\n if (!eq(resolvedVersion, installed.version)) {\n mismatched.push({\n installed: installed.version,\n pkg: pkg.name,\n remote: resolvedVersion,\n })\n }\n }\n\n return {mismatched, unresolvedPrerelease}\n}\n\nasync function getRemoteResolvedVersion(url: string): Promise<string | null> {\n let response\n try {\n response = await defaultRequester({\n method: 'HEAD',\n redirect: 'manual',\n url,\n })\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n throw new Error(`Failed to fetch remote version for ${url}: ${message}`, {cause: err})\n }\n\n // 302 is expected, but lets also handle 2xx\n if (response.status < 400) {\n const resolved = response.headers.get('x-resolved-version')\n if (!resolved) {\n throw new Error(`Missing 'x-resolved-version' header on response from HEAD ${url}`)\n }\n return resolved\n }\n\n if (response.status === 404) {\n return null\n }\n\n throw new Error(`Unexpected HTTP response: ${response.status} ${response.statusText}`)\n}\n"],"names":["path","getLocalPackageVersion","readPackageJson","createRequester","coerce","eq","prerelease","parse","semverParse","getModuleUrl","defaultRequester","httpErrors","compareDependencyVersions","packages","workDir","appId","manifest","join","skipSchemaValidation","dependencies","devDependencies","mismatched","unresolvedPrerelease","pkg","name","resolvedVersion","getRemoteResolvedVersion","version","push","Error","packageVersion","manifestVersion","installed","remote","url","response","method","redirect","err","message","String","cause","status","resolved","headers","get","statusText"],"mappings":"AAAA,OAAOA,UAAU,YAAW;AAE5B,SAAQC,sBAAsB,EAAEC,eAAe,QAAO,mBAAkB;AACxE,SAAQC,eAAe,QAAO,2BAA0B;AACxD,SAAQC,MAAM,EAAEC,EAAE,EAAEC,UAAU,EAAEC,SAASC,WAAW,QAAO,SAAQ;AAEnE,SAAQC,YAAY,QAAO,8CAA6C;AAkBxE,MAAMC,mBAAmBP,gBAAgB;IACvCQ,YAAY;AACd;AAOA;;;;;;;;;;;;;;;;;;;;;CAqBC,GACD,OAAO,eAAeC,0BACpBC,QAA2C,EAC3CC,OAAe,EACf,EAACC,KAAK,EAAmC,GAAG,CAAC,CAAC;IAE9C,MAAMC,WAAW,MAAMd,gBAAgBF,KAAKiB,IAAI,CAACH,SAAS,iBAAiB;QACzEI,sBAAsB;IACxB;IACA,MAAMC,eAAe;QAAC,GAAGH,UAAUG,YAAY;QAAE,GAAGH,UAAUI,eAAe;IAAA;IAE7E,MAAMC,aAA+C,EAAE;IACvD,MAAMC,uBAAoD,EAAE;IAE5D,KAAK,MAAMC,OAAOV,SAAU;QAC1B,gEAAgE;QAChE,IAAI,CAACM,YAAY,CAACI,IAAIC,IAAI,CAAC,EAAE;YAC3B;QACF;QAEA,MAAMC,kBAAkB,MAAMC,yBAAyBjB,aAAac,KAAK;YAACR;QAAK;QAE/E,IAAIU,oBAAoB,MAAM;YAC5B,IAAInB,WAAWiB,IAAII,OAAO,GAAG;gBAC3BL,qBAAqBM,IAAI,CAAC;oBAACL,KAAKA,IAAIC,IAAI;oBAAEG,SAASJ,IAAII,OAAO;gBAAA;gBAC9D;YACF;YACA,MAAM,IAAIE,MACR,CAAC,qCAAqC,EAAEN,IAAIC,IAAI,CAAC,CAAC,EAAED,IAAII,OAAO,CAAC,mBAAmB,CAAC;QAExF;QAEA,MAAMG,iBAAiB,MAAM7B,uBAAuBsB,IAAIC,IAAI,EAAEV;QAE9D,MAAMiB,kBAAkBZ,YAAY,CAACI,IAAIC,IAAI,CAAC;QAE9C,MAAMQ,YAAY5B,OAAO0B,iBAAiBtB,YAAYsB,kBAAkB1B,OAAO2B;QAE/E,IAAI,CAACC,WAAW;YACd,MAAM,IAAIH,MAAM,CAAC,sCAAsC,EAAEN,IAAIC,IAAI,EAAE;QACrE;QAEA,IAAI,CAACnB,GAAGoB,iBAAiBO,UAAUL,OAAO,GAAG;YAC3CN,WAAWO,IAAI,CAAC;gBACdI,WAAWA,UAAUL,OAAO;gBAC5BJ,KAAKA,IAAIC,IAAI;gBACbS,QAAQR;YACV;QACF;IACF;IAEA,OAAO;QAACJ;QAAYC;IAAoB;AAC1C;AAEA,eAAeI,yBAAyBQ,GAAW;IACjD,IAAIC;IACJ,IAAI;QACFA,WAAW,MAAMzB,iBAAiB;YAChC0B,QAAQ;YACRC,UAAU;YACVH;QACF;IACF,EAAE,OAAOI,KAAK;QACZ,MAAMC,UAAUD,eAAeT,QAAQS,IAAIC,OAAO,GAAGC,OAAOF;QAC5D,MAAM,IAAIT,MAAM,CAAC,mCAAmC,EAAEK,IAAI,EAAE,EAAEK,SAAS,EAAE;YAACE,OAAOH;QAAG;IACtF;IAEA,4CAA4C;IAC5C,IAAIH,SAASO,MAAM,GAAG,KAAK;QACzB,MAAMC,WAAWR,SAASS,OAAO,CAACC,GAAG,CAAC;QACtC,IAAI,CAACF,UAAU;YACb,MAAM,IAAId,MAAM,CAAC,0DAA0D,EAAEK,KAAK;QACpF;QACA,OAAOS;IACT;IAEA,IAAIR,SAASO,MAAM,KAAK,KAAK;QAC3B,OAAO;IACT;IAEA,MAAM,IAAIb,MAAM,CAAC,0BAA0B,EAAEM,SAASO,MAAM,CAAC,CAAC,EAAEP,SAASW,UAAU,EAAE;AACvF"}
|
|
1
|
+
{"version":3,"sources":["../../src/util/compareDependencyVersions.ts"],"sourcesContent":["import path from 'node:path'\n\nimport {getLocalPackageVersion, readPackageJson} from '@sanity/cli-core'\nimport {createRequester} from '@sanity/cli-core/request'\nimport {coerce, eq, prerelease, parse as semverParse} from 'semver'\n\nimport {getModuleUrl} from '../actions/build/getAutoUpdatesImportMap.js'\n\nexport interface CompareDependencyVersions {\n installed: string\n pkg: string\n remote: string\n}\n\nexport interface UnresolvedPrerelease {\n pkg: string\n version: string\n}\n\n/**\n * A package whose runtime version Module Server did not report, because of a network error,\n * a timeout or a 5xx.\n */\nexport interface UnavailableDependencyVersion {\n pkg: string\n reason: string\n}\n\nexport interface CompareDependencyVersionsResult {\n mismatched: Array<CompareDependencyVersions>\n unresolvedPrerelease: Array<UnresolvedPrerelease>\n\n unavailable?: Array<UnavailableDependencyVersion>\n}\n\nconst REMOTE_VERSION_TIMEOUT_MS = 5000\n\nconst defaultRequester = createRequester({\n httpErrors: false,\n timeout: REMOTE_VERSION_TIMEOUT_MS,\n})\n\ninterface CompareDependencyVersionsOptions {\n /** When provided, uses the app-specific module endpoint instead of the default endpoint. */\n appId?: string\n}\n\ntype PackageComparison =\n | {mismatch: CompareDependencyVersions; type: 'mismatched'}\n | {prerelease: UnresolvedPrerelease; type: 'unresolvedPrerelease'}\n | {type: 'matched'}\n | {type: 'unavailable'; unavailable: UnavailableDependencyVersion}\n\ntype RemoteVersion =\n | {reason: string; type: 'unavailable'}\n | {type: 'found'; version: string}\n | {type: 'not-found'}\n\n/**\n * @internal\n *\n * Compares the versions of dependencies in the studio or app with their remote versions.\n *\n * This function reads the package.json file in the provided working directory, and compares the versions of the dependencies\n * specified in the `autoUpdatesImports` parameter with their remote versions. If the versions do not match, the dependency is\n * added to a list of failed dependencies, which is returned by the function.\n *\n * The failed dependencies are anything that does not strictly match the remote version.\n * This means that if a version is lower or greater by even a patch it will be marked as failed.\n *\n * @param packages - An array of packages with their name and version to compare against remote.\n * @param workDir - The path to the working directory containing the package.json file.\n * @param options - Optional configuration for version comparison.\n *\n * @returns A promise that resolves to an object containing `mismatched` (packages whose local and remote versions differ),\n * `unresolvedPrerelease` (packages with prerelease versions that could not be resolved remotely) and `unavailable`\n * (packages Module Server did not answer for, because of a network error, a timeout or a 5xx).\n *\n * @throws Throws an error if a non-prerelease package is not found remotely, if Module Server answers with an unexpected\n * response, or if the local version of a package cannot be parsed.\n */\nexport async function compareDependencyVersions(\n packages: {name: string; version: string}[],\n workDir: string,\n {appId}: CompareDependencyVersionsOptions = {},\n): Promise<CompareDependencyVersionsResult> {\n const manifest = await readPackageJson(path.join(workDir, 'package.json'), {\n skipSchemaValidation: true,\n })\n const dependencies = {...manifest?.dependencies, ...manifest?.devDependencies}\n\n const comparisons = await Promise.all(\n packages\n .filter((pkg) => Boolean(dependencies[pkg.name]))\n .map((pkg) => comparePackageVersion(pkg, dependencies[pkg.name], {appId, workDir})),\n )\n\n return {\n mismatched: comparisons.flatMap((result) =>\n result.type === 'mismatched' ? [result.mismatch] : [],\n ),\n unavailable: comparisons.flatMap((result) =>\n result.type === 'unavailable' ? [result.unavailable] : [],\n ),\n unresolvedPrerelease: comparisons.flatMap((result) =>\n result.type === 'unresolvedPrerelease' ? [result.prerelease] : [],\n ),\n }\n}\n\n/**\n * @internal\n */\nexport function getUnavailableVersionsWarning(unavailable: UnavailableDependencyVersion[]): string {\n const packageNames = unavailable.map((entry) => entry.pkg).join(', ')\n const reasons = [...new Set(unavailable.map((entry) => entry.reason))].join('; ')\n return (\n `Could not check the runtime version of ${packageNames}: ` +\n `the Sanity module CDN request failed (${reasons}). Continuing without the check.`\n )\n}\n\nasync function comparePackageVersion(\n pkg: {name: string; version: string},\n manifestVersion: string,\n {appId, workDir}: {appId?: string; workDir: string},\n): Promise<PackageComparison> {\n const remote = await getRemoteResolvedVersion(getModuleUrl(pkg, {appId}))\n\n if (remote.type !== 'found') {\n if (prerelease(pkg.version)) {\n return {prerelease: {pkg: pkg.name, version: pkg.version}, type: 'unresolvedPrerelease'}\n }\n if (remote.type === 'unavailable') {\n return {type: 'unavailable', unavailable: {pkg: pkg.name, reason: remote.reason}}\n }\n throw new Error(\n `Failed to resolve remote version for ${pkg.name}@${pkg.version}: package not found`,\n )\n }\n\n const packageVersion = await getLocalPackageVersion(pkg.name, workDir)\n\n const installed = coerce(packageVersion ? semverParse(packageVersion) : coerce(manifestVersion))\n\n if (!installed) {\n throw new Error(`Failed to parse installed version for ${pkg.name}`)\n }\n\n return eq(remote.version, installed.version)\n ? {type: 'matched'}\n : {\n mismatch: {installed: installed.version, pkg: pkg.name, remote: remote.version},\n type: 'mismatched',\n }\n}\n\nasync function getRemoteResolvedVersion(url: string): Promise<RemoteVersion> {\n let response\n try {\n response = await defaultRequester({\n method: 'HEAD',\n redirect: 'manual',\n url,\n })\n } catch (err) {\n return {reason: err instanceof Error ? err.message : String(err), type: 'unavailable'}\n }\n\n // 302 is expected, but lets also handle 2xx\n if (response.status < 400) {\n const resolved = response.headers.get('x-resolved-version')\n if (!resolved) {\n throw new Error(`Missing 'x-resolved-version' header on response from HEAD ${url}`)\n }\n return {type: 'found', version: resolved}\n }\n\n if (response.status === 404) {\n return {type: 'not-found'}\n }\n\n if (response.status === 429 || response.status >= 500) {\n return {reason: `HTTP ${response.status} ${response.statusText}`, type: 'unavailable'}\n }\n\n throw new Error(`Unexpected HTTP response: ${response.status} ${response.statusText}`)\n}\n"],"names":["path","getLocalPackageVersion","readPackageJson","createRequester","coerce","eq","prerelease","parse","semverParse","getModuleUrl","REMOTE_VERSION_TIMEOUT_MS","defaultRequester","httpErrors","timeout","compareDependencyVersions","packages","workDir","appId","manifest","join","skipSchemaValidation","dependencies","devDependencies","comparisons","Promise","all","filter","pkg","Boolean","name","map","comparePackageVersion","mismatched","flatMap","result","type","mismatch","unavailable","unresolvedPrerelease","getUnavailableVersionsWarning","packageNames","entry","reasons","Set","reason","manifestVersion","remote","getRemoteResolvedVersion","version","Error","packageVersion","installed","url","response","method","redirect","err","message","String","status","resolved","headers","get","statusText"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sanity/cli-build",
|
|
3
|
-
"version": "7.1.
|
|
3
|
+
"version": "7.1.2",
|
|
4
4
|
"description": "Internal Sanity package for building studios and apps",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
@@ -52,16 +52,16 @@
|
|
|
52
52
|
"dependencies": {
|
|
53
53
|
"@oclif/core": "^4.11.14",
|
|
54
54
|
"@rolldown/plugin-babel": "^0.2.4",
|
|
55
|
-
"@sanity/cli-core": "^3.14.
|
|
55
|
+
"@sanity/cli-core": "^3.14.2",
|
|
56
56
|
"@sanity/generate-help-url": "^4.0.0",
|
|
57
57
|
"@sanity/schema": "^6.22.0",
|
|
58
58
|
"@sanity/telemetry": "^1.1.0",
|
|
59
59
|
"@sanity/types": "^6.22.0",
|
|
60
|
-
"@sanity/workbench-cli": "^2.15.
|
|
60
|
+
"@sanity/workbench-cli": "^2.15.2",
|
|
61
61
|
"@vitejs/plugin-react": "^6.2.1",
|
|
62
62
|
"chokidar": "^5.0.0",
|
|
63
63
|
"cjs-module-lexer": "^2.2.1",
|
|
64
|
-
"dompurify": "^3.4.
|
|
64
|
+
"dompurify": "^3.4.17",
|
|
65
65
|
"empathic": "^2.0.1",
|
|
66
66
|
"jsdom": "^29.1.1",
|
|
67
67
|
"lightningcss": "^1.33.0",
|
|
@@ -73,13 +73,13 @@
|
|
|
73
73
|
"react-is": "^19.3.0",
|
|
74
74
|
"semver": "^7.8.1",
|
|
75
75
|
"vite": "^8.3.6",
|
|
76
|
-
"zod": "^4.
|
|
76
|
+
"zod": "^4.6.7"
|
|
77
77
|
},
|
|
78
78
|
"devDependencies": {
|
|
79
79
|
"@eslint/compat": "^2.1.0",
|
|
80
80
|
"@repo/package.config": "0.0.1",
|
|
81
81
|
"@repo/tsconfig": "3.70.0",
|
|
82
|
-
"@sanity/cli-test": "24.0.
|
|
82
|
+
"@sanity/cli-test": "24.0.3",
|
|
83
83
|
"@sanity/eslint-config-cli": "^1.1.3",
|
|
84
84
|
"@sanity/pkg-utils": "^12.3.4",
|
|
85
85
|
"@sanity/ui": "^4.4.10",
|