@sanity/cli 3.67.2-corel.454 → 3.68.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- var fs$1 = require("node:fs"), os = require("node:os"), path$3 = require("node:path"), chalk = require("chalk"), loadEnv = require("./loadEnv.js"), require$$0$4 = require("path"), require$$1$2 = require("module"), require$$0$5 = require("fs"), telemetry = require("@sanity/telemetry"), childProcess = require("node:child_process"), fs = require("node:fs/promises"), util$4 = require("node:util"), require$$0$6 = require("os"), require$$0$c = require("url"), require$$1$3 = require("get-it"), require$$2$1 = require("get-it/middleware"), require$$0$7 = require("constants"), require$$0$8 = require("stream"), require$$0$a = require("util"), require$$0$9 = require("assert"), require$$0$b = require("events"), require$$6$1 = require("http"), semver = require("semver"), pkgDir = require("pkg-dir"), client$1 = require("@sanity/client"), require$$3$1 = require("crypto"), require$$1$4 = require("child_process"), require$$0$d = require("fs/promises"), require$$0$e = require("buffer"), silverFleece = require("silver-fleece"), getCliConfig = require("./getCliConfig.js"), journeyConfig = require("./journeyConfig.js"), Stream = require("node:stream"), promises$1 = require("node:stream/promises"), require$$2$2 = require("string_decoder"), require$$0$f = require("zlib"), require$$7$1 = require("process"), yaml = require("yaml"), http = require("node:http"), traverse = require("@babel/traverse"), node_url = require("node:url"), node_events = require("node:events"), node_string_decoder = require("node:string_decoder"), process$2 = require("node:process"), require$$2$3 = require("readline"), require$$0$g = require("tty");
2
+ var fs$1 = require("node:fs"), os = require("node:os"), path$3 = require("node:path"), chalk = require("chalk"), loadEnv = require("./loadEnv.js"), require$$0$4 = require("path"), require$$1$2 = require("module"), require$$0$5 = require("fs"), telemetry = require("@sanity/telemetry"), childProcess = require("node:child_process"), fs = require("node:fs/promises"), util$4 = require("node:util"), require$$0$6 = require("os"), require$$0$c = require("url"), require$$1$3 = require("get-it"), require$$2$1 = require("get-it/middleware"), require$$0$7 = require("constants"), require$$0$8 = require("stream"), require$$0$a = require("util"), require$$0$9 = require("assert"), require$$0$b = require("events"), require$$6$1 = require("http"), semver = require("semver"), pkgDir = require("pkg-dir"), client$1 = require("@sanity/client"), require$$3$1 = require("crypto"), require$$1$4 = require("child_process"), require$$0$d = require("fs/promises"), require$$0$e = require("buffer"), silverFleece = require("silver-fleece"), getCliConfig = require("./getCliConfig.js"), journeyConfig = require("./journeyConfig.js"), Stream = require("node:stream"), promises$1 = require("node:stream/promises"), templateValidator = require("@sanity/template-validator"), require$$2$2 = require("string_decoder"), require$$0$f = require("zlib"), require$$7$1 = require("process"), http = require("node:http"), traverse = require("@babel/traverse"), node_url = require("node:url"), node_events = require("node:events"), node_string_decoder = require("node:string_decoder"), process$2 = require("node:process"), require$$2$3 = require("readline"), require$$0$g = require("tty");
3
3
  function _interopDefaultCompat(e) {
4
4
  return e && typeof e == "object" && "default" in e ? e : { default: e };
5
5
  }
@@ -9067,8 +9067,8 @@ var jsYaml$3, hasRequiredJsYaml$3;
9067
9067
  function requireJsYaml$3() {
9068
9068
  if (hasRequiredJsYaml$3) return jsYaml$3;
9069
9069
  hasRequiredJsYaml$3 = 1;
9070
- var yaml2 = requireJsYaml$4();
9071
- return jsYaml$3 = yaml2, jsYaml$3;
9070
+ var yaml = requireJsYaml$4();
9071
+ return jsYaml$3 = yaml, jsYaml$3;
9072
9072
  }
9073
9073
  var toml = {}, parse$2 = { exports: {} }, tomlParser = { exports: {} }, parser$2, hasRequiredParser$1;
