sanity
Version:
Sanity is a real-time content infrastructure with a scalable, hosted backend featuring a Graph Oriented Query Language (GROQ), asset pipelines and fast edge caches
331 lines (310 loc) • 14.4 kB
JavaScript
;
var path = require("node:path"), generateHelpUrl_esm = require("./generate-help-url.esm.js"), resolveFrom = require("resolve-from"), semver = require("semver"), shouldAutoUpdate = require("./shouldAutoUpdate.js"), execa = require("execa"), oneline = require("oneline"), _internal = require("./_internal.js"), preferredPM = require("preferred-pm"), which = require("which");
function _interopDefaultCompat(e) {
return e && typeof e == "object" && "default" in e ? e : { default: e };
}
var path__default = /* @__PURE__ */ _interopDefaultCompat(path), resolveFrom__default = /* @__PURE__ */ _interopDefaultCompat(resolveFrom), semver__default = /* @__PURE__ */ _interopDefaultCompat(semver), execa__default = /* @__PURE__ */ _interopDefaultCompat(execa), oneline__default = /* @__PURE__ */ _interopDefaultCompat(oneline), preferredPM__default = /* @__PURE__ */ _interopDefaultCompat(preferredPM), which__default = /* @__PURE__ */ _interopDefaultCompat(which), peerDependencies = {
"styled-components": "^6.1.15"
};
const PACKAGES = [{
name: "react",
supported: ["^18 || ^19"],
deprecatedBelow: null
}, {
name: "react-dom",
supported: ["^18 || ^19"],
deprecatedBelow: null
}, {
name: "styled-components",
supported: ["^6"],
deprecatedBelow: null
}, {
name: "@sanity/ui",
supported: ["^2", "^3"],
deprecatedBelow: null
}];
async function checkStudioDependencyVersions(workDir) {
const manifest = await shouldAutoUpdate.readPackageJson(path__default.default.join(workDir, "package.json")), dependencies = {
...manifest.dependencies,
...manifest.devDependencies
}, packageInfo = PACKAGES.map(async (pkg) => {
const dependency = dependencies[pkg.name];
if (!dependency)
return !1;
const manifestPath = resolveFrom__default.default.silent(workDir, path__default.default.join(pkg.name, "package.json")), installed = semver__default.default.coerce(manifestPath ? (await shouldAutoUpdate.readPackageManifest(manifestPath)).version : dependency.replace(/[\D.]/g, ""));
if (!installed)
return !1;
const supported = pkg.supported.join(" || "), isUntested = !semver__default.default.satisfies(installed, supported) && semver__default.default.gtr(installed, supported), isUnsupported = !semver__default.default.satisfies(installed, supported) && !isUntested, isDeprecated = pkg.deprecatedBelow ? semver__default.default.ltr(installed, pkg.deprecatedBelow) : !1;
return {
...pkg,
installed,
isUnsupported,
isDeprecated,
isUntested
};
}), installedPackages = (await Promise.all(packageInfo)).filter((inp) => inp !== !1), unsupported = installedPackages.filter((pkg) => pkg.isUnsupported), deprecated = installedPackages.filter((pkg) => !pkg.isUnsupported && pkg.isDeprecated), untested = installedPackages.filter((pkg) => pkg.isUntested);
deprecated.length > 0 && console.warn(`
[WARN] The following package versions have been deprecated and should be upgraded:
${listPackages(deprecated)}
Support for these will be removed in a future release!
${getUpgradeInstructions(deprecated)}
`), untested.length > 0 && console.warn(`
[WARN] The following package versions have not yet been marked as supported:
${listPackages(untested)}
You _may_ encounter bugs while using these versions.
${getDowngradeInstructions(untested)}
`), unsupported.length > 0 && (console.error(`
[ERROR] The following package versions are no longer supported and needs to be upgraded:
${listPackages(unsupported)}
${getUpgradeInstructions(unsupported)}
`), process.exit(1));
}
function listPackages(pkgs) {
return pkgs.map((pkg) => `${pkg.name} (installed: ${pkg.installed}, want: ${pkg.deprecatedBelow || pkg.supported.join(" || ")})`).join(`
`);
}
function getUpgradeInstructions(pkgs) {
const inst = pkgs.map((pkg) => {
const [highestSupported] = pkg.supported.map((version) => (semver__default.default.coerce(version) || {
version: ""
}).version).sort(semver__default.default.rcompare);
return `"${pkg.name}@${highestSupported}"`;
}).join(" ");
return `To upgrade, run either:
npm install ${inst}
or
yarn add ${inst}
or
pnpm add ${inst}
Read more at ${generateHelpUrl_esm.generateHelpUrl("upgrade-packages")}`;
}
function getDowngradeInstructions(pkgs) {
const inst = pkgs.map((pkg) => {
const [highestSupported] = pkg.supported.map((version) => (semver__default.default.coerce(version) || {
version: ""
}).version).sort(semver__default.default.rcompare);
return `"${pkg.name}@${highestSupported}"`;
}).join(" ");
return `To downgrade, run either:
yarn add ${inst}
or
npm install ${inst}
or
pnpm install ${inst}`;
}
const defaultStudioManifestProps = {
name: "studio",
version: "1.0.0"
};
async function checkRequiredDependencies(context) {
if (_internal.determineIsApp(context.cliConfig))
return {
didInstall: !1,
installedSanityVersion: ""
};
const {
workDir: studioPath,
output
} = context, [studioPackageManifest, installedStyledComponentsVersion, installedSanityVersion] = await Promise.all([await shouldAutoUpdate.readPackageManifest(path__default.default.join(studioPath, "package.json"), defaultStudioManifestProps), await shouldAutoUpdate.readModuleVersion(studioPath, "styled-components"), await shouldAutoUpdate.readModuleVersion(studioPath, "sanity")]), wantedStyledComponentsVersionRange = peerDependencies["styled-components"];
if (!installedSanityVersion)
throw new Error("Failed to read the installed sanity version.");
const declaredStyledComponentsVersion = studioPackageManifest.dependencies["styled-components"] || studioPackageManifest.devDependencies["styled-components"];
if (!declaredStyledComponentsVersion) {
const [file, ...args] = process.argv;
return await installDependencies({
"styled-components": wantedStyledComponentsVersionRange
}, context), await execa__default.default(file, args, {
cwd: studioPath,
stdio: "inherit"
}), {
didInstall: !0,
installedSanityVersion
};
}
const isStyledComponentsVersionRangeInCatalog = declaredStyledComponentsVersion.startsWith("catalog:");
let minDeclaredStyledComponentsVersion = null;
try {
minDeclaredStyledComponentsVersion = semver__default.default.minVersion(declaredStyledComponentsVersion);
} catch {
}
if (!minDeclaredStyledComponentsVersion && !isStyledComponentsVersionRangeInCatalog)
throw new Error(oneline__default.default`
Declared dependency \`styled-components\` has an invalid version range:
\`${declaredStyledComponentsVersion}\`.
`);
if (!isStyledComponentsVersionRangeInCatalog && isComparableRange(declaredStyledComponentsVersion) && !semver__default.default.satisfies(minDeclaredStyledComponentsVersion, wantedStyledComponentsVersionRange) && output.warn(oneline__default.default`
Declared version of styled-components (${declaredStyledComponentsVersion})
is not compatible with the version required by sanity (${wantedStyledComponentsVersionRange}).
This might cause problems!
`), !installedStyledComponentsVersion)
throw new Error(oneline__default.default`
Declared dependency \`styled-components\` is not installed - run
\`npm install\`, \`yarn install\` or \`pnpm install\` to install it before re-running this command.
`);
return semver__default.default.satisfies(installedStyledComponentsVersion, wantedStyledComponentsVersionRange) || output.warn(oneline__default.default`
Installed version of styled-components (${installedStyledComponentsVersion})
is not compatible with the version required by sanity (${wantedStyledComponentsVersionRange}).
This might cause problems!
`), {
didInstall: !1,
installedSanityVersion
};
}
async function installDependencies(dependencies, context) {
const {
output,
prompt,
workDir,
cliPackageManager
} = context, packages = [];
output.print("The Sanity studio needs to install missing dependencies:");
for (const [pkgName, version] of Object.entries(dependencies)) {
const declaration = `${pkgName}@${version}`;
output.print(`- ${declaration}`), packages.push(declaration);
}
if (!cliPackageManager) {
output.error("ERROR: Could not determine package manager choice - run `npm install` or equivalent");
return;
}
const {
getPackageManagerChoice: getPackageManagerChoice2,
installNewPackages
} = cliPackageManager, {
mostOptimal,
chosen: pkgManager
} = await getPackageManagerChoice2(workDir, {
prompt
});
mostOptimal && pkgManager !== mostOptimal && output.warn(`WARN: This project appears to be installed with or using ${mostOptimal} - using a different package manager _may_ result in errors.`), await installNewPackages({
packages,
packageManager: pkgManager
}, context);
}
function isComparableRange(range) {
return /^[\^~]?\d+(\.\d+)?(\.\d+)?$/.test(range);
}
const EXPERIMENTAL = ["bun"];
async function getPackageManagerChoice(workDir, options) {
const rootDir = workDir || process.cwd(), preferred = (await preferredPM__default.default(rootDir))?.name;
if (preferred && await hasCommand(preferred, rootDir))
return {
chosen: preferred,
mostOptimal: preferred
};
const mostLikelyPM = await getMostLikelyInstalledPackageManager(rootDir);
if (!(typeof options.interactive == "boolean" ? options.interactive : _internal.isInteractive))
return {
chosen: mostLikelyPM || await getFallback(rootDir),
mostOptimal: preferred
};
if (!("prompt" in options))
throw new Error("Must pass `prompt` when in interactive mode");
const messageSuffix = preferred ? ` (preferred is ${preferred}, but is not installed)` : "", installed = await getAvailablePackageManagers(rootDir);
return {
chosen: await options.prompt.single({
type: "list",
choices: installed.map((pm) => ({
value: pm,
name: EXPERIMENTAL.includes(pm) ? `${pm} (experimental)` : pm
})),
default: preferred || mostLikelyPM,
message: `Package manager to use for installing dependencies?${messageSuffix}`
}),
mostOptimal: preferred
};
}
async function getFallback(cwd) {
return await hasNpmInstalled(cwd) ? "npm" : await hasYarnInstalled(cwd) ? "yarn" : await hasPnpmInstalled(cwd) ? "pnpm" : await hasBunInstalled(cwd) ? "bun" : "manual";
}
async function getAvailablePackageManagers(cwd) {
const [npm, yarn, pnpm, bun] = await Promise.all([hasNpmInstalled(cwd), hasYarnInstalled(cwd), hasPnpmInstalled(cwd), hasBunInstalled(cwd)]);
return [npm && "npm", yarn && "yarn", pnpm && "pnpm", bun && "bun", "manual"].filter((pm) => pm !== !1);
}
function hasNpmInstalled(cwd) {
return hasCommand("npm", cwd);
}
function hasYarnInstalled(cwd) {
return hasCommand("yarn", cwd);
}
function hasPnpmInstalled(cwd) {
return hasCommand("pnpm", cwd);
}
function hasBunInstalled(cwd) {
return hasCommand("bun", cwd);
}
function getNpmRunPath(cwd) {
let previous, cwdPath = path__default.default.resolve(cwd);
const result = [];
for (; previous !== cwdPath; )
result.push(path__default.default.join(cwdPath, "node_modules", ".bin")), previous = cwdPath, cwdPath = path__default.default.resolve(cwdPath, "..");
result.push(path__default.default.resolve(cwd, process.execPath, ".."));
const pathEnv = process.env[getPathEnvVarKey()];
return [...result, pathEnv].join(path__default.default.delimiter);
}
function getPartialEnvWithNpmPath(cwd) {
return {
[getPathEnvVarKey()]: getNpmRunPath(cwd)
};
}
function getPathEnvVarKey() {
return process.platform !== "win32" ? "PATH" : Object.keys(process.env).reverse().find((key) => key.toUpperCase() === "PATH") || "Path";
}
function getCommandPath(cmd, cwd) {
const options = {
path: cwd ? getNpmRunPath(cwd) : void 0
};
return which__default.default(cmd, options).catch(() => null);
}
function hasCommand(cmd, cwd) {
return getCommandPath(cmd, cwd).then((cmdPath) => cmdPath !== null);
}
async function getMostLikelyInstalledPackageManager(rootDir) {
const installed = await getAvailablePackageManagers(rootDir), running = getRunningPackageManager();
return running && installed.includes(running) ? running : void 0;
}
function getRunningPackageManager() {
const agent = process.env.npm_config_user_agent || "";
if (agent.includes("yarn"))
return "yarn";
if (agent.includes("pnpm"))
return "pnpm";
if (agent.includes("bun"))
return "bun";
if (/^npm\/\d/.test(agent))
return "npm";
}
async function upgradePackages(options, context) {
const {
packageManager,
packages
} = options, {
output,
workDir
} = context, execOptions = {
encoding: "utf8",
env: getPartialEnvWithNpmPath(workDir),
cwd: workDir,
stdio: "inherit"
}, upgradePackageArgs = packages.map((pkg) => pkg.join("@"));
let result;
if (packageManager === "npm") {
const npmArgs = ["install", "--legacy-peer-deps", ...upgradePackageArgs];
output.print(`Running 'npm ${npmArgs.join(" ")}'`), result = await execa__default.default("npm", npmArgs, execOptions);
} else if (packageManager === "yarn") {
const yarnArgs = ["upgrade ", ...upgradePackageArgs];
output.print(`Running 'yarn ${yarnArgs.join(" ")}'`), result = await execa__default.default("yarn", yarnArgs, execOptions);
} else if (packageManager === "pnpm") {
const pnpmArgs = ["upgrade", ...upgradePackageArgs];
output.print(`Running 'pnpm ${pnpmArgs.join(" ")}'`), result = await execa__default.default("pnpm", pnpmArgs, execOptions);
} else if (packageManager === "bun") {
const bunArgs = ["update", ...upgradePackageArgs];
output.print(`Running 'bun ${bunArgs.join(" ")}'`), result = await execa__default.default("bun", bunArgs, execOptions);
} else packageManager === "manual" && output.print(`Manual installation selected - run 'npm upgrade ${upgradePackageArgs.join(" ")}' or equivalent`);
if (result?.exitCode || result?.failed)
throw new Error("Package upgrade failed");
}
exports.checkRequiredDependencies = checkRequiredDependencies;
exports.checkStudioDependencyVersions = checkStudioDependencyVersions;
exports.getPackageManagerChoice = getPackageManagerChoice;
exports.upgradePackages = upgradePackages;
//# sourceMappingURL=upgradePackages.js.map