sanity 5.0.0-next-major.20251212101828 → 5.0.0-next-major.20251215132654

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.
@@ -0,0 +1,107 @@
1
+ import path from "node:path";
2
+ import resolveFrom from "resolve-from";
3
+ import semver from "semver";
4
+ import { readPackageManifest } from "./timing.js";
5
+ import chalk from "chalk";
6
+ const MODULES_HOST = process.env.SANITY_MODULES_HOST || (process.env.SANITY_INTERNAL_ENV === "staging" ? "https://sanity-cdn.work" : "https://sanity-cdn.com");
7
+ function currentUnixTime() {
8
+ return Math.floor(Date.now() / 1e3);
9
+ }
10
+ function getAutoUpdatesImportMap(packages, options = {}) {
11
+ return Object.fromEntries(packages.flatMap((pkg) => getAppAutoUpdateImportMapForPackage(pkg, options)));
12
+ }
13
+ function getAppAutoUpdateImportMapForPackage(pkg, options = {}) {
14
+ const moduleUrl = getModuleUrl(pkg, options);
15
+ return [[pkg.name, moduleUrl], [`${pkg.name}/`, `${moduleUrl}/`]];
16
+ }
17
+ function getModuleUrl(pkg, options = {}) {
18
+ const {
19
+ timestamp = currentUnixTime()
20
+ } = options;
21
+ return options.appId ? getByAppModuleUrl(pkg, {
22
+ appId: options.appId,
23
+ baseUrl: options.baseUrl,
24
+ timestamp
25
+ }) : getLegacyModuleUrl(pkg, {
26
+ timestamp,
27
+ baseUrl: options.baseUrl
28
+ });
29
+ }
30
+ function getLegacyModuleUrl(pkg, options) {
31
+ const encodedMinVer = encodeURIComponent(`^${pkg.version}`);
32
+ return `${options.baseUrl || MODULES_HOST}/v1/modules/${rewriteScopedPackage(pkg.name)}/default/${encodedMinVer}/t${options.timestamp}`;
33
+ }
34
+ function getByAppModuleUrl(pkg, options) {
35
+ const encodedMinVer = encodeURIComponent(`^${pkg.version}`);
36
+ return `${options.baseUrl || MODULES_HOST}/v1/modules/by-app/${options.appId}/t${options.timestamp}/${encodedMinVer}/${rewriteScopedPackage(pkg.name)}`;
37
+ }
38
+ function rewriteScopedPackage(pkgName) {
39
+ if (!pkgName.includes("@"))
40
+ return pkgName;
41
+ const [scope, ...pkg] = pkgName.split("/");
42
+ return `${scope}__${pkg.join("")}`;
43
+ }
44
+ function getRemoteResolvedVersion(fetchFn, url) {
45
+ return fetchFn(url, {
46
+ method: "HEAD",
47
+ redirect: "manual"
48
+ }).then((res) => {
49
+ if (res.ok || res.status < 400) {
50
+ const resolved = res.headers.get("x-resolved-version");
51
+ if (!resolved)
52
+ throw new Error(`Missing 'x-resolved-version' header on response from HEAD ${url}`);
53
+ return resolved;
54
+ }
55
+ throw new Error(`Unexpected HTTP response: ${res.status} ${res.statusText}`);
56
+ }, (err) => {
57
+ throw new Error(`Failed to fetch remote version for ${url}: ${err.message}`, {
58
+ cause: err
59
+ });
60
+ });
61
+ }
62
+ async function compareDependencyVersions(packages, workDir, {
63
+ fetchFn = globalThis.fetch
64
+ } = {}) {
65
+ const manifest = await readPackageManifest(path.join(workDir, "package.json")), dependencies = {
66
+ ...manifest.dependencies,
67
+ ...manifest.devDependencies
68
+ }, failedDependencies = [];
69
+ for (const pkg of packages) {
70
+ const resolvedVersion = await getRemoteResolvedVersion(fetchFn, getModuleUrl(pkg)), manifestPath = resolveFrom.silent(workDir, path.join(pkg.name, "package.json")), manifestVersion = dependencies[pkg.name], installed = semver.coerce(manifestPath ? semver.parse((await readPackageManifest(manifestPath)).version) : semver.coerce(manifestVersion));
71
+ if (!installed)
72
+ throw new Error(`Failed to parse installed version for ${pkg}`);
73
+ semver.eq(resolvedVersion, installed.version) || failedDependencies.push({
74
+ pkg: pkg.name,
75
+ installed: installed.version,
76
+ remote: resolvedVersion
77
+ });
78
+ }
79
+ return failedDependencies;
80
+ }
81
+ function shouldAutoUpdate({
82
+ flags,
83
+ cliConfig,
84
+ output
85
+ }) {
86
+ if ("auto-updates" in flags) {
87
+ if (output) {
88
+ const flagUsed = flags["auto-updates"] ? "--auto-updates" : "--no-auto-updates";
89
+ output.warn(chalk.yellow(`The ${flagUsed} flag is deprecated for \`deploy\` and \`build\` commands. Set the \`autoUpdates\` option in \`sanity.cli.ts\` or \`sanity.cli.js\` instead.`));
90
+ }
91
+ return !!flags["auto-updates"];
92
+ }
93
+ const hasOldCliConfigFlag = cliConfig && "autoUpdates" in cliConfig, hasNewCliConfigFlag = cliConfig && "deployment" in cliConfig && cliConfig.deployment && "autoUpdates" in cliConfig.deployment;
94
+ if (hasOldCliConfigFlag && hasNewCliConfigFlag)
95
+ throw new Error("Found both `autoUpdates` (deprecated) and `deployment.autoUpdates` in sanity.cli.js. Please remove the deprecated top level `autoUpdates` config.");
96
+ return hasOldCliConfigFlag && output?.warn(chalk.yellow(`The \`autoUpdates\` config has moved to \`deployment.autoUpdates\`.
97
+ Please update \`sanity.cli.ts\` or \`sanity.cli.js\` and make the following change:
98
+ ${chalk.red(`- autoUpdates: ${cliConfig.autoUpdates},`)}
99
+ ${chalk.green(`+ deployment: {autoUpdates: ${cliConfig.autoUpdates}}}`)}
100
+ `)), !!(hasOldCliConfigFlag ? cliConfig.autoUpdates : cliConfig?.deployment?.autoUpdates);
101
+ }
102
+ export {
103
+ compareDependencyVersions,
104
+ getAutoUpdatesImportMap,
105
+ shouldAutoUpdate
106
+ };
107
+ //# sourceMappingURL=shouldAutoUpdate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shouldAutoUpdate.js","sources":["../../src/_internal/cli/util/getAutoUpdatesImportMap.ts","../../src/_internal/cli/util/compareDependencyVersions.ts","../../src/_internal/cli/util/shouldAutoUpdate.ts"],"sourcesContent":["const MODULES_HOST =\n process.env.SANITY_MODULES_HOST ||\n (process.env.SANITY_INTERNAL_ENV === 'staging'\n ? 'https://sanity-cdn.work'\n : 'https://sanity-cdn.com')\n\nfunction currentUnixTime(): number {\n return Math.floor(Date.now() / 1000)\n}\n\ntype Package = {version: string; name: string}\n/**\n * @internal\n */\nexport function getAutoUpdatesImportMap<const Pkg extends Package>(\n packages: Pkg[],\n options: {timestamp?: number; baseUrl?: string; appId?: string} = {},\n) {\n return Object.fromEntries(\n packages.flatMap((pkg) => getAppAutoUpdateImportMapForPackage(pkg, options)),\n ) as {[K in Pkg['name'] | `${Pkg['name']}/`]: string}\n}\n\nfunction getAppAutoUpdateImportMapForPackage<const Pkg extends Package>(\n pkg: Pkg,\n options: {timestamp?: number; baseUrl?: string; appId?: string} = {},\n): [[Pkg['name'], string], [`${Pkg['name']}/`, string]] {\n const moduleUrl = getModuleUrl(pkg, options)\n\n return [\n [pkg.name, moduleUrl],\n [`${pkg.name}/`, `${moduleUrl}/`],\n ]\n}\n\nexport function getModuleUrl(\n pkg: Package,\n options: {timestamp?: number; baseUrl?: string; appId?: string} = {},\n) {\n const {timestamp = currentUnixTime()} = options\n return options.appId\n ? getByAppModuleUrl(pkg, {appId: options.appId, baseUrl: options.baseUrl, timestamp})\n : getLegacyModuleUrl(pkg, {timestamp, baseUrl: options.baseUrl})\n}\n\nfunction getLegacyModuleUrl(pkg: Package, options: {timestamp: number; baseUrl?: string}) {\n const encodedMinVer = encodeURIComponent(`^${pkg.version}`)\n return `${options.baseUrl || MODULES_HOST}/v1/modules/${rewriteScopedPackage(pkg.name)}/default/${encodedMinVer}/t${options.timestamp}`\n}\n\nfunction getByAppModuleUrl(\n pkg: Package,\n options: {appId: string; baseUrl?: string; timestamp: number},\n) {\n const encodedMinVer = encodeURIComponent(`^${pkg.version}`)\n return `${options.baseUrl || MODULES_HOST}/v1/modules/by-app/${options.appId}/t${options.timestamp}/${encodedMinVer}/${rewriteScopedPackage(pkg.name)}`\n}\n\n/**\n * replaces '/' with '__' similar to how eg `@types/scope__pkg` are rewritten\n * scoped packages are stored this way both in the manifest and in the cloud storage bucket\n */\nfunction rewriteScopedPackage(pkgName: string) {\n if (!pkgName.includes('@')) {\n return pkgName\n }\n const [scope, ...pkg] = pkgName.split('/')\n return `${scope}__${pkg.join('')}`\n}\n","import path from 'node:path'\n\nimport resolveFrom from 'resolve-from'\nimport semver from 'semver'\n\nimport {getModuleUrl} from './getAutoUpdatesImportMap'\nimport {readPackageManifest} from './readPackageManifest'\n\nfunction getRemoteResolvedVersion(fetchFn: typeof fetch, url: string) {\n return fetchFn(url, {\n method: 'HEAD',\n redirect: 'manual',\n }).then(\n (res) => {\n // 302 is expected, but lets also handle 2xx\n if (res.ok || res.status < 400) {\n const resolved = res.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 throw new Error(`Unexpected HTTP response: ${res.status} ${res.statusText}`)\n },\n (err) => {\n throw new Error(`Failed to fetch remote version for ${url}: ${err.message}`, {cause: err})\n },\n )\n}\n\ninterface CompareDependencyVersions {\n pkg: string\n installed: string\n remote: string\n}\n\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 autoUpdatesImports - An object mapping package names to their remote import URLs.\n * @param workDir - The path to the working directory containing the package.json file.\n * @param fetchFn - Optional {@link https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API | Fetch}-compatible function to use for requesting the current remote version of a module\n *\n * @returns A promise that resolves to an array of objects, each containing\n * the name of a package whose local and remote versions do not match, along with the local and remote versions.\n *\n * @throws Throws an error if the remote version of a package cannot be fetched, or if the local version of a package\n * cannot be parsed.\n */\nexport async function compareDependencyVersions(\n packages: {version: string; name: string}[],\n workDir: string,\n {fetchFn = globalThis.fetch}: {appId?: string; fetchFn?: typeof fetch} = {},\n): Promise<Array<CompareDependencyVersions>> {\n const manifest = await readPackageManifest(path.join(workDir, 'package.json'))\n const dependencies = {...manifest.dependencies, ...manifest.devDependencies}\n\n const failedDependencies: Array<CompareDependencyVersions> = []\n\n for (const pkg of packages) {\n const resolvedVersion = await getRemoteResolvedVersion(fetchFn, getModuleUrl(pkg))\n\n const manifestPath = resolveFrom.silent(workDir, path.join(pkg.name, 'package.json'))\n\n const manifestVersion = dependencies[pkg.name]\n\n const installed = semver.coerce(\n manifestPath\n ? semver.parse((await readPackageManifest(manifestPath)).version)\n : semver.coerce(manifestVersion),\n )\n\n if (!installed) {\n throw new Error(`Failed to parse installed version for ${pkg}`)\n }\n\n if (!semver.eq(resolvedVersion, installed.version)) {\n failedDependencies.push({\n pkg: pkg.name,\n installed: installed.version,\n remote: resolvedVersion,\n })\n }\n }\n\n return failedDependencies\n}\n","import {type CliConfig} from '@sanity/cli'\nimport chalk from 'chalk'\n\ninterface AutoUpdateSources {\n flags: {['auto-updates']?: boolean}\n cliConfig?: CliConfig\n output?: {warn: (message: string) => void}\n}\n\n/**\n * Compares parameters from various sources to determine whether or not to auto-update\n * @param sources - The sources of the auto-update parameter, including CLI flags and the CLI config\n * @returns boolean\n * @internal\n */\nexport function shouldAutoUpdate({flags, cliConfig, output}: AutoUpdateSources): boolean {\n // cli flags (for example, '--no-auto-updates') should take precedence\n if ('auto-updates' in flags) {\n if (output) {\n const flagUsed = flags['auto-updates'] ? '--auto-updates' : '--no-auto-updates'\n output.warn(\n chalk.yellow(\n `The ${flagUsed} flag is deprecated for \\`deploy\\` and \\`build\\` commands. Set the \\`autoUpdates\\` option in \\`sanity.cli.ts\\` or \\`sanity.cli.js\\` instead.`,\n ),\n )\n }\n return Boolean(flags['auto-updates'])\n }\n\n const hasOldCliConfigFlag = cliConfig && 'autoUpdates' in cliConfig\n const hasNewCliConfigFlag =\n cliConfig &&\n 'deployment' in cliConfig &&\n cliConfig.deployment &&\n 'autoUpdates' in cliConfig.deployment\n\n if (hasOldCliConfigFlag && hasNewCliConfigFlag) {\n throw new Error(\n 'Found both `autoUpdates` (deprecated) and `deployment.autoUpdates` in sanity.cli.js. Please remove the deprecated top level `autoUpdates` config.',\n )\n }\n if (hasOldCliConfigFlag) {\n output?.warn(\n chalk.yellow(\n `The \\`autoUpdates\\` config has moved to \\`deployment.autoUpdates\\`.\nPlease update \\`sanity.cli.ts\\` or \\`sanity.cli.js\\` and make the following change:\n${chalk.red(`- autoUpdates: ${cliConfig.autoUpdates},`)}\n${chalk.green(`+ deployment: {autoUpdates: ${cliConfig.autoUpdates}}}`)}\n`,\n ),\n )\n }\n return Boolean(hasOldCliConfigFlag ? cliConfig.autoUpdates : cliConfig?.deployment?.autoUpdates)\n}\n"],"names":["MODULES_HOST","process","env","SANITY_MODULES_HOST","SANITY_INTERNAL_ENV","currentUnixTime","Math","floor","Date","now","getAutoUpdatesImportMap","packages","options","Object","fromEntries","flatMap","pkg","getAppAutoUpdateImportMapForPackage","moduleUrl","getModuleUrl","name","timestamp","appId","getByAppModuleUrl","baseUrl","getLegacyModuleUrl","encodedMinVer","encodeURIComponent","version","rewriteScopedPackage","pkgName","includes","scope","split","join","getRemoteResolvedVersion","fetchFn","url","method","redirect","then","res","ok","status","resolved","headers","get","Error","statusText","err","message","cause","compareDependencyVersions","workDir","globalThis","fetch","manifest","readPackageManifest","path","dependencies","devDependencies","failedDependencies","resolvedVersion","manifestPath","resolveFrom","silent","manifestVersion","installed","semver","coerce","parse","eq","push","remote","shouldAutoUpdate","flags","cliConfig","output","flagUsed","warn","chalk","yellow","Boolean","hasOldCliConfigFlag","hasNewCliConfigFlag","deployment","red","autoUpdates","green"],"mappings":"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"}
@@ -76,10 +76,10 @@ function listPackages(pkgs) {
76
76
  }
