@sanity/cli 8.0.2 → 8.1.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 (66) hide show
  1. package/README.md +4 -4
  2. package/dist/SanityHelp.js.map +1 -1
  3. package/dist/actions/backup/assertDatasetExist.js +2 -1
  4. package/dist/actions/backup/assertDatasetExist.js.map +1 -1
  5. package/dist/actions/build/buildStudio.js +3 -2
  6. package/dist/actions/build/buildStudio.js.map +1 -1
  7. package/dist/actions/build/eventListenerFactory.js +7 -6
  8. package/dist/actions/build/eventListenerFactory.js.map +1 -1
  9. package/dist/actions/build/shouldAutoUpdate.js +2 -1
  10. package/dist/actions/build/shouldAutoUpdate.js.map +1 -1
  11. package/dist/actions/cors/filterAndValidateOrigin.js +3 -2
  12. package/dist/actions/cors/filterAndValidateOrigin.js.map +1 -1
  13. package/dist/actions/deploy/createUserApplication.js +2 -1
  14. package/dist/actions/deploy/createUserApplication.js.map +1 -1
  15. package/dist/actions/deploy/deployRunner.js +3 -2
  16. package/dist/actions/deploy/deployRunner.js.map +1 -1
  17. package/dist/actions/deploy/deployStudio.js +3 -3
  18. package/dist/actions/deploy/deployStudio.js.map +1 -1
  19. package/dist/actions/deploy/findUserApplication.js +8 -7
  20. package/dist/actions/deploy/findUserApplication.js.map +1 -1
  21. package/dist/actions/dev/servers/startAppDevServer.js +2 -1
  22. package/dist/actions/dev/servers/startAppDevServer.js.map +1 -1
  23. package/dist/actions/dev/servers/startStudioDevServer.js +3 -3
  24. package/dist/actions/dev/servers/startStudioDevServer.js.map +1 -1
  25. package/dist/actions/documents/validate.js +5 -2
  26. package/dist/actions/documents/validate.js.map +1 -1
  27. package/dist/actions/init/env/createOrAppendEnvVars.js +2 -1
  28. package/dist/actions/init/env/createOrAppendEnvVars.js.map +1 -1
  29. package/dist/actions/init/env/parseAndUpdateEnvVars.js +2 -2
  30. package/dist/actions/init/env/parseAndUpdateEnvVars.js.map +1 -1
  31. package/dist/actions/init/sdkAppDependencies.js +2 -2
  32. package/dist/actions/init/sdkAppDependencies.js.map +1 -1
  33. package/dist/actions/init/studioDependencies.js +2 -2
  34. package/dist/actions/init/studioDependencies.js.map +1 -1
  35. package/dist/actions/scaffold/scaffoldProject.js +11 -6
  36. package/dist/actions/scaffold/scaffoldProject.js.map +1 -1
  37. package/dist/actions/schema/extractSchema.js +2 -2
  38. package/dist/actions/schema/extractSchema.js.map +1 -1
  39. package/dist/actions/schema/extractSchemaWatcher.js +2 -1
  40. package/dist/actions/schema/extractSchemaWatcher.js.map +1 -1
  41. package/dist/actions/undeploy/runUndeploy.js +2 -2
  42. package/dist/actions/undeploy/runUndeploy.js.map +1 -1
  43. package/dist/commands/backups/list.js +5 -8
  44. package/dist/commands/backups/list.js.map +1 -1
  45. package/dist/commands/datasets/copy.js +5 -7
  46. package/dist/commands/datasets/copy.js.map +1 -1
  47. package/dist/commands/docs/search.js +2 -2
  48. package/dist/commands/docs/search.js.map +1 -1
  49. package/dist/commands/mcp/configure.js +2 -2
  50. package/dist/commands/mcp/configure.js.map +1 -1
  51. package/dist/commands/new.js +1 -2
  52. package/dist/commands/new.js.map +1 -1
  53. package/dist/commands/typegen/generate.js +6 -6
  54. package/dist/commands/typegen/generate.js.map +1 -1
  55. package/dist/services/assets.js +1 -1
  56. package/dist/services/assets.js.map +1 -1
  57. package/dist/services/mintProject.js +27 -3
  58. package/dist/services/mintProject.js.map +1 -1
  59. package/dist/util/appId.js +2 -1
  60. package/dist/util/appId.js.map +1 -1
  61. package/dist/util/dates.js +125 -0
  62. package/dist/util/dates.js.map +1 -0
  63. package/dist/util/getCliVersion.js +1 -11
  64. package/dist/util/getCliVersion.js.map +1 -1
  65. package/oclif.manifest.json +2 -2
  66. package/package.json +5 -8
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/deploy/deployStudio.ts"],"sourcesContent":["import {basename, dirname} from 'node:path'\nimport {styleText} from 'node:util'\nimport {createGzip, type Gzip} from 'node:zlib'\n\nimport {formatSchemaValidation, SchemaExtractionError} from '@sanity/cli-build/_internal/extract'\nimport {exitCodes} from '@sanity/cli-core'\nimport {spinner} from '@sanity/cli-core/ux'\nimport {\n type BrettAccess,\n type BrettWorkspace,\n createStudio,\n deployWorkbenchApp,\n getApplicationUrl,\n getWorkbench,\n toWorkbenchPayload,\n} from '@sanity/workbench-cli/deploy'\nimport {type StudioManifest} from 'sanity'\nimport {pack} from 'tar-fs'\n\nimport {createDeployment, type UserApplication} from '../../services/userApplications.js'\nimport {getAppId} from '../../util/appId.js'\nimport {NO_ORGANIZATION_ID, NO_PROJECT_ID} from '../../util/errorMessages.js'\nimport {buildStudio} from '../build/buildStudio.js'\nimport {readIconFromPath} from '../manifest/extractCoreAppManifest.js'\nimport {createStudioUserApplication} from './createUserApplication.js'\nimport {\n checkAutoUpdates,\n checkBuild,\n checkPackageVersion,\n checkStudioTarget,\n type DeployCheckReporter,\n verifyOutputDir,\n} from './deployChecks.js'\nimport {deployDebug} from './deployDebug.js'\nimport {listDeploymentFiles, reportInterfaces} from './deploymentPlan.js'\nimport {type DeployPayload, type DeployResult, runDeploy} from './deployRunner.js'\nimport {deployStudioSchemasAndManifests} from './deployStudioSchemasAndManifests.js'\nimport {findUserApplicationForStudio} from './findUserApplication.js'\nimport {type DeployAppOptions} from './types.js'\n\nconst STUDIO_PACKAGE = 'sanity'\n\nexport function deployStudio(options: DeployAppOptions): Promise<void> {\n return runDeploy(options, {\n listFiles: ({flags, projectRoot, sourceDir}) =>\n flags.external ? Promise.resolve([]) : listDeploymentFiles(sourceDir, projectRoot.directory),\n run: runStudioDeployment,\n type: 'studio',\n })\n}\n\n/** Validates the deploy, extracts and uploads the schema, and ships the build. */\nasync function runStudioDeployment(\n options: DeployAppOptions,\n reporter: DeployCheckReporter,\n): Promise<DeployResult | void> {\n const {cliConfig, flags, output, sourceDir} = options\n const workDir = options.projectRoot.directory\n const isExternal = !!flags.external\n const workbench = getWorkbench(cliConfig)\n const isWorkbenchApp = workbench !== null\n const projectId = cliConfig.api?.projectId\n const organizationId = cliConfig.app?.organizationId\n const appId = getAppId(cliConfig)\n const dryRun = !!flags['dry-run']\n\n // A federated app deploys through Sanity's build/hosting pipeline, which\n // --external skips — fail before doing any other work.\n if (isExternal && isWorkbenchApp) {\n reporter.report({\n exitCode: exitCodes.USAGE_ERROR,\n message: 'Deploying a federated application to an external host is not yet supported',\n solution: 'Remove the --external flag to deploy to Sanity hosting',\n status: 'fail',\n })\n }\n\n const appTitle = workbench\n ? flags.title?.trim() || cliConfig.app?.title?.trim() || workbench.slug\n : ''\n\n const isAutoUpdating = checkAutoUpdates(reporter, {cliConfig, flags})\n\n const version = await checkPackageVersion(reporter, {\n moduleName: STUDIO_PACKAGE,\n workDir,\n })\n\n reporter.report(\n projectId\n ? {message: `Project: ${projectId}`, status: 'pass'}\n : {\n message: NO_PROJECT_ID,\n solution: 'Add `api.projectId` to sanity.cli.ts',\n status: 'fail',\n },\n )\n\n // Workbench studios deploy to Brett (which needs the org); plain studios\n // resolve/create on user-applications, unchanged.\n let application: UserApplication | null = null\n let studioCreated = false\n let workbenchApp: object | undefined\n if (workbench && !isExternal) {\n reporter.report(\n organizationId\n ? {message: `Organization: ${organizationId}`, status: 'pass'}\n : {\n message: NO_ORGANIZATION_ID,\n solution: 'Add `app.organizationId` to sanity.cli.ts',\n status: 'fail',\n },\n )\n workbenchApp = (\n await checkStudioTarget(reporter, {\n appId,\n isWorkbenchApp: true,\n organizationId,\n slug: workbench.slug,\n title: appTitle,\n })\n )?.application\n } else {\n ;({application, created: studioCreated} = await resolveStudioApplication(options, {\n dryRun,\n reporter,\n }))\n }\n\n // A first deploy mints the app id and the build inlines it; --no-build would\n // ship an existing bundle carrying a different id, so it can't be a first deploy.\n if (workbench && !isExternal && !appId && !flags.build) {\n reporter.report({\n exitCode: exitCodes.USAGE_ERROR,\n message: 'A first deploy cannot skip the build (--no-build)',\n solution: 'Drop --no-build so the new application id is inlined into the build',\n status: 'fail',\n })\n }\n\n // Read up front so a bad icon path fails before we create or build.\n const appIcon =\n !dryRun && !isExternal && workbench?.icon\n ? await readIconFromPath(workDir, workbench.icon)\n : undefined\n\n // Create the studio before the build so the bundle carries its real id. A\n // redeploy already has it from `deployment.appId`; a dry run skips creation.\n let applicationId = appId\n let applicationCreated = false\n let rollbackApp: (() => Promise<void>) | undefined\n if (!dryRun && workbench && !isExternal && organizationId && !applicationId) {\n const created = await createStudio({\n organizationId,\n projectId,\n slug: workbench.slug,\n title: appTitle,\n visibility: workbench.visibility,\n })\n workbenchApp = created.application\n applicationId = created.application.id\n rollbackApp = created.rollback\n applicationCreated = true\n }\n\n // A record created above is stranded at its slug (and blocks retries) if any\n // step before it fully deploys fails, so undo the creation on failure.\n try {\n await checkBuild(reporter, {\n build: () =>\n buildStudio({\n applicationId: workbench ? applicationId : undefined,\n autoUpdatesEnabled: isAutoUpdating,\n calledFromDeploy: true,\n cliConfig,\n flags,\n outDir: sourceDir,\n output,\n workDir,\n }),\n skipReason: studioBuildSkipReason({build: flags.build, isExternal}),\n successMessage: 'Studio built',\n })\n\n if (!isExternal) {\n await verifyOutputDir({isWorkbenchApp, reporter, sourceDir})\n }\n\n // An external studio hosts its own bundle, so nothing registers.\n const interfaces = workbench && !isExternal ? reportInterfaces(reporter, workbench) : null\n\n const payload: DeployPayload = {\n appId: appId ?? null,\n isAutoUpdating,\n ...(organizationId ? {organizationId} : {}),\n ...(projectId ? {projectId} : {}),\n type: 'studio',\n version,\n ...toWorkbenchPayload(workbench, {interfaces, title: appTitle}),\n }\n\n // Dry run stops here — everything below mutates.\n if (dryRun) return {application: null, payload}\n\n // A real deploy has already exited if anything failed; landing here without a\n // resolved version means the deploy target was never resolved.\n if (!version) return\n\n const studioManifest = await uploadStudioSchema(options, {isExternal})\n // The studio was created (or resolved from `deployment.appId`) before the\n // build, so this only ships the deployment; plain studios use user-applications.\n if (workbench && !isExternal && organizationId && applicationId) {\n await deployWorkbenchApp({\n access: toAccess(studioManifest),\n app: cliConfig.app,\n applicationId,\n icon: appIcon,\n isApp: false,\n isAutoUpdating,\n label: 'Deploying studio',\n // Once the deployment is live, a metadata-sync failure must not delete\n // the studio.\n onDeployed: () => {\n rollbackApp = undefined\n },\n sourceDir,\n title: appTitle,\n version,\n visibility: workbench.visibility,\n workspaces: toWorkspaces(studioManifest),\n })\n const url = getApplicationUrl({id: applicationId, organizationId, type: 'studio'})\n logWorkbenchStudioDeployed({applicationId, cliConfig, output, url})\n return {\n action: applicationCreated ? 'create' : 'update',\n application: workbenchApp ?? null,\n payload,\n url,\n }\n }\n\n if (!application) return\n const location = await shipStudioDeployment({\n application,\n isAutoUpdating,\n isExternal,\n options,\n studioManifest,\n version,\n })\n\n return {\n action: studioCreated ? 'create' : 'update',\n application,\n payload,\n url: location,\n }\n } catch (err) {\n await rollbackApp?.()\n throw err\n }\n}\n\n/**\n * Finds the application a real deploy targets, registering a studio host when\n * none is configured. A dry run resolves and reports the target read-only instead.\n */\nasync function resolveStudioApplication(\n options: DeployAppOptions,\n {dryRun, reporter}: {dryRun: boolean; reporter: DeployCheckReporter},\n): Promise<{application: UserApplication | null; created: boolean}> {\n const {cliConfig, flags, output} = options\n const isExternal = !!flags.external\n const appId = getAppId(cliConfig)\n // Sets the title on a newly registered studio; blank falls back to undefined\n const title = flags.title?.trim() || undefined\n\n if (dryRun) {\n await checkStudioTarget(reporter, {\n appId,\n isExternal,\n projectId: cliConfig.api?.projectId,\n studioHost: cliConfig.studioHost,\n title,\n urlFlag: flags.url,\n })\n return {application: null, created: false}\n }\n\n const projectId = cliConfig.api?.projectId ?? ''\n // `created` is true when a configured-but-unregistered host was just registered.\n const {application, created} = await findUserApplicationForStudio({\n appId,\n isExternal,\n output,\n projectId,\n studioHost: cliConfig.studioHost,\n title,\n unattended: !!flags.yes,\n urlFlag: flags.url,\n })\n\n if (!application) {\n if (isExternal) {\n output.log('Your project has not been registered with an external studio URL.')\n output.log('Please enter the full URL where your studio is hosted.')\n } else {\n output.log('Your project has not been assigned a studio hostname.')\n output.log('To deploy your Sanity Studio to our hosted sanity.studio service,')\n output.log('you will need one. Please enter the subdomain you want to use.')\n }\n\n const registered = await createStudioUserApplication({\n projectId,\n title,\n urlType: isExternal ? 'external' : 'internal',\n })\n deployDebug('Created user application', registered)\n return {application: registered, created: true}\n }\n\n deployDebug('Found user application', application)\n return {application, created}\n}\n\n/** Extracts the studio schema and manifest and uploads them to the schema store. */\nasync function uploadStudioSchema(\n options: DeployAppOptions,\n {isExternal}: {isExternal: boolean},\n): Promise<StudioManifest | null> {\n const {cliConfig, flags, output, projectRoot, sourceDir} = options\n\n let studioManifest: StudioManifest | null = null\n try {\n studioManifest = await deployStudioSchemasAndManifests(\n {\n configPath: projectRoot.path,\n isExternal,\n outPath: `${sourceDir}/static`,\n projectId: cliConfig.api?.projectId ?? '',\n schemaRequired: flags['schema-required'],\n verbose: flags.verbose,\n workDir: projectRoot.directory,\n },\n output,\n )\n } catch (error) {\n deployDebug('Error deploying studio schemas and manifests', error)\n if (error instanceof SchemaExtractionError && error.validation?.length) {\n output.error(formatSchemaValidation(error.validation), {exit: 1})\n }\n output.error(`Error deploying studio schemas and manifests: ${error}`, {exit: 1})\n }\n\n if (!studioManifest) {\n output.error('Failed to generate studio manifest. Please check your schemas and manifests.', {\n exit: 1,\n })\n }\n\n return studioManifest\n}\n\nasync function shipStudioDeployment({\n application,\n isAutoUpdating,\n isExternal,\n options,\n studioManifest,\n version,\n}: {\n application: UserApplication\n isAutoUpdating: boolean\n isExternal: boolean\n options: DeployAppOptions\n studioManifest: StudioManifest | null\n version: string\n}): Promise<string> {\n const {cliConfig, output, sourceDir} = options\n\n let tarball: Gzip | undefined\n if (!isExternal) {\n tarball = pack(dirname(sourceDir), {entries: [basename(sourceDir)]}).pipe(createGzip())\n }\n\n const spin = spinner(isExternal ? 'Registering studio' : 'Deploying to sanity.studio').start()\n let location: string\n try {\n ;({location} = await createDeployment({\n applicationId: application.id,\n isApp: false,\n isAutoUpdating,\n manifest: studioManifest,\n projectId: cliConfig.api?.projectId,\n tarball,\n version,\n }))\n } catch (error) {\n spin.fail()\n throw error\n }\n spin.succeed()\n\n const named = application.title ? ` — \"${application.title}\"` : ''\n output.log(\n isExternal\n ? `\\nSuccess! Studio registered${named}`\n : `\\nSuccess! Studio deployed to ${styleText('cyan', location)}${named}`,\n )\n\n if (getAppId(cliConfig)) return location\n\n const example = `Example:\nexport default defineCliConfig({\n //…\n deployment: {\n ${styleText('cyan', `appId: '${application.id}'`)},\n },\n //…\n})`\n output.log(`\\nAdd ${styleText('cyan', `appId: '${application.id}'`)}`)\n output.log(`to the \\`deployment\\` section in sanity.cli.js or sanity.cli.ts`)\n output.log(`to avoid prompting for application id on next deploy.`)\n output.log(`\\n${example}`)\n\n return location\n}\n\n/**\n * One `datasets` access entry per unique workspace dataset, with a `resourceId`\n * of `\"<projectId>.<dataset>\"`. Deduped, since workspaces can share a dataset.\n */\nfunction toAccess(manifest: StudioManifest | null): BrettAccess[] {\n const resourceIds = new Set(\n (manifest?.workspaces ?? []).map((w) => `${w.projectId}.${w.dataset}`),\n )\n return [...resourceIds].map(\n (resourceId) => ({resourceId, resourceType: 'dataset'}) satisfies BrettAccess,\n )\n}\n\nfunction toWorkspaces(manifest: StudioManifest | null): BrettWorkspace[] {\n return (manifest?.workspaces ?? []).map((workspace) => ({\n basePath: workspace.basePath,\n dataset: workspace.dataset,\n icon: workspace.icon,\n name: workspace.name,\n projectId: workspace.projectId,\n schemaDescriptorId: workspace.schemaDescriptorId,\n subtitle: workspace.subtitle,\n title: workspace.title,\n }))\n}\n\n/** Renders the workbench studio's deploy result; the appId hint shows only when none is configured. */\nfunction logWorkbenchStudioDeployed({\n applicationId,\n cliConfig,\n output,\n url,\n}: {\n applicationId: string\n cliConfig: DeployAppOptions['cliConfig']\n output: DeployAppOptions['output']\n url: string\n}): void {\n output.log(`\\nSuccess! Studio deployed to ${styleText('cyan', url)}`)\n if (getAppId(cliConfig)) return\n\n output.log(`\\nAdd ${styleText('cyan', `appId: '${applicationId}'`)}`)\n output.log(`to the \\`deployment\\` section in sanity.cli.js or sanity.cli.ts`)\n output.log(`to avoid prompting for application id on next deploy.`)\n}\n\nfunction studioBuildSkipReason({build, isExternal}: {build: boolean; isExternal: boolean}) {\n if (isExternal) return 'Build skipped for externally hosted studios'\n if (!build) return 'Build skipped (--no-build) — validating existing output directory'\n return\n}\n"],"names":["basename","dirname","styleText","createGzip","formatSchemaValidation","SchemaExtractionError","exitCodes","spinner","createStudio","deployWorkbenchApp","getApplicationUrl","getWorkbench","toWorkbenchPayload","pack","createDeployment","getAppId","NO_ORGANIZATION_ID","NO_PROJECT_ID","buildStudio","readIconFromPath","createStudioUserApplication","checkAutoUpdates","checkBuild","checkPackageVersion","checkStudioTarget","verifyOutputDir","deployDebug","listDeploymentFiles","reportInterfaces","runDeploy","deployStudioSchemasAndManifests","findUserApplicationForStudio","STUDIO_PACKAGE","deployStudio","options","listFiles","flags","projectRoot","sourceDir","external","Promise","resolve","directory","run","runStudioDeployment","type","reporter","cliConfig","output","workDir","isExternal","workbench","isWorkbenchApp","projectId","api","organizationId","app","appId","dryRun","report","exitCode","USAGE_ERROR","message","solution","status","appTitle","title","trim","slug","isAutoUpdating","version","moduleName","application","studioCreated","workbenchApp","created","resolveStudioApplication","build","appIcon","icon","undefined","applicationId","applicationCreated","rollbackApp","visibility","id","rollback","autoUpdatesEnabled","calledFromDeploy","outDir","skipReason","studioBuildSkipReason","successMessage","interfaces","payload","studioManifest","uploadStudioSchema","access","toAccess","isApp","label","onDeployed","workspaces","toWorkspaces","url","logWorkbenchStudioDeployed","action","location","shipStudioDeployment","err","studioHost","urlFlag","unattended","yes","log","registered","urlType","configPath","path","outPath","schemaRequired","verbose","error","validation","length","exit","tarball","entries","pipe","spin","start","manifest","fail","succeed","named","example","resourceIds","Set","map","w","dataset","resourceId","resourceType","workspace","basePath","name","schemaDescriptorId","subtitle"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/actions/deploy/deployStudio.ts"],"sourcesContent":["import {basename, dirname} from 'node:path'\nimport {styleText} from 'node:util'\nimport {createGzip, type Gzip} from 'node:zlib'\n\nimport {formatSchemaValidation, SchemaExtractionError} from '@sanity/cli-build/_internal/extract'\nimport {exitCodes} from '@sanity/cli-core'\nimport {spinner} from '@sanity/cli-core/ux'\nimport {\n type BrettAccess,\n type BrettWorkspace,\n createStudio,\n deployWorkbenchApp,\n getApplicationUrl,\n getWorkbench,\n toWorkbenchPayload,\n} from '@sanity/workbench-cli/deploy'\nimport {type StudioManifest} from 'sanity'\nimport {pack} from 'tar-fs'\n\nimport {createDeployment, type UserApplication} from '../../services/userApplications.js'\nimport {getAppId} from '../../util/appId.js'\nimport {NO_ORGANIZATION_ID, NO_PROJECT_ID} from '../../util/errorMessages.js'\nimport {buildStudio} from '../build/buildStudio.js'\nimport {readIconFromPath} from '../manifest/extractCoreAppManifest.js'\nimport {createStudioUserApplication} from './createUserApplication.js'\nimport {\n checkAutoUpdates,\n checkBuild,\n checkPackageVersion,\n checkStudioTarget,\n type DeployCheckReporter,\n verifyOutputDir,\n} from './deployChecks.js'\nimport {deployDebug} from './deployDebug.js'\nimport {listDeploymentFiles, reportInterfaces} from './deploymentPlan.js'\nimport {type DeployPayload, type DeployResult, runDeploy} from './deployRunner.js'\nimport {deployStudioSchemasAndManifests} from './deployStudioSchemasAndManifests.js'\nimport {findUserApplicationForStudio} from './findUserApplication.js'\nimport {type DeployAppOptions} from './types.js'\n\nconst STUDIO_PACKAGE = 'sanity'\n\nexport function deployStudio(options: DeployAppOptions): Promise<void> {\n return runDeploy(options, {\n listFiles: ({flags, projectRoot, sourceDir}) =>\n flags.external ? Promise.resolve([]) : listDeploymentFiles(sourceDir, projectRoot.directory),\n run: runStudioDeployment,\n type: 'studio',\n })\n}\n\n/** Validates the deploy, extracts and uploads the schema, and ships the build. */\nasync function runStudioDeployment(\n options: DeployAppOptions,\n reporter: DeployCheckReporter,\n): Promise<DeployResult | void> {\n const {cliConfig, flags, output, sourceDir} = options\n const workDir = options.projectRoot.directory\n const isExternal = !!flags.external\n const workbench = getWorkbench(cliConfig)\n const isWorkbenchApp = workbench !== null\n const projectId = cliConfig.api?.projectId\n const organizationId = cliConfig.app?.organizationId\n const appId = getAppId(cliConfig)\n const dryRun = !!flags['dry-run']\n\n // A federated app deploys through Sanity's build/hosting pipeline, which\n // --external skips — fail before doing any other work.\n if (isExternal && isWorkbenchApp) {\n reporter.report({\n exitCode: exitCodes.USAGE_ERROR,\n message: 'Deploying a federated application to an external host is not yet supported',\n solution: 'Remove the --external flag to deploy to Sanity hosting',\n status: 'fail',\n })\n }\n\n const appTitle = workbench\n ? flags.title?.trim() || cliConfig.app?.title?.trim() || workbench.slug\n : ''\n\n const isAutoUpdating = checkAutoUpdates(reporter, {cliConfig, flags})\n\n const version = await checkPackageVersion(reporter, {\n moduleName: STUDIO_PACKAGE,\n workDir,\n })\n\n reporter.report(\n projectId\n ? {message: `Project: ${projectId}`, status: 'pass'}\n : {\n message: NO_PROJECT_ID,\n solution: 'Add `api.projectId` to sanity.cli.ts',\n status: 'fail',\n },\n )\n\n // Workbench studios deploy to Brett (which needs the org); plain studios\n // resolve/create on user-applications, unchanged.\n let application: UserApplication | null = null\n let studioCreated = false\n let workbenchApp: object | undefined\n if (workbench && !isExternal) {\n reporter.report(\n organizationId\n ? {message: `Organization: ${organizationId}`, status: 'pass'}\n : {\n message: NO_ORGANIZATION_ID,\n solution: 'Add `app.organizationId` to sanity.cli.ts',\n status: 'fail',\n },\n )\n workbenchApp = (\n await checkStudioTarget(reporter, {\n appId,\n isWorkbenchApp: true,\n organizationId,\n slug: workbench.slug,\n title: appTitle,\n })\n )?.application\n } else {\n ;({application, created: studioCreated} = await resolveStudioApplication(options, {\n dryRun,\n reporter,\n }))\n }\n\n // A first deploy mints the app id and the build inlines it; --no-build would\n // ship an existing bundle carrying a different id, so it can't be a first deploy.\n if (workbench && !isExternal && !appId && !flags.build) {\n reporter.report({\n exitCode: exitCodes.USAGE_ERROR,\n message: 'A first deploy cannot skip the build (--no-build)',\n solution: 'Drop --no-build so the new application id is inlined into the build',\n status: 'fail',\n })\n }\n\n // Read up front so a bad icon path fails before we create or build.\n const appIcon =\n !dryRun && !isExternal && workbench?.icon\n ? await readIconFromPath(workDir, workbench.icon)\n : undefined\n\n // Create the studio before the build so the bundle carries its real id. A\n // redeploy already has it from `deployment.appId`; a dry run skips creation.\n let applicationId = appId\n let applicationCreated = false\n let rollbackApp: (() => Promise<void>) | undefined\n if (!dryRun && workbench && !isExternal && organizationId && !applicationId) {\n const created = await createStudio({\n organizationId,\n projectId,\n slug: workbench.slug,\n title: appTitle,\n visibility: workbench.visibility,\n })\n workbenchApp = created.application\n applicationId = created.application.id\n rollbackApp = created.rollback\n applicationCreated = true\n }\n\n // A record created above is stranded at its slug (and blocks retries) if any\n // step before it fully deploys fails, so undo the creation on failure.\n try {\n await checkBuild(reporter, {\n build: () =>\n buildStudio({\n applicationId: workbench ? applicationId : undefined,\n autoUpdatesEnabled: isAutoUpdating,\n calledFromDeploy: true,\n cliConfig,\n flags,\n outDir: sourceDir,\n output,\n workDir,\n }),\n skipReason: studioBuildSkipReason({build: flags.build, isExternal}),\n successMessage: 'Studio built',\n })\n\n if (!isExternal) {\n await verifyOutputDir({isWorkbenchApp, reporter, sourceDir})\n }\n\n // An external studio hosts its own bundle, so nothing registers.\n const interfaces = workbench && !isExternal ? reportInterfaces(reporter, workbench) : null\n\n const payload: DeployPayload = {\n appId: appId ?? null,\n isAutoUpdating,\n ...(organizationId ? {organizationId} : {}),\n ...(projectId ? {projectId} : {}),\n type: 'studio',\n version,\n ...toWorkbenchPayload(workbench, {interfaces, title: appTitle}),\n }\n\n // Dry run stops here — everything below mutates.\n if (dryRun) return {application: null, payload}\n\n // A real deploy has already exited if anything failed; landing here without a\n // resolved version means the deploy target was never resolved.\n if (!version) return\n\n const studioManifest = await uploadStudioSchema(options, {isExternal})\n // The studio was created (or resolved from `deployment.appId`) before the\n // build, so this only ships the deployment; plain studios use user-applications.\n if (workbench && !isExternal && organizationId && applicationId) {\n await deployWorkbenchApp({\n access: toAccess(studioManifest),\n app: cliConfig.app,\n applicationId,\n icon: appIcon,\n isApp: false,\n isAutoUpdating,\n label: 'Deploying studio',\n // Once the deployment is live, a metadata-sync failure must not delete\n // the studio.\n onDeployed: () => {\n rollbackApp = undefined\n },\n sourceDir,\n title: appTitle,\n version,\n visibility: workbench.visibility,\n workspaces: toWorkspaces(studioManifest),\n })\n const url = getApplicationUrl({id: applicationId, organizationId, type: 'studio'})\n logWorkbenchStudioDeployed({applicationId, cliConfig, output, url})\n return {\n action: applicationCreated ? 'create' : 'update',\n application: workbenchApp ?? null,\n payload,\n url,\n }\n }\n\n if (!application) return\n const location = await shipStudioDeployment({\n application,\n isAutoUpdating,\n isExternal,\n options,\n studioManifest,\n version,\n })\n\n return {\n action: studioCreated ? 'create' : 'update',\n application,\n payload,\n url: location,\n }\n } catch (err) {\n await rollbackApp?.()\n throw err\n }\n}\n\n/**\n * Finds the application a real deploy targets, registering a studio host when\n * none is configured. A dry run resolves and reports the target read-only instead.\n */\nasync function resolveStudioApplication(\n options: DeployAppOptions,\n {dryRun, reporter}: {dryRun: boolean; reporter: DeployCheckReporter},\n): Promise<{application: UserApplication | null; created: boolean}> {\n const {cliConfig, flags, output} = options\n const isExternal = !!flags.external\n const appId = getAppId(cliConfig)\n // Sets the title on a newly registered studio; blank falls back to undefined\n const title = flags.title?.trim() || undefined\n\n if (dryRun) {\n await checkStudioTarget(reporter, {\n appId,\n isExternal,\n projectId: cliConfig.api?.projectId,\n studioHost: cliConfig.studioHost,\n title,\n urlFlag: flags.url,\n })\n return {application: null, created: false}\n }\n\n const projectId = cliConfig.api?.projectId ?? ''\n // `created` is true when a configured-but-unregistered host was just registered.\n const {application, created} = await findUserApplicationForStudio({\n appId,\n isExternal,\n output,\n projectId,\n studioHost: cliConfig.studioHost,\n title,\n unattended: !!flags.yes,\n urlFlag: flags.url,\n })\n\n if (!application) {\n if (isExternal) {\n output.log('Your project has not been registered with an external studio URL.')\n output.log('Please enter the full URL where your studio is hosted.')\n } else {\n output.log('Your project has not been assigned a studio hostname.')\n output.log('To deploy your Sanity Studio to our hosted sanity.studio service,')\n output.log('you will need one. Please enter the subdomain you want to use.')\n }\n\n const registered = await createStudioUserApplication({\n projectId,\n title,\n urlType: isExternal ? 'external' : 'internal',\n })\n deployDebug('Created user application', registered)\n return {application: registered, created: true}\n }\n\n deployDebug('Found user application', application)\n return {application, created}\n}\n\n/** Extracts the studio schema and manifest and uploads them to the schema store. */\nasync function uploadStudioSchema(\n options: DeployAppOptions,\n {isExternal}: {isExternal: boolean},\n): Promise<StudioManifest | null> {\n const {cliConfig, flags, output, projectRoot, sourceDir} = options\n\n let studioManifest: StudioManifest | null = null\n try {\n studioManifest = await deployStudioSchemasAndManifests(\n {\n configPath: projectRoot.path,\n isExternal,\n outPath: `${sourceDir}/static`,\n projectId: cliConfig.api?.projectId ?? '',\n schemaRequired: flags['schema-required'],\n verbose: flags.verbose,\n workDir: projectRoot.directory,\n },\n output,\n )\n } catch (error) {\n deployDebug('Error deploying studio schemas and manifests', error)\n if (error instanceof SchemaExtractionError && error.validation?.length) {\n output.error(formatSchemaValidation(error.validation), {exit: exitCodes.RUNTIME_ERROR})\n }\n output.error(`Error deploying studio schemas and manifests: ${error}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n if (!studioManifest) {\n output.error('Failed to generate studio manifest. Please check your schemas and manifests.', {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n return studioManifest\n}\n\nasync function shipStudioDeployment({\n application,\n isAutoUpdating,\n isExternal,\n options,\n studioManifest,\n version,\n}: {\n application: UserApplication\n isAutoUpdating: boolean\n isExternal: boolean\n options: DeployAppOptions\n studioManifest: StudioManifest | null\n version: string\n}): Promise<string> {\n const {cliConfig, output, sourceDir} = options\n\n let tarball: Gzip | undefined\n if (!isExternal) {\n tarball = pack(dirname(sourceDir), {entries: [basename(sourceDir)]}).pipe(createGzip())\n }\n\n const spin = spinner(isExternal ? 'Registering studio' : 'Deploying to sanity.studio').start()\n let location: string\n try {\n ;({location} = await createDeployment({\n applicationId: application.id,\n isApp: false,\n isAutoUpdating,\n manifest: studioManifest,\n projectId: cliConfig.api?.projectId,\n tarball,\n version,\n }))\n } catch (error) {\n spin.fail()\n throw error\n }\n spin.succeed()\n\n const named = application.title ? ` — \"${application.title}\"` : ''\n output.log(\n isExternal\n ? `\\nSuccess! Studio registered${named}`\n : `\\nSuccess! Studio deployed to ${styleText('cyan', location)}${named}`,\n )\n\n if (getAppId(cliConfig)) return location\n\n const example = `Example:\nexport default defineCliConfig({\n //…\n deployment: {\n ${styleText('cyan', `appId: '${application.id}'`)},\n },\n //…\n})`\n output.log(`\\nAdd ${styleText('cyan', `appId: '${application.id}'`)}`)\n output.log(`to the \\`deployment\\` section in sanity.cli.js or sanity.cli.ts`)\n output.log(`to avoid prompting for application id on next deploy.`)\n output.log(`\\n${example}`)\n\n return location\n}\n\n/**\n * One `datasets` access entry per unique workspace dataset, with a `resourceId`\n * of `\"<projectId>.<dataset>\"`. Deduped, since workspaces can share a dataset.\n */\nfunction toAccess(manifest: StudioManifest | null): BrettAccess[] {\n const resourceIds = new Set(\n (manifest?.workspaces ?? []).map((w) => `${w.projectId}.${w.dataset}`),\n )\n return [...resourceIds].map(\n (resourceId) => ({resourceId, resourceType: 'dataset'}) satisfies BrettAccess,\n )\n}\n\nfunction toWorkspaces(manifest: StudioManifest | null): BrettWorkspace[] {\n return (manifest?.workspaces ?? []).map((workspace) => ({\n basePath: workspace.basePath,\n dataset: workspace.dataset,\n icon: workspace.icon,\n name: workspace.name,\n projectId: workspace.projectId,\n schemaDescriptorId: workspace.schemaDescriptorId,\n subtitle: workspace.subtitle,\n title: workspace.title,\n }))\n}\n\n/** Renders the workbench studio's deploy result; the appId hint shows only when none is configured. */\nfunction logWorkbenchStudioDeployed({\n applicationId,\n cliConfig,\n output,\n url,\n}: {\n applicationId: string\n cliConfig: DeployAppOptions['cliConfig']\n output: DeployAppOptions['output']\n url: string\n}): void {\n output.log(`\\nSuccess! Studio deployed to ${styleText('cyan', url)}`)\n if (getAppId(cliConfig)) return\n\n output.log(`\\nAdd ${styleText('cyan', `appId: '${applicationId}'`)}`)\n output.log(`to the \\`deployment\\` section in sanity.cli.js or sanity.cli.ts`)\n output.log(`to avoid prompting for application id on next deploy.`)\n}\n\nfunction studioBuildSkipReason({build, isExternal}: {build: boolean; isExternal: boolean}) {\n if (isExternal) return 'Build skipped for externally hosted studios'\n if (!build) return 'Build skipped (--no-build) — validating existing output directory'\n return\n}\n"],"names":["basename","dirname","styleText","createGzip","formatSchemaValidation","SchemaExtractionError","exitCodes","spinner","createStudio","deployWorkbenchApp","getApplicationUrl","getWorkbench","toWorkbenchPayload","pack","createDeployment","getAppId","NO_ORGANIZATION_ID","NO_PROJECT_ID","buildStudio","readIconFromPath","createStudioUserApplication","checkAutoUpdates","checkBuild","checkPackageVersion","checkStudioTarget","verifyOutputDir","deployDebug","listDeploymentFiles","reportInterfaces","runDeploy","deployStudioSchemasAndManifests","findUserApplicationForStudio","STUDIO_PACKAGE","deployStudio","options","listFiles","flags","projectRoot","sourceDir","external","Promise","resolve","directory","run","runStudioDeployment","type","reporter","cliConfig","output","workDir","isExternal","workbench","isWorkbenchApp","projectId","api","organizationId","app","appId","dryRun","report","exitCode","USAGE_ERROR","message","solution","status","appTitle","title","trim","slug","isAutoUpdating","version","moduleName","application","studioCreated","workbenchApp","created","resolveStudioApplication","build","appIcon","icon","undefined","applicationId","applicationCreated","rollbackApp","visibility","id","rollback","autoUpdatesEnabled","calledFromDeploy","outDir","skipReason","studioBuildSkipReason","successMessage","interfaces","payload","studioManifest","uploadStudioSchema","access","toAccess","isApp","label","onDeployed","workspaces","toWorkspaces","url","logWorkbenchStudioDeployed","action","location","shipStudioDeployment","err","studioHost","urlFlag","unattended","yes","log","registered","urlType","configPath","path","outPath","schemaRequired","verbose","error","validation","length","exit","RUNTIME_ERROR","tarball","entries","pipe","spin","start","manifest","fail","succeed","named","example","resourceIds","Set","map","w","dataset","resourceId","resourceType","workspace","basePath","name","schemaDescriptorId","subtitle"],"mappings":"AAAA,SAAQA,QAAQ,EAAEC,OAAO,QAAO,YAAW;AAC3C,SAAQC,SAAS,QAAO,YAAW;AACnC,SAAQC,UAAU,QAAkB,YAAW;AAE/C,SAAQC,sBAAsB,EAAEC,qBAAqB,QAAO,sCAAqC;AACjG,SAAQC,SAAS,QAAO,mBAAkB;AAC1C,SAAQC,OAAO,QAAO,sBAAqB;AAC3C,SAGEC,YAAY,EACZC,kBAAkB,EAClBC,iBAAiB,EACjBC,YAAY,EACZC,kBAAkB,QACb,+BAA8B;AAErC,SAAQC,IAAI,QAAO,SAAQ;AAE3B,SAAQC,gBAAgB,QAA6B,qCAAoC;AACzF,SAAQC,QAAQ,QAAO,sBAAqB;AAC5C,SAAQC,kBAAkB,EAAEC,aAAa,QAAO,8BAA6B;AAC7E,SAAQC,WAAW,QAAO,0BAAyB;AACnD,SAAQC,gBAAgB,QAAO,wCAAuC;AACtE,SAAQC,2BAA2B,QAAO,6BAA4B;AACtE,SACEC,gBAAgB,EAChBC,UAAU,EACVC,mBAAmB,EACnBC,iBAAiB,EAEjBC,eAAe,QACV,oBAAmB;AAC1B,SAAQC,WAAW,QAAO,mBAAkB;AAC5C,SAAQC,mBAAmB,EAAEC,gBAAgB,QAAO,sBAAqB;AACzE,SAA+CC,SAAS,QAAO,oBAAmB;AAClF,SAAQC,+BAA+B,QAAO,uCAAsC;AACpF,SAAQC,4BAA4B,QAAO,2BAA0B;AAGrE,MAAMC,iBAAiB;AAEvB,OAAO,SAASC,aAAaC,OAAyB;IACpD,OAAOL,UAAUK,SAAS;QACxBC,WAAW,CAAC,EAACC,KAAK,EAAEC,WAAW,EAAEC,SAAS,EAAC,GACzCF,MAAMG,QAAQ,GAAGC,QAAQC,OAAO,CAAC,EAAE,IAAId,oBAAoBW,WAAWD,YAAYK,SAAS;QAC7FC,KAAKC;QACLC,MAAM;IACR;AACF;AAEA,gFAAgF,GAChF,eAAeD,oBACbV,OAAyB,EACzBY,QAA6B;IAE7B,MAAM,EAACC,SAAS,EAAEX,KAAK,EAAEY,MAAM,EAAEV,SAAS,EAAC,GAAGJ;IAC9C,MAAMe,UAAUf,QAAQG,WAAW,CAACK,SAAS;IAC7C,MAAMQ,aAAa,CAAC,CAACd,MAAMG,QAAQ;IACnC,MAAMY,YAAYxC,aAAaoC;IAC/B,MAAMK,iBAAiBD,cAAc;IACrC,MAAME,YAAYN,UAAUO,GAAG,EAAED;IACjC,MAAME,iBAAiBR,UAAUS,GAAG,EAAED;IACtC,MAAME,QAAQ1C,SAASgC;IACvB,MAAMW,SAAS,CAAC,CAACtB,KAAK,CAAC,UAAU;IAEjC,yEAAyE;IACzE,uDAAuD;IACvD,IAAIc,cAAcE,gBAAgB;QAChCN,SAASa,MAAM,CAAC;YACdC,UAAUtD,UAAUuD,WAAW;YAC/BC,SAAS;YACTC,UAAU;YACVC,QAAQ;QACV;IACF;IAEA,MAAMC,WAAWd,YACbf,MAAM8B,KAAK,EAAEC,UAAUpB,UAAUS,GAAG,EAAEU,OAAOC,UAAUhB,UAAUiB,IAAI,GACrE;IAEJ,MAAMC,iBAAiBhD,iBAAiByB,UAAU;QAACC;QAAWX;IAAK;IAEnE,MAAMkC,UAAU,MAAM/C,oBAAoBuB,UAAU;QAClDyB,YAAYvC;QACZiB;IACF;IAEAH,SAASa,MAAM,CACbN,YACI;QAACS,SAAS,CAAC,SAAS,EAAET,WAAW;QAAEW,QAAQ;IAAM,IACjD;QACEF,SAAS7C;QACT8C,UAAU;QACVC,QAAQ;IACV;IAGN,yEAAyE;IACzE,kDAAkD;IAClD,IAAIQ,cAAsC;IAC1C,IAAIC,gBAAgB;IACpB,IAAIC;IACJ,IAAIvB,aAAa,CAACD,YAAY;QAC5BJ,SAASa,MAAM,CACbJ,iBACI;YAACO,SAAS,CAAC,cAAc,EAAEP,gBAAgB;YAAES,QAAQ;QAAM,IAC3D;YACEF,SAAS9C;YACT+C,UAAU;YACVC,QAAQ;QACV;QAENU,eACE,CAAA,MAAMlD,kBAAkBsB,UAAU;YAChCW;YACAL,gBAAgB;YAChBG;YACAa,MAAMjB,UAAUiB,IAAI;YACpBF,OAAOD;QACT,EAAC,GACAO;IACL,OAAO;;QACH,CAAA,EAACA,WAAW,EAAEG,SAASF,aAAa,EAAC,GAAG,MAAMG,yBAAyB1C,SAAS;YAChFwB;YACAZ;QACF,EAAC;IACH;IAEA,6EAA6E;IAC7E,kFAAkF;IAClF,IAAIK,aAAa,CAACD,cAAc,CAACO,SAAS,CAACrB,MAAMyC,KAAK,EAAE;QACtD/B,SAASa,MAAM,CAAC;YACdC,UAAUtD,UAAUuD,WAAW;YAC/BC,SAAS;YACTC,UAAU;YACVC,QAAQ;QACV;IACF;IAEA,oEAAoE;IACpE,MAAMc,UACJ,CAACpB,UAAU,CAACR,cAAcC,WAAW4B,OACjC,MAAM5D,iBAAiB8B,SAASE,UAAU4B,IAAI,IAC9CC;IAEN,0EAA0E;IAC1E,6EAA6E;IAC7E,IAAIC,gBAAgBxB;IACpB,IAAIyB,qBAAqB;IACzB,IAAIC;IACJ,IAAI,CAACzB,UAAUP,aAAa,CAACD,cAAcK,kBAAkB,CAAC0B,eAAe;QAC3E,MAAMN,UAAU,MAAMnE,aAAa;YACjC+C;YACAF;YACAe,MAAMjB,UAAUiB,IAAI;YACpBF,OAAOD;YACPmB,YAAYjC,UAAUiC,UAAU;QAClC;QACAV,eAAeC,QAAQH,WAAW;QAClCS,gBAAgBN,QAAQH,WAAW,CAACa,EAAE;QACtCF,cAAcR,QAAQW,QAAQ;QAC9BJ,qBAAqB;IACvB;IAEA,6EAA6E;IAC7E,uEAAuE;IACvE,IAAI;QACF,MAAM5D,WAAWwB,UAAU;YACzB+B,OAAO,IACL3D,YAAY;oBACV+D,eAAe9B,YAAY8B,gBAAgBD;oBAC3CO,oBAAoBlB;oBACpBmB,kBAAkB;oBAClBzC;oBACAX;oBACAqD,QAAQnD;oBACRU;oBACAC;gBACF;YACFyC,YAAYC,sBAAsB;gBAACd,OAAOzC,MAAMyC,KAAK;gBAAE3B;YAAU;YACjE0C,gBAAgB;QAClB;QAEA,IAAI,CAAC1C,YAAY;YACf,MAAMzB,gBAAgB;gBAAC2B;gBAAgBN;gBAAUR;YAAS;QAC5D;QAEA,iEAAiE;QACjE,MAAMuD,aAAa1C,aAAa,CAACD,aAAatB,iBAAiBkB,UAAUK,aAAa;QAEtF,MAAM2C,UAAyB;YAC7BrC,OAAOA,SAAS;YAChBY;YACA,GAAId,iBAAiB;gBAACA;YAAc,IAAI,CAAC,CAAC;YAC1C,GAAIF,YAAY;gBAACA;YAAS,IAAI,CAAC,CAAC;YAChCR,MAAM;YACNyB;YACA,GAAG1D,mBAAmBuC,WAAW;gBAAC0C;gBAAY3B,OAAOD;YAAQ,EAAE;QACjE;QAEA,iDAAiD;QACjD,IAAIP,QAAQ,OAAO;YAACc,aAAa;YAAMsB;QAAO;QAE9C,8EAA8E;QAC9E,+DAA+D;QAC/D,IAAI,CAACxB,SAAS;QAEd,MAAMyB,iBAAiB,MAAMC,mBAAmB9D,SAAS;YAACgB;QAAU;QACpE,0EAA0E;QAC1E,iFAAiF;QACjF,IAAIC,aAAa,CAACD,cAAcK,kBAAkB0B,eAAe;YAC/D,MAAMxE,mBAAmB;gBACvBwF,QAAQC,SAASH;gBACjBvC,KAAKT,UAAUS,GAAG;gBAClByB;gBACAF,MAAMD;gBACNqB,OAAO;gBACP9B;gBACA+B,OAAO;gBACP,uEAAuE;gBACvE,cAAc;gBACdC,YAAY;oBACVlB,cAAcH;gBAChB;gBACA1C;gBACA4B,OAAOD;gBACPK;gBACAc,YAAYjC,UAAUiC,UAAU;gBAChCkB,YAAYC,aAAaR;YAC3B;YACA,MAAMS,MAAM9F,kBAAkB;gBAAC2E,IAAIJ;gBAAe1B;gBAAgBV,MAAM;YAAQ;YAChF4D,2BAA2B;gBAACxB;gBAAelC;gBAAWC;gBAAQwD;YAAG;YACjE,OAAO;gBACLE,QAAQxB,qBAAqB,WAAW;gBACxCV,aAAaE,gBAAgB;gBAC7BoB;gBACAU;YACF;QACF;QAEA,IAAI,CAAChC,aAAa;QAClB,MAAMmC,WAAW,MAAMC,qBAAqB;YAC1CpC;YACAH;YACAnB;YACAhB;YACA6D;YACAzB;QACF;QAEA,OAAO;YACLoC,QAAQjC,gBAAgB,WAAW;YACnCD;YACAsB;YACAU,KAAKG;QACP;IACF,EAAE,OAAOE,KAAK;QACZ,MAAM1B;QACN,MAAM0B;IACR;AACF;AAEA;;;CAGC,GACD,eAAejC,yBACb1C,OAAyB,EACzB,EAACwB,MAAM,EAAEZ,QAAQ,EAAmD;IAEpE,MAAM,EAACC,SAAS,EAAEX,KAAK,EAAEY,MAAM,EAAC,GAAGd;IACnC,MAAMgB,aAAa,CAAC,CAACd,MAAMG,QAAQ;IACnC,MAAMkB,QAAQ1C,SAASgC;IACvB,6EAA6E;IAC7E,MAAMmB,QAAQ9B,MAAM8B,KAAK,EAAEC,UAAUa;IAErC,IAAItB,QAAQ;QACV,MAAMlC,kBAAkBsB,UAAU;YAChCW;YACAP;YACAG,WAAWN,UAAUO,GAAG,EAAED;YAC1ByD,YAAY/D,UAAU+D,UAAU;YAChC5C;YACA6C,SAAS3E,MAAMoE,GAAG;QACpB;QACA,OAAO;YAAChC,aAAa;YAAMG,SAAS;QAAK;IAC3C;IAEA,MAAMtB,YAAYN,UAAUO,GAAG,EAAED,aAAa;IAC9C,iFAAiF;IACjF,MAAM,EAACmB,WAAW,EAAEG,OAAO,EAAC,GAAG,MAAM5C,6BAA6B;QAChE0B;QACAP;QACAF;QACAK;QACAyD,YAAY/D,UAAU+D,UAAU;QAChC5C;QACA8C,YAAY,CAAC,CAAC5E,MAAM6E,GAAG;QACvBF,SAAS3E,MAAMoE,GAAG;IACpB;IAEA,IAAI,CAAChC,aAAa;QAChB,IAAItB,YAAY;YACdF,OAAOkE,GAAG,CAAC;YACXlE,OAAOkE,GAAG,CAAC;QACb,OAAO;YACLlE,OAAOkE,GAAG,CAAC;YACXlE,OAAOkE,GAAG,CAAC;YACXlE,OAAOkE,GAAG,CAAC;QACb;QAEA,MAAMC,aAAa,MAAM/F,4BAA4B;YACnDiC;YACAa;YACAkD,SAASlE,aAAa,aAAa;QACrC;QACAxB,YAAY,4BAA4ByF;QACxC,OAAO;YAAC3C,aAAa2C;YAAYxC,SAAS;QAAI;IAChD;IAEAjD,YAAY,0BAA0B8C;IACtC,OAAO;QAACA;QAAaG;IAAO;AAC9B;AAEA,kFAAkF,GAClF,eAAeqB,mBACb9D,OAAyB,EACzB,EAACgB,UAAU,EAAwB;IAEnC,MAAM,EAACH,SAAS,EAAEX,KAAK,EAAEY,MAAM,EAAEX,WAAW,EAAEC,SAAS,EAAC,GAAGJ;IAE3D,IAAI6D,iBAAwC;IAC5C,IAAI;QACFA,iBAAiB,MAAMjE,gCACrB;YACEuF,YAAYhF,YAAYiF,IAAI;YAC5BpE;YACAqE,SAAS,GAAGjF,UAAU,OAAO,CAAC;YAC9Be,WAAWN,UAAUO,GAAG,EAAED,aAAa;YACvCmE,gBAAgBpF,KAAK,CAAC,kBAAkB;YACxCqF,SAASrF,MAAMqF,OAAO;YACtBxE,SAASZ,YAAYK,SAAS;QAChC,GACAM;IAEJ,EAAE,OAAO0E,OAAO;QACdhG,YAAY,gDAAgDgG;QAC5D,IAAIA,iBAAiBrH,yBAAyBqH,MAAMC,UAAU,EAAEC,QAAQ;YACtE5E,OAAO0E,KAAK,CAACtH,uBAAuBsH,MAAMC,UAAU,GAAG;gBAACE,MAAMvH,UAAUwH,aAAa;YAAA;QACvF;QACA9E,OAAO0E,KAAK,CAAC,CAAC,8CAA8C,EAAEA,OAAO,EAAE;YACrEG,MAAMvH,UAAUwH,aAAa;QAC/B;IACF;IAEA,IAAI,CAAC/B,gBAAgB;QACnB/C,OAAO0E,KAAK,CAAC,gFAAgF;YAC3FG,MAAMvH,UAAUwH,aAAa;QAC/B;IACF;IAEA,OAAO/B;AACT;AAEA,eAAea,qBAAqB,EAClCpC,WAAW,EACXH,cAAc,EACdnB,UAAU,EACVhB,OAAO,EACP6D,cAAc,EACdzB,OAAO,EAQR;IACC,MAAM,EAACvB,SAAS,EAAEC,MAAM,EAAEV,SAAS,EAAC,GAAGJ;IAEvC,IAAI6F;IACJ,IAAI,CAAC7E,YAAY;QACf6E,UAAUlH,KAAKZ,QAAQqC,YAAY;YAAC0F,SAAS;gBAAChI,SAASsC;aAAW;QAAA,GAAG2F,IAAI,CAAC9H;IAC5E;IAEA,MAAM+H,OAAO3H,QAAQ2C,aAAa,uBAAuB,8BAA8BiF,KAAK;IAC5F,IAAIxB;IACJ,IAAI;;QACA,CAAA,EAACA,QAAQ,EAAC,GAAG,MAAM7F,iBAAiB;YACpCmE,eAAeT,YAAYa,EAAE;YAC7Bc,OAAO;YACP9B;YACA+D,UAAUrC;YACV1C,WAAWN,UAAUO,GAAG,EAAED;YAC1B0E;YACAzD;QACF,EAAC;IACH,EAAE,OAAOoD,OAAO;QACdQ,KAAKG,IAAI;QACT,MAAMX;IACR;IACAQ,KAAKI,OAAO;IAEZ,MAAMC,QAAQ/D,YAAYN,KAAK,GAAG,CAAC,IAAI,EAAEM,YAAYN,KAAK,CAAC,CAAC,CAAC,GAAG;IAChElB,OAAOkE,GAAG,CACRhE,aACI,CAAC,4BAA4B,EAAEqF,OAAO,GACtC,CAAC,8BAA8B,EAAErI,UAAU,QAAQyG,YAAY4B,OAAO;IAG5E,IAAIxH,SAASgC,YAAY,OAAO4D;IAEhC,MAAM6B,UAAU,CAAC;;;;IAIf,EAAEtI,UAAU,QAAQ,CAAC,QAAQ,EAAEsE,YAAYa,EAAE,CAAC,CAAC,CAAC,EAAE;;;EAGpD,CAAC;IACDrC,OAAOkE,GAAG,CAAC,CAAC,MAAM,EAAEhH,UAAU,QAAQ,CAAC,QAAQ,EAAEsE,YAAYa,EAAE,CAAC,CAAC,CAAC,GAAG;IACrErC,OAAOkE,GAAG,CAAC,CAAC,+DAA+D,CAAC;IAC5ElE,OAAOkE,GAAG,CAAC,CAAC,qDAAqD,CAAC;IAClElE,OAAOkE,GAAG,CAAC,CAAC,EAAE,EAAEsB,SAAS;IAEzB,OAAO7B;AACT;AAEA;;;CAGC,GACD,SAAST,SAASkC,QAA+B;IAC/C,MAAMK,cAAc,IAAIC,IACtB,AAACN,CAAAA,UAAU9B,cAAc,EAAE,AAAD,EAAGqC,GAAG,CAAC,CAACC,IAAM,GAAGA,EAAEvF,SAAS,CAAC,CAAC,EAAEuF,EAAEC,OAAO,EAAE;IAEvE,OAAO;WAAIJ;KAAY,CAACE,GAAG,CACzB,CAACG,aAAgB,CAAA;YAACA;YAAYC,cAAc;QAAS,CAAA;AAEzD;AAEA,SAASxC,aAAa6B,QAA+B;IACnD,OAAO,AAACA,CAAAA,UAAU9B,cAAc,EAAE,AAAD,EAAGqC,GAAG,CAAC,CAACK,YAAe,CAAA;YACtDC,UAAUD,UAAUC,QAAQ;YAC5BJ,SAASG,UAAUH,OAAO;YAC1B9D,MAAMiE,UAAUjE,IAAI;YACpBmE,MAAMF,UAAUE,IAAI;YACpB7F,WAAW2F,UAAU3F,SAAS;YAC9B8F,oBAAoBH,UAAUG,kBAAkB;YAChDC,UAAUJ,UAAUI,QAAQ;YAC5BlF,OAAO8E,UAAU9E,KAAK;QACxB,CAAA;AACF;AAEA,qGAAqG,GACrG,SAASuC,2BAA2B,EAClCxB,aAAa,EACblC,SAAS,EACTC,MAAM,EACNwD,GAAG,EAMJ;IACCxD,OAAOkE,GAAG,CAAC,CAAC,8BAA8B,EAAEhH,UAAU,QAAQsG,MAAM;IACpE,IAAIzF,SAASgC,YAAY;IAEzBC,OAAOkE,GAAG,CAAC,CAAC,MAAM,EAAEhH,UAAU,QAAQ,CAAC,QAAQ,EAAE+E,cAAc,CAAC,CAAC,GAAG;IACpEjC,OAAOkE,GAAG,CAAC,CAAC,+DAA+D,CAAC;IAC5ElE,OAAOkE,GAAG,CAAC,CAAC,qDAAqD,CAAC;AACpE;AAEA,SAASvB,sBAAsB,EAACd,KAAK,EAAE3B,UAAU,EAAwC;IACvF,IAAIA,YAAY,OAAO;IACvB,IAAI,CAAC2B,OAAO,OAAO;IACnB;AACF"}
@@ -2,7 +2,8 @@
2
2
  * Finds (or creates) the user application a deploy targets — the interactive
3
3
  * adapter that turns the resolveDeployTarget verdicts into prompts, creation,
4
4
  * and exits. Dry runs consume the same verdicts read-only (see deployChecks).
5
- */ import { getErrorMessage } from '@sanity/cli-core/errors';
5
+ */ import { exitCodes } from '@sanity/cli-core';
6
+ import { getErrorMessage } from '@sanity/cli-core/errors';
6
7
  import { select, Separator, spinner } from '@sanity/cli-core/ux';
7
8
  import { createUserApplication } from '../../services/userApplications.js';
8
9
  import { getAppId } from '../../util/appId.js';
@@ -24,7 +25,7 @@ export async function findUserApplication(options) {
24
25
  spin.clear();
25
26
  deployDebug('Error finding user application for app', error);
26
27
  output.error(describeAppTargetError(error, organizationId), {
27
- exit: 1
28
+ exit: exitCodes.RUNTIME_ERROR
28
29
  });
29
30
  return null;
30
31
  }
@@ -47,7 +48,7 @@ export async function findUserApplication(options) {
47
48
  // needs an explicit exit here to not fall through to application creation
48
49
  if (resolution.type === 'blocked') {
49
50
  output.error(resolution.message, {
50
- exit: 1
51
+ exit: exitCodes.RUNTIME_ERROR
51
52
  });
52
53
  return null;
53
54
  }
@@ -72,7 +73,7 @@ export async function findUserApplicationForStudio(options) {
72
73
  spin.fail();
73
74
  deployDebug('Error finding user application', error);
74
75
  output.error(`Failed to resolve deploy target: ${getErrorMessage(error)}`, {
75
- exit: 1
76
+ exit: exitCodes.RUNTIME_ERROR
76
77
  });
77
78
  return {
78
79
  application: null,
@@ -123,7 +124,7 @@ export async function findUserApplicationForStudio(options) {
123
124
  // needs an explicit exit here
124
125
  if (resolution.type === 'blocked') {
125
126
  output.error(resolution.message, {
126
- exit: 1
127
+ exit: exitCodes.RUNTIME_ERROR
127
128
  });
128
129
  return {
129
130
  application: null,
@@ -172,14 +173,14 @@ export async function findUserApplicationForStudio(options) {
172
173
  409
173
174
  ].includes(e?.statusCode)) {
174
175
  output.error(e?.response?.body?.message || 'Bad request', {
175
- exit: 1
176
+ exit: exitCodes.RUNTIME_ERROR
176
177
  });
177
178
  return null;
178
179
  }
179
180
  // otherwise, it's a fatal error
180
181
  deployDebug('Error creating user application from config', e);
181
182
  output.error(`Error creating user application from config: ${e instanceof Error ? e.message : e}`, {
182
- exit: 1
183
+ exit: exitCodes.RUNTIME_ERROR
183
184
  });
184
185
  return null;
185
186
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/deploy/findUserApplication.ts"],"sourcesContent":["/**\n * Finds (or creates) the user application a deploy targets — the interactive\n * adapter that turns the resolveDeployTarget verdicts into prompts, creation,\n * and exits. Dry runs consume the same verdicts read-only (see deployChecks).\n */\n\nimport {type CliConfig, type Output} from '@sanity/cli-core'\nimport {getErrorMessage} from '@sanity/cli-core/errors'\nimport {select, Separator, spinner} from '@sanity/cli-core/ux'\n\nimport {\n createUserApplication,\n type UserApplication,\n type UserApplicationResolved,\n} from '../../services/userApplications.js'\nimport {getAppId} from '../../util/appId.js'\nimport {createFailFastReporter} from '../../util/checks.js'\nimport {describeAppTarget, describeAppTargetError, describeStudioTarget} from './deployChecks.js'\nimport {deployDebug} from './deployDebug.js'\nimport {resolveAppDeployTarget, resolveStudioDeployTarget} from './resolveDeployTarget.js'\n\ninterface FindUserApplicationOptions {\n cliConfig: CliConfig\n organizationId: string\n output: Output\n\n title?: string\n unattended?: boolean\n}\n\nexport async function findUserApplication(\n options: FindUserApplicationOptions,\n): Promise<UserApplicationResolved | null> {\n const {cliConfig, organizationId, output, title, unattended = false} = options\n const spin = spinner('Checking application info...').start()\n\n let resolution\n try {\n resolution = await resolveAppDeployTarget({appId: getAppId(cliConfig), organizationId})\n deployDebug('Resolved app deploy target', resolution)\n } catch (error) {\n spin.clear()\n deployDebug('Error finding user application for app', error)\n output.error(describeAppTargetError(error, organizationId), {exit: 1})\n return null\n }\n\n if (resolution.type === 'found') {\n spin.succeed()\n return resolution.application\n }\n\n // null tells the caller to create. Unattended runs can only create with a\n // --title; picking among existing apps (needs-input) always needs a prompt.\n if (resolution.type === 'would-create' && (!unattended || title)) {\n spin.info('No application ID configured')\n return null\n }\n if (resolution.type === 'needs-input' && !unattended) {\n spin.info('No application ID configured')\n return promptForExistingApp(resolution.existing)\n }\n\n spin.clear()\n // 'blocked' diagnoses as a skip (its root cause fails an earlier check), so it\n // needs an explicit exit here to not fall through to application creation\n if (resolution.type === 'blocked') {\n output.error(resolution.message, {exit: 1})\n return null\n }\n createFailFastReporter(output).report(describeAppTarget(resolution))\n return null\n}\n\ninterface FindUserApplicationForStudioOptions {\n isExternal: boolean\n output: Output\n projectId: string\n\n appId?: string\n studioHost?: string\n title?: string\n unattended?: boolean\n urlFlag?: string\n}\n\nexport async function findUserApplicationForStudio(\n options: FindUserApplicationForStudioOptions,\n): Promise<{application: UserApplication | null; created: boolean}> {\n const {\n appId,\n isExternal,\n output,\n projectId,\n studioHost,\n title,\n unattended = false,\n urlFlag,\n } = options\n const urlType = isExternal ? 'external' : 'internal'\n const spin = spinner('Checking project info').start()\n\n let resolution\n try {\n resolution = await resolveStudioDeployTarget({\n appId,\n isExternal,\n projectId,\n studioHost,\n urlFlag,\n })\n deployDebug('Resolved studio deploy target', resolution)\n } catch (error) {\n spin.fail()\n deployDebug('Error finding user application', error)\n output.error(`Failed to resolve deploy target: ${getErrorMessage(error)}`, {exit: 1})\n return {application: null, created: false}\n }\n\n if (resolution.type === 'found') {\n spin.succeed()\n return {application: resolution.application, created: false}\n }\n\n // The configured host isn't registered yet — a deploy registers it without\n // prompting, so this returns a newly created studio.\n if (resolution.type === 'would-create') {\n spin.succeed()\n const application = await createFromConfiguredHost({\n appHost: resolution.appHost,\n output,\n projectId,\n title,\n urlType,\n })\n return {application, created: application !== null}\n }\n\n if (resolution.type === 'needs-input' && !unattended) {\n spin.succeed()\n // Nothing to select from — the caller prompts for a brand new host\n if (resolution.existing.length === 0) return {application: null, created: false}\n // A selected existing studio is an update; \"new\" returns null and the caller registers it.\n return {\n application: await promptForExistingStudio({existing: resolution.existing, urlType}),\n created: false,\n }\n }\n\n spin.fail()\n // 'blocked' diagnoses as a skip (its root cause fails an earlier check), so it\n // needs an explicit exit here\n if (resolution.type === 'blocked') {\n output.error(resolution.message, {exit: 1})\n return {application: null, created: false}\n }\n createFailFastReporter(output).report(describeStudioTarget(resolution, {isExternal}))\n return {application: null, created: false}\n}\n\n/**\n * The host is configured (studioHost or --url) but not registered yet:\n * a deploy registers it without prompting.\n */\nasync function createFromConfiguredHost({\n appHost,\n output,\n projectId,\n title,\n urlType,\n}: {\n appHost: string\n output: Output\n projectId: string\n title?: string\n urlType: 'external' | 'internal'\n}): Promise<UserApplication | null> {\n if (urlType === 'external') {\n output.log('Your project has not been registered with an external studio URL.')\n output.log(`Registering ${appHost}`)\n } else {\n output.log('Your project has not been assigned a studio hostname.')\n output.log(`Creating https://${appHost}.sanity.studio`)\n }\n output.log('')\n\n const spin = spinner(\n urlType === 'external' ? 'Registering external studio' : 'Creating studio hostname',\n ).start()\n\n try {\n const response = await createUserApplication({\n appType: 'studio',\n body: {appHost, title, type: 'studio', urlType},\n projectId,\n })\n spin.succeed()\n return response\n } catch (e) {\n spin.fail()\n // if the name is taken, it should return a 409 so we relay to the user\n if ([402, 409].includes(e?.statusCode)) {\n output.error(e?.response?.body?.message || 'Bad request', {exit: 1})\n return null\n }\n // otherwise, it's a fatal error\n deployDebug('Error creating user application from config', e)\n output.error(\n `Error creating user application from config: ${e instanceof Error ? e.message : e}`,\n {exit: 1},\n )\n return null\n }\n}\n\nasync function promptForExistingApp(\n existing: UserApplicationResolved[],\n): Promise<UserApplicationResolved | null> {\n const choices = existing.map((app) => ({name: app.title ?? app.appHost, value: app.appHost}))\n\n const selected = await select({\n choices: [\n {name: 'New application deployment', value: 'NEW_APP'},\n new Separator(' ════ Existing applications: ════ '),\n ...choices,\n ],\n loop: false,\n message: 'Would you like to create a new application deployment, or deploy to an existing one?',\n pageSize: 10,\n })\n\n if (selected === 'NEW_APP') {\n return null\n }\n\n return existing.find((app) => app.appHost === selected)!\n}\n\nasync function promptForExistingStudio({\n existing,\n urlType,\n}: {\n existing: UserApplication[]\n urlType: 'external' | 'internal'\n}): Promise<UserApplication | null> {\n const newLabel =\n urlType === 'external' ? 'Register new external studio URL' : 'Create new studio hostname'\n const selectMessage =\n urlType === 'external'\n ? 'Select existing external studio, or register a new one'\n : 'Select existing studio hostname, or create a new one'\n\n const choices = existing.map((app) => ({name: app.title ?? app.appHost, value: app.appHost}))\n\n const selected = await select({\n choices: [{name: newLabel, value: 'NEW_STUDIO'}, new Separator(), ...choices],\n message: selectMessage,\n })\n\n if (selected === 'NEW_STUDIO') {\n return null\n }\n\n return existing.find((app) => app.appHost === selected)!\n}\n"],"names":["getErrorMessage","select","Separator","spinner","createUserApplication","getAppId","createFailFastReporter","describeAppTarget","describeAppTargetError","describeStudioTarget","deployDebug","resolveAppDeployTarget","resolveStudioDeployTarget","findUserApplication","options","cliConfig","organizationId","output","title","unattended","spin","start","resolution","appId","error","clear","exit","type","succeed","application","info","promptForExistingApp","existing","message","report","findUserApplicationForStudio","isExternal","projectId","studioHost","urlFlag","urlType","fail","created","createFromConfiguredHost","appHost","length","promptForExistingStudio","log","response","appType","body","e","includes","statusCode","Error","choices","map","app","name","value","selected","loop","pageSize","find","newLabel","selectMessage"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/actions/deploy/findUserApplication.ts"],"sourcesContent":["/**\n * Finds (or creates) the user application a deploy targets — the interactive\n * adapter that turns the resolveDeployTarget verdicts into prompts, creation,\n * and exits. Dry runs consume the same verdicts read-only (see deployChecks).\n */\n\nimport {type CliConfig, exitCodes, type Output} from '@sanity/cli-core'\nimport {getErrorMessage} from '@sanity/cli-core/errors'\nimport {select, Separator, spinner} from '@sanity/cli-core/ux'\n\nimport {\n createUserApplication,\n type UserApplication,\n type UserApplicationResolved,\n} from '../../services/userApplications.js'\nimport {getAppId} from '../../util/appId.js'\nimport {createFailFastReporter} from '../../util/checks.js'\nimport {describeAppTarget, describeAppTargetError, describeStudioTarget} from './deployChecks.js'\nimport {deployDebug} from './deployDebug.js'\nimport {resolveAppDeployTarget, resolveStudioDeployTarget} from './resolveDeployTarget.js'\n\ninterface FindUserApplicationOptions {\n cliConfig: CliConfig\n organizationId: string\n output: Output\n\n title?: string\n unattended?: boolean\n}\n\nexport async function findUserApplication(\n options: FindUserApplicationOptions,\n): Promise<UserApplicationResolved | null> {\n const {cliConfig, organizationId, output, title, unattended = false} = options\n const spin = spinner('Checking application info...').start()\n\n let resolution\n try {\n resolution = await resolveAppDeployTarget({appId: getAppId(cliConfig), organizationId})\n deployDebug('Resolved app deploy target', resolution)\n } catch (error) {\n spin.clear()\n deployDebug('Error finding user application for app', error)\n output.error(describeAppTargetError(error, organizationId), {exit: exitCodes.RUNTIME_ERROR})\n return null\n }\n\n if (resolution.type === 'found') {\n spin.succeed()\n return resolution.application\n }\n\n // null tells the caller to create. Unattended runs can only create with a\n // --title; picking among existing apps (needs-input) always needs a prompt.\n if (resolution.type === 'would-create' && (!unattended || title)) {\n spin.info('No application ID configured')\n return null\n }\n if (resolution.type === 'needs-input' && !unattended) {\n spin.info('No application ID configured')\n return promptForExistingApp(resolution.existing)\n }\n\n spin.clear()\n // 'blocked' diagnoses as a skip (its root cause fails an earlier check), so it\n // needs an explicit exit here to not fall through to application creation\n if (resolution.type === 'blocked') {\n output.error(resolution.message, {exit: exitCodes.RUNTIME_ERROR})\n return null\n }\n createFailFastReporter(output).report(describeAppTarget(resolution))\n return null\n}\n\ninterface FindUserApplicationForStudioOptions {\n isExternal: boolean\n output: Output\n projectId: string\n\n appId?: string\n studioHost?: string\n title?: string\n unattended?: boolean\n urlFlag?: string\n}\n\nexport async function findUserApplicationForStudio(\n options: FindUserApplicationForStudioOptions,\n): Promise<{application: UserApplication | null; created: boolean}> {\n const {\n appId,\n isExternal,\n output,\n projectId,\n studioHost,\n title,\n unattended = false,\n urlFlag,\n } = options\n const urlType = isExternal ? 'external' : 'internal'\n const spin = spinner('Checking project info').start()\n\n let resolution\n try {\n resolution = await resolveStudioDeployTarget({\n appId,\n isExternal,\n projectId,\n studioHost,\n urlFlag,\n })\n deployDebug('Resolved studio deploy target', resolution)\n } catch (error) {\n spin.fail()\n deployDebug('Error finding user application', error)\n output.error(`Failed to resolve deploy target: ${getErrorMessage(error)}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n return {application: null, created: false}\n }\n\n if (resolution.type === 'found') {\n spin.succeed()\n return {application: resolution.application, created: false}\n }\n\n // The configured host isn't registered yet — a deploy registers it without\n // prompting, so this returns a newly created studio.\n if (resolution.type === 'would-create') {\n spin.succeed()\n const application = await createFromConfiguredHost({\n appHost: resolution.appHost,\n output,\n projectId,\n title,\n urlType,\n })\n return {application, created: application !== null}\n }\n\n if (resolution.type === 'needs-input' && !unattended) {\n spin.succeed()\n // Nothing to select from — the caller prompts for a brand new host\n if (resolution.existing.length === 0) return {application: null, created: false}\n // A selected existing studio is an update; \"new\" returns null and the caller registers it.\n return {\n application: await promptForExistingStudio({existing: resolution.existing, urlType}),\n created: false,\n }\n }\n\n spin.fail()\n // 'blocked' diagnoses as a skip (its root cause fails an earlier check), so it\n // needs an explicit exit here\n if (resolution.type === 'blocked') {\n output.error(resolution.message, {exit: exitCodes.RUNTIME_ERROR})\n return {application: null, created: false}\n }\n createFailFastReporter(output).report(describeStudioTarget(resolution, {isExternal}))\n return {application: null, created: false}\n}\n\n/**\n * The host is configured (studioHost or --url) but not registered yet:\n * a deploy registers it without prompting.\n */\nasync function createFromConfiguredHost({\n appHost,\n output,\n projectId,\n title,\n urlType,\n}: {\n appHost: string\n output: Output\n projectId: string\n title?: string\n urlType: 'external' | 'internal'\n}): Promise<UserApplication | null> {\n if (urlType === 'external') {\n output.log('Your project has not been registered with an external studio URL.')\n output.log(`Registering ${appHost}`)\n } else {\n output.log('Your project has not been assigned a studio hostname.')\n output.log(`Creating https://${appHost}.sanity.studio`)\n }\n output.log('')\n\n const spin = spinner(\n urlType === 'external' ? 'Registering external studio' : 'Creating studio hostname',\n ).start()\n\n try {\n const response = await createUserApplication({\n appType: 'studio',\n body: {appHost, title, type: 'studio', urlType},\n projectId,\n })\n spin.succeed()\n return response\n } catch (e) {\n spin.fail()\n // if the name is taken, it should return a 409 so we relay to the user\n if ([402, 409].includes(e?.statusCode)) {\n output.error(e?.response?.body?.message || 'Bad request', {exit: exitCodes.RUNTIME_ERROR})\n return null\n }\n // otherwise, it's a fatal error\n deployDebug('Error creating user application from config', e)\n output.error(\n `Error creating user application from config: ${e instanceof Error ? e.message : e}`,\n {exit: exitCodes.RUNTIME_ERROR},\n )\n return null\n }\n}\n\nasync function promptForExistingApp(\n existing: UserApplicationResolved[],\n): Promise<UserApplicationResolved | null> {\n const choices = existing.map((app) => ({name: app.title ?? app.appHost, value: app.appHost}))\n\n const selected = await select({\n choices: [\n {name: 'New application deployment', value: 'NEW_APP'},\n new Separator(' ════ Existing applications: ════ '),\n ...choices,\n ],\n loop: false,\n message: 'Would you like to create a new application deployment, or deploy to an existing one?',\n pageSize: 10,\n })\n\n if (selected === 'NEW_APP') {\n return null\n }\n\n return existing.find((app) => app.appHost === selected)!\n}\n\nasync function promptForExistingStudio({\n existing,\n urlType,\n}: {\n existing: UserApplication[]\n urlType: 'external' | 'internal'\n}): Promise<UserApplication | null> {\n const newLabel =\n urlType === 'external' ? 'Register new external studio URL' : 'Create new studio hostname'\n const selectMessage =\n urlType === 'external'\n ? 'Select existing external studio, or register a new one'\n : 'Select existing studio hostname, or create a new one'\n\n const choices = existing.map((app) => ({name: app.title ?? app.appHost, value: app.appHost}))\n\n const selected = await select({\n choices: [{name: newLabel, value: 'NEW_STUDIO'}, new Separator(), ...choices],\n message: selectMessage,\n })\n\n if (selected === 'NEW_STUDIO') {\n return null\n }\n\n return existing.find((app) => app.appHost === selected)!\n}\n"],"names":["exitCodes","getErrorMessage","select","Separator","spinner","createUserApplication","getAppId","createFailFastReporter","describeAppTarget","describeAppTargetError","describeStudioTarget","deployDebug","resolveAppDeployTarget","resolveStudioDeployTarget","findUserApplication","options","cliConfig","organizationId","output","title","unattended","spin","start","resolution","appId","error","clear","exit","RUNTIME_ERROR","type","succeed","application","info","promptForExistingApp","existing","message","report","findUserApplicationForStudio","isExternal","projectId","studioHost","urlFlag","urlType","fail","created","createFromConfiguredHost","appHost","length","promptForExistingStudio","log","response","appType","body","e","includes","statusCode","Error","choices","map","app","name","value","selected","loop","pageSize","find","newLabel","selectMessage"],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import { styleText } from 'node:util';
2
+ import { exitCodes } from '@sanity/cli-core';
2
3
  import { isWorkbenchApp as determineIsWorkbenchApp } from '@sanity/workbench-cli';
3
4
  import { startDevServer } from '../../../server/devServer.js';
4
5
  import { gracefulServerDeath } from '../../../server/gracefulServerDeath.js';
@@ -28,7 +29,7 @@ export async function startAppDevServer(options) {
28
29
  }
29
30
  if (!organizationId) {
30
31
  output.error(`Apps require an organization ID (orgId) specified in your sanity.cli.ts file`, {
31
- exit: 1
32
+ exit: exitCodes.RUNTIME_ERROR
32
33
  });
33
34
  return {
34
35
  reason: 'missing-organization-id',
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/actions/dev/servers/startAppDevServer.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {isWorkbenchApp as determineIsWorkbenchApp} from '@sanity/workbench-cli'\n\nimport {startDevServer} from '../../../server/devServer.js'\nimport {gracefulServerDeath} from '../../../server/gracefulServerDeath.js'\nimport {devDebug} from '../devDebug.js'\nimport {type DevActionOptions, type StartDevServerResult} from '../types.js'\nimport {getDashboardAppURL} from './getDashboardAppUrl.js'\nimport {getDevServerConfig} from './getDevServerConfig.js'\n\n// Bind-only addresses ('0.0.0.0', '::') aren't routable in every browser; the\n// displayed URL falls back to localhost. The bind address itself is untouched.\nfunction toDisplayHost(host: string | undefined): string {\n if (!host || host === '0.0.0.0' || host === '::' || host === '[::]') {\n return 'localhost'\n }\n return host\n}\n\nexport async function startAppDevServer(options: DevActionOptions): Promise<StartDevServerResult> {\n const {announceUrl = true, cliConfig, flags, httpPort, output, workDir} = options\n\n const isWorkbenchApp = determineIsWorkbenchApp(cliConfig?.app)\n\n // Workbench apps don't load through the dashboard, so the flag has no\n // meaning for them and is ignored.\n if (!isWorkbenchApp && !flags['load-in-dashboard']) {\n output.warn(`Apps cannot run without the Sanity dashboard`)\n output.warn(`Starting dev server with the --load-in-dashboard flag set to true`)\n }\n\n let organizationId: string | undefined\n if (cliConfig && 'app' in cliConfig && cliConfig.app?.organizationId) {\n organizationId = cliConfig.app.organizationId\n }\n\n if (!organizationId) {\n output.error(`Apps require an organization ID (orgId) specified in your sanity.cli.ts file`, {\n exit: 1,\n })\n return {reason: 'missing-organization-id', started: false}\n }\n\n const config = getDevServerConfig({cliConfig, flags, httpPort, output, workDir})\n\n try {\n output.log('Starting dev server')\n\n const appTitle = cliConfig && 'app' in cliConfig ? cliConfig.app?.title : undefined\n const {close, server} = await startDevServer({\n ...config,\n appTitle,\n isApp: true,\n })\n\n const {port} = server.config.server\n\n // Federated apps surface through the workbench, which announces the URL;\n // only the package-unavailable fallback announces from here.\n if (isWorkbenchApp && announceUrl) {\n const url = `http://${toDisplayHost(config.httpHost)}:${port}`\n output.log(`App dev server started at ${styleText(['blue', 'underline'], url)}`)\n } else if (!isWorkbenchApp) {\n const httpHost = config.httpHost || 'localhost'\n\n const dashboardAppUrl = await getDashboardAppURL({\n httpHost,\n httpPort: port,\n organizationId,\n })\n output.log(`Dev server started on port ${port}`)\n output.log(`View your app in the Sanity dashboard here:`)\n output.log(styleText(['blue', 'underline'], dashboardAppUrl))\n }\n\n return {close, server, started: true}\n } catch (err) {\n devDebug('Error starting app dev server', err)\n throw gracefulServerDeath('dev', config.httpHost, config.httpPort, err)\n }\n}\n"],"names":["styleText","isWorkbenchApp","determineIsWorkbenchApp","startDevServer","gracefulServerDeath","devDebug","getDashboardAppURL","getDevServerConfig","toDisplayHost","host","startAppDevServer","options","announceUrl","cliConfig","flags","httpPort","output","workDir","app","warn","organizationId","error","exit","reason","started","config","log","appTitle","title","undefined","close","server","isApp","port","url","httpHost","dashboardAppUrl","err"],"mappings":"AAAA,SAAQA,SAAS,QAAO,YAAW;AAEnC,SAAQC,kBAAkBC,uBAAuB,QAAO,wBAAuB;AAE/E,SAAQC,cAAc,QAAO,+BAA8B;AAC3D,SAAQC,mBAAmB,QAAO,yCAAwC;AAC1E,SAAQC,QAAQ,QAAO,iBAAgB;AAEvC,SAAQC,kBAAkB,QAAO,0BAAyB;AAC1D,SAAQC,kBAAkB,QAAO,0BAAyB;AAE1D,8EAA8E;AAC9E,+EAA+E;AAC/E,SAASC,cAAcC,IAAwB;IAC7C,IAAI,CAACA,QAAQA,SAAS,aAAaA,SAAS,QAAQA,SAAS,QAAQ;QACnE,OAAO;IACT;IACA,OAAOA;AACT;AAEA,OAAO,eAAeC,kBAAkBC,OAAyB;IAC/D,MAAM,EAACC,cAAc,IAAI,EAAEC,SAAS,EAAEC,KAAK,EAAEC,QAAQ,EAAEC,MAAM,EAAEC,OAAO,EAAC,GAAGN;IAE1E,MAAMV,iBAAiBC,wBAAwBW,WAAWK;IAE1D,sEAAsE;IACtE,mCAAmC;IACnC,IAAI,CAACjB,kBAAkB,CAACa,KAAK,CAAC,oBAAoB,EAAE;QAClDE,OAAOG,IAAI,CAAC,CAAC,4CAA4C,CAAC;QAC1DH,OAAOG,IAAI,CAAC,CAAC,iEAAiE,CAAC;IACjF;IAEA,IAAIC;IACJ,IAAIP,aAAa,SAASA,aAAaA,UAAUK,GAAG,EAAEE,gBAAgB;QACpEA,iBAAiBP,UAAUK,GAAG,CAACE,cAAc;IAC/C;IAEA,IAAI,CAACA,gBAAgB;QACnBJ,OAAOK,KAAK,CAAC,CAAC,4EAA4E,CAAC,EAAE;YAC3FC,MAAM;QACR;QACA,OAAO;YAACC,QAAQ;YAA2BC,SAAS;QAAK;IAC3D;IAEA,MAAMC,SAASlB,mBAAmB;QAACM;QAAWC;QAAOC;QAAUC;QAAQC;IAAO;IAE9E,IAAI;QACFD,OAAOU,GAAG,CAAC;QAEX,MAAMC,WAAWd,aAAa,SAASA,YAAYA,UAAUK,GAAG,EAAEU,QAAQC;QAC1E,MAAM,EAACC,KAAK,EAAEC,MAAM,EAAC,GAAG,MAAM5B,eAAe;YAC3C,GAAGsB,MAAM;YACTE;YACAK,OAAO;QACT;QAEA,MAAM,EAACC,IAAI,EAAC,GAAGF,OAAON,MAAM,CAACM,MAAM;QAEnC,yEAAyE;QACzE,6DAA6D;QAC7D,IAAI9B,kBAAkBW,aAAa;YACjC,MAAMsB,MAAM,CAAC,OAAO,EAAE1B,cAAciB,OAAOU,QAAQ,EAAE,CAAC,EAAEF,MAAM;YAC9DjB,OAAOU,GAAG,CAAC,CAAC,0BAA0B,EAAE1B,UAAU;gBAAC;gBAAQ;aAAY,EAAEkC,MAAM;QACjF,OAAO,IAAI,CAACjC,gBAAgB;YAC1B,MAAMkC,WAAWV,OAAOU,QAAQ,IAAI;YAEpC,MAAMC,kBAAkB,MAAM9B,mBAAmB;gBAC/C6B;gBACApB,UAAUkB;gBACVb;YACF;YACAJ,OAAOU,GAAG,CAAC,CAAC,2BAA2B,EAAEO,MAAM;YAC/CjB,OAAOU,GAAG,CAAC,CAAC,2CAA2C,CAAC;YACxDV,OAAOU,GAAG,CAAC1B,UAAU;gBAAC;gBAAQ;aAAY,EAAEoC;QAC9C;QAEA,OAAO;YAACN;YAAOC;YAAQP,SAAS;QAAI;IACtC,EAAE,OAAOa,KAAK;QACZhC,SAAS,iCAAiCgC;QAC1C,MAAMjC,oBAAoB,OAAOqB,OAAOU,QAAQ,EAAEV,OAAOV,QAAQ,EAAEsB;IACrE;AACF"}
1
+ {"version":3,"sources":["../../../../src/actions/dev/servers/startAppDevServer.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {exitCodes} from '@sanity/cli-core'\nimport {isWorkbenchApp as determineIsWorkbenchApp} from '@sanity/workbench-cli'\n\nimport {startDevServer} from '../../../server/devServer.js'\nimport {gracefulServerDeath} from '../../../server/gracefulServerDeath.js'\nimport {devDebug} from '../devDebug.js'\nimport {type DevActionOptions, type StartDevServerResult} from '../types.js'\nimport {getDashboardAppURL} from './getDashboardAppUrl.js'\nimport {getDevServerConfig} from './getDevServerConfig.js'\n\n// Bind-only addresses ('0.0.0.0', '::') aren't routable in every browser; the\n// displayed URL falls back to localhost. The bind address itself is untouched.\nfunction toDisplayHost(host: string | undefined): string {\n if (!host || host === '0.0.0.0' || host === '::' || host === '[::]') {\n return 'localhost'\n }\n return host\n}\n\nexport async function startAppDevServer(options: DevActionOptions): Promise<StartDevServerResult> {\n const {announceUrl = true, cliConfig, flags, httpPort, output, workDir} = options\n\n const isWorkbenchApp = determineIsWorkbenchApp(cliConfig?.app)\n\n // Workbench apps don't load through the dashboard, so the flag has no\n // meaning for them and is ignored.\n if (!isWorkbenchApp && !flags['load-in-dashboard']) {\n output.warn(`Apps cannot run without the Sanity dashboard`)\n output.warn(`Starting dev server with the --load-in-dashboard flag set to true`)\n }\n\n let organizationId: string | undefined\n if (cliConfig && 'app' in cliConfig && cliConfig.app?.organizationId) {\n organizationId = cliConfig.app.organizationId\n }\n\n if (!organizationId) {\n output.error(`Apps require an organization ID (orgId) specified in your sanity.cli.ts file`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n return {reason: 'missing-organization-id', started: false}\n }\n\n const config = getDevServerConfig({cliConfig, flags, httpPort, output, workDir})\n\n try {\n output.log('Starting dev server')\n\n const appTitle = cliConfig && 'app' in cliConfig ? cliConfig.app?.title : undefined\n const {close, server} = await startDevServer({\n ...config,\n appTitle,\n isApp: true,\n })\n\n const {port} = server.config.server\n\n // Federated apps surface through the workbench, which announces the URL;\n // only the package-unavailable fallback announces from here.\n if (isWorkbenchApp && announceUrl) {\n const url = `http://${toDisplayHost(config.httpHost)}:${port}`\n output.log(`App dev server started at ${styleText(['blue', 'underline'], url)}`)\n } else if (!isWorkbenchApp) {\n const httpHost = config.httpHost || 'localhost'\n\n const dashboardAppUrl = await getDashboardAppURL({\n httpHost,\n httpPort: port,\n organizationId,\n })\n output.log(`Dev server started on port ${port}`)\n output.log(`View your app in the Sanity dashboard here:`)\n output.log(styleText(['blue', 'underline'], dashboardAppUrl))\n }\n\n return {close, server, started: true}\n } catch (err) {\n devDebug('Error starting app dev server', err)\n throw gracefulServerDeath('dev', config.httpHost, config.httpPort, err)\n }\n}\n"],"names":["styleText","exitCodes","isWorkbenchApp","determineIsWorkbenchApp","startDevServer","gracefulServerDeath","devDebug","getDashboardAppURL","getDevServerConfig","toDisplayHost","host","startAppDevServer","options","announceUrl","cliConfig","flags","httpPort","output","workDir","app","warn","organizationId","error","exit","RUNTIME_ERROR","reason","started","config","log","appTitle","title","undefined","close","server","isApp","port","url","httpHost","dashboardAppUrl","err"],"mappings":"AAAA,SAAQA,SAAS,QAAO,YAAW;AAEnC,SAAQC,SAAS,QAAO,mBAAkB;AAC1C,SAAQC,kBAAkBC,uBAAuB,QAAO,wBAAuB;AAE/E,SAAQC,cAAc,QAAO,+BAA8B;AAC3D,SAAQC,mBAAmB,QAAO,yCAAwC;AAC1E,SAAQC,QAAQ,QAAO,iBAAgB;AAEvC,SAAQC,kBAAkB,QAAO,0BAAyB;AAC1D,SAAQC,kBAAkB,QAAO,0BAAyB;AAE1D,8EAA8E;AAC9E,+EAA+E;AAC/E,SAASC,cAAcC,IAAwB;IAC7C,IAAI,CAACA,QAAQA,SAAS,aAAaA,SAAS,QAAQA,SAAS,QAAQ;QACnE,OAAO;IACT;IACA,OAAOA;AACT;AAEA,OAAO,eAAeC,kBAAkBC,OAAyB;IAC/D,MAAM,EAACC,cAAc,IAAI,EAAEC,SAAS,EAAEC,KAAK,EAAEC,QAAQ,EAAEC,MAAM,EAAEC,OAAO,EAAC,GAAGN;IAE1E,MAAMV,iBAAiBC,wBAAwBW,WAAWK;IAE1D,sEAAsE;IACtE,mCAAmC;IACnC,IAAI,CAACjB,kBAAkB,CAACa,KAAK,CAAC,oBAAoB,EAAE;QAClDE,OAAOG,IAAI,CAAC,CAAC,4CAA4C,CAAC;QAC1DH,OAAOG,IAAI,CAAC,CAAC,iEAAiE,CAAC;IACjF;IAEA,IAAIC;IACJ,IAAIP,aAAa,SAASA,aAAaA,UAAUK,GAAG,EAAEE,gBAAgB;QACpEA,iBAAiBP,UAAUK,GAAG,CAACE,cAAc;IAC/C;IAEA,IAAI,CAACA,gBAAgB;QACnBJ,OAAOK,KAAK,CAAC,CAAC,4EAA4E,CAAC,EAAE;YAC3FC,MAAMtB,UAAUuB,aAAa;QAC/B;QACA,OAAO;YAACC,QAAQ;YAA2BC,SAAS;QAAK;IAC3D;IAEA,MAAMC,SAASnB,mBAAmB;QAACM;QAAWC;QAAOC;QAAUC;QAAQC;IAAO;IAE9E,IAAI;QACFD,OAAOW,GAAG,CAAC;QAEX,MAAMC,WAAWf,aAAa,SAASA,YAAYA,UAAUK,GAAG,EAAEW,QAAQC;QAC1E,MAAM,EAACC,KAAK,EAAEC,MAAM,EAAC,GAAG,MAAM7B,eAAe;YAC3C,GAAGuB,MAAM;YACTE;YACAK,OAAO;QACT;QAEA,MAAM,EAACC,IAAI,EAAC,GAAGF,OAAON,MAAM,CAACM,MAAM;QAEnC,yEAAyE;QACzE,6DAA6D;QAC7D,IAAI/B,kBAAkBW,aAAa;YACjC,MAAMuB,MAAM,CAAC,OAAO,EAAE3B,cAAckB,OAAOU,QAAQ,EAAE,CAAC,EAAEF,MAAM;YAC9DlB,OAAOW,GAAG,CAAC,CAAC,0BAA0B,EAAE5B,UAAU;gBAAC;gBAAQ;aAAY,EAAEoC,MAAM;QACjF,OAAO,IAAI,CAAClC,gBAAgB;YAC1B,MAAMmC,WAAWV,OAAOU,QAAQ,IAAI;YAEpC,MAAMC,kBAAkB,MAAM/B,mBAAmB;gBAC/C8B;gBACArB,UAAUmB;gBACVd;YACF;YACAJ,OAAOW,GAAG,CAAC,CAAC,2BAA2B,EAAEO,MAAM;YAC/ClB,OAAOW,GAAG,CAAC,CAAC,2CAA2C,CAAC;YACxDX,OAAOW,GAAG,CAAC5B,UAAU;gBAAC;gBAAQ;aAAY,EAAEsC;QAC9C;QAEA,OAAO;YAACN;YAAOC;YAAQP,SAAS;QAAI;IACtC,EAAE,OAAOa,KAAK;QACZjC,SAAS,iCAAiCiC;QAC1C,MAAMlC,oBAAoB,OAAOsB,OAAOU,QAAQ,EAAEV,OAAOX,QAAQ,EAAEuB;IACrE;AACF"}
@@ -1,6 +1,6 @@
1
1
  import { styleText } from 'node:util';
2
2
  import { checkRequiredDependencies, checkStudioDependencyVersions, compareDependencyVersions } from '@sanity/cli-build/_internal/build';
3
- import { getLocalPackageVersion, isInteractive } from '@sanity/cli-core';
3
+ import { exitCodes, getLocalPackageVersion, isInteractive } from '@sanity/cli-core';
4
4
  import { confirm, logSymbols, spinner } from '@sanity/cli-core/ux';
5
5
  import { isWorkbenchApp } from '@sanity/workbench-cli';
6
6
  import { parse as semverParse } from 'semver';
@@ -108,7 +108,7 @@ export async function startStudioDevServer(options) {
108
108
  if (loadInDashboard) {
109
109
  if (!projectId) {
110
110
  output.error('Project Id is required to load in dashboard', {
111
- exit: 1
111
+ exit: exitCodes.RUNTIME_ERROR
112
112
  });
113
113
  }
114
114
  try {
@@ -117,7 +117,7 @@ export async function startStudioDevServer(options) {
117
117
  } catch (error) {
118
118
  devDebug('Error getting organization id from project id', error);
119
119
  output.error('Failed to get organization id from project id', {
120
- exit: 1
120
+ exit: exitCodes.RUNTIME_ERROR
121
121
  });
122
122
  }
123
123
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/actions/dev/servers/startStudioDevServer.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {\n checkRequiredDependencies,\n checkStudioDependencyVersions,\n compareDependencyVersions,\n} from '@sanity/cli-build/_internal/build'\nimport {getLocalPackageVersion, isInteractive} from '@sanity/cli-core'\nimport {confirm, logSymbols, spinner} from '@sanity/cli-core/ux'\nimport {isWorkbenchApp} from '@sanity/workbench-cli'\nimport {parse as semverParse} from 'semver'\n\nimport {startDevServer} from '../../../server/devServer.js'\nimport {gracefulServerDeath} from '../../../server/gracefulServerDeath.js'\nimport {getProjectById} from '../../../services/projects.js'\nimport {getAppId} from '../../../util/appId.js'\nimport {getPackageManagerChoice} from '../../../util/packageManager/packageManagerChoice.js'\nimport {upgradePackages} from '../../../util/packageManager/upgradePackages.js'\nimport {hasLocalUnclaimedProject} from '../../../util/unclaimedProjects.js'\nimport {checkDependenciesEventListenerFactory} from '../../build/eventListenerFactory.js'\nimport {shouldAutoUpdate} from '../../build/shouldAutoUpdate.js'\nimport {devDebug} from '../devDebug.js'\nimport {type DevActionOptions, type StartDevServerResult} from '../types.js'\nimport {getDashboardAppURL} from './getDashboardAppUrl.js'\nimport {getDevServerConfig} from './getDevServerConfig.js'\n\nexport async function startStudioDevServer(\n options: DevActionOptions,\n): Promise<StartDevServerResult> {\n const {announceUrl = true, cliConfig, flags, httpPort, output, workDir} = options\n const projectId = cliConfig?.api?.projectId\n let organizationId: string | undefined\n\n // Workbench apps don't load through the dashboard, so the flag has no\n // meaning for them and is ignored.\n const loadInDashboard = flags['load-in-dashboard'] && !isWorkbenchApp(cliConfig?.app)\n\n // Check studio dependency versions\n await checkStudioDependencyVersions(workDir, output)\n\n const {installedSanityVersion} = await checkRequiredDependencies({\n ...options,\n ...checkDependenciesEventListenerFactory(output),\n })\n\n // Check if auto-updates are enabled\n const autoUpdatesEnabled = shouldAutoUpdate({cliConfig, flags, output})\n\n if (autoUpdatesEnabled) {\n // Get the clean version without build metadata: https://semver.org/#spec-item-10\n const cleanSanityVersion = semverParse(installedSanityVersion)?.version\n if (!cleanSanityVersion) {\n throw new Error(`Failed to parse installed Sanity version: ${installedSanityVersion}`)\n }\n\n const sanityDependencies = [\n {name: 'sanity', version: cleanSanityVersion},\n {name: '@sanity/vision', version: cleanSanityVersion},\n ]\n\n output.log(`${logSymbols.info} Running with auto-updates enabled`)\n\n // Check local versions against deployed versions\n let result: Awaited<ReturnType<typeof compareDependencyVersions>> | undefined\n\n const appId = getAppId(cliConfig)\n\n try {\n result = await compareDependencyVersions(sanityDependencies, workDir, {appId})\n } catch (err) {\n output.warn(`Failed to compare local versions against auto-updating versions: ${err}`)\n }\n\n if (result?.unresolvedPrerelease.length) {\n for (const mod of result.unresolvedPrerelease) {\n output.warn(\n `Your local version of ${mod.pkg} (${mod.version}) is a prerelease not available on the auto-updates CDN. The locally installed version will be used.`,\n )\n }\n }\n\n // mismatch between local and auto-updating dependencies\n if (result?.mismatched.length) {\n const message =\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 run with the same versions locally as will be used when deploying.\\n\\n` +\n `${result.mismatched.map((mod) => ` - ${mod.pkg} (local version: ${mod.installed}, runtime version: ${mod.remote})`).join('\\n')}\\n\\n`\n\n if (isInteractive()) {\n const shouldUpgrade = await confirm({\n default: true,\n message: styleText('yellow', `${message}Do you want to upgrade local versions?`),\n })\n if (shouldUpgrade) {\n await upgradePackages(\n {\n packageManager: (await getPackageManagerChoice(workDir, {interactive: false})).chosen,\n packages: result.mismatched.map((res) => [res.pkg, res.remote]),\n },\n {output, workDir},\n )\n }\n } else {\n // In this case we warn the user but we don't ask them if they want to upgrade because it's not interactive.\n output.log(styleText('yellow', message))\n }\n }\n }\n\n if (cliConfig?.schemaExtraction?.enabled) {\n output.log(`${logSymbols.info} Running dev server with schema extraction enabled`)\n }\n\n const config = getDevServerConfig({cliConfig, flags, httpPort, output, workDir})\n\n if (loadInDashboard) {\n if (!projectId) {\n output.error('Project Id is required to load in dashboard', {exit: 1})\n }\n\n try {\n const project = await getProjectById(projectId!)\n organizationId = project.organizationId!\n } catch (error) {\n devDebug('Error getting organization id from project id', error)\n output.error('Failed to get organization id from project id', {exit: 1})\n }\n }\n\n try {\n const startTime = Date.now()\n const spin = spinner('Starting dev server').start()\n const {close, server} = await startDevServer(config)\n\n const {info: loggerInfo} = server.config.logger\n const {port} = server.config.server\n const httpHost = config.httpHost || 'localhost'\n\n if (loadInDashboard) {\n spin.succeed()\n\n output.log(`Dev server started on port ${port}`)\n output.log(`View your studio in the Sanity dashboard here:`)\n output.log(\n styleText(\n ['blue', 'underline'],\n await getDashboardAppURL({\n httpHost,\n httpPort: port,\n organizationId: organizationId!,\n }),\n ),\n )\n } else {\n const startupDuration = Date.now() - startTime\n const url = withUnclaimedSignInHash(\n `http://${httpHost || 'localhost'}:${port}${config.basePath}`,\n projectId,\n )\n const appType = 'Sanity Studio'\n\n const viteVersion = await getLocalPackageVersion('vite', import.meta.url)\n spin.succeed()\n\n loggerInfo(\n `${appType} ` +\n `using ${styleText('cyan', `vite@${viteVersion}`)} ` +\n `ready in ${styleText('cyan', `${Math.ceil(startupDuration)}ms`)}` +\n (announceUrl ? ` and running at ${styleText('cyan', url)}` : ''),\n )\n }\n\n return {close, server, started: true}\n } catch (err) {\n devDebug('Error starting studio dev server', err)\n throw gracefulServerDeath('dev', config.httpHost, config.httpPort, err)\n }\n}\n\nfunction withUnclaimedSignInHash(url: string, projectId: string | undefined): string {\n const token = process.env.SANITY_AUTH_TOKEN\n if (!token || !projectId || !hasLocalUnclaimedProject(projectId)) return url\n return `${url}#token=${encodeURIComponent(token)}`\n}\n"],"names":["styleText","checkRequiredDependencies","checkStudioDependencyVersions","compareDependencyVersions","getLocalPackageVersion","isInteractive","confirm","logSymbols","spinner","isWorkbenchApp","parse","semverParse","startDevServer","gracefulServerDeath","getProjectById","getAppId","getPackageManagerChoice","upgradePackages","hasLocalUnclaimedProject","checkDependenciesEventListenerFactory","shouldAutoUpdate","devDebug","getDashboardAppURL","getDevServerConfig","startStudioDevServer","options","announceUrl","cliConfig","flags","httpPort","output","workDir","projectId","api","organizationId","loadInDashboard","app","installedSanityVersion","autoUpdatesEnabled","cleanSanityVersion","version","Error","sanityDependencies","name","log","info","result","appId","err","warn","unresolvedPrerelease","length","mod","pkg","mismatched","message","map","installed","remote","join","shouldUpgrade","default","packageManager","interactive","chosen","packages","res","schemaExtraction","enabled","config","error","exit","project","startTime","Date","now","spin","start","close","server","loggerInfo","logger","port","httpHost","succeed","startupDuration","url","withUnclaimedSignInHash","basePath","appType","viteVersion","Math","ceil","started","token","process","env","SANITY_AUTH_TOKEN","encodeURIComponent"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../src/actions/dev/servers/startStudioDevServer.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {\n checkRequiredDependencies,\n checkStudioDependencyVersions,\n compareDependencyVersions,\n} from '@sanity/cli-build/_internal/build'\nimport {exitCodes, getLocalPackageVersion, isInteractive} from '@sanity/cli-core'\nimport {confirm, logSymbols, spinner} from '@sanity/cli-core/ux'\nimport {isWorkbenchApp} from '@sanity/workbench-cli'\nimport {parse as semverParse} from 'semver'\n\nimport {startDevServer} from '../../../server/devServer.js'\nimport {gracefulServerDeath} from '../../../server/gracefulServerDeath.js'\nimport {getProjectById} from '../../../services/projects.js'\nimport {getAppId} from '../../../util/appId.js'\nimport {getPackageManagerChoice} from '../../../util/packageManager/packageManagerChoice.js'\nimport {upgradePackages} from '../../../util/packageManager/upgradePackages.js'\nimport {hasLocalUnclaimedProject} from '../../../util/unclaimedProjects.js'\nimport {checkDependenciesEventListenerFactory} from '../../build/eventListenerFactory.js'\nimport {shouldAutoUpdate} from '../../build/shouldAutoUpdate.js'\nimport {devDebug} from '../devDebug.js'\nimport {type DevActionOptions, type StartDevServerResult} from '../types.js'\nimport {getDashboardAppURL} from './getDashboardAppUrl.js'\nimport {getDevServerConfig} from './getDevServerConfig.js'\n\nexport async function startStudioDevServer(\n options: DevActionOptions,\n): Promise<StartDevServerResult> {\n const {announceUrl = true, cliConfig, flags, httpPort, output, workDir} = options\n const projectId = cliConfig?.api?.projectId\n let organizationId: string | undefined\n\n // Workbench apps don't load through the dashboard, so the flag has no\n // meaning for them and is ignored.\n const loadInDashboard = flags['load-in-dashboard'] && !isWorkbenchApp(cliConfig?.app)\n\n // Check studio dependency versions\n await checkStudioDependencyVersions(workDir, output)\n\n const {installedSanityVersion} = await checkRequiredDependencies({\n ...options,\n ...checkDependenciesEventListenerFactory(output),\n })\n\n // Check if auto-updates are enabled\n const autoUpdatesEnabled = shouldAutoUpdate({cliConfig, flags, output})\n\n if (autoUpdatesEnabled) {\n // Get the clean version without build metadata: https://semver.org/#spec-item-10\n const cleanSanityVersion = semverParse(installedSanityVersion)?.version\n if (!cleanSanityVersion) {\n throw new Error(`Failed to parse installed Sanity version: ${installedSanityVersion}`)\n }\n\n const sanityDependencies = [\n {name: 'sanity', version: cleanSanityVersion},\n {name: '@sanity/vision', version: cleanSanityVersion},\n ]\n\n output.log(`${logSymbols.info} Running with auto-updates enabled`)\n\n // Check local versions against deployed versions\n let result: Awaited<ReturnType<typeof compareDependencyVersions>> | undefined\n\n const appId = getAppId(cliConfig)\n\n try {\n result = await compareDependencyVersions(sanityDependencies, workDir, {appId})\n } catch (err) {\n output.warn(`Failed to compare local versions against auto-updating versions: ${err}`)\n }\n\n if (result?.unresolvedPrerelease.length) {\n for (const mod of result.unresolvedPrerelease) {\n output.warn(\n `Your local version of ${mod.pkg} (${mod.version}) is a prerelease not available on the auto-updates CDN. The locally installed version will be used.`,\n )\n }\n }\n\n // mismatch between local and auto-updating dependencies\n if (result?.mismatched.length) {\n const message =\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 run with the same versions locally as will be used when deploying.\\n\\n` +\n `${result.mismatched.map((mod) => ` - ${mod.pkg} (local version: ${mod.installed}, runtime version: ${mod.remote})`).join('\\n')}\\n\\n`\n\n if (isInteractive()) {\n const shouldUpgrade = await confirm({\n default: true,\n message: styleText('yellow', `${message}Do you want to upgrade local versions?`),\n })\n if (shouldUpgrade) {\n await upgradePackages(\n {\n packageManager: (await getPackageManagerChoice(workDir, {interactive: false})).chosen,\n packages: result.mismatched.map((res) => [res.pkg, res.remote]),\n },\n {output, workDir},\n )\n }\n } else {\n // In this case we warn the user but we don't ask them if they want to upgrade because it's not interactive.\n output.log(styleText('yellow', message))\n }\n }\n }\n\n if (cliConfig?.schemaExtraction?.enabled) {\n output.log(`${logSymbols.info} Running dev server with schema extraction enabled`)\n }\n\n const config = getDevServerConfig({cliConfig, flags, httpPort, output, workDir})\n\n if (loadInDashboard) {\n if (!projectId) {\n output.error('Project Id is required to load in dashboard', {exit: exitCodes.RUNTIME_ERROR})\n }\n\n try {\n const project = await getProjectById(projectId!)\n organizationId = project.organizationId!\n } catch (error) {\n devDebug('Error getting organization id from project id', error)\n output.error('Failed to get organization id from project id', {exit: exitCodes.RUNTIME_ERROR})\n }\n }\n\n try {\n const startTime = Date.now()\n const spin = spinner('Starting dev server').start()\n const {close, server} = await startDevServer(config)\n\n const {info: loggerInfo} = server.config.logger\n const {port} = server.config.server\n const httpHost = config.httpHost || 'localhost'\n\n if (loadInDashboard) {\n spin.succeed()\n\n output.log(`Dev server started on port ${port}`)\n output.log(`View your studio in the Sanity dashboard here:`)\n output.log(\n styleText(\n ['blue', 'underline'],\n await getDashboardAppURL({\n httpHost,\n httpPort: port,\n organizationId: organizationId!,\n }),\n ),\n )\n } else {\n const startupDuration = Date.now() - startTime\n const url = withUnclaimedSignInHash(\n `http://${httpHost || 'localhost'}:${port}${config.basePath}`,\n projectId,\n )\n const appType = 'Sanity Studio'\n\n const viteVersion = await getLocalPackageVersion('vite', import.meta.url)\n spin.succeed()\n\n loggerInfo(\n `${appType} ` +\n `using ${styleText('cyan', `vite@${viteVersion}`)} ` +\n `ready in ${styleText('cyan', `${Math.ceil(startupDuration)}ms`)}` +\n (announceUrl ? ` and running at ${styleText('cyan', url)}` : ''),\n )\n }\n\n return {close, server, started: true}\n } catch (err) {\n devDebug('Error starting studio dev server', err)\n throw gracefulServerDeath('dev', config.httpHost, config.httpPort, err)\n }\n}\n\nfunction withUnclaimedSignInHash(url: string, projectId: string | undefined): string {\n const token = process.env.SANITY_AUTH_TOKEN\n if (!token || !projectId || !hasLocalUnclaimedProject(projectId)) return url\n return `${url}#token=${encodeURIComponent(token)}`\n}\n"],"names":["styleText","checkRequiredDependencies","checkStudioDependencyVersions","compareDependencyVersions","exitCodes","getLocalPackageVersion","isInteractive","confirm","logSymbols","spinner","isWorkbenchApp","parse","semverParse","startDevServer","gracefulServerDeath","getProjectById","getAppId","getPackageManagerChoice","upgradePackages","hasLocalUnclaimedProject","checkDependenciesEventListenerFactory","shouldAutoUpdate","devDebug","getDashboardAppURL","getDevServerConfig","startStudioDevServer","options","announceUrl","cliConfig","flags","httpPort","output","workDir","projectId","api","organizationId","loadInDashboard","app","installedSanityVersion","autoUpdatesEnabled","cleanSanityVersion","version","Error","sanityDependencies","name","log","info","result","appId","err","warn","unresolvedPrerelease","length","mod","pkg","mismatched","message","map","installed","remote","join","shouldUpgrade","default","packageManager","interactive","chosen","packages","res","schemaExtraction","enabled","config","error","exit","RUNTIME_ERROR","project","startTime","Date","now","spin","start","close","server","loggerInfo","logger","port","httpHost","succeed","startupDuration","url","withUnclaimedSignInHash","basePath","appType","viteVersion","Math","ceil","started","token","process","env","SANITY_AUTH_TOKEN","encodeURIComponent"],"mappings":"AAAA,SAAQA,SAAS,QAAO,YAAW;AAEnC,SACEC,yBAAyB,EACzBC,6BAA6B,EAC7BC,yBAAyB,QACpB,oCAAmC;AAC1C,SAAQC,SAAS,EAAEC,sBAAsB,EAAEC,aAAa,QAAO,mBAAkB;AACjF,SAAQC,OAAO,EAAEC,UAAU,EAAEC,OAAO,QAAO,sBAAqB;AAChE,SAAQC,cAAc,QAAO,wBAAuB;AACpD,SAAQC,SAASC,WAAW,QAAO,SAAQ;AAE3C,SAAQC,cAAc,QAAO,+BAA8B;AAC3D,SAAQC,mBAAmB,QAAO,yCAAwC;AAC1E,SAAQC,cAAc,QAAO,gCAA+B;AAC5D,SAAQC,QAAQ,QAAO,yBAAwB;AAC/C,SAAQC,uBAAuB,QAAO,uDAAsD;AAC5F,SAAQC,eAAe,QAAO,kDAAiD;AAC/E,SAAQC,wBAAwB,QAAO,qCAAoC;AAC3E,SAAQC,qCAAqC,QAAO,sCAAqC;AACzF,SAAQC,gBAAgB,QAAO,kCAAiC;AAChE,SAAQC,QAAQ,QAAO,iBAAgB;AAEvC,SAAQC,kBAAkB,QAAO,0BAAyB;AAC1D,SAAQC,kBAAkB,QAAO,0BAAyB;AAE1D,OAAO,eAAeC,qBACpBC,OAAyB;IAEzB,MAAM,EAACC,cAAc,IAAI,EAAEC,SAAS,EAAEC,KAAK,EAAEC,QAAQ,EAAEC,MAAM,EAAEC,OAAO,EAAC,GAAGN;IAC1E,MAAMO,YAAYL,WAAWM,KAAKD;IAClC,IAAIE;IAEJ,sEAAsE;IACtE,mCAAmC;IACnC,MAAMC,kBAAkBP,KAAK,CAAC,oBAAoB,IAAI,CAACnB,eAAekB,WAAWS;IAEjF,mCAAmC;IACnC,MAAMnC,8BAA8B8B,SAASD;IAE7C,MAAM,EAACO,sBAAsB,EAAC,GAAG,MAAMrC,0BAA0B;QAC/D,GAAGyB,OAAO;QACV,GAAGN,sCAAsCW,OAAO;IAClD;IAEA,oCAAoC;IACpC,MAAMQ,qBAAqBlB,iBAAiB;QAACO;QAAWC;QAAOE;IAAM;IAErE,IAAIQ,oBAAoB;QACtB,iFAAiF;QACjF,MAAMC,qBAAqB5B,YAAY0B,yBAAyBG;QAChE,IAAI,CAACD,oBAAoB;YACvB,MAAM,IAAIE,MAAM,CAAC,0CAA0C,EAAEJ,wBAAwB;QACvF;QAEA,MAAMK,qBAAqB;YACzB;gBAACC,MAAM;gBAAUH,SAASD;YAAkB;YAC5C;gBAACI,MAAM;gBAAkBH,SAASD;YAAkB;SACrD;QAEDT,OAAOc,GAAG,CAAC,GAAGrC,WAAWsC,IAAI,CAAC,kCAAkC,CAAC;QAEjE,iDAAiD;QACjD,IAAIC;QAEJ,MAAMC,QAAQhC,SAASY;QAEvB,IAAI;YACFmB,SAAS,MAAM5C,0BAA0BwC,oBAAoBX,SAAS;gBAACgB;YAAK;QAC9E,EAAE,OAAOC,KAAK;YACZlB,OAAOmB,IAAI,CAAC,CAAC,iEAAiE,EAAED,KAAK;QACvF;QAEA,IAAIF,QAAQI,qBAAqBC,QAAQ;YACvC,KAAK,MAAMC,OAAON,OAAOI,oBAAoB,CAAE;gBAC7CpB,OAAOmB,IAAI,CACT,CAAC,sBAAsB,EAAEG,IAAIC,GAAG,CAAC,EAAE,EAAED,IAAIZ,OAAO,CAAC,oGAAoG,CAAC;YAE1J;QACF;QAEA,wDAAwD;QACxD,IAAIM,QAAQQ,WAAWH,QAAQ;YAC7B,MAAMI,UACJ,CAAC,mGAAmG,CAAC,GACrG,CAAC,qHAAqH,CAAC,GACvH,GAAGT,OAAOQ,UAAU,CAACE,GAAG,CAAC,CAACJ,MAAQ,CAAC,GAAG,EAAEA,IAAIC,GAAG,CAAC,iBAAiB,EAAED,IAAIK,SAAS,CAAC,mBAAmB,EAAEL,IAAIM,MAAM,CAAC,CAAC,CAAC,EAAEC,IAAI,CAAC,MAAM,IAAI,CAAC;YAEvI,IAAItD,iBAAiB;gBACnB,MAAMuD,gBAAgB,MAAMtD,QAAQ;oBAClCuD,SAAS;oBACTN,SAASxD,UAAU,UAAU,GAAGwD,QAAQ,sCAAsC,CAAC;gBACjF;gBACA,IAAIK,eAAe;oBACjB,MAAM3C,gBACJ;wBACE6C,gBAAgB,AAAC,CAAA,MAAM9C,wBAAwBe,SAAS;4BAACgC,aAAa;wBAAK,EAAC,EAAGC,MAAM;wBACrFC,UAAUnB,OAAOQ,UAAU,CAACE,GAAG,CAAC,CAACU,MAAQ;gCAACA,IAAIb,GAAG;gCAAEa,IAAIR,MAAM;6BAAC;oBAChE,GACA;wBAAC5B;wBAAQC;oBAAO;gBAEpB;YACF,OAAO;gBACL,4GAA4G;gBAC5GD,OAAOc,GAAG,CAAC7C,UAAU,UAAUwD;YACjC;QACF;IACF;IAEA,IAAI5B,WAAWwC,kBAAkBC,SAAS;QACxCtC,OAAOc,GAAG,CAAC,GAAGrC,WAAWsC,IAAI,CAAC,kDAAkD,CAAC;IACnF;IAEA,MAAMwB,SAAS9C,mBAAmB;QAACI;QAAWC;QAAOC;QAAUC;QAAQC;IAAO;IAE9E,IAAII,iBAAiB;QACnB,IAAI,CAACH,WAAW;YACdF,OAAOwC,KAAK,CAAC,+CAA+C;gBAACC,MAAMpE,UAAUqE,aAAa;YAAA;QAC5F;QAEA,IAAI;YACF,MAAMC,UAAU,MAAM3D,eAAekB;YACrCE,iBAAiBuC,QAAQvC,cAAc;QACzC,EAAE,OAAOoC,OAAO;YACdjD,SAAS,iDAAiDiD;YAC1DxC,OAAOwC,KAAK,CAAC,iDAAiD;gBAACC,MAAMpE,UAAUqE,aAAa;YAAA;QAC9F;IACF;IAEA,IAAI;QACF,MAAME,YAAYC,KAAKC,GAAG;QAC1B,MAAMC,OAAOrE,QAAQ,uBAAuBsE,KAAK;QACjD,MAAM,EAACC,KAAK,EAAEC,MAAM,EAAC,GAAG,MAAMpE,eAAeyD;QAE7C,MAAM,EAACxB,MAAMoC,UAAU,EAAC,GAAGD,OAAOX,MAAM,CAACa,MAAM;QAC/C,MAAM,EAACC,IAAI,EAAC,GAAGH,OAAOX,MAAM,CAACW,MAAM;QACnC,MAAMI,WAAWf,OAAOe,QAAQ,IAAI;QAEpC,IAAIjD,iBAAiB;YACnB0C,KAAKQ,OAAO;YAEZvD,OAAOc,GAAG,CAAC,CAAC,2BAA2B,EAAEuC,MAAM;YAC/CrD,OAAOc,GAAG,CAAC,CAAC,8CAA8C,CAAC;YAC3Dd,OAAOc,GAAG,CACR7C,UACE;gBAAC;gBAAQ;aAAY,EACrB,MAAMuB,mBAAmB;gBACvB8D;gBACAvD,UAAUsD;gBACVjD,gBAAgBA;YAClB;QAGN,OAAO;YACL,MAAMoD,kBAAkBX,KAAKC,GAAG,KAAKF;YACrC,MAAMa,MAAMC,wBACV,CAAC,OAAO,EAAEJ,YAAY,YAAY,CAAC,EAAED,OAAOd,OAAOoB,QAAQ,EAAE,EAC7DzD;YAEF,MAAM0D,UAAU;YAEhB,MAAMC,cAAc,MAAMvF,uBAAuB,QAAQ,YAAYmF,GAAG;YACxEV,KAAKQ,OAAO;YAEZJ,WACE,GAAGS,QAAQ,CAAC,CAAC,GACX,CAAC,MAAM,EAAE3F,UAAU,QAAQ,CAAC,KAAK,EAAE4F,aAAa,EAAE,CAAC,CAAC,GACpD,CAAC,SAAS,EAAE5F,UAAU,QAAQ,GAAG6F,KAAKC,IAAI,CAACP,iBAAiB,EAAE,CAAC,GAAG,GACjE5D,CAAAA,cAAc,CAAC,gBAAgB,EAAE3B,UAAU,QAAQwF,MAAM,GAAG,EAAC;QAEpE;QAEA,OAAO;YAACR;YAAOC;YAAQc,SAAS;QAAI;IACtC,EAAE,OAAO9C,KAAK;QACZ3B,SAAS,oCAAoC2B;QAC7C,MAAMnC,oBAAoB,OAAOwD,OAAOe,QAAQ,EAAEf,OAAOxC,QAAQ,EAAEmB;IACrE;AACF;AAEA,SAASwC,wBAAwBD,GAAW,EAAEvD,SAA6B;IACzE,MAAM+D,QAAQC,QAAQC,GAAG,CAACC,iBAAiB;IAC3C,IAAI,CAACH,SAAS,CAAC/D,aAAa,CAACd,yBAAyBc,YAAY,OAAOuD;IACzE,OAAO,GAAGA,IAAI,OAAO,EAAEY,mBAAmBJ,QAAQ;AACpD"}
@@ -1,5 +1,6 @@
1
1
  import { getGlobalCliClient } from '@sanity/cli-core/apiClient';
2
2
  import { createStudioWorker } from '@sanity/cli-core/tasks';
3
+ import { safeStructuredClone } from '@sanity/cli-core/util';
3
4
  import { WorkerChannelReceiver } from '@sanity/worker-channels';
4
5
  import { DOCUMENTS_API_VERSION } from './constants.js';
5
6
  const defaultReporter = ({ dispose, stream })=>{
@@ -39,8 +40,10 @@ export async function validateDocuments(options) {
39
40
  name: 'validateDocuments',
40
41
  studioRootPath: workDir,
41
42
  workerData: {
42
- // removes props in the config that make this object fail to serialize
43
- clientConfig: structuredClone(clientConfig),
43
+ // drops function-valued client config properties (e.g. request handlers
44
+ // and fetch implementations) since functions cannot cross the worker
45
+ // boundary; the worker rebuilds those from its own defaults
46
+ clientConfig: safeStructuredClone(clientConfig),
44
47
  dataset,
45
48
  level,
46
49
  maxCustomValidationConcurrency,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/documents/validate.ts"],"sourcesContent":["import {getGlobalCliClient} from '@sanity/cli-core/apiClient'\nimport {createStudioWorker} from '@sanity/cli-core/tasks'\nimport {type ClientConfig} from '@sanity/client'\nimport {type ValidationMarker} from '@sanity/types'\nimport {WorkerChannelReceiver} from '@sanity/worker-channels'\n\nimport {DOCUMENTS_API_VERSION} from './constants.js'\nimport {\n Level,\n type ValidateDocumentsWorkerData,\n type ValidationReceiver,\n type ValidationWorkerChannel,\n} from './types.js'\n\ninterface ValidateDocumentsOptions<TReturn = unknown> {\n dataset?: string // override\n level?: Level\n maxCustomValidationConcurrency?: number\n maxFetchConcurrency?: number\n ndjsonFilePath?: string\n projectId?: string // override\n reporter?: (worker: ValidationReceiver) => TReturn\n studioHost?: string\n workDir?: string\n workspace?: string\n}\n\ninterface DocumentValidationResult {\n documentId: string\n documentType: string\n level: ValidationMarker['level']\n markers: ValidationMarker[]\n revision: string\n}\n\nconst defaultReporter = ({dispose, stream}: ValidationReceiver) => {\n async function* createValidationGenerator() {\n for await (const {documentId, documentType, level, markers, revision} of stream.validation()) {\n const result: DocumentValidationResult = {\n documentId,\n documentType,\n level,\n markers,\n revision,\n }\n\n yield result\n }\n\n await dispose()\n }\n\n return createValidationGenerator()\n}\n\nexport function validateDocuments<TReturn>(\n options: Required<Pick<ValidateDocumentsOptions<TReturn>, 'reporter'>> &\n ValidateDocumentsOptions<TReturn>,\n): Promise<TReturn>\nexport function validateDocuments(\n options: ValidateDocumentsOptions,\n): Promise<AsyncIterable<DocumentValidationResult>>\nexport async function validateDocuments(options: ValidateDocumentsOptions): Promise<unknown> {\n const {\n dataset,\n level,\n maxCustomValidationConcurrency,\n maxFetchConcurrency,\n ndjsonFilePath,\n projectId,\n reporter = defaultReporter,\n workDir = process.cwd(),\n workspace,\n } = options\n\n const apiClient = await getGlobalCliClient({\n apiVersion: DOCUMENTS_API_VERSION,\n requireUser: true,\n })\n\n const clientConfig: ClientConfig = {\n ...apiClient.config(),\n // we set this explictly to true because we pass in a token via the\n // `clientConfiguration` object and also mock a browser environment in\n // this worker which triggers the browser warning\n ignoreBrowserTokenWarning: true,\n // we set this explictly to true because the default client configuration\n // from the CLI comes configured with `useProjectHostname: false` when\n // `requireProject` is set to false\n useProjectHostname: true,\n }\n\n const worker = createStudioWorker(new URL('validateDocuments.worker.js', import.meta.url), {\n name: 'validateDocuments',\n studioRootPath: workDir,\n workerData: {\n // removes props in the config that make this object fail to serialize\n clientConfig: structuredClone(clientConfig),\n dataset,\n level,\n maxCustomValidationConcurrency,\n maxFetchConcurrency,\n ndjsonFilePath,\n projectId,\n studioHost: options.studioHost,\n workDir,\n workspace,\n } satisfies ValidateDocumentsWorkerData,\n })\n\n const receiver = WorkerChannelReceiver.from<ValidationWorkerChannel>(worker)\n const validationReceiver: ValidationReceiver = {\n dispose: async () => {\n receiver.unsubscribe()\n return worker.terminate()\n },\n event: receiver.event,\n stream: receiver.stream,\n }\n\n return reporter(validationReceiver)\n}\n"],"names":["getGlobalCliClient","createStudioWorker","WorkerChannelReceiver","DOCUMENTS_API_VERSION","defaultReporter","dispose","stream","createValidationGenerator","documentId","documentType","level","markers","revision","validation","result","validateDocuments","options","dataset","maxCustomValidationConcurrency","maxFetchConcurrency","ndjsonFilePath","projectId","reporter","workDir","process","cwd","workspace","apiClient","apiVersion","requireUser","clientConfig","config","ignoreBrowserTokenWarning","useProjectHostname","worker","URL","url","name","studioRootPath","workerData","structuredClone","studioHost","receiver","from","validationReceiver","unsubscribe","terminate","event"],"mappings":"AAAA,SAAQA,kBAAkB,QAAO,6BAA4B;AAC7D,SAAQC,kBAAkB,QAAO,yBAAwB;AAGzD,SAAQC,qBAAqB,QAAO,0BAAyB;AAE7D,SAAQC,qBAAqB,QAAO,iBAAgB;AA6BpD,MAAMC,kBAAkB,CAAC,EAACC,OAAO,EAAEC,MAAM,EAAqB;IAC5D,gBAAgBC;QACd,WAAW,MAAM,EAACC,UAAU,EAAEC,YAAY,EAAEC,KAAK,EAAEC,OAAO,EAAEC,QAAQ,EAAC,IAAIN,OAAOO,UAAU,GAAI;YAC5F,MAAMC,SAAmC;gBACvCN;gBACAC;gBACAC;gBACAC;gBACAC;YACF;YAEA,MAAME;QACR;QAEA,MAAMT;IACR;IAEA,OAAOE;AACT;AASA,OAAO,eAAeQ,kBAAkBC,OAAiC;IACvE,MAAM,EACJC,OAAO,EACPP,KAAK,EACLQ,8BAA8B,EAC9BC,mBAAmB,EACnBC,cAAc,EACdC,SAAS,EACTC,WAAWlB,eAAe,EAC1BmB,UAAUC,QAAQC,GAAG,EAAE,EACvBC,SAAS,EACV,GAAGV;IAEJ,MAAMW,YAAY,MAAM3B,mBAAmB;QACzC4B,YAAYzB;QACZ0B,aAAa;IACf;IAEA,MAAMC,eAA6B;QACjC,GAAGH,UAAUI,MAAM,EAAE;QACrB,mEAAmE;QACnE,sEAAsE;QACtE,iDAAiD;QACjDC,2BAA2B;QAC3B,yEAAyE;QACzE,sEAAsE;QACtE,mCAAmC;QACnCC,oBAAoB;IACtB;IAEA,MAAMC,SAASjC,mBAAmB,IAAIkC,IAAI,+BAA+B,YAAYC,GAAG,GAAG;QACzFC,MAAM;QACNC,gBAAgBf;QAChBgB,YAAY;YACV,sEAAsE;YACtET,cAAcU,gBAAgBV;YAC9Bb;YACAP;YACAQ;YACAC;YACAC;YACAC;YACAoB,YAAYzB,QAAQyB,UAAU;YAC9BlB;YACAG;QACF;IACF;IAEA,MAAMgB,WAAWxC,sBAAsByC,IAAI,CAA0BT;IACrE,MAAMU,qBAAyC;QAC7CvC,SAAS;YACPqC,SAASG,WAAW;YACpB,OAAOX,OAAOY,SAAS;QACzB;QACAC,OAAOL,SAASK,KAAK;QACrBzC,QAAQoC,SAASpC,MAAM;IACzB;IAEA,OAAOgB,SAASsB;AAClB"}
1
+ {"version":3,"sources":["../../../src/actions/documents/validate.ts"],"sourcesContent":["import {getGlobalCliClient} from '@sanity/cli-core/apiClient'\nimport {createStudioWorker} from '@sanity/cli-core/tasks'\nimport {safeStructuredClone} from '@sanity/cli-core/util'\nimport {type ClientConfig} from '@sanity/client'\nimport {type ValidationMarker} from '@sanity/types'\nimport {WorkerChannelReceiver} from '@sanity/worker-channels'\n\nimport {DOCUMENTS_API_VERSION} from './constants.js'\nimport {\n Level,\n type ValidateDocumentsWorkerData,\n type ValidationReceiver,\n type ValidationWorkerChannel,\n} from './types.js'\n\ninterface ValidateDocumentsOptions<TReturn = unknown> {\n dataset?: string // override\n level?: Level\n maxCustomValidationConcurrency?: number\n maxFetchConcurrency?: number\n ndjsonFilePath?: string\n projectId?: string // override\n reporter?: (worker: ValidationReceiver) => TReturn\n studioHost?: string\n workDir?: string\n workspace?: string\n}\n\ninterface DocumentValidationResult {\n documentId: string\n documentType: string\n level: ValidationMarker['level']\n markers: ValidationMarker[]\n revision: string\n}\n\nconst defaultReporter = ({dispose, stream}: ValidationReceiver) => {\n async function* createValidationGenerator() {\n for await (const {documentId, documentType, level, markers, revision} of stream.validation()) {\n const result: DocumentValidationResult = {\n documentId,\n documentType,\n level,\n markers,\n revision,\n }\n\n yield result\n }\n\n await dispose()\n }\n\n return createValidationGenerator()\n}\n\nexport function validateDocuments<TReturn>(\n options: Required<Pick<ValidateDocumentsOptions<TReturn>, 'reporter'>> &\n ValidateDocumentsOptions<TReturn>,\n): Promise<TReturn>\nexport function validateDocuments(\n options: ValidateDocumentsOptions,\n): Promise<AsyncIterable<DocumentValidationResult>>\nexport async function validateDocuments(options: ValidateDocumentsOptions): Promise<unknown> {\n const {\n dataset,\n level,\n maxCustomValidationConcurrency,\n maxFetchConcurrency,\n ndjsonFilePath,\n projectId,\n reporter = defaultReporter,\n workDir = process.cwd(),\n workspace,\n } = options\n\n const apiClient = await getGlobalCliClient({\n apiVersion: DOCUMENTS_API_VERSION,\n requireUser: true,\n })\n\n const clientConfig: ClientConfig = {\n ...apiClient.config(),\n // we set this explictly to true because we pass in a token via the\n // `clientConfiguration` object and also mock a browser environment in\n // this worker which triggers the browser warning\n ignoreBrowserTokenWarning: true,\n // we set this explictly to true because the default client configuration\n // from the CLI comes configured with `useProjectHostname: false` when\n // `requireProject` is set to false\n useProjectHostname: true,\n }\n\n const worker = createStudioWorker(new URL('validateDocuments.worker.js', import.meta.url), {\n name: 'validateDocuments',\n studioRootPath: workDir,\n workerData: {\n // drops function-valued client config properties (e.g. request handlers\n // and fetch implementations) since functions cannot cross the worker\n // boundary; the worker rebuilds those from its own defaults\n clientConfig: safeStructuredClone(clientConfig),\n dataset,\n level,\n maxCustomValidationConcurrency,\n maxFetchConcurrency,\n ndjsonFilePath,\n projectId,\n studioHost: options.studioHost,\n workDir,\n workspace,\n } satisfies ValidateDocumentsWorkerData,\n })\n\n const receiver = WorkerChannelReceiver.from<ValidationWorkerChannel>(worker)\n const validationReceiver: ValidationReceiver = {\n dispose: async () => {\n receiver.unsubscribe()\n return worker.terminate()\n },\n event: receiver.event,\n stream: receiver.stream,\n }\n\n return reporter(validationReceiver)\n}\n"],"names":["getGlobalCliClient","createStudioWorker","safeStructuredClone","WorkerChannelReceiver","DOCUMENTS_API_VERSION","defaultReporter","dispose","stream","createValidationGenerator","documentId","documentType","level","markers","revision","validation","result","validateDocuments","options","dataset","maxCustomValidationConcurrency","maxFetchConcurrency","ndjsonFilePath","projectId","reporter","workDir","process","cwd","workspace","apiClient","apiVersion","requireUser","clientConfig","config","ignoreBrowserTokenWarning","useProjectHostname","worker","URL","url","name","studioRootPath","workerData","studioHost","receiver","from","validationReceiver","unsubscribe","terminate","event"],"mappings":"AAAA,SAAQA,kBAAkB,QAAO,6BAA4B;AAC7D,SAAQC,kBAAkB,QAAO,yBAAwB;AACzD,SAAQC,mBAAmB,QAAO,wBAAuB;AAGzD,SAAQC,qBAAqB,QAAO,0BAAyB;AAE7D,SAAQC,qBAAqB,QAAO,iBAAgB;AA6BpD,MAAMC,kBAAkB,CAAC,EAACC,OAAO,EAAEC,MAAM,EAAqB;IAC5D,gBAAgBC;QACd,WAAW,MAAM,EAACC,UAAU,EAAEC,YAAY,EAAEC,KAAK,EAAEC,OAAO,EAAEC,QAAQ,EAAC,IAAIN,OAAOO,UAAU,GAAI;YAC5F,MAAMC,SAAmC;gBACvCN;gBACAC;gBACAC;gBACAC;gBACAC;YACF;YAEA,MAAME;QACR;QAEA,MAAMT;IACR;IAEA,OAAOE;AACT;AASA,OAAO,eAAeQ,kBAAkBC,OAAiC;IACvE,MAAM,EACJC,OAAO,EACPP,KAAK,EACLQ,8BAA8B,EAC9BC,mBAAmB,EACnBC,cAAc,EACdC,SAAS,EACTC,WAAWlB,eAAe,EAC1BmB,UAAUC,QAAQC,GAAG,EAAE,EACvBC,SAAS,EACV,GAAGV;IAEJ,MAAMW,YAAY,MAAM5B,mBAAmB;QACzC6B,YAAYzB;QACZ0B,aAAa;IACf;IAEA,MAAMC,eAA6B;QACjC,GAAGH,UAAUI,MAAM,EAAE;QACrB,mEAAmE;QACnE,sEAAsE;QACtE,iDAAiD;QACjDC,2BAA2B;QAC3B,yEAAyE;QACzE,sEAAsE;QACtE,mCAAmC;QACnCC,oBAAoB;IACtB;IAEA,MAAMC,SAASlC,mBAAmB,IAAImC,IAAI,+BAA+B,YAAYC,GAAG,GAAG;QACzFC,MAAM;QACNC,gBAAgBf;QAChBgB,YAAY;YACV,wEAAwE;YACxE,qEAAqE;YACrE,4DAA4D;YAC5DT,cAAc7B,oBAAoB6B;YAClCb;YACAP;YACAQ;YACAC;YACAC;YACAC;YACAmB,YAAYxB,QAAQwB,UAAU;YAC9BjB;YACAG;QACF;IACF;IAEA,MAAMe,WAAWvC,sBAAsBwC,IAAI,CAA0BR;IACrE,MAAMS,qBAAyC;QAC7CtC,SAAS;YACPoC,SAASG,WAAW;YACpB,OAAOV,OAAOW,SAAS;QACzB;QACAC,OAAOL,SAASK,KAAK;QACrBxC,QAAQmC,SAASnC,MAAM;IACzB;IAEA,OAAOgB,SAASqB;AAClB"}
@@ -1,5 +1,6 @@
1
1
  import { styleText } from 'node:util';
2
2
  import { CLIError } from '@oclif/core/errors';
3
+ import { exitCodes } from '@sanity/cli-core';
3
4
  import { writeEnvVarsToFile } from './writeEnvVarsToFile.js';
4
5
  export async function createOrAppendEnvVars({ envVars, filename, framework, log, output, outputPath }) {
5
6
  try {
@@ -17,7 +18,7 @@ export async function createOrAppendEnvVars({ envVars, filename, framework, log,
17
18
  } catch (err) {
18
19
  output.error(err);
19
20
  throw new CLIError('An error occurred while creating .env', {
20
- exit: 1
21
+ exit: exitCodes.RUNTIME_ERROR
21
22
  });
22
23
  }
23
24
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/actions/init/env/createOrAppendEnvVars.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {CLIError} from '@oclif/core/errors'\nimport {Output} from '@sanity/cli-core'\n\nimport {VersionedFramework} from '../types.js'\nimport {writeEnvVarsToFile} from './writeEnvVarsToFile.js'\n\ninterface CreateOrAppendEnvVarsOptions {\n envVars: Record<string, string>\n filename: string\n framework: VersionedFramework | null\n log: boolean\n output: Output\n outputPath: string\n}\n\nexport async function createOrAppendEnvVars({\n envVars,\n filename,\n framework,\n log,\n output,\n outputPath,\n}: CreateOrAppendEnvVarsOptions) {\n try {\n if (framework && framework.envPrefix && log) {\n output.log(\n `\\nDetected framework ${styleText('blue', framework?.name ?? '')}, using prefix '${\n framework.envPrefix\n }'`,\n )\n }\n\n await writeEnvVarsToFile({\n envVars,\n filename,\n framework,\n log,\n output,\n outputPath,\n })\n } catch (err) {\n output.error(err)\n throw new CLIError('An error occurred while creating .env', {exit: 1})\n }\n}\n"],"names":["styleText","CLIError","writeEnvVarsToFile","createOrAppendEnvVars","envVars","filename","framework","log","output","outputPath","envPrefix","name","err","error","exit"],"mappings":"AAAA,SAAQA,SAAS,QAAO,YAAW;AAEnC,SAAQC,QAAQ,QAAO,qBAAoB;AAI3C,SAAQC,kBAAkB,QAAO,0BAAyB;AAW1D,OAAO,eAAeC,sBAAsB,EAC1CC,OAAO,EACPC,QAAQ,EACRC,SAAS,EACTC,GAAG,EACHC,MAAM,EACNC,UAAU,EACmB;IAC7B,IAAI;QACF,IAAIH,aAAaA,UAAUI,SAAS,IAAIH,KAAK;YAC3CC,OAAOD,GAAG,CACR,CAAC,qBAAqB,EAAEP,UAAU,QAAQM,WAAWK,QAAQ,IAAI,gBAAgB,EAC/EL,UAAUI,SAAS,CACpB,CAAC,CAAC;QAEP;QAEA,MAAMR,mBAAmB;YACvBE;YACAC;YACAC;YACAC;YACAC;YACAC;QACF;IACF,EAAE,OAAOG,KAAK;QACZJ,OAAOK,KAAK,CAACD;QACb,MAAM,IAAIX,SAAS,yCAAyC;YAACa,MAAM;QAAC;IACtE;AACF"}
1
+ {"version":3,"sources":["../../../../src/actions/init/env/createOrAppendEnvVars.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {CLIError} from '@oclif/core/errors'\nimport {exitCodes, Output} from '@sanity/cli-core'\n\nimport {VersionedFramework} from '../types.js'\nimport {writeEnvVarsToFile} from './writeEnvVarsToFile.js'\n\ninterface CreateOrAppendEnvVarsOptions {\n envVars: Record<string, string>\n filename: string\n framework: VersionedFramework | null\n log: boolean\n output: Output\n outputPath: string\n}\n\nexport async function createOrAppendEnvVars({\n envVars,\n filename,\n framework,\n log,\n output,\n outputPath,\n}: CreateOrAppendEnvVarsOptions) {\n try {\n if (framework && framework.envPrefix && log) {\n output.log(\n `\\nDetected framework ${styleText('blue', framework?.name ?? '')}, using prefix '${\n framework.envPrefix\n }'`,\n )\n }\n\n await writeEnvVarsToFile({\n envVars,\n filename,\n framework,\n log,\n output,\n outputPath,\n })\n } catch (err) {\n output.error(err)\n throw new CLIError('An error occurred while creating .env', {exit: exitCodes.RUNTIME_ERROR})\n }\n}\n"],"names":["styleText","CLIError","exitCodes","writeEnvVarsToFile","createOrAppendEnvVars","envVars","filename","framework","log","output","outputPath","envPrefix","name","err","error","exit","RUNTIME_ERROR"],"mappings":"AAAA,SAAQA,SAAS,QAAO,YAAW;AAEnC,SAAQC,QAAQ,QAAO,qBAAoB;AAC3C,SAAQC,SAAS,QAAe,mBAAkB;AAGlD,SAAQC,kBAAkB,QAAO,0BAAyB;AAW1D,OAAO,eAAeC,sBAAsB,EAC1CC,OAAO,EACPC,QAAQ,EACRC,SAAS,EACTC,GAAG,EACHC,MAAM,EACNC,UAAU,EACmB;IAC7B,IAAI;QACF,IAAIH,aAAaA,UAAUI,SAAS,IAAIH,KAAK;YAC3CC,OAAOD,GAAG,CACR,CAAC,qBAAqB,EAAER,UAAU,QAAQO,WAAWK,QAAQ,IAAI,gBAAgB,EAC/EL,UAAUI,SAAS,CACpB,CAAC,CAAC;QAEP;QAEA,MAAMR,mBAAmB;YACvBE;YACAC;YACAC;YACAC;YACAC;YACAC;QACF;IACF,EAAE,OAAOG,KAAK;QACZJ,OAAOK,KAAK,CAACD;QACb,MAAM,IAAIZ,SAAS,yCAAyC;YAACc,MAAMb,UAAUc,aAAa;QAAA;IAC5F;AACF"}
@@ -1,6 +1,6 @@
1
- import dotenv from 'dotenv';
1
+ import { parseEnv } from 'node:util';
2
2
  export function parseAndUpdateEnvVars({ envVars, fileContents, log, output }) {
3
- const existingKeys = dotenv.parse(fileContents) // this will contain all vars
3
+ const existingKeys = parseEnv(fileContents) // this will contain all vars
4
4
  ;
5
5
  const updatedKeys = {} // this will only contain our vars
6
6
  ;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/actions/init/env/parseAndUpdateEnvVars.ts"],"sourcesContent":["import {Output} from '@sanity/cli-core'\nimport dotenv from 'dotenv'\n\ninterface ParseAndUpdateEnvVarsOptions {\n envVars: Record<string, string>\n fileContents: string\n log: boolean\n output: Output\n}\n\nexport function parseAndUpdateEnvVars({\n envVars,\n fileContents,\n log,\n output,\n}: ParseAndUpdateEnvVarsOptions): string {\n const existingKeys = dotenv.parse(fileContents) // this will contain all vars\n const updatedKeys: Record<string, string> = {} // this will only contain our vars\n\n // find and update keys\n for (const [key, value] of Object.entries(envVars)) {\n if (!existingKeys[key]) {\n updatedKeys[key] = value\n\n if (log) {\n output.log(`Appended ${key}=\"${envVars[key]}\"`)\n }\n\n continue\n }\n\n if (log) {\n output.log(`Found existing ${key}, replacing value.`)\n }\n updatedKeys[key] = value\n }\n\n // clone fileContents and replace existing keys by string matching\n let updatedEnv = fileContents\n for (const [key, value] of Object.entries(updatedKeys)) {\n if (existingKeys[key]) {\n const existingValue = existingKeys[key]\n\n updatedEnv = updatedEnv\n .split('\\n')\n .map((line) => {\n if (\n !line.trim().startsWith('#') && // ignore comments\n new RegExp(String.raw`(^\\s*${key})((: )|( *=))`).test(line) // match key\n ) {\n return line.replace(existingValue, value)\n }\n return line\n })\n .join('\\n')\n } else {\n updatedEnv = `${updatedEnv.trim()}\\n${key}=\"${value}\"`\n }\n }\n\n // if file is empty, add a newline\n return `${updatedEnv}${fileContents === '' ? '\\n' : ''}`\n}\n"],"names":["dotenv","parseAndUpdateEnvVars","envVars","fileContents","log","output","existingKeys","parse","updatedKeys","key","value","Object","entries","updatedEnv","existingValue","split","map","line","trim","startsWith","RegExp","String","raw","test","replace","join"],"mappings":"AACA,OAAOA,YAAY,SAAQ;AAS3B,OAAO,SAASC,sBAAsB,EACpCC,OAAO,EACPC,YAAY,EACZC,GAAG,EACHC,MAAM,EACuB;IAC7B,MAAMC,eAAeN,OAAOO,KAAK,CAACJ,cAAc,6BAA6B;;IAC7E,MAAMK,cAAsC,CAAC,EAAE,kCAAkC;;IAEjF,uBAAuB;IACvB,KAAK,MAAM,CAACC,KAAKC,MAAM,IAAIC,OAAOC,OAAO,CAACV,SAAU;QAClD,IAAI,CAACI,YAAY,CAACG,IAAI,EAAE;YACtBD,WAAW,CAACC,IAAI,GAAGC;YAEnB,IAAIN,KAAK;gBACPC,OAAOD,GAAG,CAAC,CAAC,SAAS,EAAEK,IAAI,EAAE,EAAEP,OAAO,CAACO,IAAI,CAAC,CAAC,CAAC;YAChD;YAEA;QACF;QAEA,IAAIL,KAAK;YACPC,OAAOD,GAAG,CAAC,CAAC,eAAe,EAAEK,IAAI,kBAAkB,CAAC;QACtD;QACAD,WAAW,CAACC,IAAI,GAAGC;IACrB;IAEA,kEAAkE;IAClE,IAAIG,aAAaV;IACjB,KAAK,MAAM,CAACM,KAAKC,MAAM,IAAIC,OAAOC,OAAO,CAACJ,aAAc;QACtD,IAAIF,YAAY,CAACG,IAAI,EAAE;YACrB,MAAMK,gBAAgBR,YAAY,CAACG,IAAI;YAEvCI,aAAaA,WACVE,KAAK,CAAC,MACNC,GAAG,CAAC,CAACC;gBACJ,IACE,CAACA,KAAKC,IAAI,GAAGC,UAAU,CAAC,QAAQ,kBAAkB;gBAClD,IAAIC,OAAOC,OAAOC,GAAG,CAAC,KAAK,EAAEb,IAAI,aAAa,CAAC,EAAEc,IAAI,CAACN,MAAM,YAAY;kBACxE;oBACA,OAAOA,KAAKO,OAAO,CAACV,eAAeJ;gBACrC;gBACA,OAAOO;YACT,GACCQ,IAAI,CAAC;QACV,OAAO;YACLZ,aAAa,GAAGA,WAAWK,IAAI,GAAG,EAAE,EAAET,IAAI,EAAE,EAAEC,MAAM,CAAC,CAAC;QACxD;IACF;IAEA,kCAAkC;IAClC,OAAO,GAAGG,aAAaV,iBAAiB,KAAK,OAAO,IAAI;AAC1D"}
1
+ {"version":3,"sources":["../../../../src/actions/init/env/parseAndUpdateEnvVars.ts"],"sourcesContent":["import {parseEnv} from 'node:util'\n\nimport {Output} from '@sanity/cli-core'\n\ninterface ParseAndUpdateEnvVarsOptions {\n envVars: Record<string, string>\n fileContents: string\n log: boolean\n output: Output\n}\n\nexport function parseAndUpdateEnvVars({\n envVars,\n fileContents,\n log,\n output,\n}: ParseAndUpdateEnvVarsOptions): string {\n const existingKeys = parseEnv(fileContents) // this will contain all vars\n const updatedKeys: Record<string, string> = {} // this will only contain our vars\n\n // find and update keys\n for (const [key, value] of Object.entries(envVars)) {\n if (!existingKeys[key]) {\n updatedKeys[key] = value\n\n if (log) {\n output.log(`Appended ${key}=\"${envVars[key]}\"`)\n }\n\n continue\n }\n\n if (log) {\n output.log(`Found existing ${key}, replacing value.`)\n }\n updatedKeys[key] = value\n }\n\n // clone fileContents and replace existing keys by string matching\n let updatedEnv = fileContents\n for (const [key, value] of Object.entries(updatedKeys)) {\n if (existingKeys[key]) {\n const existingValue = existingKeys[key]\n\n updatedEnv = updatedEnv\n .split('\\n')\n .map((line) => {\n if (\n !line.trim().startsWith('#') && // ignore comments\n new RegExp(String.raw`(^\\s*${key})((: )|( *=))`).test(line) // match key\n ) {\n return line.replace(existingValue, value)\n }\n return line\n })\n .join('\\n')\n } else {\n updatedEnv = `${updatedEnv.trim()}\\n${key}=\"${value}\"`\n }\n }\n\n // if file is empty, add a newline\n return `${updatedEnv}${fileContents === '' ? '\\n' : ''}`\n}\n"],"names":["parseEnv","parseAndUpdateEnvVars","envVars","fileContents","log","output","existingKeys","updatedKeys","key","value","Object","entries","updatedEnv","existingValue","split","map","line","trim","startsWith","RegExp","String","raw","test","replace","join"],"mappings":"AAAA,SAAQA,QAAQ,QAAO,YAAW;AAWlC,OAAO,SAASC,sBAAsB,EACpCC,OAAO,EACPC,YAAY,EACZC,GAAG,EACHC,MAAM,EACuB;IAC7B,MAAMC,eAAeN,SAASG,cAAc,6BAA6B;;IACzE,MAAMI,cAAsC,CAAC,EAAE,kCAAkC;;IAEjF,uBAAuB;IACvB,KAAK,MAAM,CAACC,KAAKC,MAAM,IAAIC,OAAOC,OAAO,CAACT,SAAU;QAClD,IAAI,CAACI,YAAY,CAACE,IAAI,EAAE;YACtBD,WAAW,CAACC,IAAI,GAAGC;YAEnB,IAAIL,KAAK;gBACPC,OAAOD,GAAG,CAAC,CAAC,SAAS,EAAEI,IAAI,EAAE,EAAEN,OAAO,CAACM,IAAI,CAAC,CAAC,CAAC;YAChD;YAEA;QACF;QAEA,IAAIJ,KAAK;YACPC,OAAOD,GAAG,CAAC,CAAC,eAAe,EAAEI,IAAI,kBAAkB,CAAC;QACtD;QACAD,WAAW,CAACC,IAAI,GAAGC;IACrB;IAEA,kEAAkE;IAClE,IAAIG,aAAaT;IACjB,KAAK,MAAM,CAACK,KAAKC,MAAM,IAAIC,OAAOC,OAAO,CAACJ,aAAc;QACtD,IAAID,YAAY,CAACE,IAAI,EAAE;YACrB,MAAMK,gBAAgBP,YAAY,CAACE,IAAI;YAEvCI,aAAaA,WACVE,KAAK,CAAC,MACNC,GAAG,CAAC,CAACC;gBACJ,IACE,CAACA,KAAKC,IAAI,GAAGC,UAAU,CAAC,QAAQ,kBAAkB;gBAClD,IAAIC,OAAOC,OAAOC,GAAG,CAAC,KAAK,EAAEb,IAAI,aAAa,CAAC,EAAEc,IAAI,CAACN,MAAM,YAAY;kBACxE;oBACA,OAAOA,KAAKO,OAAO,CAACV,eAAeJ;gBACrC;gBACA,OAAOO;YACT,GACCQ,IAAI,CAAC;QACV,OAAO;YACLZ,aAAa,GAAGA,WAAWK,IAAI,GAAG,EAAE,EAAET,IAAI,EAAE,EAAEC,MAAM,CAAC,CAAC;QACxD;IACF;IAEA,kCAAkC;IAClC,OAAO,GAAGG,aAAaT,iBAAiB,KAAK,OAAO,IAAI;AAC1D"}
@@ -7,9 +7,9 @@ export const sdkAppDependencies = {
7
7
  'react-dom': '^19.2.4'
8
8
  },
9
9
  devDependencies: {
10
- '@sanity/eslint-config-studio': '^6',
10
+ '@sanity/eslint-config-studio': '^7',
11
11
  '@types/react': '^19.2.14',
12
- eslint: '^9.28',
12
+ eslint: '^10.8.1',
13
13
  prettier: '^3.5',
14
14
  sanity: 'latest',
15
15
  typescript: '^5.8'
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/init/sdkAppDependencies.ts"],"sourcesContent":["export const sdkAppDependencies = {\n dependencies: {\n // change these to 'latest' as in studioDependencies.ts once SDK v3 is released\n '@sanity/sdk': '^2',\n '@sanity/sdk-react': '^2',\n react: '^19.2.4',\n 'react-dom': '^19.2.4',\n },\n\n devDependencies: {\n '@sanity/eslint-config-studio': '^6',\n '@types/react': '^19.2.14',\n eslint: '^9.28',\n prettier: '^3.5',\n sanity: 'latest',\n typescript: '^5.8', // Peer dependency of eslint-config-studio (implicitly)\n },\n}\n"],"names":["sdkAppDependencies","dependencies","react","devDependencies","eslint","prettier","sanity","typescript"],"mappings":"AAAA,OAAO,MAAMA,qBAAqB;IAChCC,cAAc;QACZ,+EAA+E;QAC/E,eAAe;QACf,qBAAqB;QACrBC,OAAO;QACP,aAAa;IACf;IAEAC,iBAAiB;QACf,gCAAgC;QAChC,gBAAgB;QAChBC,QAAQ;QACRC,UAAU;QACVC,QAAQ;QACRC,YAAY;IACd;AACF,EAAC"}
1
+ {"version":3,"sources":["../../../src/actions/init/sdkAppDependencies.ts"],"sourcesContent":["export const sdkAppDependencies = {\n dependencies: {\n // change these to 'latest' as in studioDependencies.ts once SDK v3 is released\n '@sanity/sdk': '^2',\n '@sanity/sdk-react': '^2',\n react: '^19.2.4',\n 'react-dom': '^19.2.4',\n },\n\n devDependencies: {\n '@sanity/eslint-config-studio': '^7',\n '@types/react': '^19.2.14',\n eslint: '^10.8.1',\n prettier: '^3.5',\n sanity: 'latest',\n typescript: '^5.8', // Peer dependency of eslint-config-studio (implicitly)\n },\n}\n"],"names":["sdkAppDependencies","dependencies","react","devDependencies","eslint","prettier","sanity","typescript"],"mappings":"AAAA,OAAO,MAAMA,qBAAqB;IAChCC,cAAc;QACZ,+EAA+E;QAC/E,eAAe;QACf,qBAAqB;QACrBC,OAAO;QACP,aAAa;IACf;IAEAC,iBAAiB;QACf,gCAAgC;QAChC,gBAAgB;QAChBC,QAAQ;QACRC,UAAU;QACVC,QAAQ;QACRC,YAAY;IACd;AACF,EAAC"}
@@ -12,10 +12,10 @@ export const studioDependencies = {
12
12
  },
13
13
  devDependencies: {
14
14
  // Linting/tooling
15
- '@sanity/eslint-config-studio': '^6',
15
+ '@sanity/eslint-config-studio': '^7',
16
16
  // When using typescript, we'll want the these types too, so might as well install them
17
17
  '@types/react': '^19.2.14',
18
- eslint: '^9.28',
18
+ eslint: '^10.8.1',
19
19
  prettier: '^3.5',
20
20
  typescript: '^5.8'
21
21
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/init/studioDependencies.ts"],"sourcesContent":["export const studioDependencies = {\n // Dependencies for a default Sanity installation\n dependencies: {\n // Official studio dependencies\n sanity: 'latest',\n\n // Official studio plugin dependencies\n '@sanity/vision': 'latest',\n\n // Non-Sanity dependencies\n react: '^19.2.4',\n 'react-dom': '^19.2.4',\n 'styled-components': '^6.1.18',\n },\n\n devDependencies: {\n // Linting/tooling\n '@sanity/eslint-config-studio': '^6',\n // When using typescript, we'll want the these types too, so might as well install them\n '@types/react': '^19.2.14',\n eslint: '^9.28',\n prettier: '^3.5',\n typescript: '^5.8', // Peer dependency of eslint-config-studio (implicitly)\n },\n}\n"],"names":["studioDependencies","dependencies","sanity","react","devDependencies","eslint","prettier","typescript"],"mappings":"AAAA,OAAO,MAAMA,qBAAqB;IAChC,iDAAiD;IACjDC,cAAc;QACZ,+BAA+B;QAC/BC,QAAQ;QAER,sCAAsC;QACtC,kBAAkB;QAElB,0BAA0B;QAC1BC,OAAO;QACP,aAAa;QACb,qBAAqB;IACvB;IAEAC,iBAAiB;QACf,kBAAkB;QAClB,gCAAgC;QAChC,uFAAuF;QACvF,gBAAgB;QAChBC,QAAQ;QACRC,UAAU;QACVC,YAAY;IACd;AACF,EAAC"}
1
+ {"version":3,"sources":["../../../src/actions/init/studioDependencies.ts"],"sourcesContent":["export const studioDependencies = {\n // Dependencies for a default Sanity installation\n dependencies: {\n // Official studio dependencies\n sanity: 'latest',\n\n // Official studio plugin dependencies\n '@sanity/vision': 'latest',\n\n // Non-Sanity dependencies\n react: '^19.2.4',\n 'react-dom': '^19.2.4',\n 'styled-components': '^6.1.18',\n },\n\n devDependencies: {\n // Linting/tooling\n '@sanity/eslint-config-studio': '^7',\n // When using typescript, we'll want the these types too, so might as well install them\n '@types/react': '^19.2.14',\n eslint: '^10.8.1',\n prettier: '^3.5',\n typescript: '^5.8', // Peer dependency of eslint-config-studio (implicitly)\n },\n}\n"],"names":["studioDependencies","dependencies","sanity","react","devDependencies","eslint","prettier","typescript"],"mappings":"AAAA,OAAO,MAAMA,qBAAqB;IAChC,iDAAiD;IACjDC,cAAc;QACZ,+BAA+B;QAC/BC,QAAQ;QAER,sCAAsC;QACtC,kBAAkB;QAElB,0BAA0B;QAC1BC,OAAO;QACP,aAAa;QACb,qBAAqB;IACvB;IAEAC,iBAAiB;QACf,kBAAkB;QAClB,gCAAgC;QAChC,uFAAuF;QACvF,gBAAgB;QAChBC,QAAQ;QACRC,UAAU;QACVC,YAAY;IACd;AACF,EAAC"}