9074
9074
  function requireParser$1() {
@@ -22413,14 +22413,14 @@ var jsYaml, hasRequiredJsYaml;
22413
22413
  function requireJsYaml() {
22414
22414
  if (hasRequiredJsYaml) return jsYaml;
22415
22415
  hasRequiredJsYaml = 1;
22416
- var yaml2 = requireJsYaml$1();
22417
- return jsYaml = yaml2, jsYaml;
22416
+ var yaml = requireJsYaml$1();
22417
+ return jsYaml = yaml, jsYaml;
22418
22418
  }
22419
22419
  var hasRequiredLoadYamlFile;
22420
22420
  function requireLoadYamlFile() {
22421
22421
  if (hasRequiredLoadYamlFile) return loadYamlFile.exports;
22422
22422
  hasRequiredLoadYamlFile = 1;
22423
- const fs2 = requireGracefulFs(), pify2 = requirePify(), stripBom2 = requireStripBom(), yaml2 = requireJsYaml(), parse3 = (data) => yaml2.safeLoad(stripBom2(data));
22423
+ const fs2 = requireGracefulFs(), pify2 = requirePify(), stripBom2 = requireStripBom(), yaml = requireJsYaml(), parse3 = (data) => yaml.safeLoad(stripBom2(data));
22424
22424
  return loadYamlFile.exports = (fp) => pify2(fs2.readFile)(fp, "utf8").then((data) => parse3(data)), loadYamlFile.exports.sync = (fp) => parse3(fs2.readFileSync(fp, "utf8")), loadYamlFile.exports;
22425
22425
  }
22426
22426
  var whichPm, hasRequiredWhichPm;
@@ -26596,17 +26596,17 @@ function requireTar() {
26596
26596
  return hasRequiredTar || (hasRequiredTar = 1, tar.c = tar.create = requireCreate(), tar.r = tar.replace = requireReplace(), tar.t = tar.list = requireList$1(), tar.u = tar.update = requireUpdate(), tar.x = tar.extract = requireExtract(), tar.Pack = requirePack(), tar.Unpack = requireUnpack(), tar.Parse = requireParse(), tar.ReadEntry = requireReadEntry(), tar.WriteEntry = requireWriteEntry(), tar.Header = requireHeader(), tar.Pax = requirePax(), tar.types = requireTypes$1()), tar;
26597
26597
  }
26598
26598
  var tarExports = requireTar();
26599
- const ENV_VAR = {
26600
- PROJECT_ID: /SANITY(?:_STUDIO)?_PROJECT_ID/,
26601
- // Matches SANITY_PROJECT_ID and SANITY_STUDIO_PROJECT_ID
26602
- DATASET: /SANITY(?:_STUDIO)?_DATASET/,
26603
- // Matches SANITY_DATASET and SANITY_STUDIO_DATASET
26599
+ const DISALLOWED_PATHS = [
26600
+ // Prevent security risks from unknown GitHub Actions
26601
+ "/.github/"
26602
+ ], ENV_VAR = {
26603
+ ...templateValidator.REQUIRED_ENV_VAR,
26604
26604
  READ_TOKEN: "SANITY_API_READ_TOKEN"
26605
- }, ENV_FILE = {
26606
- TEMPLATE: ".env.template",
26607
- EXAMPLE: ".env.example",
26608
- LOCAL_EXAMPLE: ".env.local.example"
26609
- }, ENV_TEMPLATE_FILES = [ENV_FILE.TEMPLATE, ENV_FILE.EXAMPLE, ENV_FILE.LOCAL_EXAMPLE];
26605
+ };
26606
+ function getGitHubRawContentUrl(repoInfo) {
26607
+ const { username, name, branch, filePath } = repoInfo;
26608
+ return `https://raw.githubusercontent.com/${username}/${name}/${branch}/${filePath}`;
26609
+ }
26610
26610
  function isGithubRepoShorthand(value) {
26611
26611
  return URL.canParse(value) ? !1 : /^[\w-]+\/[\w-.]+(\/[@\w-.]+)*$/.test(value);
26612
26612
  }
@@ -26682,134 +26682,29 @@ async function downloadAndExtractRepo(root2, { username, name, branch, filePath
26682
26682
  const pathSegments = posixPath.split(path$3.posix.sep);
26683
26683
  rootPath = pathSegments.length ? pathSegments[0] : null;
26684
26684
  }
26685
+ for (const disallowedPath of DISALLOWED_PATHS)
26686
+ if (posixPath.includes(disallowedPath)) return !1;
26685
26687
  return posixPath.startsWith(`${rootPath}${filePath ? `/${filePath}/` : "/"}`);
26686
26688
  }
26687
26689
  })