77
77
  function getUpgradeInstructions(pkgs) {
78
78
  const inst = pkgs.map((pkg) => {
79
- const [highestSupported] = pkg.supported.map((version) => (semver.coerce(version) || {
79
+ const [recommendedVersion] = pkg.supported.concat(pkg.deprecatedBelow || []).map((version) => (semver.coerce(version) || {
80
80
  version: ""
81
81
  }).version).sort(semver.rcompare);
82
- return `"${pkg.name}@^${highestSupported}"`;
82
+ return `"${pkg.name}@^${recommendedVersion}"`;
83
83
  }).join(" ");
84
84
  return `To upgrade, run either:
85
85
 
@@ -1 +1 @@
1
- {"version":3,"file":"upgradePackages.js","sources":["../../src/_internal/cli/util/checkStudioDependencyVersions.ts","../../src/_internal/cli/util/checkRequiredDependencies.ts","../../src/_internal/cli/util/packageManager/packageManagerChoice.ts","../../src/_internal/cli/util/packageManager/upgradePackages.ts"],"sourcesContent":["import path from 'node:path'\n\nimport {generateHelpUrl} from '@sanity/generate-help-url'\nimport resolveFrom from 'resolve-from'\nimport semver, {type SemVer} from 'semver'\n\nimport {readPackageJson, readPackageManifest} from './readPackageManifest'\n\ninterface PackageInfo {\n name: string\n supported: string[]\n deprecatedBelow: null | string\n installed: SemVer\n isUnsupported: boolean\n isDeprecated: boolean\n isUntested: boolean\n}\n\n// NOTE: when doing changes here, also remember to update versions in help docs at\n// https://sanity.io/admin/structure/docs;helpArticle;upgrade-packages\nconst PACKAGES = [\n {name: 'react', supported: ['^19.2.2'], deprecatedBelow: null},\n {name: 'react-dom', supported: ['^19.2.2'], deprecatedBelow: null},\n {name: 'styled-components', supported: ['^6'], deprecatedBelow: null},\n {name: '@sanity/ui', supported: ['^2', '^3'], deprecatedBelow: '^3'},\n]\n\nexport async function checkStudioDependencyVersions(workDir: string): Promise<void> {\n const manifest = await readPackageJson(path.join(workDir, 'package.json'))\n const dependencies = {...manifest.dependencies, ...manifest.devDependencies}\n\n const packageInfo = PACKAGES.map(async (pkg): Promise<PackageInfo | false> => {\n const dependency = dependencies[pkg.name]\n if (!dependency) {\n return false\n }\n\n const manifestPath = resolveFrom.silent(workDir, path.join(pkg.name, 'package.json'))\n const installed = semver.coerce(\n manifestPath\n ? (await readPackageManifest(manifestPath)).version\n : dependency.replace(/[\\D.]/g, ''),\n )\n\n if (!installed) {\n return false\n }\n\n const supported = pkg.supported.join(' || ')\n\n // \"Untested\" is usually the case where we have not upgraded the React version requirements\n // before a release, but given that is usually works in a backwards-compatible way, we want\n // to indicate that it's _untested_, not necessarily _unsupported_\n // Ex: Installed is react@20.0.0, but we've only _tested_ with react@^19\n const isUntested = !semver.satisfies(installed, supported) && semver.gtr(installed, supported)\n\n // \"Unsupported\" in that the installed version is _lower than_ the minimum version\n // Ex: Installed is react@18.0.0, but we require react@^19.2\n const isUnsupported = !semver.satisfies(installed, supported) && !isUntested\n\n // \"Deprecated\" in that we will stop supporting it at some point in the near future,\n // so users should be prompted to upgrade\n const isDeprecated = pkg.deprecatedBelow ? semver.ltr(installed, pkg.deprecatedBelow) : false\n\n return {\n ...pkg,\n installed,\n isUnsupported,\n isDeprecated,\n isUntested,\n }\n })\n\n const installedPackages = (await Promise.all(packageInfo)).filter(\n (inp): inp is PackageInfo => inp !== false,\n )\n const unsupported = installedPackages.filter((pkg) => pkg.isUnsupported)\n const deprecated = installedPackages.filter((pkg) => !pkg.isUnsupported && pkg.isDeprecated)\n const untested = installedPackages.filter((pkg) => pkg.isUntested)\n\n if (deprecated.length > 0) {\n console.warn(`\n[WARN] The following package versions have been deprecated and should be upgraded:\n\n ${listPackages(deprecated)}\n\nSupport for these will be removed in a future release!\n\n ${getUpgradeInstructions(deprecated)}\n`)\n }\n\n if (untested.length > 0) {\n console.warn(`\n[WARN] The following package versions have not yet been marked as supported:\n\n ${listPackages(untested)}\n\nYou _may_ encounter bugs while using these versions.\n\n ${getDowngradeInstructions(untested)}\n`)\n }\n\n if (unsupported.length > 0) {\n console.error(`\n[ERROR] The following package versions are no longer supported and needs to be upgraded:\n\n ${listPackages(unsupported)}\n\n ${getUpgradeInstructions(unsupported)}\n`)\n process.exit(1)\n }\n}\n\nfunction listPackages(pkgs: PackageInfo[]) {\n return pkgs\n .map(\n (pkg) =>\n `${pkg.name} (installed: ${pkg.installed}, want: ${\n pkg.deprecatedBelow || pkg.supported.join(' || ')\n })`,\n )\n .join('\\n ')\n}\n\nfunction getUpgradeInstructions(pkgs: PackageInfo[]) {\n const inst = pkgs\n .map((pkg) => {\n const [highestSupported] = pkg.supported\n .map((version) => (semver.coerce(version) || {version: ''}).version)\n .sort(semver.rcompare)\n\n return `\"${pkg.name}@^${highestSupported}\"`\n })\n .join(' ')\n\n return `To upgrade, run either:\n\n npm install ${inst}\n\n or\n\n yarn add ${inst}\n\n or\n\n pnpm add ${inst}\n\n\nRead more at ${generateHelpUrl('upgrade-packages')}`\n}\n\nfunction getDowngradeInstructions(pkgs: PackageInfo[]) {\n const inst = pkgs\n .map((pkg) => {\n const [highestSupported] = pkg.supported\n .map((version) => (semver.coerce(version) || {version: ''}).version)\n .sort(semver.rcompare)\n\n return `\"${pkg.name}@^${highestSupported}\"`\n })\n .join(' ')\n\n return `To downgrade, run either:\n\n yarn add ${inst}\n\n or\n\n npm install ${inst}\n\n or\n\n pnpm install ${inst}`\n}\n","import path from 'node:path'\n\nimport {type CliCommandContext} from '@sanity/cli'\nimport execa from 'execa'\nimport oneline from 'oneline'\nimport semver, {type SemVer} from 'semver'\n\nimport {peerDependencies} from '../../../../package.json'\nimport {determineIsApp} from './determineIsApp'\nimport {readModuleVersion} from './readModuleVersion'\nimport {type PartialPackageManifest, readPackageManifest} from './readPackageManifest'\n\nconst defaultStudioManifestProps: PartialPackageManifest = {\n name: 'studio',\n version: '1.0.0',\n}\n\ninterface CheckResult {\n didInstall: boolean\n installedSanityVersion: string\n}\n\n/**\n * Checks that the studio has declared and installed the required dependencies\n * needed by the Sanity modules. While we generally use regular, explicit\n * dependencies in modules, there are certain dependencies that are better\n * served being peer dependencies, such as react and styled-components.\n *\n * If these dependencies are not installed/declared, we want to prompt the user\n * whether or not to add them to `package.json` and install them\n *\n * Additionally, returns the version of the 'sanity' dependency from the package.json.\n */\nexport async function checkRequiredDependencies(context: CliCommandContext): Promise<CheckResult> {\n // currently there's no check needed for custom apps,\n // but this should be removed once they are more mature\n const isApp = determineIsApp(context.cliConfig)\n if (isApp) {\n return {didInstall: false, installedSanityVersion: ''}\n }\n\n const {workDir: studioPath, output} = context\n const [studioPackageManifest, installedStyledComponentsVersion, installedSanityVersion] =\n await Promise.all([\n await readPackageManifest(path.join(studioPath, 'package.json'), defaultStudioManifestProps),\n await readModuleVersion(studioPath, 'styled-components'),\n await readModuleVersion(studioPath, 'sanity'),\n ])\n\n const wantedStyledComponentsVersionRange = peerDependencies['styled-components']\n\n // Retrieve the version of the 'sanity' dependency\n if (!installedSanityVersion) {\n throw new Error('Failed to read the installed sanity version.')\n }\n\n // The studio _must_ now declare `styled-components` as a dependency. If it's not there,\n // we'll want to automatically _add it_ to the manifest and tell the user to reinstall\n // dependencies before running whatever command was being run\n const declaredStyledComponentsVersion =\n studioPackageManifest.dependencies['styled-components'] ||\n studioPackageManifest.devDependencies['styled-components']\n\n if (!declaredStyledComponentsVersion) {\n const [file, ...args] = process.argv\n const deps = {'styled-components': wantedStyledComponentsVersionRange}\n await installDependencies(deps, context)\n\n // Re-run the same command (sanity dev/sanity build etc) after installation,\n // as it can have shifted the entire `node_modules` folder around, result in\n // broken assumptions about installation paths. This is a hack, and should be\n // solved properly.\n await execa(file, args, {cwd: studioPath, stdio: 'inherit'})\n return {didInstall: true, installedSanityVersion}\n }\n\n // We ignore catalog identifiers since we check the actual version anyway\n const isStyledComponentsVersionRangeInCatalog =\n declaredStyledComponentsVersion.startsWith('catalog:')\n // Theoretically the version specified in package.json could be incorrect, eg `foo`\n let minDeclaredStyledComponentsVersion: SemVer | null = null\n try {\n minDeclaredStyledComponentsVersion = semver.minVersion(declaredStyledComponentsVersion)\n } catch (err) {\n // Intentional fall-through (variable will be left as null, throwing below)\n }\n\n if (!minDeclaredStyledComponentsVersion && !isStyledComponentsVersionRangeInCatalog) {\n throw new Error(oneline`\n Declared dependency \\`styled-components\\` has an invalid version range:\n \\`${declaredStyledComponentsVersion}\\`.\n `)\n }\n\n // The declared version should be semver-compatible with the version specified as a\n // peer dependency in `sanity`. If not, we should tell the user to change it.\n //\n // Exception: Ranges are hard to compare. `>=5.0.0 && <=5.3.2 || ^6`... Comparing this\n // to anything is going to be challenging, so only compare \"simple\" ranges/versions\n // (^x.x.x / ~x.x.x / x.x.x)\n if (\n !isStyledComponentsVersionRangeInCatalog &&\n isComparableRange(declaredStyledComponentsVersion) &&\n !semver.satisfies(minDeclaredStyledComponentsVersion!, wantedStyledComponentsVersionRange)\n ) {\n output.warn(oneline`\n Declared version of styled-components (${declaredStyledComponentsVersion})\n is not compatible with the version required by sanity (${wantedStyledComponentsVersionRange}).\n This might cause problems!\n `)\n }\n\n // Ensure the studio has _installed_ a version of `styled-components`\n if (!installedStyledComponentsVersion) {\n throw new Error(oneline`\n Declared dependency \\`styled-components\\` is not installed - run\n \\`npm install\\`, \\`yarn install\\` or \\`pnpm install\\` to install it before re-running this command.\n `)\n }\n\n // The studio should have an _installed_ version of `styled-components`, and it should\n // be semver compatible with the version specified in `sanity` peer dependencies.\n if (!semver.satisfies(installedStyledComponentsVersion, wantedStyledComponentsVersionRange)) {\n output.warn(oneline`\n Installed version of styled-components (${installedStyledComponentsVersion})\n is not compatible with the version required by sanity (${wantedStyledComponentsVersionRange}).\n This might cause problems!\n `)\n }\n\n return {didInstall: false, installedSanityVersion}\n}\n\n/**\n * Install the passed dependencies at the given version/version range,\n * prompting the user which package manager to use. We will try to detect\n * a package manager from files in the directory and show that as the default\n *\n * @param dependencies - Object of dependencies `({[package name]: version})`\n * @param context - CLI context\n */\nasync function installDependencies(\n dependencies: Record<string, string>,\n context: CliCommandContext,\n): Promise<void> {\n const {output, prompt, workDir, cliPackageManager} = context\n const packages: string[] = []\n\n output.print('The Sanity studio needs to install missing dependencies:')\n for (const [pkgName, version] of Object.entries(dependencies)) {\n const declaration = `${pkgName}@${version}`\n output.print(`- ${declaration}`)\n packages.push(declaration)\n }\n\n if (!cliPackageManager) {\n output.error(\n 'ERROR: Could not determine package manager choice - run `npm install` or equivalent',\n )\n return\n }\n\n const {getPackageManagerChoice, installNewPackages} = cliPackageManager\n const {mostOptimal, chosen: pkgManager} = await getPackageManagerChoice(workDir, {prompt})\n if (mostOptimal && pkgManager !== mostOptimal) {\n output.warn(\n `WARN: This project appears to be installed with or using ${mostOptimal} - using a different package manager _may_ result in errors.`,\n )\n }\n\n await installNewPackages({packages, packageManager: pkgManager}, context)\n}\n\nfunction isComparableRange(range: string): boolean {\n return /^[\\^~]?\\d+(\\.\\d+)?(\\.\\d+)?$/.test(range)\n}\n","import path from 'node:path'\n\nimport {type CliPrompter} from '@sanity/cli'\nimport preferredPM from 'preferred-pm'\nimport which from 'which'\n\nimport {isInteractive} from '../isInteractive'\n\nexport type PackageManager = 'npm' | 'yarn' | 'pnpm' | 'bun' | 'manual'\n\nexport const ALLOWED_PACKAGE_MANAGERS: PackageManager[] = ['npm', 'yarn', 'pnpm', 'bun', 'manual']\nexport const allowedPackageManagersString = ALLOWED_PACKAGE_MANAGERS.map((pm) => `\"${pm}\"`).join(\n ' | ',\n)\n\nconst EXPERIMENTAL = ['bun']\n\n/**\n * Attempts to resolve the most optimal package manager to use to install/upgrade\n * packages/dependencies at a given path. It does so by looking for package manager\n * specific lockfiles. If it finds a lockfile belonging to a certain package manager,\n * it prioritizes this one. However, if that package manager is not installed, it will\n * prompt the user for which one they want to use and hint at the most optimal one\n * not being installed.\n *\n * Note that this function also takes local npm binary paths into account - for instance,\n * `yarn` can be installed as a dependency of the project instead of globally, and it\n * will use that is available.\n *\n * The user can also select 'manual' to skip the process and run their preferred package\n * manager manually. Commands using this function must take this `manual` choice into\n * account and act accordingly if chosen.\n *\n * @param workDir - The working directory where a lockfile is most likely to be present\n * @param options - Pass `interactive: false` to fall back to npm if most optimal is\n * not available, instead of prompting\n * @returns Object of `chosen` and, if a lockfile is found, the `mostOptimal` choice\n */\nexport async function getPackageManagerChoice(\n workDir: string,\n options: {interactive: false} | {interactive?: true; prompt: CliPrompter},\n): Promise<{chosen: PackageManager; mostOptimal?: PackageManager}> {\n const rootDir = workDir || process.cwd()\n const preferred = (await preferredPM(rootDir))?.name\n\n if (preferred && (await hasCommand(preferred, rootDir))) {\n // There is an optimal/preferred package manager, and the user has it installed!\n return {chosen: preferred, mostOptimal: preferred}\n }\n\n const mostLikelyPM = await getMostLikelyInstalledPackageManager(rootDir)\n const interactive = typeof options.interactive === 'boolean' ? options.interactive : isInteractive\n if (!interactive) {\n // We can't ask the user for their preference, so fall back to either the one that is being run\n // or whatever is installed on the system (npm being the preferred choice).\n // Note that the most optimal choice is already picked above if available.\n return {chosen: mostLikelyPM || (await getFallback(rootDir)), mostOptimal: preferred}\n }\n\n if (!('prompt' in options)) {\n throw new Error('Must pass `prompt` when in interactive mode')\n }\n\n // We can ask the user for their preference, hurray!\n const messageSuffix = preferred ? ` (preferred is ${preferred}, but is not installed)` : ''\n const installed = await getAvailablePackageManagers(rootDir)\n const chosen = await options.prompt.single<PackageManager>({\n type: 'list',\n choices: installed.map((pm) => ({\n value: pm,\n name: EXPERIMENTAL.includes(pm) ? `${pm} (experimental)` : pm,\n })),\n default: preferred || mostLikelyPM,\n message: `Package manager to use for installing dependencies?${messageSuffix}`,\n })\n\n return {chosen, mostOptimal: preferred}\n}\n\nasync function getFallback(cwd: string): Promise<PackageManager> {\n if (await hasNpmInstalled(cwd)) {\n return 'npm'\n }\n\n if (await hasYarnInstalled(cwd)) {\n return 'yarn'\n }\n\n if (await hasPnpmInstalled(cwd)) {\n return 'pnpm'\n }\n\n if (await hasBunInstalled(cwd)) {\n return 'bun'\n }\n\n return 'manual'\n}\n\nasync function getAvailablePackageManagers(cwd: string): Promise<PackageManager[]> {\n const [npm, yarn, pnpm, bun] = await Promise.all([\n hasNpmInstalled(cwd),\n hasYarnInstalled(cwd),\n hasPnpmInstalled(cwd),\n hasBunInstalled(cwd),\n ])\n\n const choices = [npm && 'npm', yarn && 'yarn', pnpm && 'pnpm', bun && 'bun', 'manual']\n return choices.filter((pm): pm is PackageManager => pm !== false)\n}\n\nexport function hasNpmInstalled(cwd?: string): Promise<boolean> {\n return hasCommand('npm', cwd)\n}\n\nexport function hasYarnInstalled(cwd?: string): Promise<boolean> {\n return hasCommand('yarn', cwd)\n}\n\nexport function hasPnpmInstalled(cwd?: string): Promise<boolean> {\n return hasCommand('pnpm', cwd)\n}\n\nexport function hasBunInstalled(cwd?: string): Promise<boolean> {\n return hasCommand('bun', cwd)\n}\n\nexport function getNpmRunPath(cwd: string): string {\n let previous\n let cwdPath = path.resolve(cwd)\n const result: string[] = []\n\n while (previous !== cwdPath) {\n result.push(path.join(cwdPath, 'node_modules', '.bin'))\n previous = cwdPath\n cwdPath = path.resolve(cwdPath, '..')\n }\n\n result.push(path.resolve(cwd, process.execPath, '..'))\n\n const pathEnv = process.env[getPathEnvVarKey()]\n return [...result, pathEnv].join(path.delimiter)\n}\n\nexport function getPartialEnvWithNpmPath(cwd: string): NodeJS.ProcessEnv {\n const key = getPathEnvVarKey()\n return {[key]: getNpmRunPath(cwd)}\n}\n\nfunction getPathEnvVarKey(): string {\n if (process.platform !== 'win32') {\n return 'PATH'\n }\n\n return (\n Object.keys(process.env)\n .reverse()\n .find((key) => key.toUpperCase() === 'PATH') || 'Path'\n )\n}\n\nfunction getCommandPath(cmd: string, cwd?: string): Promise<string | null> {\n const options = {path: cwd ? getNpmRunPath(cwd) : undefined}\n return which(cmd, options).catch(() => null)\n}\n\nfunction hasCommand(cmd: string, cwd?: string): Promise<boolean> {\n return getCommandPath(cmd, cwd).then((cmdPath) => cmdPath !== null)\n}\n\nasync function getMostLikelyInstalledPackageManager(\n rootDir: string,\n): Promise<PackageManager | undefined> {\n const installed = await getAvailablePackageManagers(rootDir)\n const running = getRunningPackageManager()\n return running && installed.includes(running) ? running : undefined\n}\n\nfunction getRunningPackageManager(): PackageManager | undefined {\n // Yes, the env var is lowercase - it is set by the package managers themselves\n const agent = process.env.npm_config_user_agent || ''\n\n if (agent.includes('yarn')) {\n return 'yarn'\n }\n\n if (agent.includes('pnpm')) {\n return 'pnpm'\n }\n\n if (agent.includes('bun')) {\n return 'bun'\n }\n\n // Both yarn and pnpm does a `npm/?` thing, thus the slightly different match here\n // Theoretically not needed since we check for yarn/pnpm above, but in case other\n // package managers do the same thing, we'll (hopefully) catch them here.\n if (/^npm\\/\\d/.test(agent)) {\n return 'npm'\n }\n\n return undefined\n}\n","import execa, {type CommonOptions, type ExecaReturnValue} from 'execa'\n\nimport {getPartialEnvWithNpmPath, type PackageManager} from './packageManagerChoice'\n\nexport interface InstallOptions {\n packageManager: PackageManager\n packages: [name: string, version: string][]\n}\n\nexport async function upgradePackages(\n options: InstallOptions,\n context: {output: {print: (output: string) => void}; workDir: string},\n): Promise<void> {\n const {packageManager, packages} = options\n const {output, workDir} = context\n const execOptions: CommonOptions<'utf8'> = {\n encoding: 'utf8',\n env: getPartialEnvWithNpmPath(workDir),\n cwd: workDir,\n stdio: 'inherit',\n }\n const upgradePackageArgs = packages.map((pkg) => pkg.join('@'))\n let result: ExecaReturnValue<string> | undefined\n if (packageManager === 'npm') {\n const npmArgs = ['install', '--legacy-peer-deps', ...upgradePackageArgs]\n output.print(`Running 'npm ${npmArgs.join(' ')}'`)\n result = await execa('npm', npmArgs, execOptions)\n } else if (packageManager === 'yarn') {\n const yarnArgs = ['upgrade ', ...upgradePackageArgs]\n output.print(`Running 'yarn ${yarnArgs.join(' ')}'`)\n result = await execa('yarn', yarnArgs, execOptions)\n } else if (packageManager === 'pnpm') {\n const pnpmArgs = ['upgrade', ...upgradePackageArgs]\n output.print(`Running 'pnpm ${pnpmArgs.join(' ')}'`)\n result = await execa('pnpm', pnpmArgs, execOptions)\n } else if (packageManager === 'bun') {\n const bunArgs = ['update', ...upgradePackageArgs]\n output.print(`Running 'bun ${bunArgs.join(' ')}'`)\n result = await execa('bun', bunArgs, execOptions)\n } else if (packageManager === 'manual') {\n output.print(\n `Manual installation selected - run 'npm upgrade ${upgradePackageArgs.join(' ')}' or equivalent`,\n )\n }\n\n if (result?.exitCode || result?.failed) {\n throw new Error('Package upgrade failed')\n }\n}\n"],"names":["PACKAGES","name","supported","deprecatedBelow","checkStudioDependencyVersions","workDir","manifest","readPackageJson","path","join","dependencies","devDependencies","packageInfo","map","pkg","dependency","manifestPath","resolveFrom","silent","installed","semver","coerce","readPackageManifest","version","replace","isUntested","satisfies","gtr","isUnsupported","isDeprecated","ltr","installedPackages","Promise","all","filter","inp","unsupported","deprecated","untested","length","console","warn","listPackages","getUpgradeInstructions","getDowngradeInstructions","error","process","exit","pkgs","inst","highestSupported","sort","rcompare","generateHelpUrl","defaultStudioManifestProps","checkRequiredDependencies","context","determineIsApp","cliConfig","didInstall","installedSanityVersion","studioPath","output","studioPackageManifest","installedStyledComponentsVersion","readModuleVersion","wantedStyledComponentsVersionRange","peerDependencies","Error","declaredStyledComponentsVersion","file","args","argv","installDependencies","execa","cwd","stdio","isStyledComponentsVersionRangeInCatalog","startsWith","minDeclaredStyledComponentsVersion","minVersion","oneline","isComparableRange","prompt","cliPackageManager","packages","print","pkgName","Object","entries","declaration","push","getPackageManagerChoice","installNewPackages","mostOptimal","chosen","pkgManager","packageManager","range","test","EXPERIMENTAL","options","rootDir","preferred","preferredPM","hasCommand","mostLikelyPM","getMostLikelyInstalledPackageManager","interactive","isInteractive","getFallback","messageSuffix","getAvailablePackageManagers","single","type","choices","pm","value","includes","default","message","hasNpmInstalled","hasYarnInstalled","hasPnpmInstalled","hasBunInstalled","npm","yarn","pnpm","bun","getNpmRunPath","previous","cwdPath","resolve","result","execPath","pathEnv","env","getPathEnvVarKey","delimiter","getPartialEnvWithNpmPath","platform","keys","reverse","find","key","toUpperCase","getCommandPath","cmd","undefined","which","catch","then","cmdPath","running","getRunningPackageManager","agent","npm_config_user_agent","upgradePackages","execOptions","encoding","upgradePackageArgs","npmArgs","yarnArgs","pnpmArgs","bunArgs","exitCode","failed"],"mappings":";;;;;;;;;;;AAoBA,MAAMA,WAAW,CACf;AAAA,EAACC,MAAM;AAAA,EAASC,WAAW,CAAC,SAAS;AAAA,EAAGC,iBAAiB;AAAI,GAC7D;AAAA,EAACF,MAAM;AAAA,EAAaC,WAAW,CAAC,SAAS;AAAA,EAAGC,iBAAiB;AAAI,GACjE;AAAA,EAACF,MAAM;AAAA,EAAqBC,WAAW,CAAC,IAAI;AAAA,EAAGC,iBAAiB;AAAI,GACpE;AAAA,EAACF,MAAM;AAAA,EAAcC,WAAW,CAAC,MAAM,IAAI;AAAA,EAAGC,iBAAiB;AAAI,CAAC;AAGtE,eAAsBC,8BAA8BC,SAAgC;AAClF,QAAMC,WAAW,MAAMC,gBAAgBC,KAAKC,KAAKJ,SAAS,cAAc,CAAC,GACnEK,eAAe;AAAA,IAAC,GAAGJ,SAASI;AAAAA,IAAc,GAAGJ,SAASK;AAAAA,EAAAA,GAEtDC,cAAcZ,SAASa,IAAI,OAAOC,QAAsC;AAC5E,UAAMC,aAAaL,aAAaI,IAAIb,IAAI;AACxC,QAAI,CAACc;AACH,aAAO;AAGT,UAAMC,eAAeC,YAAYC,OAAOb,SAASG,KAAKC,KAAKK,IAAIb,MAAM,cAAc,CAAC,GAC9EkB,YAAYC,OAAOC,OACvBL,gBACK,MAAMM,oBAAoBN,YAAY,GAAGO,UAC1CR,WAAWS,QAAQ,UAAU,EAAE,CACrC;AAEA,QAAI,CAACL;AACH,aAAO;AAGT,UAAMjB,YAAYY,IAAIZ,UAAUO,KAAK,MAAM,GAMrCgB,aAAa,CAACL,OAAOM,UAAUP,WAAWjB,SAAS,KAAKkB,OAAOO,IAAIR,WAAWjB,SAAS,GAIvF0B,gBAAgB,CAACR,OAAOM,UAAUP,WAAWjB,SAAS,KAAK,CAACuB,YAI5DI,eAAef,IAAIX,kBAAkBiB,OAAOU,IAAIX,WAAWL,IAAIX,eAAe,IAAI;AAExF,WAAO;AAAA,MACL,GAAGW;AAAAA,MACHK;AAAAA,MACAS;AAAAA,MACAC;AAAAA,MACAJ;AAAAA,IAAAA;AAAAA,EAEJ,CAAC,GAEKM,qBAAqB,MAAMC,QAAQC,IAAIrB,WAAW,GAAGsB,OACxDC,SAA4BA,QAAQ,EACvC,GACMC,cAAcL,kBAAkBG,OAAQpB,CAAAA,QAAQA,IAAIc,aAAa,GACjES,aAAaN,kBAAkBG,OAAQpB,CAAAA,QAAQ,CAACA,IAAIc,iBAAiBd,IAAIe,YAAY,GACrFS,WAAWP,kBAAkBG,OAAQpB,CAAAA,QAAQA,IAAIW,UAAU;AAE7DY,aAAWE,SAAS,KACtBC,QAAQC,KAAK;AAAA;AAAA;AAAA,IAGbC,aAAaL,UAAU,CAAC;AAAA;AAAA;AAAA;AAAA,IAIxBM,uBAAuBN,UAAU,CAAC;AAAA,CACrC,GAGKC,SAASC,SAAS,KACpBC,QAAQC,KAAK;AAAA;AAAA;AAAA,IAGbC,aAAaJ,QAAQ,CAAC;AAAA;AAAA;AAAA;AAAA,IAItBM,yBAAyBN,QAAQ,CAAC;AAAA,CACrC,GAGKF,YAAYG,SAAS,MACvBC,QAAQK,MAAM;AAAA;AAAA;AAAA,IAGdH,aAAaN,WAAW,CAAC;AAAA;AAAA,IAEzBO,uBAAuBP,WAAW,CAAC;AAAA,CACtC,GACGU,QAAQC,KAAK,CAAC;AAElB;AAEA,SAASL,aAAaM,MAAqB;AACzC,SAAOA,KACJnC,IACEC,CAAAA,QACC,GAAGA,IAAIb,IAAI,gBAAgBa,IAAIK,SAAS,WACtCL,IAAIX,mBAAmBW,IAAIZ,UAAUO,KAAK,MAAM,CAAC,GAEvD,EACCA,KAAK;AAAA,GAAM;AAChB;AAEA,SAASkC,uBAAuBK,MAAqB;AACnD,QAAMC,OAAOD,KACVnC,IAAKC,CAAAA,QAAQ;AACZ,UAAM,CAACoC,gBAAgB,IAAIpC,IAAIZ,UAC5BW,IAAKU,CAAAA,aAAaH,OAAOC,OAAOE,OAAO,KAAK;AAAA,MAACA,SAAS;AAAA,IAAA,GAAKA,OAAO,EAClE4B,KAAK/B,OAAOgC,QAAQ;AAEvB,WAAO,IAAItC,IAAIb,IAAI,KAAKiD,gBAAgB;AAAA,EAC1C,CAAC,EACAzC,KAAK,GAAG;AAEX,SAAO;AAAA;AAAA,gBAEOwC,IAAI;AAAA;AAAA;AAAA;AAAA,aAIPA,IAAI;AAAA;AAAA;AAAA;AAAA,aAIJA,IAAI;AAAA;AAAA;AAAA,eAGFI,gBAAgB,kBAAkB,CAAC;AAClD;AAEA,SAAST,yBAAyBI,MAAqB;AACrD,QAAMC,OAAOD,KACVnC,IAAKC,CAAAA,QAAQ;AACZ,UAAM,CAACoC,gBAAgB,IAAIpC,IAAIZ,UAC5BW,IAAKU,CAAAA,aAAaH,OAAOC,OAAOE,OAAO,KAAK;AAAA,MAACA,SAAS;AAAA,IAAA,GAAKA,OAAO,EAClE4B,KAAK/B,OAAOgC,QAAQ;AAEvB,WAAO,IAAItC,IAAIb,IAAI,KAAKiD,gBAAgB;AAAA,EAC1C,CAAC,EACAzC,KAAK,GAAG;AAEX,SAAO;AAAA;AAAA,aAEIwC,IAAI;AAAA;AAAA;AAAA;AAAA,gBAIDA,IAAI;AAAA;AAAA;AAAA;AAAA,iBAIHA,IAAI;AACrB;ACpKA,MAAMK,6BAAqD;AAAA,EACzDrD,MAAM;AAAA,EACNsB,SAAS;AACX;AAkBA,eAAsBgC,0BAA0BC,SAAkD;AAIhG,MADcC,eAAeD,QAAQE,SAAS;AAE5C,WAAO;AAAA,MAACC,YAAY;AAAA,MAAOC,wBAAwB;AAAA,IAAA;AAGrD,QAAM;AAAA,IAACvD,SAASwD;AAAAA,IAAYC;AAAAA,EAAAA,IAAUN,SAChC,CAACO,uBAAuBC,kCAAkCJ,sBAAsB,IACpF,MAAM5B,QAAQC,IAAI,CAChB,MAAMX,oBAAoBd,KAAKC,KAAKoD,YAAY,cAAc,GAAGP,0BAA0B,GAC3F,MAAMW,kBAAkBJ,YAAY,mBAAmB,GACvD,MAAMI,kBAAkBJ,YAAY,QAAQ,CAAC,CAC9C,GAEGK,qCAAqCC,iBAAiB,mBAAmB;AAG/E,MAAI,CAACP;AACH,UAAM,IAAIQ,MAAM,8CAA8C;AAMhE,QAAMC,kCACJN,sBAAsBrD,aAAa,mBAAmB,KACtDqD,sBAAsBpD,gBAAgB,mBAAmB;AAE3D,MAAI,CAAC0D,iCAAiC;AACpC,UAAM,CAACC,MAAM,GAAGC,IAAI,IAAIzB,QAAQ0B;AAEhC,WAAA,MAAMC,oBADO;AAAA,MAAC,qBAAqBP;AAAAA,IAAAA,GACHV,OAAO,GAMvC,MAAMkB,MAAMJ,MAAMC,MAAM;AAAA,MAACI,KAAKd;AAAAA,MAAYe,OAAO;AAAA,IAAA,CAAU,GACpD;AAAA,MAACjB,YAAY;AAAA,MAAMC;AAAAA,IAAAA;AAAAA,EAC5B;AAGA,QAAMiB,0CACJR,gCAAgCS,WAAW,UAAU;AAEvD,MAAIC,qCAAoD;AACxD,MAAI;AACFA,yCAAqC3D,OAAO4D,WAAWX,+BAA+B;AAAA,EACxF,QAAc;AAAA,EACZ;AAGF,MAAI,CAACU,sCAAsC,CAACF;AAC1C,UAAM,IAAIT,MAAMa;AAAAA;AAAAA,UAEVZ,+BAA+B;AAAA,KACpC;AAsBH,MAZE,CAACQ,2CACDK,kBAAkBb,+BAA+B,KACjD,CAACjD,OAAOM,UAAUqD,oCAAqCb,kCAAkC,KAEzFJ,OAAOrB,KAAKwC;AAAAA,+CAC+BZ,+BAA+B;AAAA,+DACfH,kCAAkC;AAAA;AAAA,KAE5F,GAIC,CAACF;AACH,UAAM,IAAII,MAAMa;AAAAA;AAAAA;AAAAA,KAGf;AAKH,SAAK7D,OAAOM,UAAUsC,kCAAkCE,kCAAkC,KACxFJ,OAAOrB,KAAKwC;AAAAA,gDACgCjB,gCAAgC;AAAA,+DACjBE,kCAAkC;AAAA;AAAA,KAE5F,GAGI;AAAA,IAACP,YAAY;AAAA,IAAOC;AAAAA,EAAAA;AAC7B;AAUA,eAAea,oBACb/D,cACA8C,SACe;AACf,QAAM;AAAA,IAACM;AAAAA,IAAQqB;AAAAA,IAAQ9E;AAAAA,IAAS+E;AAAAA,EAAAA,IAAqB5B,SAC/C6B,WAAqB,CAAA;AAE3BvB,SAAOwB,MAAM,0DAA0D;AACvE,aAAW,CAACC,SAAShE,OAAO,KAAKiE,OAAOC,QAAQ/E,YAAY,GAAG;AAC7D,UAAMgF,cAAc,GAAGH,OAAO,IAAIhE,OAAO;AACzCuC,WAAOwB,MAAM,KAAKI,WAAW,EAAE,GAC/BL,SAASM,KAAKD,WAAW;AAAA,EAC3B;AAEA,MAAI,CAACN,mBAAmB;AACtBtB,WAAOjB,MACL,qFACF;AACA;AAAA,EACF;AAEA,QAAM;AAAA,IAAC+C,yBAAAA;AAAAA,IAAyBC;AAAAA,EAAAA,IAAsBT,mBAChD;AAAA,IAACU;AAAAA,IAAaC,QAAQC;AAAAA,EAAAA,IAAc,MAAMJ,yBAAwBvF,SAAS;AAAA,IAAC8E;AAAAA,EAAAA,CAAO;AACrFW,iBAAeE,eAAeF,eAChChC,OAAOrB,KACL,4DAA4DqD,WAAW,8DACzE,GAGF,MAAMD,mBAAmB;AAAA,IAACR;AAAAA,IAAUY,gBAAgBD;AAAAA,EAAAA,GAAaxC,OAAO;AAC1E;AAEA,SAAS0B,kBAAkBgB,OAAwB;AACjD,SAAO,8BAA8BC,KAAKD,KAAK;AACjD;AChKA,MAAME,eAAe,CAAC,KAAK;AAuB3B,eAAsBR,wBACpBvF,SACAgG,SACiE;AACjE,QAAMC,UAAUjG,WAAWyC,QAAQ6B,IAAAA,GAC7B4B,aAAa,MAAMC,YAAYF,OAAO,IAAIrG;AAEhD,MAAIsG,aAAc,MAAME,WAAWF,WAAWD,OAAO;AAEnD,WAAO;AAAA,MAACP,QAAQQ;AAAAA,MAAWT,aAAaS;AAAAA,IAAAA;AAG1C,QAAMG,eAAe,MAAMC,qCAAqCL,OAAO;AAEvE,MAAI,EADgB,OAAOD,QAAQO,eAAgB,YAAYP,QAAQO,cAAcC;AAKnF,WAAO;AAAA,MAACd,QAAQW,gBAAiB,MAAMI,YAAYR,OAAO;AAAA,MAAIR,aAAaS;AAAAA,IAAAA;AAG7E,MAAI,EAAE,YAAYF;AAChB,UAAM,IAAIjC,MAAM,6CAA6C;AAI/D,QAAM2C,gBAAgBR,YAAY,kBAAkBA,SAAS,4BAA4B,IACnFpF,YAAY,MAAM6F,4BAA4BV,OAAO;AAW3D,SAAO;AAAA,IAACP,QAVO,MAAMM,QAAQlB,OAAO8B,OAAuB;AAAA,MACzDC,MAAM;AAAA,MACNC,SAAShG,UAAUN,IAAKuG,CAAAA,QAAQ;AAAA,QAC9BC,OAAOD;AAAAA,QACPnH,MAAMmG,aAAakB,SAASF,EAAE,IAAI,GAAGA,EAAE,oBAAoBA;AAAAA,MAAAA,EAC3D;AAAA,MACFG,SAAShB,aAAaG;AAAAA,MACtBc,SAAS,sDAAsDT,aAAa;AAAA,IAAA,CAC7E;AAAA,IAEejB,aAAaS;AAAAA,EAAAA;AAC/B;AAEA,eAAeO,YAAYnC,KAAsC;AAC/D,SAAI,MAAM8C,gBAAgB9C,GAAG,IACpB,QAGL,MAAM+C,iBAAiB/C,GAAG,IACrB,SAGL,MAAMgD,iBAAiBhD,GAAG,IACrB,SAGL,MAAMiD,gBAAgBjD,GAAG,IACpB,QAGF;AACT;AAEA,eAAeqC,4BAA4BrC,KAAwC;AACjF,QAAM,CAACkD,KAAKC,MAAMC,MAAMC,GAAG,IAAI,MAAMhG,QAAQC,IAAI,CAC/CwF,gBAAgB9C,GAAG,GACnB+C,iBAAiB/C,GAAG,GACpBgD,iBAAiBhD,GAAG,GACpBiD,gBAAgBjD,GAAG,CAAC,CACrB;AAGD,SADgB,CAACkD,OAAO,OAAOC,QAAQ,QAAQC,QAAQ,QAAQC,OAAO,OAAO,QAAQ,EACtE9F,OAAQkF,CAAAA,OAA6BA,OAAO,EAAK;AAClE;AAEO,SAASK,gBAAgB9C,KAAgC;AAC9D,SAAO8B,WAAW,OAAO9B,GAAG;AAC9B;AAEO,SAAS+C,iBAAiB/C,KAAgC;AAC/D,SAAO8B,WAAW,QAAQ9B,GAAG;AAC/B;AAEO,SAASgD,iBAAiBhD,KAAgC;AAC/D,SAAO8B,WAAW,QAAQ9B,GAAG;AAC/B;AAEO,SAASiD,gBAAgBjD,KAAgC;AAC9D,SAAO8B,WAAW,OAAO9B,GAAG;AAC9B;AAEO,SAASsD,cAActD,KAAqB;AACjD,MAAIuD,UACAC,UAAU3H,KAAK4H,QAAQzD,GAAG;AAC9B,QAAM0D,SAAmB,CAAA;AAEzB,SAAOH,aAAaC;AAClBE,WAAO1C,KAAKnF,KAAKC,KAAK0H,SAAS,gBAAgB,MAAM,CAAC,GACtDD,WAAWC,SACXA,UAAU3H,KAAK4H,QAAQD,SAAS,IAAI;AAGtCE,SAAO1C,KAAKnF,KAAK4H,QAAQzD,KAAK7B,QAAQwF,UAAU,IAAI,CAAC;AAErD,QAAMC,UAAUzF,QAAQ0F,IAAIC,iBAAAA,CAAkB;AAC9C,SAAO,CAAC,GAAGJ,QAAQE,OAAO,EAAE9H,KAAKD,KAAKkI,SAAS;AACjD;AAEO,SAASC,yBAAyBhE,KAAgC;AAEvE,SAAO;AAAA,IAAC,CADI8D,iBAAAA,CACA,GAAGR,cAActD,GAAG;AAAA,EAAA;AAClC;AAEA,SAAS8D,mBAA2B;AAClC,SAAI3F,QAAQ8F,aAAa,UAChB,SAIPpD,OAAOqD,KAAK/F,QAAQ0F,GAAG,EACpBM,QAAAA,EACAC,KAAMC,CAAAA,QAAQA,IAAIC,YAAAA,MAAkB,MAAM,KAAK;AAEtD;AAEA,SAASC,eAAeC,KAAaxE,KAAsC;AACzE,QAAM0B,UAAU;AAAA,IAAC7F,MAAMmE,MAAMsD,cAActD,GAAG,IAAIyE;AAAAA,EAAAA;AAClD,SAAOC,MAAMF,KAAK9C,OAAO,EAAEiD,MAAM,MAAM,IAAI;AAC7C;AAEA,SAAS7C,WAAW0C,KAAaxE,KAAgC;AAC/D,SAAOuE,eAAeC,KAAKxE,GAAG,EAAE4E,KAAMC,CAAAA,YAAYA,YAAY,IAAI;AACpE;AAEA,eAAe7C,qCACbL,SACqC;AACrC,QAAMnF,YAAY,MAAM6F,4BAA4BV,OAAO,GACrDmD,UAAUC,yBAAAA;AAChB,SAAOD,WAAWtI,UAAUmG,SAASmC,OAAO,IAAIA,UAAUL;AAC5D;AAEA,SAASM,2BAAuD;AAE9D,QAAMC,QAAQ7G,QAAQ0F,IAAIoB,yBAAyB;AAEnD,MAAID,MAAMrC,SAAS,MAAM;AACvB,WAAO;AAGT,MAAIqC,MAAMrC,SAAS,MAAM;AACvB,WAAO;AAGT,MAAIqC,MAAMrC,SAAS,KAAK;AACtB,WAAO;AAMT,MAAI,WAAWnB,KAAKwD,KAAK;AACvB,WAAO;AAIX;ACjMA,eAAsBE,gBACpBxD,SACA7C,SACe;AACf,QAAM;AAAA,IAACyC;AAAAA,IAAgBZ;AAAAA,EAAAA,IAAYgB,SAC7B;AAAA,IAACvC;AAAAA,IAAQzD;AAAAA,EAAAA,IAAWmD,SACpBsG,cAAqC;AAAA,IACzCC,UAAU;AAAA,IACVvB,KAAKG,yBAAyBtI,OAAO;AAAA,IACrCsE,KAAKtE;AAAAA,IACLuE,OAAO;AAAA,EAAA,GAEHoF,qBAAqB3E,SAASxE,IAAKC,SAAQA,IAAIL,KAAK,GAAG,CAAC;AAC9D,MAAI4H;AACJ,MAAIpC,mBAAmB,OAAO;AAC5B,UAAMgE,UAAU,CAAC,WAAW,sBAAsB,GAAGD,kBAAkB;AACvElG,WAAOwB,MAAM,gBAAgB2E,QAAQxJ,KAAK,GAAG,CAAC,GAAG,GACjD4H,SAAS,MAAM3D,MAAM,OAAOuF,SAASH,WAAW;AAAA,EAClD,WAAW7D,mBAAmB,QAAQ;AACpC,UAAMiE,WAAW,CAAC,YAAY,GAAGF,kBAAkB;AACnDlG,WAAOwB,MAAM,iBAAiB4E,SAASzJ,KAAK,GAAG,CAAC,GAAG,GACnD4H,SAAS,MAAM3D,MAAM,QAAQwF,UAAUJ,WAAW;AAAA,EACpD,WAAW7D,mBAAmB,QAAQ;AACpC,UAAMkE,WAAW,CAAC,WAAW,GAAGH,kBAAkB;AAClDlG,WAAOwB,MAAM,iBAAiB6E,SAAS1J,KAAK,GAAG,CAAC,GAAG,GACnD4H,SAAS,MAAM3D,MAAM,QAAQyF,UAAUL,WAAW;AAAA,EACpD,WAAW7D,mBAAmB,OAAO;AACnC,UAAMmE,UAAU,CAAC,UAAU,GAAGJ,kBAAkB;AAChDlG,WAAOwB,MAAM,gBAAgB8E,QAAQ3J,KAAK,GAAG,CAAC,GAAG,GACjD4H,SAAS,MAAM3D,MAAM,OAAO0F,SAASN,WAAW;AAAA,EAClD,MAAW7D,oBAAmB,YAC5BnC,OAAOwB,MACL,mDAAmD0E,mBAAmBvJ,KAAK,GAAG,CAAC,iBACjF;AAGF,MAAI4H,QAAQgC,YAAYhC,QAAQiC;AAC9B,UAAM,IAAIlG,MAAM,wBAAwB;AAE5C;"}
1
+ {"version":3,"file":"upgradePackages.js","sources":["../../src/_internal/cli/util/checkStudioDependencyVersions.ts","../../src/_internal/cli/util/checkRequiredDependencies.ts","../../src/_internal/cli/util/packageManager/packageManagerChoice.ts","../../src/_internal/cli/util/packageManager/upgradePackages.ts"],"sourcesContent":["import path from 'node:path'\n\nimport {generateHelpUrl} from '@sanity/generate-help-url'\nimport resolveFrom from 'resolve-from'\nimport semver, {type SemVer} from 'semver'\n\nimport {readPackageJson, readPackageManifest} from './readPackageManifest'\n\ninterface PackageInfo {\n name: string\n supported: string[]\n deprecatedBelow: null | string\n installed: SemVer\n isUnsupported: boolean\n isDeprecated: boolean\n isUntested: boolean\n}\n\n// NOTE: when doing changes here, also remember to update versions in help docs at\n// https://sanity.io/admin/structure/docs;helpArticle;upgrade-packages\nconst PACKAGES = [\n {name: 'react', supported: ['^19.2.2'], deprecatedBelow: null},\n {name: 'react-dom', supported: ['^19.2.2'], deprecatedBelow: null},\n {name: 'styled-components', supported: ['^6'], deprecatedBelow: null},\n {name: '@sanity/ui', supported: ['^2', '^3'], deprecatedBelow: '^3'},\n]\n\nexport async function checkStudioDependencyVersions(workDir: string): Promise<void> {\n const manifest = await readPackageJson(path.join(workDir, 'package.json'))\n const dependencies = {...manifest.dependencies, ...manifest.devDependencies}\n\n const packageInfo = PACKAGES.map(async (pkg): Promise<PackageInfo | false> => {\n const dependency = dependencies[pkg.name]\n if (!dependency) {\n return false\n }\n\n const manifestPath = resolveFrom.silent(workDir, path.join(pkg.name, 'package.json'))\n const installed = semver.coerce(\n manifestPath\n ? (await readPackageManifest(manifestPath)).version\n : dependency.replace(/[\\D.]/g, ''),\n )\n\n if (!installed) {\n return false\n }\n\n const supported = pkg.supported.join(' || ')\n\n // \"Untested\" is usually the case where we have not upgraded the React version requirements\n // before a release, but given that is usually works in a backwards-compatible way, we want\n // to indicate that it's _untested_, not necessarily _unsupported_\n // Ex: Installed is react@20.0.0, but we've only _tested_ with react@^19\n const isUntested = !semver.satisfies(installed, supported) && semver.gtr(installed, supported)\n\n // \"Unsupported\" in that the installed version is _lower than_ the minimum version\n // Ex: Installed is react@18.0.0, but we require react@^19.2\n const isUnsupported = !semver.satisfies(installed, supported) && !isUntested\n\n // \"Deprecated\" in that we will stop supporting it at some point in the near future,\n // so users should be prompted to upgrade\n const isDeprecated = pkg.deprecatedBelow ? semver.ltr(installed, pkg.deprecatedBelow) : false\n\n return {\n ...pkg,\n installed,\n isUnsupported,\n isDeprecated,\n isUntested,\n }\n })\n\n const installedPackages = (await Promise.all(packageInfo)).filter(\n (inp): inp is PackageInfo => inp !== false,\n )\n const unsupported = installedPackages.filter((pkg) => pkg.isUnsupported)\n const deprecated = installedPackages.filter((pkg) => !pkg.isUnsupported && pkg.isDeprecated)\n const untested = installedPackages.filter((pkg) => pkg.isUntested)\n\n if (deprecated.length > 0) {\n console.warn(`\n[WARN] The following package versions have been deprecated and should be upgraded:\n\n ${listPackages(deprecated)}\n\nSupport for these will be removed in a future release!\n\n ${getUpgradeInstructions(deprecated)}\n`)\n }\n\n if (untested.length > 0) {\n console.warn(`\n[WARN] The following package versions have not yet been marked as supported:\n\n ${listPackages(untested)}\n\nYou _may_ encounter bugs while using these versions.\n\n ${getDowngradeInstructions(untested)}\n`)\n }\n\n if (unsupported.length > 0) {\n console.error(`\n[ERROR] The following package versions are no longer supported and needs to be upgraded:\n\n ${listPackages(unsupported)}\n\n ${getUpgradeInstructions(unsupported)}\n`)\n process.exit(1)\n }\n}\n\nfunction listPackages(pkgs: PackageInfo[]) {\n return pkgs\n .map(\n (pkg) =>\n `${pkg.name} (installed: ${pkg.installed}, want: ${\n pkg.deprecatedBelow || pkg.supported.join(' || ')\n })`,\n )\n .join('\\n ')\n}\n\nfunction getUpgradeInstructions(pkgs: PackageInfo[]) {\n const inst = pkgs\n .map((pkg) => {\n const [recommendedVersion] = pkg.supported\n .concat(pkg.deprecatedBelow || [])\n .map((version) => (semver.coerce(version) || {version: ''}).version)\n .sort(semver.rcompare)\n\n return `\"${pkg.name}@^${recommendedVersion}\"`\n })\n .join(' ')\n\n return `To upgrade, run either:\n\n npm install ${inst}\n\n or\n\n yarn add ${inst}\n\n or\n\n pnpm add ${inst}\n\n\nRead more at ${generateHelpUrl('upgrade-packages')}`\n}\n\nfunction getDowngradeInstructions(pkgs: PackageInfo[]) {\n const inst = pkgs\n .map((pkg) => {\n const [highestSupported] = pkg.supported\n .map((version) => (semver.coerce(version) || {version: ''}).version)\n .sort(semver.rcompare)\n\n return `\"${pkg.name}@^${highestSupported}\"`\n })\n .join(' ')\n\n return `To downgrade, run either:\n\n yarn add ${inst}\n\n or\n\n npm install ${inst}\n\n or\n\n pnpm install ${inst}`\n}\n","import path from 'node:path'\n\nimport {type CliCommandContext} from '@sanity/cli'\nimport execa from 'execa'\nimport oneline from 'oneline'\nimport semver, {type SemVer} from 'semver'\n\nimport {peerDependencies} from '../../../../package.json'\nimport {determineIsApp} from './determineIsApp'\nimport {readModuleVersion} from './readModuleVersion'\nimport {type PartialPackageManifest, readPackageManifest} from './readPackageManifest'\n\nconst defaultStudioManifestProps: PartialPackageManifest = {\n name: 'studio',\n version: '1.0.0',\n}\n\ninterface CheckResult {\n didInstall: boolean\n installedSanityVersion: string\n}\n\n/**\n * Checks that the studio has declared and installed the required dependencies\n * needed by the Sanity modules. While we generally use regular, explicit\n * dependencies in modules, there are certain dependencies that are better\n * served being peer dependencies, such as react and styled-components.\n *\n * If these dependencies are not installed/declared, we want to prompt the user\n * whether or not to add them to `package.json` and install them\n *\n * Additionally, returns the version of the 'sanity' dependency from the package.json.\n */\nexport async function checkRequiredDependencies(context: CliCommandContext): Promise<CheckResult> {\n // currently there's no check needed for custom apps,\n // but this should be removed once they are more mature\n const isApp = determineIsApp(context.cliConfig)\n if (isApp) {\n return {didInstall: false, installedSanityVersion: ''}\n }\n\n const {workDir: studioPath, output} = context\n const [studioPackageManifest, installedStyledComponentsVersion, installedSanityVersion] =\n await Promise.all([\n await readPackageManifest(path.join(studioPath, 'package.json'), defaultStudioManifestProps),\n await readModuleVersion(studioPath, 'styled-components'),\n await readModuleVersion(studioPath, 'sanity'),\n ])\n\n const wantedStyledComponentsVersionRange = peerDependencies['styled-components']\n\n // Retrieve the version of the 'sanity' dependency\n if (!installedSanityVersion) {\n throw new Error('Failed to read the installed sanity version.')\n }\n\n // The studio _must_ now declare `styled-components` as a dependency. If it's not there,\n // we'll want to automatically _add it_ to the manifest and tell the user to reinstall\n // dependencies before running whatever command was being run\n const declaredStyledComponentsVersion =\n studioPackageManifest.dependencies['styled-components'] ||\n studioPackageManifest.devDependencies['styled-components']\n\n if (!declaredStyledComponentsVersion) {\n const [file, ...args] = process.argv\n const deps = {'styled-components': wantedStyledComponentsVersionRange}\n await installDependencies(deps, context)\n\n // Re-run the same command (sanity dev/sanity build etc) after installation,\n // as it can have shifted the entire `node_modules` folder around, result in\n // broken assumptions about installation paths. This is a hack, and should be\n // solved properly.\n await execa(file, args, {cwd: studioPath, stdio: 'inherit'})\n return {didInstall: true, installedSanityVersion}\n }\n\n // We ignore catalog identifiers since we check the actual version anyway\n const isStyledComponentsVersionRangeInCatalog =\n declaredStyledComponentsVersion.startsWith('catalog:')\n // Theoretically the version specified in package.json could be incorrect, eg `foo`\n let minDeclaredStyledComponentsVersion: SemVer | null = null\n try {\n minDeclaredStyledComponentsVersion = semver.minVersion(declaredStyledComponentsVersion)\n } catch (err) {\n // Intentional fall-through (variable will be left as null, throwing below)\n }\n\n if (!minDeclaredStyledComponentsVersion && !isStyledComponentsVersionRangeInCatalog) {\n throw new Error(oneline`\n Declared dependency \\`styled-components\\` has an invalid version range:\n \\`${declaredStyledComponentsVersion}\\`.\n `)\n }\n\n // The declared version should be semver-compatible with the version specified as a\n // peer dependency in `sanity`. If not, we should tell the user to change it.\n //\n // Exception: Ranges are hard to compare. `>=5.0.0 && <=5.3.2 || ^6`... Comparing this\n // to anything is going to be challenging, so only compare \"simple\" ranges/versions\n // (^x.x.x / ~x.x.x / x.x.x)\n if (\n !isStyledComponentsVersionRangeInCatalog &&\n isComparableRange(declaredStyledComponentsVersion) &&\n !semver.satisfies(minDeclaredStyledComponentsVersion!, wantedStyledComponentsVersionRange)\n ) {\n output.warn(oneline`\n Declared version of styled-components (${declaredStyledComponentsVersion})\n is not compatible with the version required by sanity (${wantedStyledComponentsVersionRange}).\n This might cause problems!\n `)\n }\n\n // Ensure the studio has _installed_ a version of `styled-components`\n if (!installedStyledComponentsVersion) {\n throw new Error(oneline`\n Declared dependency \\`styled-components\\` is not installed - run\n \\`npm install\\`, \\`yarn install\\` or \\`pnpm install\\` to install it before re-running this command.\n `)\n }\n\n // The studio should have an _installed_ version of `styled-components`, and it should\n // be semver compatible with the version specified in `sanity` peer dependencies.\n if (!semver.satisfies(installedStyledComponentsVersion, wantedStyledComponentsVersionRange)) {\n output.warn(oneline`\n Installed version of styled-components (${installedStyledComponentsVersion})\n is not compatible with the version required by sanity (${wantedStyledComponentsVersionRange}).\n This might cause problems!\n `)\n }\n\n return {didInstall: false, installedSanityVersion}\n}\n\n/**\n * Install the passed dependencies at the given version/version range,\n * prompting the user which package manager to use. We will try to detect\n * a package manager from files in the directory and show that as the default\n *\n * @param dependencies - Object of dependencies `({[package name]: version})`\n * @param context - CLI context\n */\nasync function installDependencies(\n dependencies: Record<string, string>,\n context: CliCommandContext,\n): Promise<void> {\n const {output, prompt, workDir, cliPackageManager} = context\n const packages: string[] = []\n\n output.print('The Sanity studio needs to install missing dependencies:')\n for (const [pkgName, version] of Object.entries(dependencies)) {\n const declaration = `${pkgName}@${version}`\n output.print(`- ${declaration}`)\n packages.push(declaration)\n }\n\n if (!cliPackageManager) {\n output.error(\n 'ERROR: Could not determine package manager choice - run `npm install` or equivalent',\n )\n return\n }\n\n const {getPackageManagerChoice, installNewPackages} = cliPackageManager\n const {mostOptimal, chosen: pkgManager} = await getPackageManagerChoice(workDir, {prompt})\n if (mostOptimal && pkgManager !== mostOptimal) {\n output.warn(\n `WARN: This project appears to be installed with or using ${mostOptimal} - using a different package manager _may_ result in errors.`,\n )\n }\n\n await installNewPackages({packages, packageManager: pkgManager}, context)\n}\n\nfunction isComparableRange(range: string): boolean {\n return /^[\\^~]?\\d+(\\.\\d+)?(\\.\\d+)?$/.test(range)\n}\n","import path from 'node:path'\n\nimport {type CliPrompter} from '@sanity/cli'\nimport preferredPM from 'preferred-pm'\nimport which from 'which'\n\nimport {isInteractive} from '../isInteractive'\n\nexport type PackageManager = 'npm' | 'yarn' | 'pnpm' | 'bun' | 'manual'\n\nexport const ALLOWED_PACKAGE_MANAGERS: PackageManager[] = ['npm', 'yarn', 'pnpm', 'bun', 'manual']\nexport const allowedPackageManagersString = ALLOWED_PACKAGE_MANAGERS.map((pm) => `\"${pm}\"`).join(\n ' | ',\n)\n\nconst EXPERIMENTAL = ['bun']\n\n/**\n * Attempts to resolve the most optimal package manager to use to install/upgrade\n * packages/dependencies at a given path. It does so by looking for package manager\n * specific lockfiles. If it finds a lockfile belonging to a certain package manager,\n * it prioritizes this one. However, if that package manager is not installed, it will\n * prompt the user for which one they want to use and hint at the most optimal one\n * not being installed.\n *\n * Note that this function also takes local npm binary paths into account - for instance,\n * `yarn` can be installed as a dependency of the project instead of globally, and it\n * will use that is available.\n *\n * The user can also select 'manual' to skip the process and run their preferred package\n * manager manually. Commands using this function must take this `manual` choice into\n * account and act accordingly if chosen.\n *\n * @param workDir - The working directory where a lockfile is most likely to be present\n * @param options - Pass `interactive: false` to fall back to npm if most optimal is\n * not available, instead of prompting\n * @returns Object of `chosen` and, if a lockfile is found, the `mostOptimal` choice\n */\nexport async function getPackageManagerChoice(\n workDir: string,\n options: {interactive: false} | {interactive?: true; prompt: CliPrompter},\n): Promise<{chosen: PackageManager; mostOptimal?: PackageManager}> {\n const rootDir = workDir || process.cwd()\n const preferred = (await preferredPM(rootDir))?.name\n\n if (preferred && (await hasCommand(preferred, rootDir))) {\n // There is an optimal/preferred package manager, and the user has it installed!\n return {chosen: preferred, mostOptimal: preferred}\n }\n\n const mostLikelyPM = await getMostLikelyInstalledPackageManager(rootDir)\n const interactive = typeof options.interactive === 'boolean' ? options.interactive : isInteractive\n if (!interactive) {\n // We can't ask the user for their preference, so fall back to either the one that is being run\n // or whatever is installed on the system (npm being the preferred choice).\n // Note that the most optimal choice is already picked above if available.\n return {chosen: mostLikelyPM || (await getFallback(rootDir)), mostOptimal: preferred}\n }\n\n if (!('prompt' in options)) {\n throw new Error('Must pass `prompt` when in interactive mode')\n }\n\n // We can ask the user for their preference, hurray!\n const messageSuffix = preferred ? ` (preferred is ${preferred}, but is not installed)` : ''\n const installed = await getAvailablePackageManagers(rootDir)\n const chosen = await options.prompt.single<PackageManager>({\n type: 'list',\n choices: installed.map((pm) => ({\n value: pm,\n name: EXPERIMENTAL.includes(pm) ? `${pm} (experimental)` : pm,\n })),\n default: preferred || mostLikelyPM,\n message: `Package manager to use for installing dependencies?${messageSuffix}`,\n })\n\n return {chosen, mostOptimal: preferred}\n}\n\nasync function getFallback(cwd: string): Promise<PackageManager> {\n if (await hasNpmInstalled(cwd)) {\n return 'npm'\n }\n\n if (await hasYarnInstalled(cwd)) {\n return 'yarn'\n }\n\n if (await hasPnpmInstalled(cwd)) {\n return 'pnpm'\n }\n\n if (await hasBunInstalled(cwd)) {\n return 'bun'\n }\n\n return 'manual'\n}\n\nasync function getAvailablePackageManagers(cwd: string): Promise<PackageManager[]> {\n const [npm, yarn, pnpm, bun] = await Promise.all([\n hasNpmInstalled(cwd),\n hasYarnInstalled(cwd),\n hasPnpmInstalled(cwd),\n hasBunInstalled(cwd),\n ])\n\n const choices = [npm && 'npm', yarn && 'yarn', pnpm && 'pnpm', bun && 'bun', 'manual']\n return choices.filter((pm): pm is PackageManager => pm !== false)\n}\n\nexport function hasNpmInstalled(cwd?: string): Promise<boolean> {\n return hasCommand('npm', cwd)\n}\n\nexport function hasYarnInstalled(cwd?: string): Promise<boolean> {\n return hasCommand('yarn', cwd)\n}\n\nexport function hasPnpmInstalled(cwd?: string): Promise<boolean> {\n return hasCommand('pnpm', cwd)\n}\n\nexport function hasBunInstalled(cwd?: string): Promise<boolean> {\n return hasCommand('bun', cwd)\n}\n\nexport function getNpmRunPath(cwd: string): string {\n let previous\n let cwdPath = path.resolve(cwd)\n const result: string[] = []\n\n while (previous !== cwdPath) {\n result.push(path.join(cwdPath, 'node_modules', '.bin'))\n previous = cwdPath\n cwdPath = path.resolve(cwdPath, '..')\n }\n\n result.push(path.resolve(cwd, process.execPath, '..'))\n\n const pathEnv = process.env[getPathEnvVarKey()]\n return [...result, pathEnv].join(path.delimiter)\n}\n\nexport function getPartialEnvWithNpmPath(cwd: string): NodeJS.ProcessEnv {\n const key = getPathEnvVarKey()\n return {[key]: getNpmRunPath(cwd)}\n}\n\nfunction getPathEnvVarKey(): string {\n if (process.platform !== 'win32') {\n return 'PATH'\n }\n\n return (\n Object.keys(process.env)\n .reverse()\n .find((key) => key.toUpperCase() === 'PATH') || 'Path'\n )\n}\n\nfunction getCommandPath(cmd: string, cwd?: string): Promise<string | null> {\n const options = {path: cwd ? getNpmRunPath(cwd) : undefined}\n return which(cmd, options).catch(() => null)\n}\n\nfunction hasCommand(cmd: string, cwd?: string): Promise<boolean> {\n return getCommandPath(cmd, cwd).then((cmdPath) => cmdPath !== null)\n}\n\nasync function getMostLikelyInstalledPackageManager(\n rootDir: string,\n): Promise<PackageManager | undefined> {\n const installed = await getAvailablePackageManagers(rootDir)\n const running = getRunningPackageManager()\n return running && installed.includes(running) ? running : undefined\n}\n\nfunction getRunningPackageManager(): PackageManager | undefined {\n // Yes, the env var is lowercase - it is set by the package managers themselves\n const agent = process.env.npm_config_user_agent || ''\n\n if (agent.includes('yarn')) {\n return 'yarn'\n }\n\n if (agent.includes('pnpm')) {\n return 'pnpm'\n }\n\n if (agent.includes('bun')) {\n return 'bun'\n }\n\n // Both yarn and pnpm does a `npm/?` thing, thus the slightly different match here\n // Theoretically not needed since we check for yarn/pnpm above, but in case other\n // package managers do the same thing, we'll (hopefully) catch them here.\n if (/^npm\\/\\d/.test(agent)) {\n return 'npm'\n }\n\n return undefined\n}\n","import execa, {type CommonOptions, type ExecaReturnValue} from 'execa'\n\nimport {getPartialEnvWithNpmPath, type PackageManager} from './packageManagerChoice'\n\nexport interface InstallOptions {\n packageManager: PackageManager\n packages: [name: string, version: string][]\n}\n\nexport async function upgradePackages(\n options: InstallOptions,\n context: {output: {print: (output: string) => void}; workDir: string},\n): Promise<void> {\n const {packageManager, packages} = options\n const {output, workDir} = context\n const execOptions: CommonOptions<'utf8'> = {\n encoding: 'utf8',\n env: getPartialEnvWithNpmPath(workDir),\n cwd: workDir,\n stdio: 'inherit',\n }\n const upgradePackageArgs = packages.map((pkg) => pkg.join('@'))\n let result: ExecaReturnValue<string> | undefined\n if (packageManager === 'npm') {\n const npmArgs = ['install', '--legacy-peer-deps', ...upgradePackageArgs]\n output.print(`Running 'npm ${npmArgs.join(' ')}'`)\n result = await execa('npm', npmArgs, execOptions)\n } else if (packageManager === 'yarn') {\n const yarnArgs = ['upgrade ', ...upgradePackageArgs]\n output.print(`Running 'yarn ${yarnArgs.join(' ')}'`)\n result = await execa('yarn', yarnArgs, execOptions)\n } else if (packageManager === 'pnpm') {\n const pnpmArgs = ['upgrade', ...upgradePackageArgs]\n output.print(`Running 'pnpm ${pnpmArgs.join(' ')}'`)\n result = await execa('pnpm', pnpmArgs, execOptions)\n } else if (packageManager === 'bun') {\n const bunArgs = ['update', ...upgradePackageArgs]\n output.print(`Running 'bun ${bunArgs.join(' ')}'`)\n result = await execa('bun', bunArgs, execOptions)\n } else if (packageManager === 'manual') {\n output.print(\n `Manual installation selected - run 'npm upgrade ${upgradePackageArgs.join(' ')}' or equivalent`,\n )\n }\n\n if (result?.exitCode || result?.failed) {\n throw new Error('Package upgrade failed')\n }\n}\n"],"names":["PACKAGES","name","supported","deprecatedBelow","checkStudioDependencyVersions","workDir","manifest","readPackageJson","path","join","dependencies","devDependencies","packageInfo","map","pkg","dependency","manifestPath","resolveFrom","silent","installed","semver","coerce","readPackageManifest","version","replace","isUntested","satisfies","gtr","isUnsupported","isDeprecated","ltr","installedPackages","Promise","all","filter","inp","unsupported","deprecated","untested","length","console","warn","listPackages","getUpgradeInstructions","getDowngradeInstructions","error","process","exit","pkgs","inst","recommendedVersion","concat","sort","rcompare","generateHelpUrl","highestSupported","defaultStudioManifestProps","checkRequiredDependencies","context","determineIsApp","cliConfig","didInstall","installedSanityVersion","studioPath","output","studioPackageManifest","installedStyledComponentsVersion","readModuleVersion","wantedStyledComponentsVersionRange","peerDependencies","Error","declaredStyledComponentsVersion","file","args","argv","installDependencies","execa","cwd","stdio","isStyledComponentsVersionRangeInCatalog","startsWith","minDeclaredStyledComponentsVersion","minVersion","oneline","isComparableRange","prompt","cliPackageManager","packages","print","pkgName","Object","entries","declaration","push","getPackageManagerChoice","installNewPackages","mostOptimal","chosen","pkgManager","packageManager","range","test","EXPERIMENTAL","options","rootDir","preferred","preferredPM","hasCommand","mostLikelyPM","getMostLikelyInstalledPackageManager","interactive","isInteractive","getFallback","messageSuffix","getAvailablePackageManagers","single","type","choices","pm","value","includes","default","message","hasNpmInstalled","hasYarnInstalled","hasPnpmInstalled","hasBunInstalled","npm","yarn","pnpm","bun","getNpmRunPath","previous","cwdPath","resolve","result","execPath","pathEnv","env","getPathEnvVarKey","delimiter","getPartialEnvWithNpmPath","platform","keys","reverse","find","key","toUpperCase","getCommandPath","cmd","undefined","which","catch","then","cmdPath","running","getRunningPackageManager","agent","npm_config_user_agent","upgradePackages","execOptions","encoding","upgradePackageArgs","npmArgs","yarnArgs","pnpmArgs","bunArgs","exitCode","failed"],"mappings":"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"}
@@ -7,7 +7,7 @@ try {
7
7
  try {
8
8
  buildVersion = buildVersion || // This is replaced by `@sanity/pkg-utils` at build time
9
9
  // and must always be references by its full static name, e.g. no optional chaining, no `if (process && process.env)` etc.
10
- "5.0.0-next-major.20251212101828+ef23a1b280";
10
+ "5.0.0-next-major.20251215132654+534d769f6c";
11
11
  } catch {
12
12
  }
13
13
  const SANITY_VERSION = buildVersion || `${version}-dev`;
@@ -1,104 +1,146 @@
1
+ import fs from "node:fs";
1
2
  import path from "node:path";
2
3
  import resolveFrom from "resolve-from";
3
4
  import semver from "semver";
4
- import { readPackageManifest } from "./timing.js";
5
+ import { createExternalFromImportMap } from "./runtime.js";
5
6
  import chalk from "chalk";
6
7
  import logSymbols from "log-symbols";
7
- const MODULES_HOST = process.env.SANITY_MODULES_HOST || (process.env.SANITY_INTERNAL_ENV === "staging" ? "https://sanity-cdn.work" : "https://sanity-cdn.com");
8
- function currentUnixTime() {
9
- return Math.floor(Date.now() / 1e3);
10
- }
11
- function getAutoUpdatesImportMap(packages, options = {}) {
12
- return Object.fromEntries(packages.flatMap((pkg) => getAppAutoUpdateImportMapForPackage(pkg, options)));
13
- }
14
- function getAppAutoUpdateImportMapForPackage(pkg, options = {}) {
15
- const moduleUrl = getModuleUrl(pkg, options);
16
- return [[pkg.name, moduleUrl], [`${pkg.name}/`, `${moduleUrl}/`]];
17
- }
18
- function getModuleUrl(pkg, options = {}) {
8
+ const VENDOR_DIR = "vendor", VENDOR_IMPORTS = {
9
+ react: {
10
+ "^19.2.0": {
11
+ ".": "./cjs/react.production.js",
12
+ "./jsx-runtime": "./cjs/react-jsx-runtime.production.js",
13
+ "./jsx-dev-runtime": "./cjs/react-jsx-dev-runtime.production.js",
14
+ "./compiler-runtime": "./cjs/react-compiler-runtime.production.js",
15
+ "./package.json": "./package.json"
16
+ }
17
+ },
18
+ "react-dom": {
19
+ "^19.2.0": {
20
+ ".": "./cjs/react-dom.production.js",
21
+ "./client": "./cjs/react-dom-client.production.js",
22
+ "./server": "./cjs/react-dom-server-legacy.browser.production.js",
23
+ "./server.browser": "./cjs/react-dom-server-legacy.browser.production.js",
24
+ "./static": "./cjs/react-dom-server.browser.production.js",
25
+ "./static.browser": "./cjs/react-dom-server.browser.production.js",
26
+ "./package.json": "./package.json"
27
+ }
28
+ },
29
+ "styled-components": {
30
+ "^6.1.0": {
31
+ ".": "./dist/styled-components.browser.esm.js",
32
+ "./package.json": "./package.json"
33
+ }
34
+ }
35
+ };
36
+ async function buildVendorDependencies({
37
+ cwd,
38
+ outputDir,
39
+ basePath
40
+ }) {
41
+ const dir = path.relative(process.cwd(), path.resolve(cwd)), entry = {}, imports = {};
42
+ for (const [packageName, ranges] of Object.entries(VENDOR_IMPORTS)) {
43
+ const packageJsonPath = resolveFrom.silent(cwd, path.join(packageName, "package.json"));
44
+ if (!packageJsonPath)
45
+ throw new Error(`Could not find package.json for package '${packageName}' from directory '${dir}'. Is it installed?`);
46
+ let packageJson;
47
+ try {
48
+ packageJson = JSON.parse(await fs.promises.readFile(packageJsonPath, "utf-8"));
49
+ } catch (e) {
50
+ const message = `Could not read package.json for package '${packageName}' from directory '${dir}'`;
51
+ throw typeof e?.message == "string" ? (e.message = `${message}: ${e.message}`, e) : new Error(message, {
52
+ cause: e
53
+ });
54
+ }
55
+ const version = semver.coerce(packageJson.version)?.version;
56
+ if (!version)
57
+ throw new Error(`Could not parse version '${packageJson.version}' from '${packageName}'`);
58
+ const sortedRanges = Object.keys(ranges).sort((range1, range2) => {
59
+ const min1 = semver.minVersion(range1), min2 = semver.minVersion(range2);
60
+ if (!min1) throw new Error(`Could not parse range '${range1}'`);
61
+ if (!min2) throw new Error(`Could not parse range '${range2}'`);
62
+ return semver.rcompare(min1.version, min2.version);
63
+ }), matchedRange = sortedRanges.find((range) => semver.satisfies(version, range));
64
+ if (!matchedRange) {
65
+ const min = semver.minVersion(sortedRanges[sortedRanges.length - 1]);
66
+ throw min ? semver.gt(min.version, version) ? new Error(`Package '${packageName}' requires at least ${min.version}.`) : new Error(`Version '${version}' of package '${packageName}' is not supported yet.`) : new Error(`Could not find a minimum version for package '${packageName}'`);
67
+ }
68
+ const subpaths = ranges[matchedRange];
69
+ for (const [subpath, relativeEntryPoint] of Object.entries(subpaths)) {
70
+ const packagePath = path.dirname(packageJsonPath), entryPoint = resolveFrom.silent(packagePath, relativeEntryPoint);
71
+ if (!entryPoint)
72
+ throw new Error(`Failed to resolve entry point '${path.join(packageName, relativeEntryPoint)}'. `);
73
+ const specifier = path.posix.join(packageName, subpath), chunkName = path.posix.join(packageName, path.relative(packageName, specifier) || "index");
74
+ entry[chunkName] = entryPoint, imports[specifier] = path.posix.join("/", basePath, VENDOR_DIR, `${chunkName}.mjs`);
75
+ }
76
+ }
19
77
  const {
20
- timestamp = currentUnixTime()
21
- } = options;
22
- return options.appId ? getByAppModuleUrl(pkg, {
23
- appId: options.appId,
24
- baseUrl: options.baseUrl,
25
- timestamp
26
- }) : getLegacyModuleUrl(pkg, {
27
- timestamp,
28
- baseUrl: options.baseUrl
78
+ build
79
+ } = await import("vite");
80
+ let buildResult = await build({
81
+ // Define a custom cache directory so that sanity's vite cache
82
+ // does not conflict with any potential local vite projects
83
+ cacheDir: "node_modules/.sanity/vite-vendor",
84
+ root: cwd,
85
+ configFile: !1,
86
+ logLevel: "silent",
87
+ appType: "custom",
88
+ mode: "production",
89
+ define: {
90
+ "process.env.NODE_ENV": JSON.stringify("production")
91
+ },
92
+ build: {
93
+ commonjsOptions: {
94
+ strictRequires: "auto"
95
+ },
96
+ minify: !0,
97
+ emptyOutDir: !1,
98
+ // Rely on CLI to do this
99
+ outDir: path.join(outputDir, VENDOR_DIR),
100
+ lib: {
101
+ entry,
102
+ formats: ["es"]
103
+ },
104
+ rollupOptions: {
105
+ external: createExternalFromImportMap({
106
+ imports
107
+ }),
108
+ output: {
109
+ entryFileNames: "[name]-[hash].mjs",
110
+ chunkFileNames: "[name]-[hash].mjs",
111
+ exports: "named",
112
+ format: "es"
113
+ },
114
+ treeshake: {
115
+ preset: "recommended"
116
+ }
117
+ }
118
+ }
29
119
  });
120
+ buildResult = Array.isArray(buildResult) ? buildResult : [buildResult];
121
+ const hashedImports = {}, output = buildResult.flatMap((i) => i.output);
122
+ for (const chunk of output)
123
+ if (chunk.type !== "asset")
124
+ for (const [specifier, originalPath] of Object.entries(imports))
125
+ originalPath.endsWith(`${chunk.name}.mjs`) && (hashedImports[specifier] = path.posix.join("/", basePath, VENDOR_DIR, chunk.fileName));
126
+ return hashedImports;
30
127
  }
31
- function getLegacyModuleUrl(pkg, options) {
32
- const encodedMinVer = encodeURIComponent(`^${pkg.version}`);
33
- return `${options.baseUrl || MODULES_HOST}/v1/modules/${rewriteScopedPackage(pkg.name)}/default/${encodedMinVer}/t${options.timestamp}`;
128
+ function formatSize(bytes) {
129
+ return chalk.cyan(`${(bytes / 1024).toFixed()} kB`);
34
130
  }
35
- function getByAppModuleUrl(pkg, options) {
36
- const encodedMinVer = encodeURIComponent(`^${pkg.version}`);
37
- return `${options.baseUrl || MODULES_HOST}/v1/modules/by-app/${options.appId}/t${options.timestamp}/${encodedMinVer}/${rewriteScopedPackage(pkg.name)}`;
131
+ function formatModuleSizes(modules) {
132
+ const lines = [];
133
+ for (const mod of modules)
134
+ lines.push(` - ${formatModuleName(mod.name)} (${formatSize(mod.renderedLength)})`);
135
+ return lines.join(`
136
+ `);
38
137
  }
39
- function rewriteScopedPackage(pkgName) {
40
- if (!pkgName.includes("@"))
41
- return pkgName;
42
- const [scope, ...pkg] = pkgName.split("/");
43
- return `${scope}__${pkg.join("")}`;
44
- }
45
- function getRemoteResolvedVersion(fetchFn, url) {
46
- return fetchFn(url, {
47
- method: "HEAD",
48
- redirect: "manual"
49
- }).then((res) => {
50
- if (res.ok || res.status < 400) {
51
- const resolved = res.headers.get("x-resolved-version");
52
- if (!resolved)
53
- throw new Error(`Missing 'x-resolved-version' header on response from HEAD ${url}`);
54
- return resolved;
55
- }
56
- throw new Error(`Unexpected HTTP response: ${res.status} ${res.statusText}`);
57
- }, (err) => {
58
- throw new Error(`Failed to fetch remote version for ${url}: ${err.message}`, {
59
- cause: err
60
- });
61
- });
138
+ function formatModuleName(modName) {
139
+ const delimiter = "/node_modules/", nodeIndex = modName.lastIndexOf(delimiter);
140
+ return nodeIndex === -1 ? modName : modName.slice(nodeIndex + delimiter.length);
62
141
  }
63
- async function compareDependencyVersions(packages, workDir, {
64
- fetchFn = globalThis.fetch
65
- } = {}) {
66
- const manifest = await readPackageManifest(path.join(workDir, "package.json")), dependencies = {
67
- ...manifest.dependencies,
68
- ...manifest.devDependencies
69
- }, failedDependencies = [];
70
- for (const pkg of packages) {
71
- const resolvedVersion = await getRemoteResolvedVersion(fetchFn, getModuleUrl(pkg)), manifestPath = resolveFrom.silent(workDir, path.join(pkg.name, "package.json")), manifestVersion = dependencies[pkg.name], installed = semver.coerce(manifestPath ? semver.parse((await readPackageManifest(manifestPath)).version) : semver.coerce(manifestVersion));
72
- if (!installed)
73
- throw new Error(`Failed to parse installed version for ${pkg}`);
74
- semver.eq(resolvedVersion, installed.version) || failedDependencies.push({
75
- pkg: pkg.name,
76
- installed: installed.version,
77
- remote: resolvedVersion
78
- });
79
- }
80
- return failedDependencies;
81
- }
82
- function shouldAutoUpdate({
83
- flags,
84
- cliConfig,
85
- output
86
- }) {
87
- if ("auto-updates" in flags) {
88
- if (output) {
89
- const flagUsed = flags["auto-updates"] ? "--auto-updates" : "--no-auto-updates";
90
- output.warn(chalk.yellow(`The ${flagUsed} flag is deprecated for \`deploy\` and \`build\` commands. Set the \`autoUpdates\` option in \`sanity.cli.ts\` or \`sanity.cli.js\` instead.`));
91
- }
92
- return !!flags["auto-updates"];
93
- }
94
- const hasOldCliConfigFlag = cliConfig && "autoUpdates" in cliConfig, hasNewCliConfigFlag = cliConfig && "deployment" in cliConfig && cliConfig.deployment && "autoUpdates" in cliConfig.deployment;
95
- if (hasOldCliConfigFlag && hasNewCliConfigFlag)
96
- throw new Error("Found both `autoUpdates` (deprecated) and `deployment.autoUpdates` in sanity.cli.js. Please remove the deprecated top level `autoUpdates` config.");
97
- return hasOldCliConfigFlag && output?.warn(chalk.yellow(`The \`autoUpdates\` config has moved to \`deployment.autoUpdates\`.
98
- Please update \`sanity.cli.ts\` or \`sanity.cli.js\` and make the following change:
99
- ${chalk.red(`- autoUpdates: ${cliConfig.autoUpdates},`)}
100
- ${chalk.green(`+ deployment: {autoUpdates: ${cliConfig.autoUpdates}}}`)}
101
- `)), !!(hasOldCliConfigFlag ? cliConfig.autoUpdates : cliConfig?.deployment?.autoUpdates);
142
+ function sortModulesBySize(chunks) {
143
+ return chunks.flatMap((chunk) => chunk.modules).sort((modA, modB) => modB.renderedLength - modA.renderedLength);
102
144
  }
103
145
  const baseUrl = process.env.SANITY_INTERNAL_ENV === "staging" ? "https://www.sanity.work" : "https://www.sanity.io";
104
146
  function warnAboutMissingAppId({
@@ -112,9 +154,9 @@ function warnAboutMissingAppId({
112
154
  `);
113
155
  }
114
156
  export {
115
- compareDependencyVersions,
116
- getAutoUpdatesImportMap,
117
- shouldAutoUpdate,
157
+ buildVendorDependencies,
158
+ formatModuleSizes,
159
+ sortModulesBySize,
118
160
  warnAboutMissingAppId
119
161
  };
120
162
  //# sourceMappingURL=warnAboutMissingAppId.js.map