@sanity/cli 8.10.0 → 8.12.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.
- package/README.md +69 -26
- package/dist/actions/assets/ingestAssetFromUrlWithProgress.js +21 -0
- package/dist/actions/assets/ingestAssetFromUrlWithProgress.js.map +1 -0
- package/dist/actions/assets/withUrlIngestProgress.js +45 -0
- package/dist/actions/assets/withUrlIngestProgress.js.map +1 -0
- package/dist/actions/auth/authServer.js +5 -8
- package/dist/actions/auth/authServer.js.map +1 -1
- package/dist/actions/auth/login/getProvider.js +10 -14
- package/dist/actions/auth/login/getProvider.js.map +1 -1
- package/dist/actions/auth/login/login.js +0 -1
- package/dist/actions/auth/login/login.js.map +1 -1
- package/dist/actions/deploy/deployApp.js +5 -2
- package/dist/actions/deploy/deployApp.js.map +1 -1
- package/dist/actions/deploy/deployChecks.js +3 -2
- package/dist/actions/deploy/deployChecks.js.map +1 -1
- package/dist/actions/deploy/findUserApplication.js +3 -2
- package/dist/actions/deploy/findUserApplication.js.map +1 -1
- package/dist/actions/deploy/resolveDeployTarget.js +6 -1
- package/dist/actions/deploy/resolveDeployTarget.js.map +1 -1
- package/dist/actions/documents/validateDocuments.worker.js +1 -4
- package/dist/actions/documents/validateDocuments.worker.js.map +1 -1
- package/dist/actions/media/importMedia.js.map +1 -1
- package/dist/actions/media/ingestMediaAssetFromUrlWithProgress.js +19 -0
- package/dist/actions/media/ingestMediaAssetFromUrlWithProgress.js.map +1 -0
- package/dist/commands/assets/upload.js +78 -52
- package/dist/commands/assets/upload.js.map +1 -1
- package/dist/commands/deploy.js +33 -1
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/media/import.js +149 -13
- package/dist/commands/media/import.js.map +1 -1
- package/dist/exports/invokeSanityCli/commandPolicies/index.js +1 -4
- package/dist/exports/invokeSanityCli/commandPolicies/index.js.map +1 -1
- package/dist/exports/invokeSanityCli/commandPolicies/mcpPolicy.js +26 -6
- package/dist/exports/invokeSanityCli/commandPolicies/mcpPolicy.js.map +1 -1
- package/dist/exports/invokeSanityCli/commandPolicies/resolve.js +112 -0
- package/dist/exports/invokeSanityCli/commandPolicies/resolve.js.map +1 -0
- package/dist/exports/invokeSanityCli/help.js +8 -1
- package/dist/exports/invokeSanityCli/help.js.map +1 -1
- package/dist/exports/invokeSanityCli/index.d.ts +1 -2
- package/dist/exports/invokeSanityCli/index.js +37 -15
- package/dist/exports/invokeSanityCli/index.js.map +1 -1
- package/dist/generated/apiRoutes.js +2 -0
- package/dist/generated/apiRoutes.js.map +1 -1
- package/dist/services/assets.js +46 -1
- package/dist/services/assets.js.map +1 -1
- package/dist/services/mediaLibraries.js +39 -1
- package/dist/services/mediaLibraries.js.map +1 -1
- package/dist/util/assetSourceValidation.js +56 -0
- package/dist/util/assetSourceValidation.js.map +1 -0
- package/dist/util/assetUploadErrors.js +64 -0
- package/dist/util/assetUploadErrors.js.map +1 -0
- package/dist/util/isRemoteAssetSource.js +19 -0
- package/dist/util/isRemoteAssetSource.js.map +1 -0
- package/dist/util/parseAspectFlags.js +34 -0
- package/dist/util/parseAspectFlags.js.map +1 -0
- package/oclif.config.js +0 -1
- package/oclif.manifest.json +2134 -2055
- package/package.json +18 -18
- package/templates/app-quickstart/AGENTS.md +18 -0
- package/templates/app-sanity-ui/AGENTS.md +18 -0
- package/templates/shopify/.gitignore +26 -0
- package/dist/exports/invokeSanityCli/commandPolicies/policy.js +0 -46
- package/dist/exports/invokeSanityCli/commandPolicies/policy.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/deploy/deployApp.ts"],"sourcesContent":["import {basename, dirname} from 'node:path'\nimport {styleText} from 'node:util'\nimport {createGzip} from 'node:zlib'\n\nimport {\n type CoreAppManifest,\n extractCoreAppManifest,\n readIconFromPath,\n resolveTitleUpdate,\n} from '@sanity/cli-build/_internal/manifest'\nimport {type AppVisibility, exitCodes} from '@sanity/cli-core'\nimport {getErrorMessage} from '@sanity/cli-core/errors'\nimport {getCoreAppUrl} from '@sanity/cli-core/util'\nimport {spinner} from '@sanity/cli-core/ux'\nimport {\n createCoreApp,\n deployConfig,\n deployWorkbenchApp,\n getApplicationUrl,\n getWorkbench,\n resolveInstallationId,\n resolveWorkbenchConfig,\n summarizeConfig,\n toWorkbenchPayload,\n} from '@sanity/workbench-cli/deploy'\nimport {c as createTar} from 'tar'\n\nimport {\n createDeployment,\n updateUserApplication,\n type UserApplication,\n type UserApplicationResolved,\n} from '../../services/userApplications.js'\nimport {getAppId} from '../../util/appId.js'\nimport {EXTERNAL_APP_NOT_SUPPORTED, NO_ORGANIZATION_ID} from '../../util/errorMessages.js'\nimport {buildApp} from '../build/buildApp.js'\nimport {createUserApplication} from './createUserApplication.js'\nimport {\n checkAppId,\n checkAppTarget,\n checkAutoUpdates,\n checkBuild,\n checkPackageVersion,\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 {findUserApplication} from './findUserApplication.js'\nimport {type DeployAppOptions} from './types.js'\n\nconst APP_PACKAGE = '@sanity/sdk-react'\n\nexport function deployApp(options: DeployAppOptions): Promise<void> {\n return runDeploy(options, {\n listFiles: ({projectRoot, sourceDir}) => listDeploymentFiles(sourceDir, projectRoot.directory),\n run: runAppDeployment,\n type: 'coreApp',\n })\n}\n\n/** Validates the deploy, syncs the title from the manifest, and ships the build. */\nasync function runAppDeployment(\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 organizationId = cliConfig.app?.organizationId\n const appId = getAppId(cliConfig)\n const workbench = getWorkbench(cliConfig)\n // A config (the Media Library) is not an app — it resolves through its own\n // brand and persists to the org's installation instead of hosting an application.\n const config = resolveWorkbenchConfig(cliConfig)\n const dryRun = !!flags['dry-run']\n\n const deployConfigOnly = !!config\n const deployApplication = !config && (!workbench || workbench.hasInterfaces)\n\n const appTitle = workbench\n ? flags.title?.trim() || cliConfig.app?.title?.trim() || workbench.slug\n : ''\n\n // A federated app with no entry, view or service would ship a remote with\n // nothing to load — reported first so it fails before any prompt or API call.\n if (workbench) {\n try {\n workbench.assertDeployable()\n } catch (err) {\n reporter.report({\n exitCode: exitCodes.USAGE_ERROR,\n message: getErrorMessage(err),\n solution: 'Declare at least one entry, view, or service in the app',\n status: 'fail',\n })\n }\n }\n\n // A config with no fields would overwrite the org's live config with an empty\n // snapshot, so block it here — same \"nothing to deploy\" gate an app gets.\n if (config && config.fields.length === 0) {\n reporter.report({\n exitCode: exitCodes.USAGE_ERROR,\n message: 'Nothing to deploy: the media library config declares no fields.',\n solution: 'Add at least one field to the media library config',\n status: 'fail',\n })\n }\n\n const isAutoUpdating = checkAutoUpdates(reporter, {cliConfig, flags})\n\n // An application ships the SDK runtime; a media-library config stamps its\n // `sanity` version instead.\n let version: string | null = null\n if (deployApplication) {\n version = await checkPackageVersion(reporter, {moduleName: APP_PACKAGE, workDir})\n } else if (deployConfigOnly) {\n version = await checkPackageVersion(reporter, {moduleName: 'sanity', workDir})\n }\n\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\n checkAppId(reporter, {cliConfig})\n\n let application: UserApplicationResolved | null = null\n let appCreated = false\n let workbenchApp: object | undefined\n if (flags.external) {\n reporter.report({\n message: EXTERNAL_APP_NOT_SUPPORTED,\n solution: 'Remove the --external flag — apps deploy to Sanity hosting',\n status: 'fail',\n })\n } else if (deployApplication && workbench) {\n workbenchApp = (\n await checkAppTarget(reporter, {\n appId,\n isWorkbenchApp: true,\n organizationId,\n slug: workbench.slug,\n title: appTitle,\n })\n )?.application\n } else if (deployApplication) {\n ;({application, created: appCreated} = await resolveAppApplication(options, {dryRun, reporter}))\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 (deployApplication && workbench && !appId && !flags.external && !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 && workbench?.icon ? await readIconFromPath(workDir, workbench.icon) : undefined\n\n // Create the app 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 && deployApplication && workbench && organizationId && !applicationId) {\n const created = await createCoreApp({\n isSingleton: workbench.isSingleton,\n name: workbench.name,\n organizationId,\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 buildApp({\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: flags.build\n ? undefined\n : 'Build skipped (--no-build) — validating existing output directory',\n successMessage: 'App built',\n })\n\n await verifyOutputDir({\n isWorkbenchApp: workbench !== null || config !== null,\n reporter,\n sourceDir,\n })\n\n // Workbench apps and configs ship a federation remote and don't read the\n // core-app manifest; only plain core-apps do. Manifests aren't strictly\n // essential, so a failure warns and continues.\n let manifest: CoreAppManifest | undefined\n if (!workbench && !config) {\n try {\n manifest = await extractCoreAppManifest({workDir})\n } catch (err) {\n deployDebug('Error extracting app manifest', err)\n reporter.report({\n message: `Error extracting app manifest: ${getErrorMessage(err)}`,\n status: 'warn',\n })\n }\n }\n\n // Resolve the installation in both modes so the report — dry-run and real —\n // shows whether the config is deployable; a missing one fails the deploy here.\n let installationId: string | undefined\n let configSummary: string | undefined\n const configAppType = config?.appType\n if (deployConfigOnly && organizationId && config && configAppType) {\n installationId = await resolveInstallationId({appType: configAppType, organizationId})\n configSummary = summarizeConfig(config)\n reporter.report(\n installationId\n ? {message: configSummary, status: 'pass'}\n : {\n exitCode: exitCodes.USAGE_ERROR,\n message: `No active \"${configAppType}\" installation for organization \"${organizationId}\"`,\n solution:\n 'Install the Media Library for the organization before deploying its config',\n status: 'fail',\n },\n )\n }\n\n const interfaces = deployApplication && workbench ? reportInterfaces(reporter, workbench) : null\n\n // Applied after the app is live (see below) so a failed deploy never leaves\n // the org's installation config without its application.\n const deployApplicationConfig = async (): Promise<void> => {\n if (installationId && version && configAppType && organizationId) {\n await deployConfig({\n appType: configAppType,\n installationId,\n organizationId,\n output,\n sourceDir,\n version,\n })\n }\n }\n\n const payload: DeployPayload = {\n appId: appId ?? null,\n isAutoUpdating,\n ...(organizationId ? {organizationId} : {}),\n type: 'coreApp',\n version,\n ...toWorkbenchPayload(workbench, {config: configSummary, interfaces, title: appTitle}),\n ...(configSummary ? {config: configSummary} : {}),\n }\n\n // Dry run stops here — everything below mutates.\n if (dryRun) return {application: null, payload}\n\n // A config-only singleton ships no application, only its config.\n if (!deployApplication) {\n await deployApplicationConfig()\n if (installationId && version) {\n return {application: null, installationId, payload}\n }\n return\n }\n\n // A real deploy already exited on a version-resolution failure; this narrows the type.\n if (!version) return\n\n // The app was created (or resolved from `deployment.appId`) before the build,\n // so this only ships the deployment; plain coreApps use user-applications below.\n if (workbench && organizationId && applicationId) {\n await deployWorkbenchApp({\n app: cliConfig.app,\n applicationId,\n icon: appIcon,\n isApp: true,\n isAutoUpdating,\n // Once the deployment is live, a metadata-sync or later config failure\n // must not delete the app.\n onDeployed: () => {\n rollbackApp = undefined\n },\n slug: workbench.slug,\n sourceDir,\n title: appTitle,\n version,\n visibility: workbench.visibility,\n })\n await deployApplicationConfig()\n const url = getApplicationUrl({id: applicationId, organizationId, type: 'coreApp'})\n logAppDeployed({\n applicationId,\n cliConfig,\n created: applicationCreated,\n organizationId,\n output,\n title: appTitle,\n url,\n })\n return {\n action: applicationCreated ? 'create' : 'update',\n application: workbenchApp ?? null,\n payload,\n url,\n }\n }\n\n // A real deploy has already exited if anything failed; landing here without a\n // resolved application means the deploy target was never resolved.\n if (!application) return\n\n application = await syncApplicationMetadata({\n application,\n manifest,\n output,\n visibility: cliConfig.app?.visibility,\n })\n await shipAppDeployment({application, isAutoUpdating, manifest, sourceDir, version})\n logAppDeployed({\n applicationId: application.id,\n cliConfig,\n created: appCreated,\n organizationId: application.organizationId,\n output,\n title: application.title,\n })\n return {\n action: appCreated ? 'create' : 'update',\n application,\n payload,\n url: getCoreAppUrl(application.organizationId, application.id),\n }\n } catch (err) {\n await rollbackApp?.()\n throw err\n }\n}\n\n/**\n * Finds the application a real deploy targets, creating one when none is\n * configured. A dry run resolves and reports the target read-only instead.\n */\nasync function resolveAppApplication(\n options: DeployAppOptions,\n {dryRun, reporter}: {dryRun: boolean; reporter: DeployCheckReporter},\n): Promise<{application: UserApplicationResolved | null; created: boolean}> {\n const {cliConfig, flags, output} = options\n const organizationId = cliConfig.app?.organizationId ?? ''\n // Create name from --title or `app.title` config; blank falls back to the prompt\n const title = flags.title?.trim() || cliConfig.app?.title?.trim() || undefined\n\n if (dryRun) {\n await checkAppTarget(reporter, {appId: getAppId(cliConfig), organizationId, title})\n return {application: null, created: false}\n }\n\n let application = await findUserApplication({\n cliConfig,\n organizationId,\n output,\n title,\n unattended: !!flags.yes,\n })\n deployDebug('User application found', application)\n\n if (!application) {\n deployDebug('No user application found. Creating a new one')\n application = await createUserApplication(organizationId, title, cliConfig.app?.visibility)\n deployDebug('User application created', application)\n return {application, created: true}\n }\n\n return {application, created: false}\n}\n\n/**\n * Syncs application metadata on redeploy when it has changed: the title from the\n * manifest and the dashboard visibility from config. Sends a single PATCH with\n * only the changed fields, and skips the request entirely when nothing changed.\n */\nexport async function syncApplicationMetadata({\n application,\n manifest,\n output,\n visibility,\n}: {\n application: UserApplicationResolved\n manifest: CoreAppManifest | undefined\n output: DeployAppOptions['output']\n visibility: AppVisibility | undefined\n}): Promise<UserApplicationResolved> {\n const titleUpdate = resolveTitleUpdate(manifest, application)\n // Treat an unset server value as `default` so a config of `default` is a no-op.\n const visibilityChanged =\n visibility !== undefined && visibility !== (application.dashboardStatus ?? 'default')\n\n if (!titleUpdate && !visibilityChanged) return application\n\n if (titleUpdate) {\n deployDebug('Updating application title from manifest', titleUpdate)\n output.log(\n titleUpdate.from\n ? `Updating title from \"${titleUpdate.from}\" to \"${titleUpdate.to}\"`\n : `Setting application title to \"${titleUpdate.to}\"`,\n )\n }\n if (visibilityChanged) {\n output.log(`Setting dashboard visibility to \"${visibility}\"`)\n }\n\n const spin = spinner('Updating application').start()\n try {\n const updated = await updateUserApplication({\n applicationId: application.id,\n appType: 'coreApp',\n body: {\n ...(titleUpdate ? {title: titleUpdate.to} : {}),\n ...(visibilityChanged ? {dashboardStatus: visibility} : {}),\n },\n })\n spin.succeed()\n return updated\n } catch (err) {\n spin.fail()\n const message = getErrorMessage(err)\n deployDebug('Error updating application metadata', {message})\n output.warn(`Error updating application metadata: ${message}`)\n return application\n }\n}\n\nasync function shipAppDeployment({\n application,\n isAutoUpdating,\n manifest,\n sourceDir,\n version,\n}: {\n application: UserApplication\n isAutoUpdating: boolean\n manifest: CoreAppManifest | undefined\n sourceDir: string\n version: string\n}): Promise<void> {\n const tarball = createTar({cwd: dirname(sourceDir)}, [basename(sourceDir)]).pipe(createGzip())\n\n const spin = spinner('Deploying...').start()\n try {\n await createDeployment({\n applicationId: application.id,\n isApp: true,\n isAutoUpdating,\n manifest,\n tarball,\n version,\n })\n } catch (error) {\n spin.clear()\n throw error\n }\n spin.succeed()\n}\n\nexport function logAppDeployed({\n applicationId,\n cliConfig,\n created,\n organizationId,\n output,\n title,\n url = getCoreAppUrl(organizationId, applicationId),\n}: {\n applicationId: string\n cliConfig: DeployAppOptions['cliConfig']\n created: boolean\n organizationId: string\n output: DeployAppOptions['output']\n title: string | null\n url?: string\n}): void {\n const named = title ? ` — \"${title}\"` : ''\n output.log(`\\nSuccess! Application deployed to ${styleText('cyan', url)}${named}`)\n output.log(created ? 'Created a new application.' : 'Updated the existing application.')\n\n if (getAppId(cliConfig)) return\n\n output.log(`\\n════ ${styleText('bold', 'Next step:')} ════`)\n if (created) {\n output.log(\n styleText(\n 'yellow',\n '\\nDeploying again without `deployment.appId` creates another new application.',\n ),\n )\n }\n output.log(\n styleText('bold', '\\nAdd the deployment.appId to your sanity.cli.js or sanity.cli.ts file:'),\n )\n output.log(`\n${styleText(\n 'dim',\n `app: {\n // your application config here…\n}`,\n)},\n${styleText(\n ['bold', 'green'],\n `deployment: {\n appId: '${applicationId}',\n}\\n`,\n)}`)\n}\n"],"names":["basename","dirname","styleText","createGzip","extractCoreAppManifest","readIconFromPath","resolveTitleUpdate","exitCodes","getErrorMessage","getCoreAppUrl","spinner","createCoreApp","deployConfig","deployWorkbenchApp","getApplicationUrl","getWorkbench","resolveInstallationId","resolveWorkbenchConfig","summarizeConfig","toWorkbenchPayload","c","createTar","createDeployment","updateUserApplication","getAppId","EXTERNAL_APP_NOT_SUPPORTED","NO_ORGANIZATION_ID","buildApp","createUserApplication","checkAppId","checkAppTarget","checkAutoUpdates","checkBuild","checkPackageVersion","verifyOutputDir","deployDebug","listDeploymentFiles","reportInterfaces","runDeploy","findUserApplication","APP_PACKAGE","deployApp","options","listFiles","projectRoot","sourceDir","directory","run","runAppDeployment","type","reporter","cliConfig","flags","output","workDir","organizationId","app","appId","workbench","config","dryRun","deployConfigOnly","deployApplication","hasInterfaces","appTitle","title","trim","slug","assertDeployable","err","report","exitCode","USAGE_ERROR","message","solution","status","fields","length","isAutoUpdating","version","moduleName","application","appCreated","workbenchApp","external","isWorkbenchApp","created","resolveAppApplication","build","appIcon","icon","undefined","applicationId","applicationCreated","rollbackApp","isSingleton","name","visibility","id","rollback","autoUpdatesEnabled","calledFromDeploy","outDir","skipReason","successMessage","manifest","installationId","configSummary","configAppType","appType","interfaces","deployApplicationConfig","payload","isApp","onDeployed","url","logAppDeployed","action","syncApplicationMetadata","shipAppDeployment","unattended","yes","titleUpdate","visibilityChanged","dashboardStatus","log","from","to","spin","start","updated","body","succeed","fail","warn","tarball","cwd","pipe","error","clear","named"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/deploy/deployApp.ts"],"sourcesContent":["import {basename, dirname} from 'node:path'\nimport {styleText} from 'node:util'\nimport {createGzip} from 'node:zlib'\n\nimport {\n type CoreAppManifest,\n extractCoreAppManifest,\n readIconFromPath,\n resolveTitleUpdate,\n} from '@sanity/cli-build/_internal/manifest'\nimport {type AppVisibility, exitCodes} from '@sanity/cli-core'\nimport {getErrorMessage} from '@sanity/cli-core/errors'\nimport {getCoreAppUrl} from '@sanity/cli-core/util'\nimport {spinner} from '@sanity/cli-core/ux'\nimport {\n createCoreApp,\n deployConfig,\n deployWorkbenchApp,\n getApplicationUrl,\n getWorkbench,\n resolveInstallationId,\n resolveWorkbenchConfig,\n summarizeConfig,\n toWorkbenchPayload,\n} from '@sanity/workbench-cli/deploy'\nimport {c as createTar} from 'tar'\n\nimport {\n createDeployment,\n updateUserApplication,\n type UserApplication,\n type UserApplicationResolved,\n} from '../../services/userApplications.js'\nimport {getAppId} from '../../util/appId.js'\nimport {EXTERNAL_APP_NOT_SUPPORTED, NO_ORGANIZATION_ID} from '../../util/errorMessages.js'\nimport {buildApp} from '../build/buildApp.js'\nimport {createUserApplication} from './createUserApplication.js'\nimport {\n checkAppId,\n checkAppTarget,\n checkAutoUpdates,\n checkBuild,\n checkPackageVersion,\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 {findUserApplication} from './findUserApplication.js'\nimport {type DeployAppOptions} from './types.js'\n\nconst APP_PACKAGE = '@sanity/sdk-react'\n\nexport function deployApp(options: DeployAppOptions): Promise<void> {\n return runDeploy(options, {\n listFiles: ({projectRoot, sourceDir}) => listDeploymentFiles(sourceDir, projectRoot.directory),\n run: runAppDeployment,\n type: 'coreApp',\n })\n}\n\n/** Validates the deploy, syncs the title from the manifest, and ships the build. */\nasync function runAppDeployment(\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 organizationId = cliConfig.app?.organizationId\n const appId = getAppId(cliConfig)\n const workbench = getWorkbench(cliConfig)\n // A config (the Media Library) is not an app — it resolves through its own\n // brand and persists to the org's installation instead of hosting an application.\n const config = resolveWorkbenchConfig(cliConfig)\n const dryRun = !!flags['dry-run']\n\n const deployConfigOnly = !!config\n const deployApplication = !config && (!workbench || workbench.hasInterfaces)\n\n const appTitle = workbench\n ? flags.title?.trim() || cliConfig.app?.title?.trim() || workbench.slug\n : ''\n\n // A federated app with no entry, view or service would ship a remote with\n // nothing to load — reported first so it fails before any prompt or API call.\n if (workbench) {\n try {\n workbench.assertDeployable()\n } catch (err) {\n reporter.report({\n exitCode: exitCodes.USAGE_ERROR,\n message: getErrorMessage(err),\n solution: 'Declare at least one entry, view, or service in the app',\n status: 'fail',\n })\n }\n }\n\n // A config with no fields would overwrite the org's live config with an empty\n // snapshot, so block it here — same \"nothing to deploy\" gate an app gets.\n if (config && config.fields.length === 0) {\n reporter.report({\n exitCode: exitCodes.USAGE_ERROR,\n message: 'Nothing to deploy: the media library config declares no fields.',\n solution: 'Add at least one field to the media library config',\n status: 'fail',\n })\n }\n\n const isAutoUpdating = checkAutoUpdates(reporter, {cliConfig, flags})\n\n // An application ships the SDK runtime; a media-library config stamps its\n // `sanity` version instead.\n let version: string | null = null\n if (deployApplication) {\n version = await checkPackageVersion(reporter, {moduleName: APP_PACKAGE, workDir})\n } else if (deployConfigOnly) {\n version = await checkPackageVersion(reporter, {moduleName: 'sanity', workDir})\n }\n\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\n checkAppId(reporter, {cliConfig})\n\n let application: UserApplicationResolved | null = null\n let appCreated = false\n let workbenchApp: object | undefined\n if (flags.external) {\n reporter.report({\n message: EXTERNAL_APP_NOT_SUPPORTED,\n solution: 'Remove the --external flag — apps deploy to Sanity hosting',\n status: 'fail',\n })\n } else if (deployApplication && workbench) {\n workbenchApp = (\n await checkAppTarget(reporter, {\n appId,\n isWorkbenchApp: true,\n organizationId,\n slug: workbench.slug,\n title: appTitle,\n })\n )?.application\n } else if (deployApplication) {\n ;({application, created: appCreated} = await resolveAppApplication(options, {dryRun, reporter}))\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 (deployApplication && workbench && !appId && !flags.external && !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 && workbench?.icon ? await readIconFromPath(workDir, workbench.icon) : undefined\n\n // Create the app 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 && deployApplication && workbench && organizationId && !applicationId) {\n const created = await createCoreApp({\n isSingleton: workbench.isSingleton,\n name: workbench.name,\n organizationId,\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 buildApp({\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: flags.build\n ? undefined\n : 'Build skipped (--no-build) — validating existing output directory',\n successMessage: 'App built',\n })\n\n await verifyOutputDir({\n isWorkbenchApp: workbench !== null || config !== null,\n reporter,\n sourceDir,\n })\n\n // Workbench apps and configs ship a federation remote and don't read the\n // core-app manifest; only plain core-apps do. Manifests aren't strictly\n // essential, so a failure warns and continues.\n let manifest: CoreAppManifest | undefined\n if (!workbench && !config) {\n try {\n manifest = await extractCoreAppManifest({workDir})\n } catch (err) {\n deployDebug('Error extracting app manifest', err)\n reporter.report({\n message: `Error extracting app manifest: ${getErrorMessage(err)}`,\n status: 'warn',\n })\n }\n }\n\n // Resolve the installation in both modes so the report — dry-run and real —\n // shows whether the config is deployable; a missing one fails the deploy here.\n let installationId: string | undefined\n let configSummary: string | undefined\n const configAppType = config?.appType\n if (deployConfigOnly && organizationId && config && configAppType) {\n installationId = await resolveInstallationId({appType: configAppType, organizationId})\n configSummary = summarizeConfig(config)\n reporter.report(\n installationId\n ? {message: configSummary, status: 'pass'}\n : {\n exitCode: exitCodes.USAGE_ERROR,\n message: `No active \"${configAppType}\" installation for organization \"${organizationId}\"`,\n solution:\n 'Install the Media Library for the organization before deploying its config',\n status: 'fail',\n },\n )\n }\n\n const interfaces = deployApplication && workbench ? reportInterfaces(reporter, workbench) : null\n\n // Applied after the app is live (see below) so a failed deploy never leaves\n // the org's installation config without its application.\n const deployApplicationConfig = async (): Promise<void> => {\n if (installationId && version && configAppType && organizationId) {\n await deployConfig({\n appType: configAppType,\n installationId,\n organizationId,\n output,\n sourceDir,\n version,\n })\n }\n }\n\n const payload: DeployPayload = {\n appId: appId ?? null,\n isAutoUpdating,\n ...(organizationId ? {organizationId} : {}),\n type: 'coreApp',\n version,\n ...toWorkbenchPayload(workbench, {config: configSummary, interfaces, title: appTitle}),\n ...(configSummary ? {config: configSummary} : {}),\n }\n\n // Dry run stops here — everything below mutates.\n if (dryRun) return {application: null, payload}\n\n // A config-only singleton ships no application, only its config.\n if (!deployApplication) {\n await deployApplicationConfig()\n if (installationId && version) {\n return {application: null, installationId, payload}\n }\n return\n }\n\n // A real deploy already exited on a version-resolution failure; this narrows the type.\n if (!version) return\n\n // The app was created (or resolved from `deployment.appId`) before the build,\n // so this only ships the deployment; plain coreApps use user-applications below.\n if (workbench && organizationId && applicationId) {\n await deployWorkbenchApp({\n app: cliConfig.app,\n applicationId,\n icon: appIcon,\n isApp: true,\n isAutoUpdating,\n // Once the deployment is live, a metadata-sync or later config failure\n // must not delete the app.\n onDeployed: () => {\n rollbackApp = undefined\n },\n slug: workbench.slug,\n sourceDir,\n title: appTitle,\n version,\n visibility: workbench.visibility,\n })\n await deployApplicationConfig()\n const url = getApplicationUrl({id: applicationId, organizationId, type: 'coreApp'})\n logAppDeployed({\n applicationId,\n cliConfig,\n created: applicationCreated,\n organizationId,\n output,\n title: appTitle,\n url,\n })\n return {\n action: applicationCreated ? 'create' : 'update',\n application: workbenchApp ?? null,\n payload,\n url,\n }\n }\n\n // A real deploy has already exited if anything failed; landing here without a\n // resolved application means the deploy target was never resolved.\n if (!application) return\n\n application = await syncApplicationMetadata({\n application,\n manifest,\n output,\n visibility: cliConfig.app?.visibility,\n })\n await shipAppDeployment({application, isAutoUpdating, manifest, sourceDir, version})\n logAppDeployed({\n applicationId: application.id,\n cliConfig,\n created: appCreated,\n createRequested: flags.create,\n organizationId: application.organizationId,\n output,\n title: application.title,\n })\n return {\n action: appCreated ? 'create' : 'update',\n application,\n payload,\n url: getCoreAppUrl(application.organizationId, application.id),\n }\n } catch (err) {\n await rollbackApp?.()\n throw err\n }\n}\n\n/**\n * Finds the application a real deploy targets, creating one when none is\n * configured. A dry run resolves and reports the target read-only instead.\n */\nasync function resolveAppApplication(\n options: DeployAppOptions,\n {dryRun, reporter}: {dryRun: boolean; reporter: DeployCheckReporter},\n): Promise<{application: UserApplicationResolved | null; created: boolean}> {\n const {cliConfig, flags, output} = options\n const organizationId = cliConfig.app?.organizationId ?? ''\n // Create name from --title or `app.title` config; blank falls back to the prompt\n const title = flags.title?.trim() || cliConfig.app?.title?.trim() || undefined\n\n if (dryRun) {\n await checkAppTarget(reporter, {\n appId: getAppId(cliConfig),\n create: flags.create,\n organizationId,\n title,\n })\n return {application: null, created: false}\n }\n\n let application = await findUserApplication({\n cliConfig,\n create: flags.create,\n organizationId,\n output,\n title,\n unattended: !!flags.yes,\n })\n deployDebug('User application found', application)\n\n if (!application) {\n deployDebug('No user application found. Creating a new one')\n application = await createUserApplication(organizationId, title, cliConfig.app?.visibility)\n deployDebug('User application created', application)\n return {application, created: true}\n }\n\n return {application, created: false}\n}\n\n/**\n * Syncs application metadata on redeploy when it has changed: the title from the\n * manifest and the dashboard visibility from config. Sends a single PATCH with\n * only the changed fields, and skips the request entirely when nothing changed.\n */\nexport async function syncApplicationMetadata({\n application,\n manifest,\n output,\n visibility,\n}: {\n application: UserApplicationResolved\n manifest: CoreAppManifest | undefined\n output: DeployAppOptions['output']\n visibility: AppVisibility | undefined\n}): Promise<UserApplicationResolved> {\n const titleUpdate = resolveTitleUpdate(manifest, application)\n // Treat an unset server value as `default` so a config of `default` is a no-op.\n const visibilityChanged =\n visibility !== undefined && visibility !== (application.dashboardStatus ?? 'default')\n\n if (!titleUpdate && !visibilityChanged) return application\n\n if (titleUpdate) {\n deployDebug('Updating application title from manifest', titleUpdate)\n output.log(\n titleUpdate.from\n ? `Updating title from \"${titleUpdate.from}\" to \"${titleUpdate.to}\"`\n : `Setting application title to \"${titleUpdate.to}\"`,\n )\n }\n if (visibilityChanged) {\n output.log(`Setting dashboard visibility to \"${visibility}\"`)\n }\n\n const spin = spinner('Updating application').start()\n try {\n const updated = await updateUserApplication({\n applicationId: application.id,\n appType: 'coreApp',\n body: {\n ...(titleUpdate ? {title: titleUpdate.to} : {}),\n ...(visibilityChanged ? {dashboardStatus: visibility} : {}),\n },\n })\n spin.succeed()\n return updated\n } catch (err) {\n spin.fail()\n const message = getErrorMessage(err)\n deployDebug('Error updating application metadata', {message})\n output.warn(`Error updating application metadata: ${message}`)\n return application\n }\n}\n\nasync function shipAppDeployment({\n application,\n isAutoUpdating,\n manifest,\n sourceDir,\n version,\n}: {\n application: UserApplication\n isAutoUpdating: boolean\n manifest: CoreAppManifest | undefined\n sourceDir: string\n version: string\n}): Promise<void> {\n const tarball = createTar({cwd: dirname(sourceDir)}, [basename(sourceDir)]).pipe(createGzip())\n\n const spin = spinner('Deploying...').start()\n try {\n await createDeployment({\n applicationId: application.id,\n isApp: true,\n isAutoUpdating,\n manifest,\n tarball,\n version,\n })\n } catch (error) {\n spin.clear()\n throw error\n }\n spin.succeed()\n}\n\nexport function logAppDeployed({\n applicationId,\n cliConfig,\n created,\n createRequested = false,\n organizationId,\n output,\n title,\n url = getCoreAppUrl(organizationId, applicationId),\n}: {\n applicationId: string\n cliConfig: DeployAppOptions['cliConfig']\n created: boolean\n createRequested?: boolean\n organizationId: string\n output: DeployAppOptions['output']\n title: string | null\n url?: string\n}): void {\n const named = title ? ` — \"${title}\"` : ''\n output.log(`\\nSuccess! Application deployed to ${styleText('cyan', url)}${named}`)\n output.log(created ? 'Created a new application.' : 'Updated the existing application.')\n\n if (getAppId(cliConfig)) return\n\n output.log(`\\n════ ${styleText('bold', 'Next step:')} ════`)\n if (created) {\n output.log(\n styleText(\n 'yellow',\n createRequested\n ? '\\nSave `deployment.appId` and omit --create on later deploys to update this application.'\n : '\\nSave `deployment.appId` to update this application on later deploys.',\n ),\n )\n }\n output.log(\n styleText('bold', '\\nAdd the deployment.appId to your sanity.cli.js or sanity.cli.ts file:'),\n )\n output.log(`\n${styleText(\n 'dim',\n `app: {\n // your application config here…\n}`,\n)},\n${styleText(\n ['bold', 'green'],\n `deployment: {\n appId: '${applicationId}',\n}\\n`,\n)}`)\n}\n"],"names":["basename","dirname","styleText","createGzip","extractCoreAppManifest","readIconFromPath","resolveTitleUpdate","exitCodes","getErrorMessage","getCoreAppUrl","spinner","createCoreApp","deployConfig","deployWorkbenchApp","getApplicationUrl","getWorkbench","resolveInstallationId","resolveWorkbenchConfig","summarizeConfig","toWorkbenchPayload","c","createTar","createDeployment","updateUserApplication","getAppId","EXTERNAL_APP_NOT_SUPPORTED","NO_ORGANIZATION_ID","buildApp","createUserApplication","checkAppId","checkAppTarget","checkAutoUpdates","checkBuild","checkPackageVersion","verifyOutputDir","deployDebug","listDeploymentFiles","reportInterfaces","runDeploy","findUserApplication","APP_PACKAGE","deployApp","options","listFiles","projectRoot","sourceDir","directory","run","runAppDeployment","type","reporter","cliConfig","flags","output","workDir","organizationId","app","appId","workbench","config","dryRun","deployConfigOnly","deployApplication","hasInterfaces","appTitle","title","trim","slug","assertDeployable","err","report","exitCode","USAGE_ERROR","message","solution","status","fields","length","isAutoUpdating","version","moduleName","application","appCreated","workbenchApp","external","isWorkbenchApp","created","resolveAppApplication","build","appIcon","icon","undefined","applicationId","applicationCreated","rollbackApp","isSingleton","name","visibility","id","rollback","autoUpdatesEnabled","calledFromDeploy","outDir","skipReason","successMessage","manifest","installationId","configSummary","configAppType","appType","interfaces","deployApplicationConfig","payload","isApp","onDeployed","url","logAppDeployed","action","syncApplicationMetadata","shipAppDeployment","createRequested","create","unattended","yes","titleUpdate","visibilityChanged","dashboardStatus","log","from","to","spin","start","updated","body","succeed","fail","warn","tarball","cwd","pipe","error","clear","named"],"mappings":"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"}
|
|
@@ -149,7 +149,7 @@ export async function checkBuild(reporter, { build, skipReason, successMessage }
|
|
|
149
149
|
return {
|
|
150
150
|
exitCode: exitCodes.USAGE_ERROR,
|
|
151
151
|
message: `No \`deployment.appId\` configured (${resolution.existing.length} existing ${resolution.existing.length === 1 ? 'application' : 'applications'} to choose from)`,
|
|
152
|
-
solution: '
|
|
152
|
+
solution: 'Set `deployment.appId` in sanity.cli.ts to deploy to an existing app, or run `sanity deploy --create --title "<name>" --yes` to create a new one',
|
|
153
153
|
status: 'fail'
|
|
154
154
|
};
|
|
155
155
|
}
|
|
@@ -230,7 +230,7 @@ export function describeAppTargetError(err, organizationId) {
|
|
|
230
230
|
}
|
|
231
231
|
});
|
|
232
232
|
}
|
|
233
|
-
const { appId, organizationId } = options;
|
|
233
|
+
const { appId, create, organizationId } = options;
|
|
234
234
|
return runStep(reporter, {
|
|
235
235
|
debug: deployDebug,
|
|
236
236
|
formatError: (err)=>describeAppTargetError(err, organizationId),
|
|
@@ -238,6 +238,7 @@ export function describeAppTargetError(err, organizationId) {
|
|
|
238
238
|
work: async ()=>{
|
|
239
239
|
const check = describeAppTarget(await resolveAppDeployTarget({
|
|
240
240
|
appId,
|
|
241
|
+
create,
|
|
241
242
|
organizationId
|
|
242
243
|
}), {
|
|
243
244
|
title
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/deploy/deployChecks.ts"],"sourcesContent":["import {type CliConfig, exitCodes, getLocalPackageVersion} from '@sanity/cli-core'\nimport {getErrorMessage} from '@sanity/cli-core/errors'\nimport {getCoreAppUrl} from '@sanity/cli-core/util'\nimport {spinner} from '@sanity/cli-core/ux'\nimport {checkBuiltOutput} from '@sanity/workbench-cli/deploy'\n\nimport {resolveAppIdIssue} from '../../util/appId.js'\nimport {type Check, type CheckReporter, runStep} from '../../util/checks.js'\nimport {APP_ID_NOT_FOUND_IN_ORGANIZATION} from '../../util/errorMessages.js'\nimport {\n getAutoUpdateIssueMessage,\n getAutoUpdateMigrationHint,\n resolveAutoUpdates,\n} from '../build/shouldAutoUpdate.js'\nimport {checkDir} from './checkDir.js'\nimport {deployDebug} from './deployDebug.js'\nimport {\n type AppDeployTargetResolution,\n type DeployTargetApp,\n resolveAppDeployTarget,\n resolveStudioDeployTarget,\n resolveWorkbenchApp,\n resolveWorkbenchStudio,\n type StudioDeployTargetResolution,\n} from './resolveDeployTarget.js'\nimport {type DeployFlags} from './types.js'\n\n/**\n * Where a deploy resolves to, computed once from the deploy-target verdict. The\n * dry-run report and its JSON both read this, so the human and machine outputs\n * can't drift.\n */\nexport interface DeployTarget {\n /** Whether the deploy creates a new application/studio or updates an existing one. */\n action: 'create' | 'update'\n /** `null` until the deploy creates the application. */\n id: string | null\n title: string | null\n type: 'coreApp' | 'studio'\n url: string | null\n\n /** Absent on a plain app, whose backend reports `appHost` instead. */\n slug?: string\n}\n\nexport interface DeployCheck extends Check {\n /** The backend's record, verbatim; `--json` reports it once the deploy succeeds. */\n application?: object\n /** Set on the deploy-target check with the resolved target both reporters read. */\n target?: DeployTarget\n}\n\nexport type DeployCheckReporter = CheckReporter<DeployCheck>\n\nexport async function checkPackageVersion(\n reporter: DeployCheckReporter,\n {moduleName, workDir}: {moduleName: string; workDir: string},\n): Promise<string | null> {\n const version = await getLocalPackageVersion(moduleName, workDir)\n reporter.report(\n version\n ? {message: `Using ${moduleName} ${version}`, status: 'pass'}\n : {\n message: `Failed to find installed ${moduleName} version`,\n solution: `Install ${moduleName} in this project`,\n status: 'fail',\n },\n )\n return version\n}\n\nexport function checkAutoUpdates(\n reporter: DeployCheckReporter,\n {cliConfig, flags}: {cliConfig: CliConfig; flags: DeployFlags},\n): boolean {\n const {enabled, issue} = resolveAutoUpdates({cliConfig, flags})\n\n if (issue) {\n reporter.report({\n message: getAutoUpdateIssueMessage(issue),\n // A config conflict makes a real deploy refuse to run; deprecations only warn\n status: issue.type === 'conflicting-config' ? 'fail' : 'warn',\n })\n\n // The deprecated top-level config also gets the styled migration edit, the\n // same second warning the build/dev path prints through shouldAutoUpdate.\n if (issue.type === 'deprecated-config') {\n reporter.report({\n message: getAutoUpdateMigrationHint(cliConfig.autoUpdates),\n status: 'warn',\n })\n }\n }\n\n return enabled\n}\n\n/**\n * The dry-run form of the `app.id` config check a real deploy runs in\n * `findUserApplication`: a conflict fails (both `app.id` and `deployment.appId`\n * set), the deprecated config alone warns.\n */\nexport function checkAppId(\n reporter: DeployCheckReporter,\n {cliConfig}: {cliConfig: CliConfig},\n): void {\n const issue = resolveAppIdIssue(cliConfig)\n if (issue === 'conflicting-config') {\n reporter.report({\n message: 'Both `app.id` (deprecated) and `deployment.appId` are set',\n solution: 'Remove `app.id` from sanity.cli.ts',\n status: 'fail',\n })\n } else if (issue === 'deprecated-config') {\n reporter.report({\n message: 'The `app.id` config is deprecated',\n solution: 'Move it to `deployment.appId` in sanity.cli.ts',\n status: 'warn',\n })\n }\n}\n\nexport async function checkBuild(\n reporter: DeployCheckReporter,\n {\n build,\n skipReason,\n successMessage,\n }: {build: () => Promise<void>; skipReason: string | undefined; successMessage: string},\n): Promise<void> {\n if (skipReason) {\n reporter.report({message: skipReason, status: 'skip'})\n return\n }\n\n await runStep(reporter, {\n debug: deployDebug,\n formatError: (err) => `Build failed: ${getErrorMessage(err)}`,\n name: 'build',\n solution: 'Fix the build error above, then retry',\n work: async () => {\n await build()\n reporter.report({message: successMessage, status: 'pass'})\n },\n })\n}\n\n/**\n * The deploy directory must exist and hold the right build output: a federation\n * remote for a workbench app, an `index.html` SPA otherwise.\n */\nexport async function verifyOutputDir({\n isWorkbenchApp,\n reporter,\n sourceDir,\n}: {\n isWorkbenchApp: boolean\n reporter: DeployCheckReporter\n sourceDir: string\n}): Promise<void> {\n const spin = spinner('Verifying local content...').start()\n const verifyBuild = isWorkbenchApp ? checkBuiltOutput : checkDir\n try {\n await verifyBuild(sourceDir)\n spin.succeed()\n } catch (err) {\n spin.fail()\n deployDebug('Error checking directory', err)\n reporter.report({\n message: getErrorMessage(err),\n solution: 'Run the build first, or check the output directory',\n status: 'fail',\n })\n }\n}\n\n/**\n * The single diagnosis for each app deploy-target verdict, shared by the\n * dry-run report and the real deploy's unattended error paths so message,\n * fix, and exit code can't drift between the two.\n */\nexport function describeAppTarget(\n resolution: AppDeployTargetResolution,\n {title}: {title?: string} = {},\n): DeployCheck {\n switch (resolution.type) {\n case 'blocked': {\n return {message: `Deploy target not resolved — ${resolution.message}`, status: 'skip'}\n }\n case 'found': {\n const {application} = resolution\n const title = application.title ?? application.appHost\n const url = application.url ?? getCoreAppUrl(application.organizationId, application.id)\n return {\n application,\n message: `Deploys to existing application \"${title}\" at ${url}`,\n status: 'pass',\n target: {\n action: 'update',\n id: application.id,\n title: application.title,\n type: 'coreApp',\n url,\n },\n }\n }\n case 'invalid': {\n return {\n message: APP_ID_NOT_FOUND_IN_ORGANIZATION,\n solution: 'Check `deployment.appId` matches an app in your organization',\n status: 'fail',\n }\n }\n case 'needs-input': {\n return {\n exitCode: exitCodes.USAGE_ERROR,\n message: `No \\`deployment.appId\\` configured (${resolution.existing.length} existing ${resolution.existing.length === 1 ? 'application' : 'applications'} to choose from)`,\n solution: 'Add `deployment.appId` to sanity.cli.ts',\n status: 'fail',\n }\n }\n case 'slug-taken': {\n return describeSlugTaken(resolution)\n }\n // Without --title, creating an app needs a prompt no unattended run can answer\n case 'would-create': {\n const {appHost} = resolution\n if (title) {\n return {\n message: `Would create a new application \"${title}\"${appHost ? ` with slug \"${appHost}\"` : ''}`,\n status: 'pass',\n target: {\n action: 'create',\n id: null,\n ...(appHost ? {slug: appHost} : {}),\n title,\n type: 'coreApp',\n url: null,\n },\n }\n }\n return {\n exitCode: exitCodes.USAGE_ERROR,\n message: 'No application to deploy to — creating one needs a title',\n solution:\n 'Pass `--title \"<name>\"` or set `app.title` in sanity.cli.ts to create one, or set `deployment.appId` to deploy to an existing app',\n status: 'fail',\n }\n }\n }\n}\n\n/** One diagnosis for both the app and studio verdicts: they share a slug namespace. */\nfunction describeSlugTaken({\n appHost,\n existing,\n}: {\n appHost: string\n existing: DeployTargetApp\n}): DeployCheck {\n return {\n application: existing,\n exitCode: exitCodes.USAGE_ERROR,\n message: `An application already exists at slug \"${appHost}\" in this organization (app ID ${existing.id})`,\n solution: `Add \\`deployment: {appId: '${existing.id}'}\\` to sanity.cli.ts to redeploy it`,\n status: 'fail',\n target: {\n action: 'update',\n id: existing.id,\n title: existing.title,\n type: existing.type,\n url: existing.url ?? null,\n },\n }\n}\n\nexport function describeAppTargetError(err: unknown, organizationId: string | undefined): string {\n return (err as {statusCode?: number})?.statusCode === 403\n ? `You don’t have permission to view applications for the configured organization ID (\"${organizationId}\"). Verify the organization ID, or ask your organization’s admin for access.`\n : `Failed to resolve deploy target: ${getErrorMessage(err)}`\n}\n\n/**\n * Reports the app deploy target as a check and returns the resolved target;\n * `isWorkbenchApp` selects the backend. Both modes run it — a real deploy uses\n * it to reject a bad `appId` before building.\n */\nexport async function checkAppTarget(\n reporter: DeployCheckReporter,\n options:\n | {\n appId: string | undefined\n isWorkbenchApp: true\n organizationId?: string\n slug?: string\n title?: string\n }\n | {\n appId: string | undefined\n isWorkbenchApp?: false\n organizationId: string | undefined\n title?: string\n },\n): Promise<DeployCheck | null> {\n const {title} = options\n if (options.isWorkbenchApp) {\n const {appId, organizationId, slug} = options\n return runStep(reporter, {\n debug: deployDebug,\n name: 'target',\n work: async () => {\n const resolution = await resolveWorkbenchApp({appId, organizationId, slug})\n const check = describeAppTarget(resolution, {title})\n reporter.report(check)\n return check\n },\n })\n }\n\n const {appId, organizationId} = options\n return runStep(reporter, {\n debug: deployDebug,\n formatError: (err) => describeAppTargetError(err, organizationId),\n name: 'target',\n work: async () => {\n const check = describeAppTarget(await resolveAppDeployTarget({appId, organizationId}), {\n title,\n })\n reporter.report(check)\n return check\n },\n })\n}\n\n/** Same contract as {@link describeAppTarget}, for the studio verdicts. */\nexport function describeStudioTarget(\n resolution: StudioDeployTargetResolution,\n {isExternal, isWorkbench, title}: {isExternal: boolean; isWorkbench?: boolean; title?: string},\n): DeployCheck {\n const studioUrl = (host: string) => (isExternal ? host : `https://${host}.sanity.studio`)\n\n switch (resolution.type) {\n case 'blocked': {\n return {message: `Deploy target not resolved — ${resolution.message}`, status: 'skip'}\n }\n case 'found': {\n const {appHost} = resolution.application\n const url = resolution.application.url ?? (appHost ? studioUrl(appHost) : null)\n return {\n application: resolution.application,\n message: `Deploys to existing studio ${url}`,\n status: 'pass',\n target: {\n action: 'update',\n id: resolution.application.id,\n title: resolution.application.title,\n type: 'studio',\n url,\n },\n }\n }\n case 'invalid': {\n return {\n // A bad host is a usage error; other invalid targets exit 1\n exitCode: resolution.reason === 'invalid-host' ? exitCodes.USAGE_ERROR : 1,\n message: resolution.message,\n solution: 'Check `studioHost` and `deployment.appId` in sanity.cli.ts',\n status: 'fail',\n }\n }\n case 'needs-input': {\n return {\n exitCode: exitCodes.USAGE_ERROR,\n message: isExternal ? 'No external studio URL configured' : 'No studio hostname configured',\n solution: isExternal\n ? 'Set `studioHost` in sanity.cli.ts, or pass the full URL with --url'\n : 'Set `studioHost` in sanity.cli.ts, or pass a hostname with --url',\n status: 'fail',\n }\n }\n case 'slug-taken': {\n return describeSlugTaken(resolution)\n }\n case 'would-create': {\n const appHost = resolution.appHost\n const url = isWorkbench ? null : studioUrl(appHost)\n const result = {\n status: 'pass',\n target: {action: 'create', id: null, title: title || null, type: 'studio', url},\n } as const\n const titled = title ? ` titled \"${title}\"` : ''\n\n if (isExternal) {\n return {\n message: `Would register external studio at ${appHost}${titled}`,\n ...result,\n }\n }\n\n if (isWorkbench) {\n return {\n message: `Would create a new studio${title ? ` \"${title}\"` : ''} with slug \"${appHost}\" (name availability is checked on deploy)`,\n ...result,\n target: {...result.target, slug: appHost},\n }\n }\n\n return {\n message: `Would create studio hostname ${url}${titled} (name availability is checked on deploy)`,\n ...result,\n }\n }\n }\n}\n\n/**\n * Reports the studio deploy target as a check and returns the resolved target;\n * `isWorkbenchApp` selects the backend. Both modes run it — a real deploy uses\n * it to reject a bad `appId` before building.\n */\nexport async function checkStudioTarget(\n reporter: DeployCheckReporter,\n options:\n | {\n appId: string | undefined\n isExternal: boolean\n isWorkbenchApp?: false\n projectId: string | undefined\n studioHost: string | undefined\n title: string | undefined\n urlFlag: string | undefined\n }\n | {\n appId: string | undefined\n isWorkbenchApp: true\n organizationId?: string\n slug: string\n title?: string\n },\n): Promise<DeployCheck | null> {\n const {title} = options\n const resolve = options.isWorkbenchApp\n ? resolveWorkbenchStudio(options)\n : resolveStudioDeployTarget(options)\n // Workbench studios always deploy to Sanity hosting, never an external URL.\n const isExternal = options.isWorkbenchApp ? false : options.isExternal\n\n return runStep(reporter, {\n debug: deployDebug,\n formatError: (err) => `Failed to resolve deploy target: ${getErrorMessage(err)}`,\n name: 'target',\n work: async () => {\n const check = describeStudioTarget(await resolve, {\n isExternal,\n isWorkbench: !!options.isWorkbenchApp,\n title,\n })\n reporter.report(check)\n return check\n },\n })\n}\n"],"names":["exitCodes","getLocalPackageVersion","getErrorMessage","getCoreAppUrl","spinner","checkBuiltOutput","resolveAppIdIssue","runStep","APP_ID_NOT_FOUND_IN_ORGANIZATION","getAutoUpdateIssueMessage","getAutoUpdateMigrationHint","resolveAutoUpdates","checkDir","deployDebug","resolveAppDeployTarget","resolveStudioDeployTarget","resolveWorkbenchApp","resolveWorkbenchStudio","checkPackageVersion","reporter","moduleName","workDir","version","report","message","status","solution","checkAutoUpdates","cliConfig","flags","enabled","issue","type","autoUpdates","checkAppId","checkBuild","build","skipReason","successMessage","debug","formatError","err","name","work","verifyOutputDir","isWorkbenchApp","sourceDir","spin","start","verifyBuild","succeed","fail","describeAppTarget","resolution","title","application","appHost","url","organizationId","id","target","action","exitCode","USAGE_ERROR","existing","length","describeSlugTaken","slug","describeAppTargetError","statusCode","checkAppTarget","options","appId","check","describeStudioTarget","isExternal","isWorkbench","studioUrl","host","reason","result","titled","checkStudioTarget","resolve"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/deploy/deployChecks.ts"],"sourcesContent":["import {type CliConfig, exitCodes, getLocalPackageVersion} from '@sanity/cli-core'\nimport {getErrorMessage} from '@sanity/cli-core/errors'\nimport {getCoreAppUrl} from '@sanity/cli-core/util'\nimport {spinner} from '@sanity/cli-core/ux'\nimport {checkBuiltOutput} from '@sanity/workbench-cli/deploy'\n\nimport {resolveAppIdIssue} from '../../util/appId.js'\nimport {type Check, type CheckReporter, runStep} from '../../util/checks.js'\nimport {APP_ID_NOT_FOUND_IN_ORGANIZATION} from '../../util/errorMessages.js'\nimport {\n getAutoUpdateIssueMessage,\n getAutoUpdateMigrationHint,\n resolveAutoUpdates,\n} from '../build/shouldAutoUpdate.js'\nimport {checkDir} from './checkDir.js'\nimport {deployDebug} from './deployDebug.js'\nimport {\n type AppDeployTargetResolution,\n type DeployTargetApp,\n resolveAppDeployTarget,\n resolveStudioDeployTarget,\n resolveWorkbenchApp,\n resolveWorkbenchStudio,\n type StudioDeployTargetResolution,\n} from './resolveDeployTarget.js'\nimport {type DeployFlags} from './types.js'\n\n/**\n * Where a deploy resolves to, computed once from the deploy-target verdict. The\n * dry-run report and its JSON both read this, so the human and machine outputs\n * can't drift.\n */\nexport interface DeployTarget {\n /** Whether the deploy creates a new application/studio or updates an existing one. */\n action: 'create' | 'update'\n /** `null` until the deploy creates the application. */\n id: string | null\n title: string | null\n type: 'coreApp' | 'studio'\n url: string | null\n\n /** Absent on a plain app, whose backend reports `appHost` instead. */\n slug?: string\n}\n\nexport interface DeployCheck extends Check {\n /** The backend's record, verbatim; `--json` reports it once the deploy succeeds. */\n application?: object\n /** Set on the deploy-target check with the resolved target both reporters read. */\n target?: DeployTarget\n}\n\nexport type DeployCheckReporter = CheckReporter<DeployCheck>\n\nexport async function checkPackageVersion(\n reporter: DeployCheckReporter,\n {moduleName, workDir}: {moduleName: string; workDir: string},\n): Promise<string | null> {\n const version = await getLocalPackageVersion(moduleName, workDir)\n reporter.report(\n version\n ? {message: `Using ${moduleName} ${version}`, status: 'pass'}\n : {\n message: `Failed to find installed ${moduleName} version`,\n solution: `Install ${moduleName} in this project`,\n status: 'fail',\n },\n )\n return version\n}\n\nexport function checkAutoUpdates(\n reporter: DeployCheckReporter,\n {cliConfig, flags}: {cliConfig: CliConfig; flags: DeployFlags},\n): boolean {\n const {enabled, issue} = resolveAutoUpdates({cliConfig, flags})\n\n if (issue) {\n reporter.report({\n message: getAutoUpdateIssueMessage(issue),\n // A config conflict makes a real deploy refuse to run; deprecations only warn\n status: issue.type === 'conflicting-config' ? 'fail' : 'warn',\n })\n\n // The deprecated top-level config also gets the styled migration edit, the\n // same second warning the build/dev path prints through shouldAutoUpdate.\n if (issue.type === 'deprecated-config') {\n reporter.report({\n message: getAutoUpdateMigrationHint(cliConfig.autoUpdates),\n status: 'warn',\n })\n }\n }\n\n return enabled\n}\n\n/**\n * The dry-run form of the `app.id` config check a real deploy runs in\n * `findUserApplication`: a conflict fails (both `app.id` and `deployment.appId`\n * set), the deprecated config alone warns.\n */\nexport function checkAppId(\n reporter: DeployCheckReporter,\n {cliConfig}: {cliConfig: CliConfig},\n): void {\n const issue = resolveAppIdIssue(cliConfig)\n if (issue === 'conflicting-config') {\n reporter.report({\n message: 'Both `app.id` (deprecated) and `deployment.appId` are set',\n solution: 'Remove `app.id` from sanity.cli.ts',\n status: 'fail',\n })\n } else if (issue === 'deprecated-config') {\n reporter.report({\n message: 'The `app.id` config is deprecated',\n solution: 'Move it to `deployment.appId` in sanity.cli.ts',\n status: 'warn',\n })\n }\n}\n\nexport async function checkBuild(\n reporter: DeployCheckReporter,\n {\n build,\n skipReason,\n successMessage,\n }: {build: () => Promise<void>; skipReason: string | undefined; successMessage: string},\n): Promise<void> {\n if (skipReason) {\n reporter.report({message: skipReason, status: 'skip'})\n return\n }\n\n await runStep(reporter, {\n debug: deployDebug,\n formatError: (err) => `Build failed: ${getErrorMessage(err)}`,\n name: 'build',\n solution: 'Fix the build error above, then retry',\n work: async () => {\n await build()\n reporter.report({message: successMessage, status: 'pass'})\n },\n })\n}\n\n/**\n * The deploy directory must exist and hold the right build output: a federation\n * remote for a workbench app, an `index.html` SPA otherwise.\n */\nexport async function verifyOutputDir({\n isWorkbenchApp,\n reporter,\n sourceDir,\n}: {\n isWorkbenchApp: boolean\n reporter: DeployCheckReporter\n sourceDir: string\n}): Promise<void> {\n const spin = spinner('Verifying local content...').start()\n const verifyBuild = isWorkbenchApp ? checkBuiltOutput : checkDir\n try {\n await verifyBuild(sourceDir)\n spin.succeed()\n } catch (err) {\n spin.fail()\n deployDebug('Error checking directory', err)\n reporter.report({\n message: getErrorMessage(err),\n solution: 'Run the build first, or check the output directory',\n status: 'fail',\n })\n }\n}\n\n/**\n * The single diagnosis for each app deploy-target verdict, shared by the\n * dry-run report and the real deploy's unattended error paths so message,\n * fix, and exit code can't drift between the two.\n */\nexport function describeAppTarget(\n resolution: AppDeployTargetResolution,\n {title}: {title?: string} = {},\n): DeployCheck {\n switch (resolution.type) {\n case 'blocked': {\n return {message: `Deploy target not resolved — ${resolution.message}`, status: 'skip'}\n }\n case 'found': {\n const {application} = resolution\n const title = application.title ?? application.appHost\n const url = application.url ?? getCoreAppUrl(application.organizationId, application.id)\n return {\n application,\n message: `Deploys to existing application \"${title}\" at ${url}`,\n status: 'pass',\n target: {\n action: 'update',\n id: application.id,\n title: application.title,\n type: 'coreApp',\n url,\n },\n }\n }\n case 'invalid': {\n return {\n message: APP_ID_NOT_FOUND_IN_ORGANIZATION,\n solution: 'Check `deployment.appId` matches an app in your organization',\n status: 'fail',\n }\n }\n case 'needs-input': {\n return {\n exitCode: exitCodes.USAGE_ERROR,\n message: `No \\`deployment.appId\\` configured (${resolution.existing.length} existing ${resolution.existing.length === 1 ? 'application' : 'applications'} to choose from)`,\n solution:\n 'Set `deployment.appId` in sanity.cli.ts to deploy to an existing app, or run `sanity deploy --create --title \"<name>\" --yes` to create a new one',\n status: 'fail',\n }\n }\n case 'slug-taken': {\n return describeSlugTaken(resolution)\n }\n // Without --title, creating an app needs a prompt no unattended run can answer\n case 'would-create': {\n const {appHost} = resolution\n if (title) {\n return {\n message: `Would create a new application \"${title}\"${appHost ? ` with slug \"${appHost}\"` : ''}`,\n status: 'pass',\n target: {\n action: 'create',\n id: null,\n ...(appHost ? {slug: appHost} : {}),\n title,\n type: 'coreApp',\n url: null,\n },\n }\n }\n return {\n exitCode: exitCodes.USAGE_ERROR,\n message: 'No application to deploy to — creating one needs a title',\n solution:\n 'Pass `--title \"<name>\"` or set `app.title` in sanity.cli.ts to create one, or set `deployment.appId` to deploy to an existing app',\n status: 'fail',\n }\n }\n }\n}\n\n/** One diagnosis for both the app and studio verdicts: they share a slug namespace. */\nfunction describeSlugTaken({\n appHost,\n existing,\n}: {\n appHost: string\n existing: DeployTargetApp\n}): DeployCheck {\n return {\n application: existing,\n exitCode: exitCodes.USAGE_ERROR,\n message: `An application already exists at slug \"${appHost}\" in this organization (app ID ${existing.id})`,\n solution: `Add \\`deployment: {appId: '${existing.id}'}\\` to sanity.cli.ts to redeploy it`,\n status: 'fail',\n target: {\n action: 'update',\n id: existing.id,\n title: existing.title,\n type: existing.type,\n url: existing.url ?? null,\n },\n }\n}\n\nexport function describeAppTargetError(err: unknown, organizationId: string | undefined): string {\n return (err as {statusCode?: number})?.statusCode === 403\n ? `You don’t have permission to view applications for the configured organization ID (\"${organizationId}\"). Verify the organization ID, or ask your organization’s admin for access.`\n : `Failed to resolve deploy target: ${getErrorMessage(err)}`\n}\n\n/**\n * Reports the app deploy target as a check and returns the resolved target;\n * `isWorkbenchApp` selects the backend. Both modes run it — a real deploy uses\n * it to reject a bad `appId` before building.\n */\nexport async function checkAppTarget(\n reporter: DeployCheckReporter,\n options:\n | {\n appId: string | undefined\n create?: boolean\n isWorkbenchApp?: false\n organizationId: string | undefined\n title?: string\n }\n | {\n appId: string | undefined\n isWorkbenchApp: true\n organizationId?: string\n slug?: string\n title?: string\n },\n): Promise<DeployCheck | null> {\n const {title} = options\n if (options.isWorkbenchApp) {\n const {appId, organizationId, slug} = options\n return runStep(reporter, {\n debug: deployDebug,\n name: 'target',\n work: async () => {\n const resolution = await resolveWorkbenchApp({appId, organizationId, slug})\n const check = describeAppTarget(resolution, {title})\n reporter.report(check)\n return check\n },\n })\n }\n\n const {appId, create, organizationId} = options\n return runStep(reporter, {\n debug: deployDebug,\n formatError: (err) => describeAppTargetError(err, organizationId),\n name: 'target',\n work: async () => {\n const check = describeAppTarget(\n await resolveAppDeployTarget({appId, create, organizationId}),\n {\n title,\n },\n )\n reporter.report(check)\n return check\n },\n })\n}\n\n/** Same contract as {@link describeAppTarget}, for the studio verdicts. */\nexport function describeStudioTarget(\n resolution: StudioDeployTargetResolution,\n {isExternal, isWorkbench, title}: {isExternal: boolean; isWorkbench?: boolean; title?: string},\n): DeployCheck {\n const studioUrl = (host: string) => (isExternal ? host : `https://${host}.sanity.studio`)\n\n switch (resolution.type) {\n case 'blocked': {\n return {message: `Deploy target not resolved — ${resolution.message}`, status: 'skip'}\n }\n case 'found': {\n const {appHost} = resolution.application\n const url = resolution.application.url ?? (appHost ? studioUrl(appHost) : null)\n return {\n application: resolution.application,\n message: `Deploys to existing studio ${url}`,\n status: 'pass',\n target: {\n action: 'update',\n id: resolution.application.id,\n title: resolution.application.title,\n type: 'studio',\n url,\n },\n }\n }\n case 'invalid': {\n return {\n // A bad host is a usage error; other invalid targets exit 1\n exitCode: resolution.reason === 'invalid-host' ? exitCodes.USAGE_ERROR : 1,\n message: resolution.message,\n solution: 'Check `studioHost` and `deployment.appId` in sanity.cli.ts',\n status: 'fail',\n }\n }\n case 'needs-input': {\n return {\n exitCode: exitCodes.USAGE_ERROR,\n message: isExternal ? 'No external studio URL configured' : 'No studio hostname configured',\n solution: isExternal\n ? 'Set `studioHost` in sanity.cli.ts, or pass the full URL with --url'\n : 'Set `studioHost` in sanity.cli.ts, or pass a hostname with --url',\n status: 'fail',\n }\n }\n case 'slug-taken': {\n return describeSlugTaken(resolution)\n }\n case 'would-create': {\n const appHost = resolution.appHost\n const url = isWorkbench ? null : studioUrl(appHost)\n const result = {\n status: 'pass',\n target: {action: 'create', id: null, title: title || null, type: 'studio', url},\n } as const\n const titled = title ? ` titled \"${title}\"` : ''\n\n if (isExternal) {\n return {\n message: `Would register external studio at ${appHost}${titled}`,\n ...result,\n }\n }\n\n if (isWorkbench) {\n return {\n message: `Would create a new studio${title ? ` \"${title}\"` : ''} with slug \"${appHost}\" (name availability is checked on deploy)`,\n ...result,\n target: {...result.target, slug: appHost},\n }\n }\n\n return {\n message: `Would create studio hostname ${url}${titled} (name availability is checked on deploy)`,\n ...result,\n }\n }\n }\n}\n\n/**\n * Reports the studio deploy target as a check and returns the resolved target;\n * `isWorkbenchApp` selects the backend. Both modes run it — a real deploy uses\n * it to reject a bad `appId` before building.\n */\nexport async function checkStudioTarget(\n reporter: DeployCheckReporter,\n options:\n | {\n appId: string | undefined\n isExternal: boolean\n isWorkbenchApp?: false\n projectId: string | undefined\n studioHost: string | undefined\n title: string | undefined\n urlFlag: string | undefined\n }\n | {\n appId: string | undefined\n isWorkbenchApp: true\n organizationId?: string\n slug: string\n title?: string\n },\n): Promise<DeployCheck | null> {\n const {title} = options\n const resolve = options.isWorkbenchApp\n ? resolveWorkbenchStudio(options)\n : resolveStudioDeployTarget(options)\n // Workbench studios always deploy to Sanity hosting, never an external URL.\n const isExternal = options.isWorkbenchApp ? false : options.isExternal\n\n return runStep(reporter, {\n debug: deployDebug,\n formatError: (err) => `Failed to resolve deploy target: ${getErrorMessage(err)}`,\n name: 'target',\n work: async () => {\n const check = describeStudioTarget(await resolve, {\n isExternal,\n isWorkbench: !!options.isWorkbenchApp,\n title,\n })\n reporter.report(check)\n return check\n },\n })\n}\n"],"names":["exitCodes","getLocalPackageVersion","getErrorMessage","getCoreAppUrl","spinner","checkBuiltOutput","resolveAppIdIssue","runStep","APP_ID_NOT_FOUND_IN_ORGANIZATION","getAutoUpdateIssueMessage","getAutoUpdateMigrationHint","resolveAutoUpdates","checkDir","deployDebug","resolveAppDeployTarget","resolveStudioDeployTarget","resolveWorkbenchApp","resolveWorkbenchStudio","checkPackageVersion","reporter","moduleName","workDir","version","report","message","status","solution","checkAutoUpdates","cliConfig","flags","enabled","issue","type","autoUpdates","checkAppId","checkBuild","build","skipReason","successMessage","debug","formatError","err","name","work","verifyOutputDir","isWorkbenchApp","sourceDir","spin","start","verifyBuild","succeed","fail","describeAppTarget","resolution","title","application","appHost","url","organizationId","id","target","action","exitCode","USAGE_ERROR","existing","length","describeSlugTaken","slug","describeAppTargetError","statusCode","checkAppTarget","options","appId","check","create","describeStudioTarget","isExternal","isWorkbench","studioUrl","host","reason","result","titled","checkStudioTarget","resolve"],"mappings":"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"}
|
|
@@ -12,12 +12,13 @@ import { describeAppTarget, describeAppTargetError, describeStudioTarget } from
|
|
|
12
12
|
import { deployDebug } from './deployDebug.js';
|
|
13
13
|
import { resolveAppDeployTarget, resolveStudioDeployTarget } from './resolveDeployTarget.js';
|
|
14
14
|
export async function findUserApplication(options) {
|
|
15
|
-
const { cliConfig, organizationId, output, title, unattended = false } = options;
|
|
15
|
+
const { cliConfig, create, organizationId, output, title, unattended = false } = options;
|
|
16
16
|
const spin = spinner('Checking application info...').start();
|
|
17
17
|
let resolution;
|
|
18
18
|
try {
|
|
19
19
|
resolution = await resolveAppDeployTarget({
|
|
20
20
|
appId: getAppId(cliConfig),
|
|
21
|
+
create,
|
|
21
22
|
organizationId
|
|
22
23
|
});
|
|
23
24
|
deployDebug('Resolved app deploy target', resolution);
|
|
@@ -34,7 +35,7 @@ export async function findUserApplication(options) {
|
|
|
34
35
|
return resolution.application;
|
|
35
36
|
}
|
|
36
37
|
// null tells the caller to create. Unattended runs can only create with a
|
|
37
|
-
//
|
|
38
|
+
// title; picking among existing apps (needs-input) always needs a prompt.
|
|
38
39
|
if (resolution.type === 'would-create' && (!unattended || title)) {
|
|
39
40
|
spin.info('No application ID configured');
|
|
40
41
|
return null;
|
|
@@ -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, 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
|
+
{"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 create?: boolean\n title?: string\n unattended?: boolean\n}\n\nexport async function findUserApplication(\n options: FindUserApplicationOptions,\n): Promise<UserApplicationResolved | null> {\n const {cliConfig, create, 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), create, 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","create","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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"}
|
|
@@ -100,7 +100,7 @@ import { normalizeUrl, validateUrl } from './urlUtils.js';
|
|
|
100
100
|
*
|
|
101
101
|
* @internal
|
|
102
102
|
*/ export async function resolveAppDeployTarget(options) {
|
|
103
|
-
const { appId, organizationId } = options;
|
|
103
|
+
const { appId, create, organizationId } = options;
|
|
104
104
|
if (appId) {
|
|
105
105
|
const application = await getUserApplication({
|
|
106
106
|
appId,
|
|
@@ -124,6 +124,11 @@ import { normalizeUrl, validateUrl } from './urlUtils.js';
|
|
|
124
124
|
type: 'blocked'
|
|
125
125
|
};
|
|
126
126
|
}
|
|
127
|
+
if (create) {
|
|
128
|
+
return {
|
|
129
|
+
type: 'would-create'
|
|
130
|
+
};
|
|
131
|
+
}
|
|
127
132
|
const existing = await getUserApplications({
|
|
128
133
|
appType: 'coreApp',
|
|
129
134
|
organizationId
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/deploy/resolveDeployTarget.ts"],"sourcesContent":["import {getApplication, getApplicationUrl, listApplications} from '@sanity/workbench-cli/deploy'\n\nimport {\n getUserApplication,\n getUserApplications,\n type UserApplication,\n type UserApplicationResolved,\n} from '../../services/userApplications.js'\nimport {APP_ID_NOT_FOUND_IN_ORGANIZATION} from '../../util/errorMessages.js'\nimport {normalizeUrl, validateUrl} from './urlUtils.js'\n\n/** The application fields a deploy-target verdict carries for reporting. */\nexport interface DeployTargetApp {\n id: string\n title: string | null\n type: 'coreApp' | 'studio'\n\n appHost?: string\n url?: string\n}\n\n/** A coreApp verdict also carries the organization, for the dashboard URL. */\ninterface DeployTargetCoreApp extends DeployTargetApp {\n organizationId: string\n}\n\n/**\n * The read-only outcome of resolving where a deploy would go.\n *\n * - `found` — the deploy targets this existing application\n * - `would-create` — nothing registered yet; a deploy would create it without prompting\n * - `needs-input` — config doesn't determine a target; a deploy would prompt\n * (`existing` lists the applications a prompt would offer)\n * - `invalid` — the configured target can never resolve (bad host, unknown appId)\n * - `blocked` — resolution requires config that's missing (projectId/organizationId)\n *\n * Transport errors (network, permissions) throw — they're not verdicts.\n *\n * The user-applications resolvers carry the full {@link UserApplication} (the\n * real deploy needs it); the workbench resolvers and the report only need\n * {@link DeployTargetApp}, so `App` defaults to that widened shape.\n */\ntype CommonDeployTargetResolution<App = DeployTargetApp> =\n | {application: App; type: 'found'}\n | {existing: App[]; type: 'needs-input'}\n | {message: string; reason: 'app-not-found' | 'invalid-host'; type: 'invalid'}\n | {message: string; type: 'blocked'}\n\nexport type StudioDeployTargetResolution<App = DeployTargetApp> =\n | CommonDeployTargetResolution<App>\n | {appHost: string; existing: App; type: 'slug-taken'}\n | {appHost: string; type: 'would-create'}\n\nexport type AppDeployTargetResolution<App = DeployTargetCoreApp> =\n | CommonDeployTargetResolution<App>\n | {appHost: string; existing: App; type: 'slug-taken'}\n | {appHost?: string; type: 'would-create'}\n\n/**\n * Owns the studio deploy-target rules: the --url flag over studioHost config,\n * appId over appHost precedence, external URL normalization and validation.\n * Both the real deploy and the dry run consume these verdicts.\n *\n * @internal\n */\nexport async function resolveStudioDeployTarget(options: {\n appId: string | undefined\n isExternal: boolean\n projectId: string | undefined\n studioHost: string | undefined\n urlFlag: string | undefined\n}): Promise<StudioDeployTargetResolution<UserApplication>> {\n const {appId, isExternal, projectId, studioHost, urlFlag} = options\n\n // appId wins over host config (and undeploy resolves it the same way): a\n // configured appId deploys even when studioHost is stale or invalid, so it's\n // resolved before any host validation.\n if (appId) {\n if (!projectId) {\n return {message: 'api.projectId is missing', type: 'blocked'}\n }\n const application = await getUserApplication({appId, isSdkApp: false, projectId})\n if (application) {\n return {application, type: 'found'}\n }\n return {\n message: `Cannot find app with app ID ${appId}`,\n reason: 'app-not-found',\n type: 'invalid',\n }\n }\n\n const {error: hostError, host: resolvedHost} = resolveAppHost({\n isExternal,\n studioHost,\n url: urlFlag,\n })\n if (hostError) {\n return {message: hostError, reason: 'invalid-host', type: 'invalid'}\n }\n\n // A host from config hasn't passed through the --url validation yet\n let appHost = resolvedHost\n if (appHost && isExternal) {\n appHost = normalizeUrl(appHost)\n const validation = validateUrl(appHost)\n if (validation !== true) {\n return {message: validation, reason: 'invalid-host', type: 'invalid'}\n }\n }\n\n if (appHost) {\n if (!projectId) {\n return {message: 'api.projectId is missing', type: 'blocked'}\n }\n const application = await getUserApplication({appHost, isSdkApp: false, projectId})\n if (application) {\n return {application, type: 'found'}\n }\n return {appHost, type: 'would-create'}\n }\n\n // Neither appId nor host configured — a deploy would prompt.\n // Without a project there is nothing to list; a deploy would still prompt.\n const existing = projectId ? await listStudioApplications(projectId, isExternal) : []\n return {existing, type: 'needs-input'}\n}\n\n/**\n * Owns the app deploy-target rules: appId lookup, falling back to listing the\n * organization's applications. Both the real deploy and the dry run consume\n * these verdicts.\n *\n * @internal\n */\nexport async function resolveAppDeployTarget(options: {\n appId: string | undefined\n organizationId: string | undefined\n}): Promise<AppDeployTargetResolution<UserApplicationResolved>> {\n const {appId, organizationId} = options\n\n if (appId) {\n const application = await getUserApplication({appId, isSdkApp: true})\n if (application) {\n return {application, type: 'found'}\n }\n return {\n message: `Cannot find app with app ID ${appId}`,\n reason: 'app-not-found',\n type: 'invalid',\n }\n }\n\n if (!organizationId) {\n return {message: 'app.organizationId is missing', type: 'blocked'}\n }\n\n const existing = await getUserApplications({appType: 'coreApp', organizationId})\n if (existing?.length) {\n return {existing, type: 'needs-input'}\n }\n\n return {type: 'would-create'}\n}\n\n/**\n * The dry-run counterpart to a workbench app's create-on-deploy: without an\n * `appId`, an org already holding the slug resolves to that app, so the report\n * can name its id instead of a create that would fail.\n *\n * @internal\n */\nexport async function resolveWorkbenchApp({\n appId,\n organizationId,\n slug,\n}: {\n appId: string | undefined\n organizationId?: string\n slug?: string\n}): Promise<AppDeployTargetResolution> {\n if (appId) return resolveAppById(appId)\n\n if (organizationId && slug) {\n const existing = (await listApplications(organizationId)).find((app) => app.slug === slug)\n if (existing) {\n return {\n appHost: slug,\n existing: {...existing, url: getApplicationUrl(existing)},\n type: 'slug-taken',\n }\n }\n }\n\n return {appHost: slug, type: 'would-create'}\n}\n\n/**\n * {@link resolveWorkbenchApp} narrowed for a studio, whose slug is always configured.\n *\n * @internal\n */\nexport async function resolveWorkbenchStudio(options: {\n appId: string | undefined\n organizationId?: string\n slug: string\n}): Promise<StudioDeployTargetResolution> {\n const resolution = await resolveWorkbenchApp(options)\n return resolution.type === 'would-create'\n ? {appHost: options.slug, type: 'would-create'}\n : resolution\n}\n\nasync function resolveAppById(\n appId: string,\n): Promise<CommonDeployTargetResolution<DeployTargetCoreApp>> {\n const application = await getApplication(appId)\n return application\n ? {\n application: {...application, url: getApplicationUrl(application)},\n type: 'found',\n }\n : {message: APP_ID_NOT_FOUND_IN_ORGANIZATION, reason: 'app-not-found', type: 'invalid'}\n}\n\nasync function listStudioApplications(\n projectId: string,\n isExternal: boolean,\n): Promise<UserApplication[]> {\n const urlType = isExternal ? 'external' : 'internal'\n const applications = await getUserApplications({appType: 'studio', projectId})\n // External deploys should only see external studios and vice versa\n return applications?.filter((application) => application.urlType === urlType) ?? []\n}\n\nfunction resolveAppHost({\n isExternal,\n studioHost,\n url,\n}: {\n isExternal: boolean\n studioHost: string | undefined\n url: string | undefined\n}): {error?: string; host?: string} {\n if (!url) {\n return {host: studioHost}\n }\n\n if (isExternal) {\n const normalized = normalizeUrl(url)\n const validation = validateUrl(normalized)\n if (validation !== true) {\n return {error: validation}\n }\n return {host: normalized}\n }\n\n // For internal deploys, strip protocol prefix and .sanity.studio suffix if present\n const hostname = url.replace(/^https?:\\/\\//i, '').replace(/\\.sanity\\.studio\\/?$/i, '')\n\n // If the result still looks like a URL (contains dots), the user likely meant --external\n if (hostname.includes('.')) {\n return {\n error: `\"${hostname}\" does not look like a sanity.studio hostname. Did you mean to use --external?`,\n }\n }\n\n // Validate hostname characters (alphanumeric and hyphens only)\n if (!/^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/i.test(hostname)) {\n return {\n error: `Invalid studio hostname \"${hostname}\". Hostnames can only contain letters, numbers, and hyphens.`,\n }\n }\n\n return {host: hostname}\n}\n"],"names":["getApplication","getApplicationUrl","listApplications","getUserApplication","getUserApplications","APP_ID_NOT_FOUND_IN_ORGANIZATION","normalizeUrl","validateUrl","resolveStudioDeployTarget","options","appId","isExternal","projectId","studioHost","urlFlag","message","type","application","isSdkApp","reason","error","hostError","host","resolvedHost","resolveAppHost","url","appHost","validation","existing","listStudioApplications","resolveAppDeployTarget","organizationId","appType","length","resolveWorkbenchApp","slug","resolveAppById","find","app","resolveWorkbenchStudio","resolution","urlType","applications","filter","normalized","hostname","replace","includes","test"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/deploy/resolveDeployTarget.ts"],"sourcesContent":["import {getApplication, getApplicationUrl, listApplications} from '@sanity/workbench-cli/deploy'\n\nimport {\n getUserApplication,\n getUserApplications,\n type UserApplication,\n type UserApplicationResolved,\n} from '../../services/userApplications.js'\nimport {APP_ID_NOT_FOUND_IN_ORGANIZATION} from '../../util/errorMessages.js'\nimport {normalizeUrl, validateUrl} from './urlUtils.js'\n\n/** The application fields a deploy-target verdict carries for reporting. */\nexport interface DeployTargetApp {\n id: string\n title: string | null\n type: 'coreApp' | 'studio'\n\n appHost?: string\n url?: string\n}\n\n/** A coreApp verdict also carries the organization, for the dashboard URL. */\ninterface DeployTargetCoreApp extends DeployTargetApp {\n organizationId: string\n}\n\n/**\n * The read-only outcome of resolving where a deploy would go.\n *\n * - `found` — the deploy targets this existing application\n * - `would-create` — nothing registered yet; a deploy would create it without prompting\n * - `needs-input` — config doesn't determine a target; a deploy would prompt\n * (`existing` lists the applications a prompt would offer)\n * - `invalid` — the configured target can never resolve (bad host, unknown appId)\n * - `blocked` — resolution requires config that's missing (projectId/organizationId)\n *\n * Transport errors (network, permissions) throw — they're not verdicts.\n *\n * The user-applications resolvers carry the full {@link UserApplication} (the\n * real deploy needs it); the workbench resolvers and the report only need\n * {@link DeployTargetApp}, so `App` defaults to that widened shape.\n */\ntype CommonDeployTargetResolution<App = DeployTargetApp> =\n | {application: App; type: 'found'}\n | {existing: App[]; type: 'needs-input'}\n | {message: string; reason: 'app-not-found' | 'invalid-host'; type: 'invalid'}\n | {message: string; type: 'blocked'}\n\nexport type StudioDeployTargetResolution<App = DeployTargetApp> =\n | CommonDeployTargetResolution<App>\n | {appHost: string; existing: App; type: 'slug-taken'}\n | {appHost: string; type: 'would-create'}\n\nexport type AppDeployTargetResolution<App = DeployTargetCoreApp> =\n | CommonDeployTargetResolution<App>\n | {appHost: string; existing: App; type: 'slug-taken'}\n | {appHost?: string; type: 'would-create'}\n\n/**\n * Owns the studio deploy-target rules: the --url flag over studioHost config,\n * appId over appHost precedence, external URL normalization and validation.\n * Both the real deploy and the dry run consume these verdicts.\n *\n * @internal\n */\nexport async function resolveStudioDeployTarget(options: {\n appId: string | undefined\n isExternal: boolean\n projectId: string | undefined\n studioHost: string | undefined\n urlFlag: string | undefined\n}): Promise<StudioDeployTargetResolution<UserApplication>> {\n const {appId, isExternal, projectId, studioHost, urlFlag} = options\n\n // appId wins over host config (and undeploy resolves it the same way): a\n // configured appId deploys even when studioHost is stale or invalid, so it's\n // resolved before any host validation.\n if (appId) {\n if (!projectId) {\n return {message: 'api.projectId is missing', type: 'blocked'}\n }\n const application = await getUserApplication({appId, isSdkApp: false, projectId})\n if (application) {\n return {application, type: 'found'}\n }\n return {\n message: `Cannot find app with app ID ${appId}`,\n reason: 'app-not-found',\n type: 'invalid',\n }\n }\n\n const {error: hostError, host: resolvedHost} = resolveAppHost({\n isExternal,\n studioHost,\n url: urlFlag,\n })\n if (hostError) {\n return {message: hostError, reason: 'invalid-host', type: 'invalid'}\n }\n\n // A host from config hasn't passed through the --url validation yet\n let appHost = resolvedHost\n if (appHost && isExternal) {\n appHost = normalizeUrl(appHost)\n const validation = validateUrl(appHost)\n if (validation !== true) {\n return {message: validation, reason: 'invalid-host', type: 'invalid'}\n }\n }\n\n if (appHost) {\n if (!projectId) {\n return {message: 'api.projectId is missing', type: 'blocked'}\n }\n const application = await getUserApplication({appHost, isSdkApp: false, projectId})\n if (application) {\n return {application, type: 'found'}\n }\n return {appHost, type: 'would-create'}\n }\n\n // Neither appId nor host configured — a deploy would prompt.\n // Without a project there is nothing to list; a deploy would still prompt.\n const existing = projectId ? await listStudioApplications(projectId, isExternal) : []\n return {existing, type: 'needs-input'}\n}\n\n/**\n * Owns the app deploy-target rules: appId lookup, falling back to listing the\n * organization's applications. Both the real deploy and the dry run consume\n * these verdicts.\n *\n * @internal\n */\nexport async function resolveAppDeployTarget(options: {\n appId: string | undefined\n create?: boolean\n organizationId: string | undefined\n}): Promise<AppDeployTargetResolution<UserApplicationResolved>> {\n const {appId, create, organizationId} = options\n\n if (appId) {\n const application = await getUserApplication({appId, isSdkApp: true})\n if (application) {\n return {application, type: 'found'}\n }\n return {\n message: `Cannot find app with app ID ${appId}`,\n reason: 'app-not-found',\n type: 'invalid',\n }\n }\n\n if (!organizationId) {\n return {message: 'app.organizationId is missing', type: 'blocked'}\n }\n\n if (create) {\n return {type: 'would-create'}\n }\n\n const existing = await getUserApplications({appType: 'coreApp', organizationId})\n if (existing?.length) {\n return {existing, type: 'needs-input'}\n }\n\n return {type: 'would-create'}\n}\n\n/**\n * The dry-run counterpart to a workbench app's create-on-deploy: without an\n * `appId`, an org already holding the slug resolves to that app, so the report\n * can name its id instead of a create that would fail.\n *\n * @internal\n */\nexport async function resolveWorkbenchApp({\n appId,\n organizationId,\n slug,\n}: {\n appId: string | undefined\n organizationId?: string\n slug?: string\n}): Promise<AppDeployTargetResolution> {\n if (appId) return resolveAppById(appId)\n\n if (organizationId && slug) {\n const existing = (await listApplications(organizationId)).find((app) => app.slug === slug)\n if (existing) {\n return {\n appHost: slug,\n existing: {...existing, url: getApplicationUrl(existing)},\n type: 'slug-taken',\n }\n }\n }\n\n return {appHost: slug, type: 'would-create'}\n}\n\n/**\n * {@link resolveWorkbenchApp} narrowed for a studio, whose slug is always configured.\n *\n * @internal\n */\nexport async function resolveWorkbenchStudio(options: {\n appId: string | undefined\n organizationId?: string\n slug: string\n}): Promise<StudioDeployTargetResolution> {\n const resolution = await resolveWorkbenchApp(options)\n return resolution.type === 'would-create'\n ? {appHost: options.slug, type: 'would-create'}\n : resolution\n}\n\nasync function resolveAppById(\n appId: string,\n): Promise<CommonDeployTargetResolution<DeployTargetCoreApp>> {\n const application = await getApplication(appId)\n return application\n ? {\n application: {...application, url: getApplicationUrl(application)},\n type: 'found',\n }\n : {message: APP_ID_NOT_FOUND_IN_ORGANIZATION, reason: 'app-not-found', type: 'invalid'}\n}\n\nasync function listStudioApplications(\n projectId: string,\n isExternal: boolean,\n): Promise<UserApplication[]> {\n const urlType = isExternal ? 'external' : 'internal'\n const applications = await getUserApplications({appType: 'studio', projectId})\n // External deploys should only see external studios and vice versa\n return applications?.filter((application) => application.urlType === urlType) ?? []\n}\n\nfunction resolveAppHost({\n isExternal,\n studioHost,\n url,\n}: {\n isExternal: boolean\n studioHost: string | undefined\n url: string | undefined\n}): {error?: string; host?: string} {\n if (!url) {\n return {host: studioHost}\n }\n\n if (isExternal) {\n const normalized = normalizeUrl(url)\n const validation = validateUrl(normalized)\n if (validation !== true) {\n return {error: validation}\n }\n return {host: normalized}\n }\n\n // For internal deploys, strip protocol prefix and .sanity.studio suffix if present\n const hostname = url.replace(/^https?:\\/\\//i, '').replace(/\\.sanity\\.studio\\/?$/i, '')\n\n // If the result still looks like a URL (contains dots), the user likely meant --external\n if (hostname.includes('.')) {\n return {\n error: `\"${hostname}\" does not look like a sanity.studio hostname. Did you mean to use --external?`,\n }\n }\n\n // Validate hostname characters (alphanumeric and hyphens only)\n if (!/^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/i.test(hostname)) {\n return {\n error: `Invalid studio hostname \"${hostname}\". Hostnames can only contain letters, numbers, and hyphens.`,\n }\n }\n\n return {host: hostname}\n}\n"],"names":["getApplication","getApplicationUrl","listApplications","getUserApplication","getUserApplications","APP_ID_NOT_FOUND_IN_ORGANIZATION","normalizeUrl","validateUrl","resolveStudioDeployTarget","options","appId","isExternal","projectId","studioHost","urlFlag","message","type","application","isSdkApp","reason","error","hostError","host","resolvedHost","resolveAppHost","url","appHost","validation","existing","listStudioApplications","resolveAppDeployTarget","create","organizationId","appType","length","resolveWorkbenchApp","slug","resolveAppById","find","app","resolveWorkbenchStudio","resolution","urlType","applications","filter","normalized","hostname","replace","includes","test"],"mappings":"AAAA,SAAQA,cAAc,EAAEC,iBAAiB,EAAEC,gBAAgB,QAAO,+BAA8B;AAEhG,SACEC,kBAAkB,EAClBC,mBAAmB,QAGd,qCAAoC;AAC3C,SAAQC,gCAAgC,QAAO,8BAA6B;AAC5E,SAAQC,YAAY,EAAEC,WAAW,QAAO,gBAAe;AAiDvD;;;;;;CAMC,GACD,OAAO,eAAeC,0BAA0BC,OAM/C;IACC,MAAM,EAACC,KAAK,EAAEC,UAAU,EAAEC,SAAS,EAAEC,UAAU,EAAEC,OAAO,EAAC,GAAGL;IAE5D,yEAAyE;IACzE,6EAA6E;IAC7E,uCAAuC;IACvC,IAAIC,OAAO;QACT,IAAI,CAACE,WAAW;YACd,OAAO;gBAACG,SAAS;gBAA4BC,MAAM;YAAS;QAC9D;QACA,MAAMC,cAAc,MAAMd,mBAAmB;YAACO;YAAOQ,UAAU;YAAON;QAAS;QAC/E,IAAIK,aAAa;YACf,OAAO;gBAACA;gBAAaD,MAAM;YAAO;QACpC;QACA,OAAO;YACLD,SAAS,CAAC,4BAA4B,EAAEL,OAAO;YAC/CS,QAAQ;YACRH,MAAM;QACR;IACF;IAEA,MAAM,EAACI,OAAOC,SAAS,EAAEC,MAAMC,YAAY,EAAC,GAAGC,eAAe;QAC5Db;QACAE;QACAY,KAAKX;IACP;IACA,IAAIO,WAAW;QACb,OAAO;YAACN,SAASM;YAAWF,QAAQ;YAAgBH,MAAM;QAAS;IACrE;IAEA,oEAAoE;IACpE,IAAIU,UAAUH;IACd,IAAIG,WAAWf,YAAY;QACzBe,UAAUpB,aAAaoB;QACvB,MAAMC,aAAapB,YAAYmB;QAC/B,IAAIC,eAAe,MAAM;YACvB,OAAO;gBAACZ,SAASY;gBAAYR,QAAQ;gBAAgBH,MAAM;YAAS;QACtE;IACF;IAEA,IAAIU,SAAS;QACX,IAAI,CAACd,WAAW;YACd,OAAO;gBAACG,SAAS;gBAA4BC,MAAM;YAAS;QAC9D;QACA,MAAMC,cAAc,MAAMd,mBAAmB;YAACuB;YAASR,UAAU;YAAON;QAAS;QACjF,IAAIK,aAAa;YACf,OAAO;gBAACA;gBAAaD,MAAM;YAAO;QACpC;QACA,OAAO;YAACU;YAASV,MAAM;QAAc;IACvC;IAEA,6DAA6D;IAC7D,2EAA2E;IAC3E,MAAMY,WAAWhB,YAAY,MAAMiB,uBAAuBjB,WAAWD,cAAc,EAAE;IACrF,OAAO;QAACiB;QAAUZ,MAAM;IAAa;AACvC;AAEA;;;;;;CAMC,GACD,OAAO,eAAec,uBAAuBrB,OAI5C;IACC,MAAM,EAACC,KAAK,EAAEqB,MAAM,EAAEC,cAAc,EAAC,GAAGvB;IAExC,IAAIC,OAAO;QACT,MAAMO,cAAc,MAAMd,mBAAmB;YAACO;YAAOQ,UAAU;QAAI;QACnE,IAAID,aAAa;YACf,OAAO;gBAACA;gBAAaD,MAAM;YAAO;QACpC;QACA,OAAO;YACLD,SAAS,CAAC,4BAA4B,EAAEL,OAAO;YAC/CS,QAAQ;YACRH,MAAM;QACR;IACF;IAEA,IAAI,CAACgB,gBAAgB;QACnB,OAAO;YAACjB,SAAS;YAAiCC,MAAM;QAAS;IACnE;IAEA,IAAIe,QAAQ;QACV,OAAO;YAACf,MAAM;QAAc;IAC9B;IAEA,MAAMY,WAAW,MAAMxB,oBAAoB;QAAC6B,SAAS;QAAWD;IAAc;IAC9E,IAAIJ,UAAUM,QAAQ;QACpB,OAAO;YAACN;YAAUZ,MAAM;QAAa;IACvC;IAEA,OAAO;QAACA,MAAM;IAAc;AAC9B;AAEA;;;;;;CAMC,GACD,OAAO,eAAemB,oBAAoB,EACxCzB,KAAK,EACLsB,cAAc,EACdI,IAAI,EAKL;IACC,IAAI1B,OAAO,OAAO2B,eAAe3B;IAEjC,IAAIsB,kBAAkBI,MAAM;QAC1B,MAAMR,WAAW,AAAC,CAAA,MAAM1B,iBAAiB8B,eAAc,EAAGM,IAAI,CAAC,CAACC,MAAQA,IAAIH,IAAI,KAAKA;QACrF,IAAIR,UAAU;YACZ,OAAO;gBACLF,SAASU;gBACTR,UAAU;oBAAC,GAAGA,QAAQ;oBAAEH,KAAKxB,kBAAkB2B;gBAAS;gBACxDZ,MAAM;YACR;QACF;IACF;IAEA,OAAO;QAACU,SAASU;QAAMpB,MAAM;IAAc;AAC7C;AAEA;;;;CAIC,GACD,OAAO,eAAewB,uBAAuB/B,OAI5C;IACC,MAAMgC,aAAa,MAAMN,oBAAoB1B;IAC7C,OAAOgC,WAAWzB,IAAI,KAAK,iBACvB;QAACU,SAASjB,QAAQ2B,IAAI;QAAEpB,MAAM;IAAc,IAC5CyB;AACN;AAEA,eAAeJ,eACb3B,KAAa;IAEb,MAAMO,cAAc,MAAMjB,eAAeU;IACzC,OAAOO,cACH;QACEA,aAAa;YAAC,GAAGA,WAAW;YAAEQ,KAAKxB,kBAAkBgB;QAAY;QACjED,MAAM;IACR,IACA;QAACD,SAASV;QAAkCc,QAAQ;QAAiBH,MAAM;IAAS;AAC1F;AAEA,eAAea,uBACbjB,SAAiB,EACjBD,UAAmB;IAEnB,MAAM+B,UAAU/B,aAAa,aAAa;IAC1C,MAAMgC,eAAe,MAAMvC,oBAAoB;QAAC6B,SAAS;QAAUrB;IAAS;IAC5E,mEAAmE;IACnE,OAAO+B,cAAcC,OAAO,CAAC3B,cAAgBA,YAAYyB,OAAO,KAAKA,YAAY,EAAE;AACrF;AAEA,SAASlB,eAAe,EACtBb,UAAU,EACVE,UAAU,EACVY,GAAG,EAKJ;IACC,IAAI,CAACA,KAAK;QACR,OAAO;YAACH,MAAMT;QAAU;IAC1B;IAEA,IAAIF,YAAY;QACd,MAAMkC,aAAavC,aAAamB;QAChC,MAAME,aAAapB,YAAYsC;QAC/B,IAAIlB,eAAe,MAAM;YACvB,OAAO;gBAACP,OAAOO;YAAU;QAC3B;QACA,OAAO;YAACL,MAAMuB;QAAU;IAC1B;IAEA,mFAAmF;IACnF,MAAMC,WAAWrB,IAAIsB,OAAO,CAAC,iBAAiB,IAAIA,OAAO,CAAC,yBAAyB;IAEnF,yFAAyF;IACzF,IAAID,SAASE,QAAQ,CAAC,MAAM;QAC1B,OAAO;YACL5B,OAAO,CAAC,CAAC,EAAE0B,SAAS,8EAA8E,CAAC;QACrG;IACF;IAEA,+DAA+D;IAC/D,IAAI,CAAC,mCAAmCG,IAAI,CAACH,WAAW;QACtD,OAAO;YACL1B,OAAO,CAAC,yBAAyB,EAAE0B,SAAS,4DAA4D,CAAC;QAC3G;IACF;IAEA,OAAO;QAACxB,MAAMwB;IAAQ;AACxB"}
|
|
@@ -196,10 +196,7 @@ async function main() {
|
|
|
196
196
|
validateDocument({
|
|
197
197
|
document,
|
|
198
198
|
environment: 'cli',
|
|
199
|
-
|
|
200
|
-
// @sanity/client major; the runtime surface validation uses is
|
|
201
|
-
// compatible across v7/v8.
|
|
202
|
-
getClient: getClient,
|
|
199
|
+
getClient,
|
|
203
200
|
getDocumentExists,
|
|
204
201
|
maxCustomValidationConcurrency,
|
|
205
202
|
maxFetchConcurrency,
|