26688
26690
  );
26689
26691
  }
26690
- async function getMonoRepo(repoInfo, bearerToken) {
26691
- const { username, name, branch, filePath } = repoInfo, baseUrl = `https://raw.githubusercontent.com/${username}/${name}/${branch}/${filePath}`, headers = {};
26692
- bearerToken && (headers.Authorization = `Bearer ${bearerToken}`);
26693
- const handlers = {
26694
- "package.json": {
26695
- check: (content) => {
26696
- try {
26697
- const pkg = JSON.parse(content);
26698
- return pkg.workspaces ? Array.isArray(pkg.workspaces) ? pkg.workspaces : pkg.workspaces.packages : void 0;
26699
- } catch {
26700
- return;
26701
- }
26702
- }
26703
- },
26704
- "pnpm-workspace.yaml": {
26705
- check: (content) => {
26706
- try {
26707
- return yaml.parse(content).packages;
26708
- } catch {
26709
- return;
26710
- }
26711
- }
26712
- },
26713
- "lerna.json": {
26714
- check: (content) => {
26715
- try {
26716
- return JSON.parse(content).packages;
26717
- } catch {
26718
- return;
26719
- }
26720
- }
26721
- },
26722
- "rush.json": {
26723
- check: (content) => {
26724
- try {
26725
- return JSON.parse(content).projects?.map((p) => p.packageName);
26726
- } catch {
26727
- return;
26728
- }
26729
- }
26730
- }
26731
- }, fileChecks = await Promise.all(
26732
- Object.keys(handlers).map(async (file) => {
26733
- const response = await fetch(`${baseUrl}/${file}`, { headers });
26734
- return { file, exists: response.status === 200, content: await response.text() };
26735
- })
26736
- );
26737
- for (const check of fileChecks) {
26738
- if (!check.exists) continue;
26739
- const result = handlers[check.file].check(check.content);
26740
- if (result) return result;
26741
- }
26742
- }
26743
- async function validatePackage(baseUrl, packagePath, headers) {
26744
- const packageUrl = packagePath ? `${baseUrl}/${packagePath}` : baseUrl, requiredFiles = [
26745
- "package.json",
26746
- "sanity.config.ts",
26747
- "sanity.config.js",
26748
- "sanity.cli.ts",
26749
- "sanity.cli.js",
26750
- ...ENV_TEMPLATE_FILES
26751
- ], fileChecks = await Promise.all(
26752
- requiredFiles.map(async (file) => {
26753
- const response = await fetch(`${packageUrl}/${file}`, { headers });
26754
- return { file, exists: response.status === 200, content: await response.text() };
26755
- })
26756
- ), packageJson = fileChecks.find((f) => f.file === "package.json");
26757
- if (!packageJson?.exists)
26758
- throw new Error(`Package at ${packagePath || "root"} must include a package.json file`);
26759
- let hasSanityDep = !1;
26760
- try {
26761
- const pkg = JSON.parse(packageJson.content);
26762
- hasSanityDep = !!(pkg.dependencies?.sanity || pkg.devDependencies?.sanity);
26763
- } catch {
26764
- throw new Error(`Invalid package.json file in ${packagePath || "root"}`);
26765
- }
26766
- const hasSanityConfig = fileChecks.some(
26767
- (f) => f.exists && (f.file === "sanity.config.ts" || f.file === "sanity.config.js")
26768
- ), hasSanityCli = fileChecks.some(
26769
- (f) => f.exists && (f.file === "sanity.cli.ts" || f.file === "sanity.cli.js")
26770
- ), envFile = fileChecks.find(
26771
- (f) => f.exists && ENV_TEMPLATE_FILES.includes(f.file)
26772
- );
26773
- if (envFile) {
26774
- const envContent = envFile.content, hasProjectId = envContent.match(ENV_VAR.PROJECT_ID), hasDataset = envContent.match(ENV_VAR.DATASET);
26775
- if (!hasProjectId || !hasDataset) {
26776
- const missing = [];
26777
- throw hasProjectId || missing.push("SANITY_PROJECT_ID or SANITY_STUDIO_PROJECT_ID"), hasDataset || missing.push("SANITY_DATASET or SANITY_STUDIO_DATASET"), new Error(
26778
- `Environment template in ${packagePath || "repo"} must include the following variables: ${missing.join(", ")}`
26779
- );
26780
- }
26781
- }
26782
- return {
26783
- hasSanityConfig,
26784
- hasSanityCli,
26785
- hasEnvFile: !!envFile,
26786
- hasSanityDep
26787
- };
26692
+ async function getPackages(repoInfo, bearerToken) {
26693
+ const headers = {};
26694
+ return bearerToken && (headers.Authorization = `Bearer ${bearerToken}`), templateValidator.getMonoRepo(getGitHubRawContentUrl(repoInfo), headers);
26788
26695
  }
26789
26696
  async function validateRemoteTemplate(repoInfo, packages = [""], bearerToken) {
26790
- const { username, name, branch, filePath } = repoInfo, baseUrl = `https://raw.githubusercontent.com/${username}/${name}/${branch}/${filePath}`, headers = {};
26697
+ const headers = {};
26791
26698
  bearerToken && (headers.Authorization = `Bearer ${bearerToken}`);
26792
- const validations = await Promise.all(
26793
- packages.map((pkg) => validatePackage(baseUrl, pkg, headers))
26794
- );
26795
- if (!validations.some((v) => v.hasSanityDep))
26796
- throw new Error('At least one package must include "sanity" as a dependency in package.json');
26797
- if (!validations.some((v) => v.hasSanityConfig))
26798
- throw new Error("At least one package must include a sanity.config.js or sanity.config.ts file");
26799
- if (!validations.some((v) => v.hasSanityCli))
26800
- throw new Error("At least one package must include a sanity.cli.js or sanity.cli.ts file");
26801
- const missingEnvPackages = packages.filter((pkg, i) => !validations[i].hasEnvFile);
26802
- if (missingEnvPackages.length > 0)
26803
- throw new Error(
26804
- `The following packages are missing .env.template, .env.example, or .env.local.example files: ${missingEnvPackages.join(
26805
- ", "
26806
- )}`
26807
- );
26699
+ const result = await templateValidator.validateSanityTemplate(getGitHubRawContentUrl(repoInfo), packages, headers);
26700
+ if (!result.isValid)
26701
+ throw new Error(result.errors.join(`
26702
+ `));
26808
26703
  }
26809
26704
  async function checkNeedsReadToken(root2) {
26810
26705
  try {
26811
26706
  const templatePath = await Promise.any(
26812
- ENV_TEMPLATE_FILES.map(async (file) => (await fs.access(path$3.join(root2, file)), file))
26707
+ templateValidator.ENV_TEMPLATE_FILES.map(async (file) => (await fs.access(path$3.join(root2, file)), file))
26813
26708
  );
26814
26709
  return (await fs.readFile(path$3.join(root2, templatePath), "utf8")).includes(ENV_VAR.READ_TOKEN);
26815
26710
  } catch {
@@ -26818,7 +26713,7 @@ async function checkNeedsReadToken(root2) {
26818
26713
  }
26819
26714
  async function applyEnvVariables(root2, envData, targetName = ".env") {
26820
26715
  const templatePath = await Promise.any(
26821
- ENV_TEMPLATE_FILES.map(async (file) => (await fs.access(path$3.join(root2, file)), file))
26716
+ templateValidator.ENV_TEMPLATE_FILES.map(async (file) => (await fs.access(path$3.join(root2, file)), file))
26822
26717
  ).catch(() => {
26823
26718
  throw new Error("Could not find .env.template, .env.example or .env.local.example file");
26824
26719
  });
@@ -26865,6 +26760,17 @@ async function generateSanityApiReadToken(label, projectId, apiClient) {
26865
26760
  }
26866
26761
  })).key;
26867
26762
  }
