@sanity/cli 6.1.7 → 6.2.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.
Files changed (143) hide show
  1. package/README.md +105 -103
  2. package/dist/actions/build/buildStudio.js +1 -1
  3. package/dist/actions/build/buildStudio.js.map +1 -1
  4. package/dist/actions/debug/gatherDebugInfo.js +130 -81
  5. package/dist/actions/debug/gatherDebugInfo.js.map +1 -1
  6. package/dist/actions/debug/output.js +25 -0
  7. package/dist/actions/debug/output.js.map +1 -0
  8. package/dist/actions/debug/types.js.map +1 -1
  9. package/dist/actions/mcp/setupMCP.js +5 -5
  10. package/dist/actions/mcp/setupMCP.js.map +1 -1
  11. package/dist/actions/schema/getExtractOptions.js.map +1 -1
  12. package/dist/commands/{backup → backups}/disable.js +3 -0
  13. package/dist/commands/backups/disable.js.map +1 -0
  14. package/dist/commands/{backup → backups}/download.js +3 -0
  15. package/dist/commands/backups/download.js.map +1 -0
  16. package/dist/commands/{backup → backups}/enable.js +3 -0
  17. package/dist/commands/backups/enable.js.map +1 -0
  18. package/dist/commands/{backup → backups}/list.js +3 -0
  19. package/dist/commands/backups/list.js.map +1 -0
  20. package/dist/commands/{dataset → datasets}/alias/create.js +3 -0
  21. package/dist/commands/datasets/alias/create.js.map +1 -0
  22. package/dist/commands/{dataset → datasets}/alias/delete.js +3 -0
  23. package/dist/commands/datasets/alias/delete.js.map +1 -0
  24. package/dist/commands/{dataset → datasets}/alias/link.js +3 -0
  25. package/dist/commands/datasets/alias/link.js.map +1 -0
  26. package/dist/commands/{dataset → datasets}/alias/unlink.js +3 -0
  27. package/dist/commands/datasets/alias/unlink.js.map +1 -0
  28. package/dist/commands/{dataset → datasets}/copy.js +3 -0
  29. package/dist/commands/datasets/copy.js.map +1 -0
  30. package/dist/commands/{dataset → datasets}/create.js +3 -0
  31. package/dist/commands/datasets/create.js.map +1 -0
  32. package/dist/commands/{dataset → datasets}/delete.js +3 -0
  33. package/dist/commands/datasets/delete.js.map +1 -0
  34. package/dist/commands/{dataset → datasets}/embeddings/disable.js +3 -0
  35. package/dist/commands/datasets/embeddings/disable.js.map +1 -0
  36. package/dist/commands/{dataset → datasets}/embeddings/enable.js +3 -0
  37. package/dist/commands/datasets/embeddings/enable.js.map +1 -0
  38. package/dist/commands/{dataset → datasets}/embeddings/status.js +3 -0
  39. package/dist/commands/datasets/embeddings/status.js.map +1 -0
  40. package/dist/commands/{dataset → datasets}/export.js +3 -0
  41. package/dist/commands/datasets/export.js.map +1 -0
  42. package/dist/commands/{dataset → datasets}/import.js +3 -0
  43. package/dist/commands/datasets/import.js.map +1 -0
  44. package/dist/commands/{dataset → datasets}/list.js +3 -0
  45. package/dist/commands/datasets/list.js.map +1 -0
  46. package/dist/commands/{dataset → datasets}/visibility/get.js +3 -0
  47. package/dist/commands/datasets/visibility/get.js.map +1 -0
  48. package/dist/commands/{dataset → datasets}/visibility/set.js +3 -0
  49. package/dist/commands/datasets/visibility/set.js.map +1 -0
  50. package/dist/commands/debug.js +189 -74
  51. package/dist/commands/debug.js.map +1 -1
  52. package/dist/commands/documents/create.js +3 -0
  53. package/dist/commands/documents/create.js.map +1 -1
  54. package/dist/commands/documents/delete.js +3 -0
  55. package/dist/commands/documents/delete.js.map +1 -1
  56. package/dist/commands/documents/get.js +3 -0
  57. package/dist/commands/documents/get.js.map +1 -1
  58. package/dist/commands/documents/query.js +3 -0
  59. package/dist/commands/documents/query.js.map +1 -1
  60. package/dist/commands/documents/validate.js +3 -0
  61. package/dist/commands/documents/validate.js.map +1 -1
  62. package/dist/commands/{hook → hooks}/attempt.js +3 -0
  63. package/dist/commands/hooks/attempt.js.map +1 -0
  64. package/dist/commands/{hook → hooks}/create.js +3 -0
  65. package/dist/commands/hooks/create.js.map +1 -0
  66. package/dist/commands/{hook → hooks}/delete.js +3 -0
  67. package/dist/commands/hooks/delete.js.map +1 -0
  68. package/dist/commands/{hook → hooks}/list.js +3 -0
  69. package/dist/commands/hooks/list.js.map +1 -0
  70. package/dist/commands/{hook → hooks}/logs.js +3 -0
  71. package/dist/commands/hooks/logs.js.map +1 -0
  72. package/dist/commands/init.js +65 -13
  73. package/dist/commands/init.js.map +1 -1
  74. package/dist/commands/mcp/configure.js +3 -2
  75. package/dist/commands/mcp/configure.js.map +1 -1
  76. package/dist/commands/preview.js +1 -0
  77. package/dist/commands/preview.js.map +1 -1
  78. package/dist/commands/projects/create.js +3 -0
  79. package/dist/commands/projects/create.js.map +1 -1
  80. package/dist/commands/projects/list.js +3 -0
  81. package/dist/commands/projects/list.js.map +1 -1
  82. package/dist/commands/{schema → schemas}/delete.js +3 -0
  83. package/dist/commands/schemas/delete.js.map +1 -0
  84. package/dist/commands/{schema → schemas}/deploy.js +3 -0
  85. package/dist/commands/schemas/deploy.js.map +1 -0
  86. package/dist/commands/{schema → schemas}/extract.js +3 -0
  87. package/dist/commands/schemas/extract.js.map +1 -0
  88. package/dist/commands/{schema → schemas}/list.js +3 -0
  89. package/dist/commands/schemas/list.js.map +1 -0
  90. package/dist/commands/{schema → schemas}/validate.js +3 -0
  91. package/dist/commands/schemas/validate.js.map +1 -0
  92. package/dist/commands/tokens/add.js +3 -0
  93. package/dist/commands/tokens/add.js.map +1 -1
  94. package/dist/commands/tokens/delete.js +3 -0
  95. package/dist/commands/tokens/delete.js.map +1 -1
  96. package/dist/commands/tokens/list.js +3 -0
  97. package/dist/commands/tokens/list.js.map +1 -1
  98. package/dist/commands/users/invite.js +3 -0
  99. package/dist/commands/users/invite.js.map +1 -1
  100. package/dist/commands/users/list.js +3 -0
  101. package/dist/commands/users/list.js.map +1 -1
  102. package/dist/hooks/commandNotFound/topicAliases.js +71 -0
  103. package/dist/hooks/commandNotFound/topicAliases.js.map +1 -0
  104. package/dist/services/mcp.js +32 -44
  105. package/dist/services/mcp.js.map +1 -1
  106. package/dist/topicAliases.js +51 -0
  107. package/dist/topicAliases.js.map +1 -0
  108. package/oclif.config.js +20 -7
  109. package/oclif.manifest.json +321 -209
  110. package/package.json +22 -21
  111. package/dist/actions/debug/formatters.js +0 -22
  112. package/dist/actions/debug/formatters.js.map +0 -1
  113. package/dist/actions/debug/getGlobalConfigLocation.js +0 -7
  114. package/dist/actions/debug/getGlobalConfigLocation.js.map +0 -1
  115. package/dist/commands/backup/disable.js.map +0 -1
  116. package/dist/commands/backup/download.js.map +0 -1
  117. package/dist/commands/backup/enable.js.map +0 -1
  118. package/dist/commands/backup/list.js.map +0 -1
  119. package/dist/commands/dataset/alias/create.js.map +0 -1
  120. package/dist/commands/dataset/alias/delete.js.map +0 -1
  121. package/dist/commands/dataset/alias/link.js.map +0 -1
  122. package/dist/commands/dataset/alias/unlink.js.map +0 -1
  123. package/dist/commands/dataset/copy.js.map +0 -1
  124. package/dist/commands/dataset/create.js.map +0 -1
  125. package/dist/commands/dataset/delete.js.map +0 -1
  126. package/dist/commands/dataset/embeddings/disable.js.map +0 -1
  127. package/dist/commands/dataset/embeddings/enable.js.map +0 -1
  128. package/dist/commands/dataset/embeddings/status.js.map +0 -1
  129. package/dist/commands/dataset/export.js.map +0 -1
  130. package/dist/commands/dataset/import.js.map +0 -1
  131. package/dist/commands/dataset/list.js.map +0 -1
  132. package/dist/commands/dataset/visibility/get.js.map +0 -1
  133. package/dist/commands/dataset/visibility/set.js.map +0 -1
  134. package/dist/commands/hook/attempt.js.map +0 -1
  135. package/dist/commands/hook/create.js.map +0 -1
  136. package/dist/commands/hook/delete.js.map +0 -1
  137. package/dist/commands/hook/list.js.map +0 -1
  138. package/dist/commands/hook/logs.js.map +0 -1
  139. package/dist/commands/schema/delete.js.map +0 -1
  140. package/dist/commands/schema/deploy.js.map +0 -1
  141. package/dist/commands/schema/extract.js.map +0 -1
  142. package/dist/commands/schema/list.js.map +0 -1
  143. package/dist/commands/schema/validate.js.map +0 -1
@@ -39,7 +39,7 @@ import { shouldAutoUpdate } from './shouldAutoUpdate.js';
39
39
  output,
40
40
  workDir
41
41
  });