26763
+ async function setCorsOrigin(origin, projectId, apiClient) {
26764
+ try {
26765
+ await apiClient({ api: { projectId } }).request({
26766
+ method: "POST",
26767
+ url: "/cors",
26768
+ body: { origin, allowCredentials: !1 }
26769
+ });
26770
+ } catch (error2) {
26771
+ loadEnv.debug("Failed to set CORS origin", error2);
26772
+ }
26773
+ }
26868
26774
  function canLaunchBrowser() {
26869
26775
  return ["win32", "darwin"].includes(os__default.default.platform()) ? !0 : !!(process.env.XDG_CURRENT_DESKTOP || process.env.GDMSESSION);
26870
26776
  }
@@ -47029,6 +46935,55 @@ ${chalk__default.default.yellow("\u26A0")} File "${filePath}" already exists, sk
47029
46935
  function toTypeScriptPath(originalPath) {
47030
46936
  return originalPath.replace(/\.js$/, ".ts");
47031
46937
  }
46938
+ const portMap = {
46939
+ nextjs: 3e3,
46940
+ blitzjs: 3e3,
46941
+ gatsby: 8e3,
46942
+ remix: 3e3,
46943
+ astro: 3e3,
46944
+ hexo: 4e3,
46945
+ eleventy: 8080,
46946
+ docusaurus: 3e3,
46947
+ "docusaurus-2": 3e3,
46948
+ preact: 8080,
46949
+ solidstart: 3e3,
46950
+ "solidstart-1": 3e3,
46951
+ dojo: 3e3,
46952
+ ember: 4200,
46953
+ vue: 8080,
46954
+ scully: 1668,
46955
+ "ionic-angular": 4200,
46956
+ angular: 4200,
46957
+ polymer: 8081,
46958
+ svelte: 5e3,
46959
+ sveltekit: 5173,
46960
+ "sveltekit-1": 5173,
46961
+ "ionic-react": 3e3,
46962
+ "create-react-app": 3e3,
46963
+ gridsome: 8080,
46964
+ umijs: 8e3,
46965
+ saber: 3e3,
46966
+ stencil: 3333,
46967
+ nuxtjs: 3e3,
46968
+ redwoodjs: 8910,
46969
+ hugo: 1313,
46970
+ jekyll: 4e3,
46971
+ brunch: 3333,
46972
+ middleman: 4567,
46973
+ zola: 1111,
46974
+ hydrogen: 3e3,
46975
+ vite: 5173,
46976
+ vitepress: 5173,
46977
+ vuepress: 8080,
46978
+ parcel: 1234,
46979
+ fasthtml: 8e3,
46980
+ sanity: 3333,
46981
+ "sanity-v3": 3333,
46982
+ storybook: 6006
46983
+ };
46984
+ function getDefaultPortForFramework(frameworkSlug) {
46985
+ return portMap[frameworkSlug ?? ""] ?? 3e3;
46986
+ }
47032
46987
  var braceExpansionExports = requireBraceExpansion(), expand$2 = /* @__PURE__ */ loadEnv.getDefaultExportFromCjs(braceExpansionExports);
47033
46988
  const MAX_PATTERN_LENGTH = 1024 * 64, assertValidPattern = (pattern) => {
47034
46989
  if (typeof pattern != "string")
@@ -51896,7 +51851,7 @@ const INITIAL_COMMIT_MESSAGE = "Initial commit from Sanity CLI";
51896
51851
  async function bootstrapRemoteTemplate(opts, context) {
51897
51852
  const { outputPath, repoInfo, bearerToken, variables, packageName } = opts, { output, apiClient } = context, name = [repoInfo.username, repoInfo.name, repoInfo.filePath].filter(Boolean).join("/"), spinner = output.spinner(`Bootstrapping files from template "${name}"`).start();
51898
51853
  loadEnv.debug("Validating remote template");
51899
- const packages = await getMonoRepo(repoInfo, bearerToken);
51854
+ const packages = await getPackages(repoInfo, bearerToken);
51900
51855
  await validateRemoteTemplate(repoInfo, packages, bearerToken), loadEnv.debug('Create new directory "%s"', outputPath), await fs.mkdir(outputPath, { recursive: !0 }), loadEnv.debug("Downloading and extracting repo to %s", outputPath), await downloadAndExtractRepo(outputPath, repoInfo, bearerToken), loadEnv.debug("Checking if template needs read token");
51901
51856
  const needsReadToken = await Promise.all(
51902
51857
  (packages ?? [""]).map((pkg) => checkNeedsReadToken(path$3.join(outputPath, pkg)))
@@ -51904,10 +51859,12 @@ async function bootstrapRemoteTemplate(opts, context) {
51904
51859
  loadEnv.debug("Applying environment variables");
51905
51860
  const readToken = needsReadToken ? await generateSanityApiReadToken("API Read Token", variables.projectId, apiClient) : void 0;
51906
51861
  for (const pkg of packages ?? [""]) {
51907
- const packagePath = path$3.join(outputPath, pkg), envName = (await distExports.detectFrameworkRecord({
51862
+ const packagePath = path$3.join(outputPath, pkg), packageFramework = await distExports.detectFrameworkRecord({
51908
51863
  fs: new distExports.LocalFileSystemDetector(packagePath),
51909
51864
  frameworkList: frameworksExports.frameworks
51910
- }))?.slug === "nextjs" ? ".env.local" : ".env";
51865
+ }), port = getDefaultPortForFramework(packageFramework?.slug);
51866
+ loadEnv.debug("Setting CORS origin to http://localhost:%d", port), await setCorsOrigin(`http://localhost:${port}`, variables.projectId, apiClient), loadEnv.debug("Applying environment variables to %s", pkg);
51867
+ const envName = packageFramework?.slug === "nextjs" ? ".env.local" : ".env";
51911
51868
  await applyEnvVariables(packagePath, { ...variables, readToken }, envName);
51912
51869
  }
51913
51870
  loadEnv.debug("Setting package name to %s", packageName), await tryApplyPackageName(outputPath, packageName), loadEnv.debug("Initializing git repository"), tryGitInit(outputPath, INITIAL_COMMIT_MESSAGE), loadEnv.debug("Updating initial template metadata"), await updateInitialTemplateMetadata(apiClient, variables.projectId, `external-${name}`), spinner.succeed();
@@ -55825,20 +55782,20 @@ var cliOutputter = {
55825
55782
  print(...args) {
55826
55783
  console.log(...args);
55827
55784
  },
55828
- success(...args) {
55829
- console.log(`${SYMBOL_CHECK} ${args.join(" ")}`);
55785
+ success(firstPartOfMessage, ...args) {
55786
+ console.log(`${SYMBOL_CHECK} ${firstPartOfMessage}`, ...args);
55830
55787
  },
55831
- warn(...args) {
55832
- console.warn(`${SYMBOL_WARN} ${args.join(" ")}`);
55788
+ warn(firstPartOfMessage, ...args) {
55789
+ console.warn(`${SYMBOL_WARN} ${firstPartOfMessage}`, ...args);
55833
55790
  },
55834
- error(...args) {
55835
- args[0] instanceof Error ? console.error(`${SYMBOL_FAIL} ${chalk__default.default.red(args[0].stack)}`) : console.error(`${SYMBOL_FAIL} ${args.join(" ")}`);
55791
+ error(firstPartOfMessage, ...args) {
55792
+ firstPartOfMessage instanceof Error ? console.error(`${SYMBOL_FAIL} ${chalk__default.default.red(firstPartOfMessage.stack)}`) : console.error(`${SYMBOL_FAIL} ${firstPartOfMessage}`, ...args);
55836
55793
  },
55837
55794
  clear: () => {
55838
55795
  process.stdout.write(isFirstClear ? "\x1Bc" : "\x1B[2J\x1B[0f"), isFirstClear = !1;
55839
55796
  },
55840
55797
  spinner(options2) {
55841
- const spinner = ora({ ...options2, spinner: "dots" });
55798
+ const spinner = ora(options2);
55842
55799
  return spinner.succeed = (text) => spinner.stopAndPersist({ text, symbol: SYMBOL_CHECK }), spinner.warn = (text) => spinner.stopAndPersist({ text, symbol: SYMBOL_WARN }), spinner.fail = (text) => spinner.stopAndPersist({ text, symbol: SYMBOL_FAIL }), spinner;
55843
55800
  }
55844
55801
  }, inquirer$1 = { exports: {} }, escapeStringRegexp$1, hasRequiredEscapeStringRegexp$1;