42
- let autoUpdatesEnabled = shouldAutoUpdate({
42
+ let autoUpdatesEnabled = options.calledFromDeploy ? options.autoUpdatesEnabled : shouldAutoUpdate({
43
43
  cliConfig,
44
44
  flags,
45
45
  output
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/build/buildStudio.ts"],"sourcesContent":["import {rm} from 'node:fs/promises'\nimport path from 'node:path'\nimport {styleText} from 'node:util'\n\nimport {getCliTelemetry, getTimer, isInteractive} from '@sanity/cli-core'\nimport {confirm, logSymbols, select, spinner, type SpinnerInstance} from '@sanity/cli-core/ux'\nimport semver from 'semver'\n\nimport {StudioBuildTrace} from '../../telemetry/build.telemetry.js'\nimport {getAppId} from '../../util/appId.js'\nimport {compareDependencyVersions} from '../../util/compareDependencyVersions.js'\nimport {formatModuleSizes, sortModulesBySize} from '../../util/moduleFormatUtils.js'\nimport {getPackageManagerChoice} from '../../util/packageManager/packageManagerChoice.js'\nimport {upgradePackages} from '../../util/packageManager/upgradePackages.js'\nimport {warnAboutMissingAppId} from '../../util/warnAboutMissingAppId.js'\nimport {buildDebug} from './buildDebug.js'\nimport {buildStaticFiles} from './buildStaticFiles.js'\nimport {buildVendorDependencies} from './buildVendorDependencies.js'\nimport {checkRequiredDependencies} from './checkRequiredDependencies.js'\nimport {checkStudioDependencyVersions} from './checkStudioDependencyVersions.js'\nimport {determineBasePath} from './determineBasePath.js'\nimport {getAutoUpdatesImportMap} from './getAutoUpdatesImportMap.js'\nimport {getStudioEnvVars} from './getStudioEnvVars.js'\nimport {handlePrereleaseVersions} from './handlePrereleaseVersions.js'\nimport {shouldAutoUpdate} from './shouldAutoUpdate.js'\nimport {type BuildOptions} from './types.js'\n\n/**\n * Build the Sanity Studio.\n *\n * @internal\n */\nexport async function buildStudio(options: BuildOptions): Promise<void> {\n const timer = getTimer()\n const {cliConfig, flags, outDir, output, workDir} = options\n\n const unattendedMode = Boolean(flags.yes)\n const defaultOutputDir = path.resolve(path.join(workDir, 'dist'))\n const outputDir = path.resolve(outDir || defaultOutputDir)\n\n await checkStudioDependencyVersions(workDir, output)\n\n // If the check resulted in a dependency install, the CLI command will be re-run,\n // thus we want to exit early\n const {installedSanityVersion} = await checkRequiredDependencies({\n cliConfig,\n output,\n workDir,\n })\n\n let autoUpdatesEnabled = shouldAutoUpdate({cliConfig, flags, output})\n\n let autoUpdatesImports = {}\n\n if (autoUpdatesEnabled) {\n // Get the clean version without build metadata: https://semver.org/#spec-item-10\n const cleanSanityVersion = semver.parse(installedSanityVersion)?.version\n if (!cleanSanityVersion) {\n throw new Error(`Failed to parse installed Sanity version: ${installedSanityVersion}`)\n }\n\n output.log(`${logSymbols.info} Building with auto-updates enabled`)\n\n const projectId = cliConfig?.api?.projectId\n const appId = getAppId(cliConfig)\n\n // Warn if auto updates enabled but no appId configured.\n // Skip when called from deploy, since deploy handles appId itself\n // (prompts the user and tells them to add it to config).\n if (!appId && !options.calledFromDeploy) {\n warnAboutMissingAppId({appType: 'studio', output, projectId})\n }\n\n const sanityDependencies = [\n {name: 'sanity', version: cleanSanityVersion},\n {name: '@sanity/vision', version: cleanSanityVersion},\n ]\n autoUpdatesImports = getAutoUpdatesImportMap(sanityDependencies, {appId})\n\n // Check the versions\n const {mismatched, unresolvedPrerelease} = await compareDependencyVersions(\n sanityDependencies,\n workDir,\n {appId},\n )\n\n if (unresolvedPrerelease.length > 0) {\n await handlePrereleaseVersions({output, unattendedMode, unresolvedPrerelease})\n autoUpdatesImports = {}\n autoUpdatesEnabled = false\n }\n\n if (mismatched.length > 0 && autoUpdatesEnabled) {\n const versionMismatchWarning =\n `The following local package versions are different from the versions currently served at runtime.\\n` +\n `When using auto updates, we recommend that you test locally with the same versions before deploying. \\n\\n` +\n `${mismatched.map((mod) => ` - ${mod.pkg} (local version: ${mod.installed}, runtime version: ${mod.remote})`).join('\\n')}`\n\n // If it is non-interactive or in unattended mode, we don't want to prompt\n if (isInteractive() && !unattendedMode) {\n const choice = await select({\n choices: [\n {\n name: `Upgrade local versions (recommended). You will need to run the build command again`,\n value: 'upgrade',\n },\n {\n name: `Upgrade and proceed with build`,\n value: 'upgrade-and-proceed',\n },\n {\n name: `Continue anyway`,\n value: 'continue',\n },\n {name: 'Cancel', value: 'cancel'},\n ],\n default: 'upgrade',\n message: styleText(\n 'yellow',\n `${logSymbols.warning} ${versionMismatchWarning}\\n\\nDo you want to upgrade local versions before deploying?`,\n ),\n })\n\n if (choice === 'cancel') {\n output.error('Declined to continue with build', {exit: 1})\n return\n }\n\n if (choice === 'upgrade' || choice === 'upgrade-and-proceed') {\n await upgradePackages(\n {\n packageManager: (await getPackageManagerChoice(workDir, {interactive: false})).chosen,\n packages: mismatched.map((res) => [res.pkg, res.remote]),\n },\n {output, workDir},\n )\n\n if (choice === 'upgrade') {\n return\n }\n }\n } else {\n // if non-interactive or unattended, just show the warning\n output.warn(versionMismatchWarning)\n }\n }\n }\n\n const envVarKeys = getStudioEnvVars()\n if (envVarKeys.length > 0) {\n output.log('\\nIncluding the following environment variables as part of the JavaScript bundle:')\n for (const key of envVarKeys) {\n output.log(`- ${key}`)\n }\n output.log('')\n }\n\n let shouldClean = true\n if (outputDir !== defaultOutputDir && !unattendedMode && isInteractive()) {\n shouldClean = await confirm({\n default: true,\n message: `Do you want to delete the existing directory (${outputDir}) first?`,\n })\n }\n\n // Determine base path for built studio\n const basePath = determineBasePath(cliConfig, 'studio', output)\n\n let spin: SpinnerInstance\n if (shouldClean) {\n timer.start('cleanOutputFolder')\n spin = spinner('Clean output folder').start()\n await rm(outputDir, {force: true, recursive: true})\n const cleanDuration = timer.end('cleanOutputFolder')\n spin.text = `Clean output folder (${cleanDuration.toFixed(0)}ms)`\n spin.succeed()\n }\n\n spin = spinner(`Build Sanity Studio`).start()\n\n const trace = getCliTelemetry().trace(StudioBuildTrace)\n trace.start()\n\n let importMap\n\n if (autoUpdatesEnabled) {\n importMap = {\n imports: {\n ...(await buildVendorDependencies({basePath, cwd: workDir, isApp: false, outputDir})),\n ...autoUpdatesImports,\n },\n }\n }\n\n try {\n timer.start('bundleStudio')\n\n const bundle = await buildStaticFiles({\n basePath,\n cwd: workDir,\n importMap,\n minify: Boolean(flags.minify),\n outputDir,\n reactCompiler:\n cliConfig && 'reactCompiler' in cliConfig ? cliConfig.reactCompiler : undefined,\n sourceMap: Boolean(flags['source-maps']),\n vite: cliConfig && 'vite' in cliConfig ? cliConfig.vite : undefined,\n })\n\n trace.log({\n outputSize: bundle.chunks\n .flatMap((chunk) => chunk.modules.flatMap((mod) => mod.renderedLength))\n .reduce((sum, n) => sum + n, 0),\n })\n const buildDuration = timer.end('bundleStudio')\n\n spin.text = `Build Sanity Studio (${buildDuration.toFixed(0)}ms)`\n spin.succeed()\n\n trace.complete()\n if (flags.stats) {\n output.log('\\nLargest module files:')\n output.log(formatModuleSizes(sortModulesBySize(bundle.chunks).slice(0, 15)))\n }\n } catch (error) {\n spin.fail()\n trace.error(error)\n const message = error instanceof Error ? error.message : String(error)\n buildDebug(`Failed to build Sanity Studio`, {error})\n output.error(`Failed to build Sanity Studio: ${message}`, {exit: 1})\n }\n}\n"],"names":["rm","path","styleText","getCliTelemetry","getTimer","isInteractive","confirm","logSymbols","select","spinner","semver","StudioBuildTrace","getAppId","compareDependencyVersions","formatModuleSizes","sortModulesBySize","getPackageManagerChoice","upgradePackages","warnAboutMissingAppId","buildDebug","buildStaticFiles","buildVendorDependencies","checkRequiredDependencies","checkStudioDependencyVersions","determineBasePath","getAutoUpdatesImportMap","getStudioEnvVars","handlePrereleaseVersions","shouldAutoUpdate","buildStudio","options","timer","cliConfig","flags","outDir","output","workDir","unattendedMode","Boolean","yes","defaultOutputDir","resolve","join","outputDir","installedSanityVersion","autoUpdatesEnabled","autoUpdatesImports","cleanSanityVersion","parse","version","Error","log","info","projectId","api","appId","calledFromDeploy","appType","sanityDependencies","name","mismatched","unresolvedPrerelease","length","versionMismatchWarning","map","mod","pkg","installed","remote","choice","choices","value","default","message","warning","error","exit","packageManager","interactive","chosen","packages","res","warn","envVarKeys","key","shouldClean","basePath","spin","start","force","recursive","cleanDuration","end","text","toFixed","succeed","trace","importMap","imports","cwd","isApp","bundle","minify","reactCompiler","undefined","sourceMap","vite","outputSize","chunks","flatMap","chunk","modules","renderedLength","reduce","sum","n","buildDuration","complete","stats","slice","fail","String"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/actions/build/buildStudio.ts"],"sourcesContent":["import {rm} from 'node:fs/promises'\nimport path from 'node:path'\nimport {styleText} from 'node:util'\n\nimport {getCliTelemetry, getTimer, isInteractive} from '@sanity/cli-core'\nimport {confirm, logSymbols, select, spinner, type SpinnerInstance} from '@sanity/cli-core/ux'\nimport semver from 'semver'\n\nimport {StudioBuildTrace} from '../../telemetry/build.telemetry.js'\nimport {getAppId} from '../../util/appId.js'\nimport {compareDependencyVersions} from '../../util/compareDependencyVersions.js'\nimport {formatModuleSizes, sortModulesBySize} from '../../util/moduleFormatUtils.js'\nimport {getPackageManagerChoice} from '../../util/packageManager/packageManagerChoice.js'\nimport {upgradePackages} from '../../util/packageManager/upgradePackages.js'\nimport {warnAboutMissingAppId} from '../../util/warnAboutMissingAppId.js'\nimport {buildDebug} from './buildDebug.js'\nimport {buildStaticFiles} from './buildStaticFiles.js'\nimport {buildVendorDependencies} from './buildVendorDependencies.js'\nimport {checkRequiredDependencies} from './checkRequiredDependencies.js'\nimport {checkStudioDependencyVersions} from './checkStudioDependencyVersions.js'\nimport {determineBasePath} from './determineBasePath.js'\nimport {getAutoUpdatesImportMap} from './getAutoUpdatesImportMap.js'\nimport {getStudioEnvVars} from './getStudioEnvVars.js'\nimport {handlePrereleaseVersions} from './handlePrereleaseVersions.js'\nimport {shouldAutoUpdate} from './shouldAutoUpdate.js'\nimport {type BuildOptions} from './types.js'\n\n/**\n * Build the Sanity Studio.\n *\n * @internal\n */\nexport async function buildStudio(options: BuildOptions): Promise<void> {\n const timer = getTimer()\n const {cliConfig, flags, outDir, output, workDir} = options\n\n const unattendedMode = Boolean(flags.yes)\n const defaultOutputDir = path.resolve(path.join(workDir, 'dist'))\n const outputDir = path.resolve(outDir || defaultOutputDir)\n\n await checkStudioDependencyVersions(workDir, output)\n\n // If the check resulted in a dependency install, the CLI command will be re-run,\n // thus we want to exit early\n const {installedSanityVersion} = await checkRequiredDependencies({\n cliConfig,\n output,\n workDir,\n })\n\n let autoUpdatesEnabled = options.calledFromDeploy\n ? options.autoUpdatesEnabled\n : shouldAutoUpdate({cliConfig, flags, output})\n\n let autoUpdatesImports = {}\n\n if (autoUpdatesEnabled) {\n // Get the clean version without build metadata: https://semver.org/#spec-item-10\n const cleanSanityVersion = semver.parse(installedSanityVersion)?.version\n if (!cleanSanityVersion) {\n throw new Error(`Failed to parse installed Sanity version: ${installedSanityVersion}`)\n }\n\n output.log(`${logSymbols.info} Building with auto-updates enabled`)\n\n const projectId = cliConfig?.api?.projectId\n const appId = getAppId(cliConfig)\n\n // Warn if auto updates enabled but no appId configured.\n // Skip when called from deploy, since deploy handles appId itself\n // (prompts the user and tells them to add it to config).\n if (!appId && !options.calledFromDeploy) {\n warnAboutMissingAppId({appType: 'studio', output, projectId})\n }\n\n const sanityDependencies = [\n {name: 'sanity', version: cleanSanityVersion},\n {name: '@sanity/vision', version: cleanSanityVersion},\n ]\n autoUpdatesImports = getAutoUpdatesImportMap(sanityDependencies, {appId})\n\n // Check the versions\n const {mismatched, unresolvedPrerelease} = await compareDependencyVersions(\n sanityDependencies,\n workDir,\n {appId},\n )\n\n if (unresolvedPrerelease.length > 0) {\n await handlePrereleaseVersions({output, unattendedMode, unresolvedPrerelease})\n autoUpdatesImports = {}\n autoUpdatesEnabled = false\n }\n\n if (mismatched.length > 0 && autoUpdatesEnabled) {\n const versionMismatchWarning =\n `The following local package versions are different from the versions currently served at runtime.\\n` +\n `When using auto updates, we recommend that you test locally with the same versions before deploying. \\n\\n` +\n `${mismatched.map((mod) => ` - ${mod.pkg} (local version: ${mod.installed}, runtime version: ${mod.remote})`).join('\\n')}`\n\n // If it is non-interactive or in unattended mode, we don't want to prompt\n if (isInteractive() && !unattendedMode) {\n const choice = await select({\n choices: [\n {\n name: `Upgrade local versions (recommended). You will need to run the build command again`,\n value: 'upgrade',\n },\n {\n name: `Upgrade and proceed with build`,\n value: 'upgrade-and-proceed',\n },\n {\n name: `Continue anyway`,\n value: 'continue',\n },\n {name: 'Cancel', value: 'cancel'},\n ],\n default: 'upgrade',\n message: styleText(\n 'yellow',\n `${logSymbols.warning} ${versionMismatchWarning}\\n\\nDo you want to upgrade local versions before deploying?`,\n ),\n })\n\n if (choice === 'cancel') {\n output.error('Declined to continue with build', {exit: 1})\n return\n }\n\n if (choice === 'upgrade' || choice === 'upgrade-and-proceed') {\n await upgradePackages(\n {\n packageManager: (await getPackageManagerChoice(workDir, {interactive: false})).chosen,\n packages: mismatched.map((res) => [res.pkg, res.remote]),\n },\n {output, workDir},\n )\n\n if (choice === 'upgrade') {\n return\n }\n }\n } else {\n // if non-interactive or unattended, just show the warning\n output.warn(versionMismatchWarning)\n }\n }\n }\n\n const envVarKeys = getStudioEnvVars()\n if (envVarKeys.length > 0) {\n output.log('\\nIncluding the following environment variables as part of the JavaScript bundle:')\n for (const key of envVarKeys) {\n output.log(`- ${key}`)\n }\n output.log('')\n }\n\n let shouldClean = true\n if (outputDir !== defaultOutputDir && !unattendedMode && isInteractive()) {\n shouldClean = await confirm({\n default: true,\n message: `Do you want to delete the existing directory (${outputDir}) first?`,\n })\n }\n\n // Determine base path for built studio\n const basePath = determineBasePath(cliConfig, 'studio', output)\n\n let spin: SpinnerInstance\n if (shouldClean) {\n timer.start('cleanOutputFolder')\n spin = spinner('Clean output folder').start()\n await rm(outputDir, {force: true, recursive: true})\n const cleanDuration = timer.end('cleanOutputFolder')\n spin.text = `Clean output folder (${cleanDuration.toFixed(0)}ms)`\n spin.succeed()\n }\n\n spin = spinner(`Build Sanity Studio`).start()\n\n const trace = getCliTelemetry().trace(StudioBuildTrace)\n trace.start()\n\n let importMap\n\n if (autoUpdatesEnabled) {\n importMap = {\n imports: {\n ...(await buildVendorDependencies({basePath, cwd: workDir, isApp: false, outputDir})),\n ...autoUpdatesImports,\n },\n }\n }\n\n try {\n timer.start('bundleStudio')\n\n const bundle = await buildStaticFiles({\n basePath,\n cwd: workDir,\n importMap,\n minify: Boolean(flags.minify),\n outputDir,\n reactCompiler:\n cliConfig && 'reactCompiler' in cliConfig ? cliConfig.reactCompiler : undefined,\n sourceMap: Boolean(flags['source-maps']),\n vite: cliConfig && 'vite' in cliConfig ? cliConfig.vite : undefined,\n })\n\n trace.log({\n outputSize: bundle.chunks\n .flatMap((chunk) => chunk.modules.flatMap((mod) => mod.renderedLength))\n .reduce((sum, n) => sum + n, 0),\n })\n const buildDuration = timer.end('bundleStudio')\n\n spin.text = `Build Sanity Studio (${buildDuration.toFixed(0)}ms)`\n spin.succeed()\n\n trace.complete()\n if (flags.stats) {\n output.log('\\nLargest module files:')\n output.log(formatModuleSizes(sortModulesBySize(bundle.chunks).slice(0, 15)))\n }\n } catch (error) {\n spin.fail()\n trace.error(error)\n const message = error instanceof Error ? error.message : String(error)\n buildDebug(`Failed to build Sanity Studio`, {error})\n output.error(`Failed to build Sanity Studio: ${message}`, {exit: 1})\n }\n}\n"],"names":["rm","path","styleText","getCliTelemetry","getTimer","isInteractive","confirm","logSymbols","select","spinner","semver","StudioBuildTrace","getAppId","compareDependencyVersions","formatModuleSizes","sortModulesBySize","getPackageManagerChoice","upgradePackages","warnAboutMissingAppId","buildDebug","buildStaticFiles","buildVendorDependencies","checkRequiredDependencies","checkStudioDependencyVersions","determineBasePath","getAutoUpdatesImportMap","getStudioEnvVars","handlePrereleaseVersions","shouldAutoUpdate","buildStudio","options","timer","cliConfig","flags","outDir","output","workDir","unattendedMode","Boolean","yes","defaultOutputDir","resolve","join","outputDir","installedSanityVersion","autoUpdatesEnabled","calledFromDeploy","autoUpdatesImports","cleanSanityVersion","parse","version","Error","log","info","projectId","api","appId","appType","sanityDependencies","name","mismatched","unresolvedPrerelease","length","versionMismatchWarning","map","mod","pkg","installed","remote","choice","choices","value","default","message","warning","error","exit","packageManager","interactive","chosen","packages","res","warn","envVarKeys","key","shouldClean","basePath","spin","start","force","recursive","cleanDuration","end","text","toFixed","succeed","trace","importMap","imports","cwd","isApp","bundle","minify","reactCompiler","undefined","sourceMap","vite","outputSize","chunks","flatMap","chunk","modules","renderedLength","reduce","sum","n","buildDuration","complete","stats","slice","fail","String"],"mappings":"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"}
@@ -1,102 +1,151 @@
1
- import { getCliToken, getUserConfig } from '@sanity/cli-core';
1
+ import { access } from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { getCliToken, getStudioConfig, getUserConfig, tryFindStudioConfigPath } from '@sanity/cli-core';
2
4
  import { getProjectById } from '../../services/projects.js';
3
5
  import { getCliUser, getProjectUser } from '../../services/user.js';
4
- import { findSanityModulesVersions } from '../versions/findSanityModulesVersions.js';
5
- export async function gatherDebugInfo(options) {
6
- const { cliConfig, includeSecrets, projectRoot } = options;
7
- // Gather all info in parallel where possible
8
- const [auth, globalConfig, projectConfigResult, versions] = await Promise.all([
9
- gatherAuthInfo(includeSecrets),
10
- gatherGlobalConfig(),
11
- cliConfig ? gatherProjectConfig(cliConfig) : undefined,
12
- gatherVersionsInfo(projectRoot)
13
- ]);
14
- // Gather user and project info that depend on auth
15
- const user = await gatherUserInfo(projectConfigResult, auth.hasToken);
16
- const project = await gatherProjectInfo(projectConfigResult, auth.hasToken, user);
17
- return {
18
- auth,
19
- globalConfig,
20
- project,
21
- projectConfig: projectConfigResult,
22
- user,
23
- versions
24
- };
25
- }
26
- async function gatherAuthInfo(includeSecrets) {
6
+ import { getCliVersion } from '../../util/getCliVersion.js';
7
+ import { detectCliInstallation } from '../../util/packageManager/installationInfo/index.js';
8
+ export async function gatherUserInfo(projectId) {
27
9
  const token = await getCliToken();
28
- const hasToken = Boolean(token);
29
- return {
30
- authToken: includeSecrets && token ? token : '<redacted>',
31
- hasToken,
32
- userType: 'normal'
33
- };
34
- }
35
- function gatherGlobalConfig() {
36
- return getUserConfig().all;
37
- }
38
- function gatherProjectConfig(cliConfig) {
39
- if (!cliConfig.api?.projectId) {
40
- return new Error('Missing required "api.projectId" key');
41
- }
42
- return cliConfig;
43
- }
44
- async function gatherVersionsInfo(projectRoot) {
45
- if (!projectRoot) {
46
- return undefined;
47
- }
48
- try {
49
- return await findSanityModulesVersions({
50
- cwd: projectRoot.directory
51
- });
52
- } catch {
53
- return [];
54
- }
55
- }
56
- async function gatherUserInfo(projectConfig, hasToken) {
57
- if (!hasToken) {
10
+ if (!token) {
58
11
  return new Error('Not logged in');
59
12
  }
60
13
  try {
61
- /**
62
- * If the project config has a project ID, get the user for the project
63
- * Otherwise, get the user for the global client
64
- */ const userInfo = !projectConfig || projectConfig instanceof Error || !projectConfig.api?.projectId ? await getCliUser() : await getProjectUser(projectConfig.api.projectId);
14
+ const userInfo = projectId ? await getProjectUser(projectId) : await getCliUser();
65
15
  return {
66
16
  email: userInfo.email,
67
17
  id: userInfo.id,
68
- name: userInfo.name
18
+ name: userInfo.name,
19
+ provider: userInfo.provider
69
20
  };
70
21
  } catch (error) {
71
22
  return error instanceof Error ? error : new Error('Failed to fetch user info');
72
23
  }
73
24
  }
74
- async function gatherProjectInfo(projectConfig, hasToken, user) {
75
- if (!hasToken || !projectConfig || projectConfig instanceof Error) {
76
- return null;
25
+ export async function gatherAuthInfo(includeSecrets) {
26
+ const token = await getCliToken();
27
+ const hasToken = Boolean(token);
28
+ const config = getUserConfig();
29
+ const authType = config.get('authType');
30
+ return {
31
+ authToken: token ? includeSecrets ? token : '<redacted>' : undefined,
32
+ hasToken,
33
+ userType: typeof authType === 'string' ? authType : 'normal'
34
+ };
35
+ }
36
+ export async function gatherCliInfo() {
37
+ const [version, installation] = await Promise.all([
38
+ getCliVersion(),
39
+ detectCliInstallation()
40
+ ]);
41
+ const { packageManager, resolvedFrom } = installation.currentExecution;
42
+ let installContext;
43
+ switch(resolvedFrom){
44
+ case 'global':
45
+ {
46
+ installContext = packageManager ? `globally (${packageManager})` : 'globally';
47
+ break;
48
+ }
49
+ case 'local':
50
+ {
51
+ installContext = 'locally';
52
+ break;
53
+ }
54
+ case 'npx':
55
+ {
56
+ installContext = 'via npx';
57
+ break;
58
+ }
59
+ default:
60
+ {
61
+ installContext = 'unknown';
62
+ }
63
+ }
64
+ return {
65
+ installContext,
66
+ version
67
+ };
68
+ }
69
+ export async function gatherProjectInfo(projectDirectory) {
70
+ if (!projectDirectory) {
71
+ return undefined;
77
72
  }
78
- const projectId = projectConfig.api?.projectId;
79
- if (!projectId) {
80
- return null;
73
+ const [cliConfigName, studioConfigFullPath] = await Promise.all([
74
+ findCliConfigFile(projectDirectory),
75
+ tryFindStudioConfigPath(projectDirectory)
76
+ ]);
77
+ return {
78
+ cliConfigPath: cliConfigName,
79
+ rootPath: projectDirectory,
80
+ studioConfigPath: studioConfigFullPath ? path.basename(studioConfigFullPath) : undefined
81
+ };
82
+ }
83
+ export async function gatherStudioWorkspaces(projectDirectory) {
84
+ const rawConfig = await getStudioConfig(projectDirectory, {
85
+ resolvePlugins: false
86
+ });
87
+ if (Array.isArray(rawConfig)) {
88
+ return rawConfig.map((ws)=>({
89
+ dataset: ws.dataset,
90
+ name: ws.name,
91
+ projectId: ws.projectId
92
+ }));
81
93
  }
82
- try {
83
- const projectInfo = await getProjectById(projectId);
84
- if (!projectInfo) {
85
- return new Error(`Project specified in configuration (${projectId}) does not exist in API`);
94
+ return [
95
+ {
96
+ dataset: rawConfig.dataset,
97
+ name: rawConfig.name,
98
+ projectId: rawConfig.projectId
99
+ }
100
+ ];
101
+ }
102
+ export async function gatherResolvedWorkspaces(projectDirectory, userId) {
103
+ // resolvePlugins: true goes through getStudioWorkspaces() which calls resolveConfig()
104
+ // from the sanity package. resolveConfig() always returns an array of workspaces,
105
+ // so resolvedConfigSchema (z.array(...)) is guaranteed to match.
106
+ const resolvedConfig = await getStudioConfig(projectDirectory, {
107
+ resolvePlugins: true
108
+ });
109
+ const projectMap = await fetchRolesByProject(resolvedConfig, userId);
110
+ return resolvedConfig.map((ws)=>({
111
+ name: ws.name,
112
+ roles: projectMap.get(ws.projectId) ?? [],
113
+ title: ws.title
114
+ }));
115
+ }
116
+ async function findCliConfigFile(directory) {
117
+ for (const name of [
118
+ 'sanity.cli.ts',
119
+ 'sanity.cli.js'
120
+ ]){
121
+ try {
122
+ await access(path.join(directory, name));
123
+ return name;
124
+ } catch {
125
+ // File doesn't exist, try next
86
126
  }
87
- const userId = user instanceof Error || !user ? null : user.id;
88
- const member = (projectInfo.members || []).find((member)=>member.id === userId);
89
- return {
90
- displayName: projectInfo.displayName,
91
- id: projectId,
92
- // @ts-expect-error - Incorrect type definition in @sanity/client
93
- userRoles: member && member.roles ? member.roles.map((role)=>role.name) : [
94
- '<none>'
95
- ]
96
- };
97
- } catch (error) {
98
- return error instanceof Error ? error : new Error('Failed to fetch project info');
99
127
  }
128
+ return undefined;
129
+ }
130
+ async function fetchRolesByProject(workspaces, userId) {
131
+ const projectMap = new Map();
132
+ if (!userId) return projectMap;
133
+ const projectIds = [
134
+ ...new Set(workspaces.map((ws)=>ws.projectId))
135
+ ];
136
+ await Promise.all(projectIds.map(async (projectId)=>{
137
+ try {
138
+ const project = await getProjectById(projectId);
139
+ if (!project) return;
140
+ const member = (project.members || []).find((m)=>m.id === userId);
141
+ // @ts-expect-error - Incorrect type definition in @sanity/client
142
+ const roles = member?.roles?.map((r)=>r.name) ?? [];
143
+ projectMap.set(projectId, roles);
144
+ } catch {
145
+ // Project not accessible, skip roles
146
+ }
147
+ }));
148
+ return projectMap;
100
149
  }
101
150
 
102
151
  //# sourceMappingURL=gatherDebugInfo.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/debug/gatherDebugInfo.ts"],"sourcesContent":["import {type CliConfig, getCliToken, getUserConfig, type ProjectRootResult} from '@sanity/cli-core'\n\nimport {getProjectById} from '../../services/projects.js'\nimport {getCliUser, getProjectUser} from '../../services/user.js'\nimport {findSanityModulesVersions} from '../versions/findSanityModulesVersions.js'\nimport {type ModuleVersionResult} from '../versions/types.js'\nimport {\n type AuthInfo,\n type DebugInfo,\n type DebugInfoOptions,\n type ProjectInfo,\n type UserInfo,\n} from './types.js'\n\nexport async function gatherDebugInfo(options: DebugInfoOptions): Promise<DebugInfo> {\n const {cliConfig, includeSecrets, projectRoot} = options\n\n // Gather all info in parallel where possible\n const [auth, globalConfig, projectConfigResult, versions] = await Promise.all([\n gatherAuthInfo(includeSecrets),\n gatherGlobalConfig(),\n cliConfig ? gatherProjectConfig(cliConfig) : undefined,\n gatherVersionsInfo(projectRoot),\n ])\n\n // Gather user and project info that depend on auth\n const user = await gatherUserInfo(projectConfigResult, auth.hasToken)\n const project = await gatherProjectInfo(projectConfigResult, auth.hasToken, user)\n\n return {\n auth,\n globalConfig,\n project,\n projectConfig: projectConfigResult,\n user,\n versions,\n }\n}\n\nasync function gatherAuthInfo(includeSecrets: boolean): Promise<AuthInfo> {\n const token = await getCliToken()\n const hasToken = Boolean(token)\n\n return {\n authToken: includeSecrets && token ? token : '<redacted>',\n hasToken,\n userType: 'normal',\n }\n}\n\nfunction gatherGlobalConfig(): Record<string, unknown> {\n return getUserConfig().all\n}\n\nfunction gatherProjectConfig(cliConfig: CliConfig): CliConfig | Error {\n if (!cliConfig.api?.projectId) {\n return new Error('Missing required \"api.projectId\" key')\n }\n\n return cliConfig\n}\n\nasync function gatherVersionsInfo(\n projectRoot: ProjectRootResult | undefined,\n): Promise<ModuleVersionResult[] | undefined> {\n if (!projectRoot) {\n return undefined\n }\n\n try {\n return await findSanityModulesVersions({cwd: projectRoot.directory})\n } catch {\n return []\n }\n}\n\nasync function gatherUserInfo(\n projectConfig: CliConfig | Error | undefined,\n hasToken: boolean,\n): Promise<Error | UserInfo | null> {\n if (!hasToken) {\n return new Error('Not logged in')\n }\n\n try {\n /**\n * If the project config has a project ID, get the user for the project\n * Otherwise, get the user for the global client\n */\n const userInfo =\n !projectConfig || projectConfig instanceof Error || !projectConfig.api?.projectId\n ? await getCliUser()\n : await getProjectUser(projectConfig.api.projectId)\n\n return {\n email: userInfo.email,\n id: userInfo.id,\n name: userInfo.name,\n }\n } catch (error) {\n return error instanceof Error ? error : new Error('Failed to fetch user info')\n }\n}\n\nasync function gatherProjectInfo(\n projectConfig: CliConfig | Error | undefined,\n hasToken: boolean,\n user: Error | UserInfo | null,\n): Promise<Error | ProjectInfo | null> {\n if (!hasToken || !projectConfig || projectConfig instanceof Error) {\n return null\n }\n\n const projectId = projectConfig.api?.projectId\n if (!projectId) {\n return null\n }\n\n try {\n const projectInfo = await getProjectById(projectId)\n\n if (!projectInfo) {\n return new Error(`Project specified in configuration (${projectId}) does not exist in API`)\n }\n\n const userId = user instanceof Error || !user ? null : user.id\n const member = (projectInfo.members || []).find((member) => member.id === userId)\n\n return {\n displayName: projectInfo.displayName,\n id: projectId,\n // @ts-expect-error - Incorrect type definition in @sanity/client\n userRoles: member && member.roles ? member.roles.map((role) => role.name) : ['<none>'],\n }\n } catch (error) {\n return error instanceof Error ? error : new Error('Failed to fetch project info')\n }\n}\n"],"names":["getCliToken","getUserConfig","getProjectById","getCliUser","getProjectUser","findSanityModulesVersions","gatherDebugInfo","options","cliConfig","includeSecrets","projectRoot","auth","globalConfig","projectConfigResult","versions","Promise","all","gatherAuthInfo","gatherGlobalConfig","gatherProjectConfig","undefined","gatherVersionsInfo","user","gatherUserInfo","hasToken","project","gatherProjectInfo","projectConfig","token","Boolean","authToken","userType","api","projectId","Error","cwd","directory","userInfo","email","id","name","error","projectInfo","userId","member","members","find","displayName","userRoles","roles","map","role"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/actions/debug/gatherDebugInfo.ts"],"sourcesContent":["import {access} from 'node:fs/promises'\nimport path from 'node:path'\n\nimport {\n getCliToken,\n getStudioConfig,\n getUserConfig,\n tryFindStudioConfigPath,\n} from '@sanity/cli-core'\n\nimport {getProjectById} from '../../services/projects.js'\nimport {getCliUser, getProjectUser} from '../../services/user.js'\nimport {getCliVersion} from '../../util/getCliVersion.js'\nimport {detectCliInstallation} from '../../util/packageManager/installationInfo/index.js'\nimport {\n type AuthInfo,\n type CliInfo,\n type ProjectInfo,\n type ResolvedWorkspace,\n type StudioWorkspace,\n type UserInfo,\n} from './types.js'\n\nexport async function gatherUserInfo(projectId: string | undefined): Promise<Error | UserInfo> {\n const token = await getCliToken()\n if (!token) {\n return new Error('Not logged in')\n }\n\n try {\n const userInfo = projectId ? await getProjectUser(projectId) : await getCliUser()\n\n return {\n email: userInfo.email,\n id: userInfo.id,\n name: userInfo.name,\n provider: userInfo.provider,\n }\n } catch (error) {\n return error instanceof Error ? error : new Error('Failed to fetch user info')\n }\n}\n\nexport async function gatherAuthInfo(includeSecrets: boolean): Promise<AuthInfo> {\n const token = await getCliToken()\n const hasToken = Boolean(token)\n const config = getUserConfig()\n const authType = config.get('authType')\n\n return {\n authToken: token ? (includeSecrets ? token : '<redacted>') : undefined,\n hasToken,\n userType: typeof authType === 'string' ? authType : 'normal',\n }\n}\n\nexport async function gatherCliInfo(): Promise<CliInfo> {\n const [version, installation] = await Promise.all([getCliVersion(), detectCliInstallation()])\n\n const {packageManager, resolvedFrom} = installation.currentExecution\n\n let installContext: string\n switch (resolvedFrom) {\n case 'global': {\n installContext = packageManager ? `globally (${packageManager})` : 'globally'\n break\n }\n case 'local': {\n installContext = 'locally'\n break\n }\n case 'npx': {\n installContext = 'via npx'\n break\n }\n default: {\n installContext = 'unknown'\n }\n }\n\n return {installContext, version}\n}\n\nexport async function gatherProjectInfo(\n projectDirectory: string | undefined,\n): Promise<ProjectInfo | undefined> {\n if (!projectDirectory) {\n return undefined\n }\n\n const [cliConfigName, studioConfigFullPath] = await Promise.all([\n findCliConfigFile(projectDirectory),\n tryFindStudioConfigPath(projectDirectory),\n ])\n\n return {\n cliConfigPath: cliConfigName,\n rootPath: projectDirectory,\n studioConfigPath: studioConfigFullPath ? path.basename(studioConfigFullPath) : undefined,\n }\n}\n\nexport async function gatherStudioWorkspaces(projectDirectory: string): Promise<StudioWorkspace[]> {\n const rawConfig = await getStudioConfig(projectDirectory, {resolvePlugins: false})\n\n if (Array.isArray(rawConfig)) {\n return rawConfig.map((ws) => ({\n dataset: ws.dataset,\n name: ws.name,\n projectId: ws.projectId,\n }))\n }\n\n return [\n {\n dataset: rawConfig.dataset,\n name: rawConfig.name,\n projectId: rawConfig.projectId,\n },\n ]\n}\n\nexport async function gatherResolvedWorkspaces(\n projectDirectory: string,\n userId: string | undefined,\n): Promise<ResolvedWorkspace[]> {\n // resolvePlugins: true goes through getStudioWorkspaces() which calls resolveConfig()\n // from the sanity package. resolveConfig() always returns an array of workspaces,\n // so resolvedConfigSchema (z.array(...)) is guaranteed to match.\n const resolvedConfig = await getStudioConfig(projectDirectory, {resolvePlugins: true})\n\n const projectMap = await fetchRolesByProject(resolvedConfig, userId)\n\n return resolvedConfig.map((ws) => ({\n name: ws.name,\n roles: projectMap.get(ws.projectId) ?? [],\n title: ws.title,\n }))\n}\n\nasync function findCliConfigFile(directory: string): Promise<string | undefined> {\n for (const name of ['sanity.cli.ts', 'sanity.cli.js']) {\n try {\n await access(path.join(directory, name))\n return name\n } catch {\n // File doesn't exist, try next\n }\n }\n return undefined\n}\n\nasync function fetchRolesByProject(\n workspaces: {projectId: string}[],\n userId: string | undefined,\n): Promise<Map<string, string[]>> {\n const projectMap = new Map<string, string[]>()\n if (!userId) return projectMap\n\n const projectIds = [...new Set(workspaces.map((ws) => ws.projectId))]\n await Promise.all(\n projectIds.map(async (projectId) => {\n try {\n const project = await getProjectById(projectId)\n if (!project) return\n const member = (project.members || []).find((m) => m.id === userId)\n // @ts-expect-error - Incorrect type definition in @sanity/client\n const roles: string[] = member?.roles?.map((r) => r.name) ?? []\n projectMap.set(projectId, roles)\n } catch {\n // Project not accessible, skip roles\n }\n }),\n )\n return projectMap\n}\n"],"names":["access","path","getCliToken","getStudioConfig","getUserConfig","tryFindStudioConfigPath","getProjectById","getCliUser","getProjectUser","getCliVersion","detectCliInstallation","gatherUserInfo","projectId","token","Error","userInfo","email","id","name","provider","error","gatherAuthInfo","includeSecrets","hasToken","Boolean","config","authType","get","authToken","undefined","userType","gatherCliInfo","version","installation","Promise","all","packageManager","resolvedFrom","currentExecution","installContext","gatherProjectInfo","projectDirectory","cliConfigName","studioConfigFullPath","findCliConfigFile","cliConfigPath","rootPath","studioConfigPath","basename","gatherStudioWorkspaces","rawConfig","resolvePlugins","Array","isArray","map","ws","dataset","gatherResolvedWorkspaces","userId","resolvedConfig","projectMap","fetchRolesByProject","roles","title","directory","join","workspaces","Map","projectIds","Set","project","member","members","find","m","r","set"],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import { inspect, styleText } from 'node:util';
2
+ export function sectionHeader(title) {
3
+ return styleText('bold', `${title}:`);
4
+ }
5
+ export function formatKeyValue(key, value, options) {
6
+ const indent = options?.indent ?? 2;
7
+ const padTo = options?.padTo ?? 0;
8
+ const paddedKey = `${key}:`.padEnd(padTo > 0 ? padTo + 1 : key.length + 1);
9
+ const formattedValue = formatValue(value);
10
+ return `${' '.repeat(indent)}${styleText('dim', paddedKey)} ${formattedValue}`;
11
+ }
12
+ function formatValue(value) {
13
+ if (Array.isArray(value)) {
14
+ return `[ ${value.map((v)=>JSON.stringify(v)).join(', ')} ]`;
15
+ }
16
+ if (typeof value === 'string') {
17
+ return value;
18
+ }
19
+ return inspect(value, {
20
+ colors: true,
21
+ depth: Infinity
22
+ });
23
+ }
24
+
25
+ //# sourceMappingURL=output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/actions/debug/output.ts"],"sourcesContent":["import {inspect, styleText} from 'node:util'\n\nexport function sectionHeader(title: string): string {\n return styleText('bold', `${title}:`)\n}\n\nexport function formatKeyValue(\n key: string,\n value: unknown,\n options?: {indent?: number; padTo?: number},\n): string {\n const indent = options?.indent ?? 2\n const padTo = options?.padTo ?? 0\n const paddedKey = `${key}:`.padEnd(padTo > 0 ? padTo + 1 : key.length + 1)\n const formattedValue = formatValue(value)\n return `${' '.repeat(indent)}${styleText('dim', paddedKey)} ${formattedValue}`\n}\n\nfunction formatValue(value: unknown): string {\n if (Array.isArray(value)) {\n return `[ ${value.map((v) => JSON.stringify(v)).join(', ')} ]`\n }\n if (typeof value === 'string') {\n return value\n }\n return inspect(value, {colors: true, depth: Infinity})\n}\n"],"names":["inspect","styleText","sectionHeader","title","formatKeyValue","key","value","options","indent","padTo","paddedKey","padEnd","length","formattedValue","formatValue","repeat","Array","isArray","map","v","JSON","stringify","join","colors","depth","Infinity"],"mappings":"AAAA,SAAQA,OAAO,EAAEC,SAAS,QAAO,YAAW;AAE5C,OAAO,SAASC,cAAcC,KAAa;IACzC,OAAOF,UAAU,QAAQ,GAAGE,MAAM,CAAC,CAAC;AACtC;AAEA,OAAO,SAASC,eACdC,GAAW,EACXC,KAAc,EACdC,OAA2C;IAE3C,MAAMC,SAASD,SAASC,UAAU;IAClC,MAAMC,QAAQF,SAASE,SAAS;IAChC,MAAMC,YAAY,GAAGL,IAAI,CAAC,CAAC,CAACM,MAAM,CAACF,QAAQ,IAAIA,QAAQ,IAAIJ,IAAIO,MAAM,GAAG;IACxE,MAAMC,iBAAiBC,YAAYR;IACnC,OAAO,GAAG,IAAIS,MAAM,CAACP,UAAUP,UAAU,OAAOS,WAAW,CAAC,EAAEG,gBAAgB;AAChF;AAEA,SAASC,YAAYR,KAAc;IACjC,IAAIU,MAAMC,OAAO,CAACX,QAAQ;QACxB,OAAO,CAAC,EAAE,EAAEA,MAAMY,GAAG,CAAC,CAACC,IAAMC,KAAKC,SAAS,CAACF,IAAIG,IAAI,CAAC,MAAM,EAAE,CAAC;IAChE;IACA,IAAI,OAAOhB,UAAU,UAAU;QAC7B,OAAOA;IACT;IACA,OAAON,QAAQM,OAAO;QAACiB,QAAQ;QAAMC,OAAOC;IAAQ;AACtD"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/debug/types.ts"],"sourcesContent":["import {type CliConfig, type ProjectRootResult} from '@sanity/cli-core'\n\nimport {type ModuleVersionResult} from '../versions/types.js'\n\nexport interface DebugInfoOptions {\n cliConfig: CliConfig | undefined\n includeSecrets: boolean\n projectRoot: ProjectRootResult | undefined\n}\n\nexport interface UserInfo {\n email: string\n id: string\n name: string\n}\n\nexport interface ProjectInfo {\n displayName: string\n id: string\n userRoles: string[]\n}\n\nexport interface AuthInfo {\n authToken: string\n hasToken: boolean\n userType: string\n}\n\nexport interface DebugInfo {\n auth: AuthInfo\n globalConfig: Record<string, unknown>\n project: Error | ProjectInfo | null\n projectConfig: CliConfig | Error | undefined\n user: Error | UserInfo | null\n versions: ModuleVersionResult[] | undefined\n}\n"],"names":[],"mappings":"AA4BA,WAOC"}
1
+ {"version":3,"sources":["../../../src/actions/debug/types.ts"],"sourcesContent":["export interface UserInfo {\n email: string\n id: string\n name: string\n provider: string\n}\n\nexport interface AuthInfo {\n authToken: string | undefined\n hasToken: boolean\n userType: string\n}\n\nexport interface CliInfo {\n installContext: string\n version: string\n}\n\nexport interface ProjectInfo {\n cliConfigPath: string | undefined\n rootPath: string\n studioConfigPath: string | undefined\n}\n\nexport interface StudioWorkspace {\n dataset: string\n name: string | undefined\n projectId: string\n}\n\nexport interface ResolvedWorkspace {\n name: string\n roles: string[]\n title: string\n}\n"],"names":[],"mappings":"AA8BA,WAIC"}
@@ -12,10 +12,10 @@ const NO_EDITORS_DETECTED_MESSAGE = `Couldn't auto-configure Sanity MCP server f
12
12
  * Main MCP setup orchestration
13
13
  * Opt-out by default: runs automatically unless skip option is set
14
14
  */ export async function setupMCP(options) {
15
- const { explicit = false, skip = false } = options ?? {};
15
+ const { explicit = false, mode = 'prompt' } = options ?? {};
16
16
  // 1. Check for explicit opt-out
17
- if (skip) {
18
- ux.warn('Skipping MCP configuration due to --no-mcp flag');
17
+ if (mode === 'skip') {
18
+ mcpDebug('Skipping MCP configuration (mode: skip)');
19
19
  return {
20
20
  alreadyConfiguredEditors: [],
21
21
  configuredEditors: [],
@@ -57,8 +57,8 @@ const NO_EDITORS_DETECTED_MESSAGE = `Couldn't auto-configure Sanity MCP server f
57
57
  }
58
58
  // Non-actionable editors are already configured with valid credentials
59
59
  const alreadyConfiguredEditors = editors.filter((e)=>!actionable.includes(e)).map((e)=>e.name);
60
- // 5. Prompt user (shows only actionable editors, annotates auth issues)
61
- const selected = await promptForMCPSetup(actionable);
60
+ // 5. Select editors to configure prompt interactively or auto-select all
61
+ const selected = mode === 'auto' ? actionable : await promptForMCPSetup(actionable);
62
62
  if (!selected || selected.length === 0) {
63
63
  // User deselected all editors
64
64
  ux.stdout('MCP configuration skipped');
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/mcp/setupMCP.ts"],"sourcesContent":["import {ux} from '@oclif/core'\nimport {subdebug} from '@sanity/cli-core'\nimport {logSymbols} from '@sanity/cli-core/ux'\n\nimport {createMCPToken, MCP_SERVER_URL} from '../../services/mcp.js'\nimport {detectAvailableEditors} from './detectAvailableEditors.js'\nimport {type EditorName} from './editorConfigs.js'\nimport {promptForMCPSetup} from './promptForMCPSetup.js'\nimport {validateEditorTokens} from './validateEditorTokens.js'\nimport {writeMCPConfig} from './writeMCPConfig.js'\n\nconst mcpDebug = subdebug('mcp:setup')\n\nconst NO_EDITORS_DETECTED_MESSAGE = `Couldn't auto-configure Sanity MCP server for your editor. Visit ${MCP_SERVER_URL} for setup instructions.`\n\ninterface MCPSetupOptions {\n /**\n * Whether the user explicitly requested MCP configuration (e.g. `sanity mcp configure`).\n * When true, shows status messages even when there's nothing to do.\n * When false/undefined (e.g. called from `sanity init`), stays quiet.\n */\n explicit?: boolean\n\n /**\n * If true, skip MCP configuration entirely (e.g. --no-mcp flag).\n */\n skip?: boolean\n}\n\ninterface MCPSetupResult {\n /** Editors that were already configured with valid credentials (nothing to do) */\n alreadyConfiguredEditors: EditorName[]\n configuredEditors: EditorName[]\n detectedEditors: EditorName[]\n skipped: boolean\n\n error?: Error\n}\n\n/**\n * Main MCP setup orchestration\n * Opt-out by default: runs automatically unless skip option is set\n */\nexport async function setupMCP(options?: MCPSetupOptions): Promise<MCPSetupResult> {\n const {explicit = false, skip = false} = options ?? {}\n\n // 1. Check for explicit opt-out\n if (skip) {\n ux.warn('Skipping MCP configuration due to --no-mcp flag')\n return {\n alreadyConfiguredEditors: [],\n configuredEditors: [],\n detectedEditors: [],\n skipped: true,\n }\n }\n\n // 2. Detect available editors (filters out unparseable configs)\n const editors = await detectAvailableEditors()\n const detectedEditors = editors.map((e) => e.name)\n\n mcpDebug('Detected %d editors: %s', detectedEditors.length, detectedEditors)\n\n if (editors.length === 0) {\n if (explicit) {\n ux.warn(NO_EDITORS_DETECTED_MESSAGE)\n }\n return {\n alreadyConfiguredEditors: [],\n configuredEditors: [],\n detectedEditors,\n skipped: true,\n }\n }\n\n // 3. Validate existing tokens against the Sanity API\n await validateEditorTokens(editors)\n\n // 4. Check if there's anything actionable\n const actionable = editors.filter((e) => !e.configured || e.authStatus !== 'valid')\n\n if (actionable.length === 0) {\n mcpDebug('All editors configured with valid credentials')\n const alreadyConfiguredEditors = editors\n .filter((e) => e.configured && e.authStatus === 'valid')\n .map((e) => e.name)\n if (explicit) {\n ux.stdout(`${logSymbols.success} All detected editors are already configured`)\n }\n return {\n alreadyConfiguredEditors,\n configuredEditors: [],\n detectedEditors,\n skipped: true,\n }\n }\n\n // Non-actionable editors are already configured with valid credentials\n const alreadyConfiguredEditors = editors.filter((e) => !actionable.includes(e)).map((e) => e.name)\n\n // 5. Prompt user (shows only actionable editors, annotates auth issues)\n const selected = await promptForMCPSetup(actionable)\n\n if (!selected || selected.length === 0) {\n // User deselected all editors\n ux.stdout('MCP configuration skipped')\n return {\n alreadyConfiguredEditors,\n configuredEditors: [],\n detectedEditors,\n skipped: true,\n }\n }\n\n // 6. Get a token — reuse a valid existing one or create a new one\n let token: string | undefined\n\n // Look for an existing valid token we can reuse\n const validEditor = editors.find((e) => e.authStatus === 'valid' && e.existingToken)\n if (validEditor?.existingToken) {\n mcpDebug('Reusing valid token from %s', validEditor.name)\n token = validEditor.existingToken\n }\n\n // Fall back to creating a new token\n if (!token) {\n try {\n token = await createMCPToken()\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error))\n mcpDebug('Error creating MCP token', error)\n ux.warn(`Could not configure MCP: ${err.message}`)\n ux.warn('You can set up MCP manually later using https://mcp.sanity.io')\n return {\n alreadyConfiguredEditors,\n configuredEditors: [],\n detectedEditors,\n error: err,\n skipped: false,\n }\n }\n }\n\n // 7. Write configs for each selected editor\n const configuredEditors: EditorName[] = []\n try {\n for (const editor of selected) {\n await writeMCPConfig(editor, token)\n configuredEditors.push(editor.name)\n }\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error))\n mcpDebug('Error writing MCP config', error)\n ux.warn(`Could not configure MCP: ${err.message}`)\n ux.warn('You can set up MCP manually later using https://mcp.sanity.io')\n return {\n alreadyConfiguredEditors,\n configuredEditors,\n detectedEditors,\n error: err,\n skipped: false,\n }\n }\n\n ux.stdout(`${logSymbols.success} MCP configured for ${configuredEditors.join(', ')}`)\n\n return {\n alreadyConfiguredEditors,\n configuredEditors,\n detectedEditors,\n skipped: false,\n }\n}\n"],"names":["ux","subdebug","logSymbols","createMCPToken","MCP_SERVER_URL","detectAvailableEditors","promptForMCPSetup","validateEditorTokens","writeMCPConfig","mcpDebug","NO_EDITORS_DETECTED_MESSAGE","setupMCP","options","explicit","skip","warn","alreadyConfiguredEditors","configuredEditors","detectedEditors","skipped","editors","map","e","name","length","actionable","filter","configured","authStatus","stdout","success","includes","selected","token","validEditor","find","existingToken","error","err","Error","String","message","editor","push","join"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/actions/mcp/setupMCP.ts"],"sourcesContent":["import {ux} from '@oclif/core'\nimport {subdebug} from '@sanity/cli-core'\nimport {logSymbols} from '@sanity/cli-core/ux'\n\nimport {createMCPToken, MCP_SERVER_URL} from '../../services/mcp.js'\nimport {detectAvailableEditors} from './detectAvailableEditors.js'\nimport {type EditorName} from './editorConfigs.js'\nimport {promptForMCPSetup} from './promptForMCPSetup.js'\nimport {validateEditorTokens} from './validateEditorTokens.js'\nimport {writeMCPConfig} from './writeMCPConfig.js'\n\nconst mcpDebug = subdebug('mcp:setup')\n\nconst NO_EDITORS_DETECTED_MESSAGE = `Couldn't auto-configure Sanity MCP server for your editor. Visit ${MCP_SERVER_URL} for setup instructions.`\n\ninterface MCPSetupOptions {\n /**\n * Whether the user explicitly requested MCP configuration (e.g. `sanity mcp configure`).\n * When true, shows status messages even when there's nothing to do.\n * When false/undefined (e.g. called from `sanity init`), stays quiet.\n */\n explicit?: boolean\n\n /**\n * Controls how MCP setup behaves:\n * - 'prompt': Ask the user which editors to configure (default)\n * - 'auto': Auto-configure all detected editors without prompting\n * - 'skip': Skip MCP configuration entirely\n */\n mode?: 'auto' | 'prompt' | 'skip'\n}\n\ninterface MCPSetupResult {\n /** Editors that were already configured with valid credentials (nothing to do) */\n alreadyConfiguredEditors: EditorName[]\n configuredEditors: EditorName[]\n detectedEditors: EditorName[]\n skipped: boolean\n\n error?: Error\n}\n\n/**\n * Main MCP setup orchestration\n * Opt-out by default: runs automatically unless skip option is set\n */\nexport async function setupMCP(options?: MCPSetupOptions): Promise<MCPSetupResult> {\n const {explicit = false, mode = 'prompt'} = options ?? {}\n\n // 1. Check for explicit opt-out\n if (mode === 'skip') {\n mcpDebug('Skipping MCP configuration (mode: skip)')\n return {\n alreadyConfiguredEditors: [],\n configuredEditors: [],\n detectedEditors: [],\n skipped: true,\n }\n }\n\n // 2. Detect available editors (filters out unparseable configs)\n const editors = await detectAvailableEditors()\n const detectedEditors = editors.map((e) => e.name)\n\n mcpDebug('Detected %d editors: %s', detectedEditors.length, detectedEditors)\n\n if (editors.length === 0) {\n if (explicit) {\n ux.warn(NO_EDITORS_DETECTED_MESSAGE)\n }\n return {\n alreadyConfiguredEditors: [],\n configuredEditors: [],\n detectedEditors,\n skipped: true,\n }\n }\n\n // 3. Validate existing tokens against the Sanity API\n await validateEditorTokens(editors)\n\n // 4. Check if there's anything actionable\n const actionable = editors.filter((e) => !e.configured || e.authStatus !== 'valid')\n\n if (actionable.length === 0) {\n mcpDebug('All editors configured with valid credentials')\n const alreadyConfiguredEditors = editors\n .filter((e) => e.configured && e.authStatus === 'valid')\n .map((e) => e.name)\n if (explicit) {\n ux.stdout(`${logSymbols.success} All detected editors are already configured`)\n }\n return {\n alreadyConfiguredEditors,\n configuredEditors: [],\n detectedEditors,\n skipped: true,\n }\n }\n\n // Non-actionable editors are already configured with valid credentials\n const alreadyConfiguredEditors = editors.filter((e) => !actionable.includes(e)).map((e) => e.name)\n\n // 5. Select editors to configure prompt interactively or auto-select all\n const selected = mode === 'auto' ? actionable : await promptForMCPSetup(actionable)\n\n if (!selected || selected.length === 0) {\n // User deselected all editors\n ux.stdout('MCP configuration skipped')\n return {\n alreadyConfiguredEditors,\n configuredEditors: [],\n detectedEditors,\n skipped: true,\n }\n }\n\n // 6. Get a token — reuse a valid existing one or create a new one\n let token: string | undefined\n\n // Look for an existing valid token we can reuse\n const validEditor = editors.find((e) => e.authStatus === 'valid' && e.existingToken)\n if (validEditor?.existingToken) {\n mcpDebug('Reusing valid token from %s', validEditor.name)\n token = validEditor.existingToken\n }\n\n // Fall back to creating a new token\n if (!token) {\n try {\n token = await createMCPToken()\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error))\n mcpDebug('Error creating MCP token', error)\n ux.warn(`Could not configure MCP: ${err.message}`)\n ux.warn('You can set up MCP manually later using https://mcp.sanity.io')\n return {\n alreadyConfiguredEditors,\n configuredEditors: [],\n detectedEditors,\n error: err,\n skipped: false,\n }\n }\n }\n\n // 7. Write configs for each selected editor\n const configuredEditors: EditorName[] = []\n try {\n for (const editor of selected) {\n await writeMCPConfig(editor, token)\n configuredEditors.push(editor.name)\n }\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error))\n mcpDebug('Error writing MCP config', error)\n ux.warn(`Could not configure MCP: ${err.message}`)\n ux.warn('You can set up MCP manually later using https://mcp.sanity.io')\n return {\n alreadyConfiguredEditors,\n configuredEditors,\n detectedEditors,\n error: err,\n skipped: false,\n }\n }\n\n ux.stdout(`${logSymbols.success} MCP configured for ${configuredEditors.join(', ')}`)\n\n return {\n alreadyConfiguredEditors,\n configuredEditors,\n detectedEditors,\n skipped: false,\n }\n}\n"],"names":["ux","subdebug","logSymbols","createMCPToken","MCP_SERVER_URL","detectAvailableEditors","promptForMCPSetup","validateEditorTokens","writeMCPConfig","mcpDebug","NO_EDITORS_DETECTED_MESSAGE","setupMCP","options","explicit","mode","alreadyConfiguredEditors","configuredEditors","detectedEditors","skipped","editors","map","e","name","length","warn","actionable","filter","configured","authStatus","stdout","success","includes","selected","token","validEditor","find","existingToken","error","err","Error","String","message","editor","push","join"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/schema/getExtractOptions.ts"],"sourcesContent":["import {existsSync, statSync} from 'node:fs'\nimport {extname, join, resolve} from 'node:path'\n\nimport {type CliConfig, ProjectRootResult} from '@sanity/cli-core'\n\nimport {type ExtractSchemaCommand} from '../../commands/schema/extract.js'\n\nexport interface ExtractOptions {\n configPath: string\n enforceRequiredFields: boolean\n format: string\n outputPath: string\n watchPatterns: string[]\n workspace: string | undefined\n}\n\ninterface GetExtractionOptions {\n flags: ExtractSchemaCommand['flags']\n projectRoot: ProjectRootResult\n schemaExtraction: CliConfig['schemaExtraction']\n}\n\nexport function getExtractOptions({\n flags,\n projectRoot,\n schemaExtraction,\n}: GetExtractionOptions): ExtractOptions {\n const pathFlag = flags.path ?? schemaExtraction?.path\n let outputPath: string\n if (pathFlag) {\n const resolved = resolve(join(projectRoot.directory, pathFlag))\n const isExistingDirectory = existsSync(resolved) && statSync(resolved).isDirectory()\n\n outputPath =\n isExistingDirectory || !extname(resolved) ? join(resolved, 'schema.json') : resolved\n } else {\n outputPath = resolve(join(projectRoot.directory, 'schema.json'))\n }\n\n return {\n configPath: projectRoot.path,\n enforceRequiredFields:\n flags['enforce-required-fields'] ?? schemaExtraction?.enforceRequiredFields ?? false,\n format: flags.format ?? 'groq-type-nodes',\n outputPath,\n watchPatterns: flags['watch-patterns'] ?? schemaExtraction?.watchPatterns ?? [],\n workspace: flags.workspace ?? schemaExtraction?.workspace,\n }\n}\n"],"names":["existsSync","statSync","extname","join","resolve","getExtractOptions","flags","projectRoot","schemaExtraction","pathFlag","path","outputPath","resolved","directory","isExistingDirectory","isDirectory","configPath","enforceRequiredFields","format","watchPatterns","workspace"],"mappings":"AAAA,SAAQA,UAAU,EAAEC,QAAQ,QAAO,UAAS;AAC5C,SAAQC,OAAO,EAAEC,IAAI,EAAEC,OAAO,QAAO,YAAW;AAqBhD,OAAO,SAASC,kBAAkB,EAChCC,KAAK,EACLC,WAAW,EACXC,gBAAgB,EACK;IACrB,MAAMC,WAAWH,MAAMI,IAAI,IAAIF,kBAAkBE;IACjD,IAAIC;IACJ,IAAIF,UAAU;QACZ,MAAMG,WAAWR,QAAQD,KAAKI,YAAYM,SAAS,EAAEJ;QACrD,MAAMK,sBAAsBd,WAAWY,aAAaX,SAASW,UAAUG,WAAW;QAElFJ,aACEG,uBAAuB,CAACZ,QAAQU,YAAYT,KAAKS,UAAU,iBAAiBA;IAChF,OAAO;QACLD,aAAaP,QAAQD,KAAKI,YAAYM,SAAS,EAAE;IACnD;IAEA,OAAO;QACLG,YAAYT,YAAYG,IAAI;QAC5BO,uBACEX,KAAK,CAAC,0BAA0B,IAAIE,kBAAkBS,yBAAyB;QACjFC,QAAQZ,MAAMY,MAAM,IAAI;QACxBP;QACAQ,eAAeb,KAAK,CAAC,iBAAiB,IAAIE,kBAAkBW,iBAAiB,EAAE;QAC/EC,WAAWd,MAAMc,SAAS,IAAIZ,kBAAkBY;IAClD;AACF"}
1
+ {"version":3,"sources":["../../../src/actions/schema/getExtractOptions.ts"],"sourcesContent":["import {existsSync, statSync} from 'node:fs'\nimport {extname, join, resolve} from 'node:path'\n\nimport {type CliConfig, ProjectRootResult} from '@sanity/cli-core'\n\nimport {type ExtractSchemaCommand} from '../../commands/schemas/extract.js'\n\nexport interface ExtractOptions {\n configPath: string\n enforceRequiredFields: boolean\n format: string\n outputPath: string\n watchPatterns: string[]\n workspace: string | undefined\n}\n\ninterface GetExtractionOptions {\n flags: ExtractSchemaCommand['flags']\n projectRoot: ProjectRootResult\n schemaExtraction: CliConfig['schemaExtraction']\n}\n\nexport function getExtractOptions({\n flags,\n projectRoot,\n schemaExtraction,\n}: GetExtractionOptions): ExtractOptions {\n const pathFlag = flags.path ?? schemaExtraction?.path\n let outputPath: string\n if (pathFlag) {\n const resolved = resolve(join(projectRoot.directory, pathFlag))\n const isExistingDirectory = existsSync(resolved) && statSync(resolved).isDirectory()\n\n outputPath =\n isExistingDirectory || !extname(resolved) ? join(resolved, 'schema.json') : resolved\n } else {\n outputPath = resolve(join(projectRoot.directory, 'schema.json'))\n }\n\n return {\n configPath: projectRoot.path,\n enforceRequiredFields:\n flags['enforce-required-fields'] ?? schemaExtraction?.enforceRequiredFields ?? false,\n format: flags.format ?? 'groq-type-nodes',\n outputPath,\n watchPatterns: flags['watch-patterns'] ?? schemaExtraction?.watchPatterns ?? [],\n workspace: flags.workspace ?? schemaExtraction?.workspace,\n }\n}\n"],"names":["existsSync","statSync","extname","join","resolve","getExtractOptions","flags","projectRoot","schemaExtraction","pathFlag","path","outputPath","resolved","directory","isExistingDirectory","isDirectory","configPath","enforceRequiredFields","format","watchPatterns","workspace"],"mappings":"AAAA,SAAQA,UAAU,EAAEC,QAAQ,QAAO,UAAS;AAC5C,SAAQC,OAAO,EAAEC,IAAI,EAAEC,OAAO,QAAO,YAAW;AAqBhD,OAAO,SAASC,kBAAkB,EAChCC,KAAK,EACLC,WAAW,EACXC,gBAAgB,EACK;IACrB,MAAMC,WAAWH,MAAMI,IAAI,IAAIF,kBAAkBE;IACjD,IAAIC;IACJ,IAAIF,UAAU;QACZ,MAAMG,WAAWR,QAAQD,KAAKI,YAAYM,SAAS,EAAEJ;QACrD,MAAMK,sBAAsBd,WAAWY,aAAaX,SAASW,UAAUG,WAAW;QAElFJ,aACEG,uBAAuB,CAACZ,QAAQU,YAAYT,KAAKS,UAAU,iBAAiBA;IAChF,OAAO;QACLD,aAAaP,QAAQD,KAAKI,YAAYM,SAAS,EAAE;IACnD;IAEA,OAAO;QACLG,YAAYT,YAAYG,IAAI;QAC5BO,uBACEX,KAAK,CAAC,0BAA0B,IAAIE,kBAAkBS,yBAAyB;QACjFC,QAAQZ,MAAMY,MAAM,IAAI;QACxBP;QACAQ,eAAeb,KAAK,CAAC,iBAAiB,IAAIE,kBAAkBW,iBAAiB,EAAE;QAC/EC,WAAWd,MAAMc,SAAS,IAAIZ,kBAAkBY;IAClD;AACF"}
@@ -32,6 +32,9 @@ export class DisableBackupCommand extends SanityCommand {
32
32
  semantics: 'override'
33
33
  })
34
34
  };
35
+ static hiddenAliases = [
36
+ 'backup:disable'
37
+ ];
35
38
  async run() {
36
39
  const { args } = await this.parse(DisableBackupCommand);
37
40
  let { dataset } = args;
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/commands/backups/disable.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {Args} from '@oclif/core'\nimport {SanityCommand, subdebug} from '@sanity/cli-core'\nimport {select} from '@sanity/cli-core/ux'\nimport {type DatasetsResponse} from '@sanity/client'\n\nimport {assertDatasetExists} from '../../actions/backup/assertDatasetExist.js'\nimport {promptForProject} from '../../prompts/promptForProject.js'\nimport {setBackup} from '../../services/backup.js'\nimport {listDatasets} from '../../services/datasets.js'\nimport {getProjectIdFlag} from '../../util/sharedFlags.js'\n\nconst disableBackupDebug = subdebug('backup:disable')\n\nexport class DisableBackupCommand extends SanityCommand<typeof DisableBackupCommand> {\n static override args = {\n dataset: Args.string({\n description: 'Dataset name to disable backup for',\n required: false,\n }),\n }\n\n static override description = 'Disable backup for a dataset.'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Interactively disable backup for a dataset',\n },\n {\n command: '<%= config.bin %> <%= command.id %> production',\n description: 'Disable backup for the production dataset',\n },\n ]\n\n static override flags = {\n ...getProjectIdFlag({\n description: 'Project ID to disable backups for',\n semantics: 'override',\n }),\n }\n\n static override hiddenAliases: string[] = ['backup:disable']\n\n public async run(): Promise<void> {\n const {args} = await this.parse(DisableBackupCommand)\n let {dataset} = args\n\n const projectId = await this.getProjectId({\n fallback: () =>\n promptForProject({\n requiredPermissions: [\n {grant: 'read', permission: 'sanity.project.datasets'},\n {grant: 'update', permission: 'sanity.project.datasets'},\n ],\n }),\n })\n\n let datasets: DatasetsResponse\n\n try {\n datasets = await listDatasets(projectId)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n disableBackupDebug(`Failed to list datasets: ${message}`, error)\n this.error(`Failed to list datasets: ${message}`, {exit: 1})\n }\n\n if (datasets.length === 0) {\n this.error('No datasets found in this project.', {exit: 1})\n }\n\n if (dataset) {\n assertDatasetExists(datasets, dataset)\n } else {\n dataset = await this.promptForDataset(datasets)\n }\n\n try {\n await setBackup({dataset, projectId, status: false})\n\n this.log(`${styleText('green', `Disabled daily backups for dataset ${dataset}.\\n`)}`)\n this.log(\n `${styleText('yellow', 'Note: Existing backups will be retained according to your retention policy.\\n')}`,\n )\n\n disableBackupDebug(`Successfully disabled backup for dataset ${dataset}`)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n disableBackupDebug(`Failed to disable backup for dataset`, error)\n this.error(`Disabling dataset backup failed: ${message}`, {exit: 1})\n }\n }\n\n private async promptForDataset(datasets: DatasetsResponse): Promise<string> {\n try {\n const choices = datasets.map((dataset) => ({\n name: dataset.name,\n value: dataset.name,\n }))\n\n return select({\n choices,\n message: 'Select the dataset name:',\n })\n } catch (error) {\n const err = error as Error\n disableBackupDebug(`Error fetching datasets`, err)\n this.error(`Failed to fetch datasets:\\n${err.message}`, {exit: 1})\n }\n }\n}\n"],"names":["styleText","Args","SanityCommand","subdebug","select","assertDatasetExists","promptForProject","setBackup","listDatasets","getProjectIdFlag","disableBackupDebug","DisableBackupCommand","args","dataset","string","description","required","examples","command","flags","semantics","hiddenAliases","run","parse","projectId","getProjectId","fallback","requiredPermissions","grant","permission","datasets","error","message","Error","String","exit","length","promptForDataset","status","log","choices","map","name","value","err"],"mappings":"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"}
@@ -73,6 +73,9 @@ export class DownloadBackupCommand extends SanityCommand {
73
73
  description: 'Allows overwriting of existing backup file'
74
74
  })
75
75
  };
76
+ static hiddenAliases = [
77
+ 'backup:download'
78
+ ];
76
79
  async run() {
77
80
  const { args } = await this.parse(DownloadBackupCommand);
78
81
  let { dataset } = args;