@sanity/cli 7.9.0 → 7.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (188) hide show
  1. package/README.md +163 -22
  2. package/dist/actions/auth/ensureAuthenticated.js +2 -0
  3. package/dist/actions/auth/ensureAuthenticated.js.map +1 -1
  4. package/dist/actions/auth/login/getProvider.js +7 -2
  5. package/dist/actions/auth/login/getProvider.js.map +1 -1
  6. package/dist/actions/auth/login/loginInstructions.js +19 -0
  7. package/dist/actions/auth/login/loginInstructions.js.map +1 -0
  8. package/dist/actions/dataset/create.js +2 -2
  9. package/dist/actions/dataset/create.js.map +1 -1
  10. package/dist/actions/dataset/resolveDataset.js +7 -1
  11. package/dist/actions/dataset/resolveDataset.js.map +1 -1
  12. package/dist/actions/deploy/createUserApplication.js +8 -5
  13. package/dist/actions/deploy/createUserApplication.js.map +1 -1
  14. package/dist/actions/deploy/deployApp.js +47 -24
  15. package/dist/actions/deploy/deployApp.js.map +1 -1
  16. package/dist/actions/deploy/deployStudio.js +2 -0
  17. package/dist/actions/deploy/deployStudio.js.map +1 -1
  18. package/dist/actions/graphql/resolveApiGeneration.js +9 -6
  19. package/dist/actions/graphql/resolveApiGeneration.js.map +1 -1
  20. package/dist/actions/init/initAction.js +23 -15
  21. package/dist/actions/init/initAction.js.map +1 -1
  22. package/dist/actions/manifest/extractCoreAppManifest.js +11 -4
  23. package/dist/actions/manifest/extractCoreAppManifest.js.map +1 -1
  24. package/dist/actions/migration/constants.js +10 -0
  25. package/dist/actions/migration/constants.js.map +1 -0
  26. package/dist/actions/migration/ensureApiVersionFormat.js +16 -0
  27. package/dist/actions/migration/ensureApiVersionFormat.js.map +1 -0
  28. package/dist/actions/migration/fileExists.js +13 -0
  29. package/dist/actions/migration/fileExists.js.map +1 -0
  30. package/dist/actions/migration/prettyMutationFormatter.js +155 -0
  31. package/dist/actions/migration/prettyMutationFormatter.js.map +1 -0
  32. package/dist/actions/migration/resolveMigrationScript.js +75 -0
  33. package/dist/actions/migration/resolveMigrationScript.js.map +1 -0
  34. package/dist/actions/migration/resolveMigrations.js +50 -0
  35. package/dist/actions/migration/resolveMigrations.js.map +1 -0
  36. package/dist/actions/migration/templates/index.js +7 -0
  37. package/dist/actions/migration/templates/index.js.map +1 -0
  38. package/dist/actions/migration/templates/minimalAdvanced.js +21 -0
  39. package/dist/actions/migration/templates/minimalAdvanced.js.map +1 -0
  40. package/dist/actions/migration/templates/minimalSimple.js +61 -0
  41. package/dist/actions/migration/templates/minimalSimple.js.map +1 -0
  42. package/dist/actions/migration/templates/renameField.js +20 -0
  43. package/dist/actions/migration/templates/renameField.js.map +1 -0
  44. package/dist/actions/migration/templates/renameType.js +19 -0
  45. package/dist/actions/migration/templates/renameType.js.map +1 -0
  46. package/dist/actions/migration/templates/stringToPTE.js +32 -0
  47. package/dist/actions/migration/templates/stringToPTE.js.map +1 -0
  48. package/dist/actions/migration/tree.js +111 -0
  49. package/dist/actions/migration/tree.js.map +1 -0
  50. package/dist/actions/organizations/getOrganization.js +7 -3
  51. package/dist/actions/organizations/getOrganization.js.map +1 -1
  52. package/dist/actions/organizations/validateOrganizationSlug.js +20 -0
  53. package/dist/actions/organizations/validateOrganizationSlug.js.map +1 -0
  54. package/dist/actions/preview/previewAction.js +33 -1
  55. package/dist/actions/preview/previewAction.js.map +1 -1
  56. package/dist/actions/schema/listSchemas.js +6 -4
  57. package/dist/actions/schema/listSchemas.js.map +1 -1
  58. package/dist/actions/tokens/validateRole.js +2 -1
  59. package/dist/actions/tokens/validateRole.js.map +1 -1
  60. package/dist/actions/undeploy/runUndeploy.js +13 -4
  61. package/dist/actions/undeploy/runUndeploy.js.map +1 -1
  62. package/dist/commands/backups/disable.js +5 -1
  63. package/dist/commands/backups/disable.js.map +1 -1
  64. package/dist/commands/backups/download.js +30 -6
  65. package/dist/commands/backups/download.js.map +1 -1
  66. package/dist/commands/backups/enable.js +5 -1
  67. package/dist/commands/backups/enable.js.map +1 -1
  68. package/dist/commands/backups/list.js +5 -1
  69. package/dist/commands/backups/list.js.map +1 -1
  70. package/dist/commands/cors/add.js +15 -7
  71. package/dist/commands/cors/add.js.map +1 -1
  72. package/dist/commands/cors/delete.js +6 -1
  73. package/dist/commands/cors/delete.js.map +1 -1
  74. package/dist/commands/datasets/alias/create.js +25 -18
  75. package/dist/commands/datasets/alias/create.js.map +1 -1
  76. package/dist/commands/datasets/alias/delete.js +15 -8
  77. package/dist/commands/datasets/alias/delete.js.map +1 -1
  78. package/dist/commands/datasets/alias/link.js +39 -17
  79. package/dist/commands/datasets/alias/link.js.map +1 -1
  80. package/dist/commands/datasets/alias/unlink.js +23 -2
  81. package/dist/commands/datasets/alias/unlink.js.map +1 -1
  82. package/dist/commands/datasets/copy.js +18 -2
  83. package/dist/commands/datasets/copy.js.map +1 -1
  84. package/dist/commands/datasets/create.js +8 -2
  85. package/dist/commands/datasets/create.js.map +1 -1
  86. package/dist/commands/datasets/delete.js +14 -17
  87. package/dist/commands/datasets/delete.js.map +1 -1
  88. package/dist/commands/datasets/embeddings/disable.js +3 -0
  89. package/dist/commands/datasets/embeddings/disable.js.map +1 -1
  90. package/dist/commands/datasets/embeddings/enable.js +5 -2
  91. package/dist/commands/datasets/embeddings/enable.js.map +1 -1
  92. package/dist/commands/datasets/embeddings/status.js +3 -0
  93. package/dist/commands/datasets/embeddings/status.js.map +1 -1
  94. package/dist/commands/datasets/export.js +27 -15
  95. package/dist/commands/datasets/export.js.map +1 -1
  96. package/dist/commands/datasets/import.js +3 -3
  97. package/dist/commands/datasets/import.js.map +1 -1
  98. package/dist/commands/datasets/visibility/get.js +2 -2
  99. package/dist/commands/datasets/visibility/get.js.map +1 -1
  100. package/dist/commands/datasets/visibility/set.js +2 -2
  101. package/dist/commands/datasets/visibility/set.js.map +1 -1
  102. package/dist/commands/docs/read.js +3 -3
  103. package/dist/commands/docs/read.js.map +1 -1
  104. package/dist/commands/documents/create.js +18 -13
  105. package/dist/commands/documents/create.js.map +1 -1
  106. package/dist/commands/documents/delete.js +3 -3
  107. package/dist/commands/documents/delete.js.map +1 -1
  108. package/dist/commands/documents/get.js +3 -3
  109. package/dist/commands/documents/get.js.map +1 -1
  110. package/dist/commands/documents/query.js +3 -3
  111. package/dist/commands/documents/query.js.map +1 -1
  112. package/dist/commands/documents/validate.js +29 -26
  113. package/dist/commands/documents/validate.js.map +1 -1
  114. package/dist/commands/graphql/deploy.js +20 -16
  115. package/dist/commands/graphql/deploy.js.map +1 -1
  116. package/dist/commands/graphql/undeploy.js +15 -18
  117. package/dist/commands/graphql/undeploy.js.map +1 -1
  118. package/dist/commands/hooks/create.js +4 -0
  119. package/dist/commands/hooks/create.js.map +1 -1
  120. package/dist/commands/hooks/delete.js +6 -1
  121. package/dist/commands/hooks/delete.js.map +1 -1
  122. package/dist/commands/hooks/logs.js +6 -1
  123. package/dist/commands/hooks/logs.js.map +1 -1
  124. package/dist/commands/install.js +1 -1
  125. package/dist/commands/install.js.map +1 -1
  126. package/dist/commands/login.js +2 -1
  127. package/dist/commands/login.js.map +1 -1
  128. package/dist/commands/media/create-aspect.js +20 -8
  129. package/dist/commands/media/create-aspect.js.map +1 -1
  130. package/dist/commands/media/delete-aspect.js +31 -16
  131. package/dist/commands/media/delete-aspect.js.map +1 -1
  132. package/dist/commands/media/deploy-aspect.js +10 -5
  133. package/dist/commands/media/deploy-aspect.js.map +1 -1
  134. package/dist/commands/media/export.js +9 -4
  135. package/dist/commands/media/export.js.map +1 -1
  136. package/dist/commands/media/import.js +6 -1
  137. package/dist/commands/media/import.js.map +1 -1
  138. package/dist/commands/migrations/create.js +150 -0
  139. package/dist/commands/migrations/create.js.map +1 -0
  140. package/dist/commands/migrations/list.js +64 -0
  141. package/dist/commands/migrations/list.js.map +1 -0
  142. package/dist/commands/migrations/run.js +306 -0
  143. package/dist/commands/migrations/run.js.map +1 -0
  144. package/dist/commands/organizations/create.js +79 -0
  145. package/dist/commands/organizations/create.js.map +1 -0
  146. package/dist/commands/organizations/delete.js +100 -0
  147. package/dist/commands/organizations/delete.js.map +1 -0
  148. package/dist/commands/organizations/get.js +48 -0
  149. package/dist/commands/organizations/get.js.map +1 -0
  150. package/dist/commands/organizations/list.js +60 -0
  151. package/dist/commands/organizations/list.js.map +1 -0
  152. package/dist/commands/organizations/update.js +115 -0
  153. package/dist/commands/organizations/update.js.map +1 -0
  154. package/dist/commands/preview.js +1 -0
  155. package/dist/commands/preview.js.map +1 -1
  156. package/dist/commands/projects/create.js +3 -1
  157. package/dist/commands/projects/create.js.map +1 -1
  158. package/dist/commands/schemas/delete.js +23 -2
  159. package/dist/commands/schemas/delete.js.map +1 -1
  160. package/dist/commands/schemas/deploy.js +6 -4
  161. package/dist/commands/schemas/deploy.js.map +1 -1
  162. package/dist/commands/schemas/extract.js +22 -1
  163. package/dist/commands/schemas/extract.js.map +1 -1
  164. package/dist/commands/schemas/list.js +8 -8
  165. package/dist/commands/schemas/list.js.map +1 -1
  166. package/dist/commands/tokens/{add.js → create.js} +25 -18
  167. package/dist/commands/tokens/create.js.map +1 -0
  168. package/dist/commands/tokens/delete.js +41 -23
  169. package/dist/commands/tokens/delete.js.map +1 -1
  170. package/dist/commands/undeploy.js +2 -7
  171. package/dist/commands/undeploy.js.map +1 -1
  172. package/dist/commands/users/invite.js +25 -3
  173. package/dist/commands/users/invite.js.map +1 -1
  174. package/dist/prompts/promptForOrganizationName.js +2 -1
  175. package/dist/prompts/promptForOrganizationName.js.map +1 -1
  176. package/dist/services/organizations.js +45 -2
  177. package/dist/services/organizations.js.map +1 -1
  178. package/dist/services/userApplications.js.map +1 -1
  179. package/dist/topicAliases.js +10 -0
  180. package/dist/topicAliases.js.map +1 -1
  181. package/dist/util/formatCliErrorMessages.js +5 -0
  182. package/dist/util/formatCliErrorMessages.js.map +1 -0
  183. package/dist/util/organizationAliases.js +12 -0
  184. package/dist/util/organizationAliases.js.map +1 -0
  185. package/oclif.config.js +6 -1
  186. package/oclif.manifest.json +464 -11
  187. package/package.json +28 -28
  188. package/dist/commands/tokens/add.js.map +0 -1
@@ -11,7 +11,7 @@ import { createDeployment, updateUserApplication } from '../../services/userAppl
11
11
  import { getAppId } from '../../util/appId.js';
12
12
  import { EXTERNAL_APP_NOT_SUPPORTED, NO_ORGANIZATION_ID } from '../../util/errorMessages.js';
13
13
  import { buildApp } from '../build/buildApp.js';
14
- import { extractCoreAppManifest, resolveTitleUpdate } from '../manifest/extractCoreAppManifest.js';
14
+ import { extractCoreAppManifest, readIconFromPath, resolveTitleUpdate } from '../manifest/extractCoreAppManifest.js';
15
15
  import { createUserApplication, generateAppSlug } from './createUserApplication.js';
16
16
  import { checkAppId, checkAppTarget, checkAutoUpdates, checkBuild, checkPackageVersion, verifyOutputDir } from './deployChecks.js';
17
17
  import { deployDebug } from './deployDebug.js';
@@ -121,18 +121,22 @@ export function deployApp(options) {
121
121
  reporter,
122
122
  sourceDir
123
123
  });
124
- // Manifests aren't strictly essential, so a failure warns and continues
124
+ // Workbench apps ship their icon straight to Brett (below) and don't read the
125
+ // core-app manifest; only plain core-apps do. Manifests aren't strictly
126
+ // essential, so a failure warns and continues.
125
127
  let manifest;
126
- try {
127
- manifest = await extractCoreAppManifest({
128
- workDir
129
- });
130
- } catch (err) {
131
- deployDebug('Error extracting app manifest', err);
132
- reporter.report({
133
- message: `Error extracting app manifest: ${getErrorMessage(err)}`,
134
- status: 'warn'
135
- });
128
+ if (!workbench) {
129
+ try {
130
+ manifest = await extractCoreAppManifest({
131
+ workDir
132
+ });
133
+ } catch (err) {
134
+ deployDebug('Error extracting app manifest', err);
135
+ reporter.report({
136
+ message: `Error extracting app manifest: ${getErrorMessage(err)}`,
137
+ status: 'warn'
138
+ });
139
+ }
136
140
  }
137
141
  // Resolve the installation in both modes so the report — dry-run and real —
138
142
  // shows whether the config is deployable; a missing one fails the deploy here.
@@ -201,6 +205,7 @@ export function deployApp(options) {
201
205
  const slug = workbench.slug ?? generateAppSlug();
202
206
  const { applicationId } = await deployWorkbenchCoreApp({
203
207
  appId,
208
+ icon: workbench.icon ? await readIconFromPath(workDir, workbench.icon) : undefined,
204
209
  interfaces: buildExposes(workbench, {
205
210
  appName: workbench.name,
206
211
  appTitle,
@@ -213,7 +218,8 @@ export function deployApp(options) {
213
218
  slug,
214
219
  sourceDir,
215
220
  title: appTitle,
216
- version
221
+ version,
222
+ visibility: workbench.visibility
217
223
  });
218
224
  const url = getApplicationUrl({
219
225
  id: applicationId,
@@ -253,10 +259,11 @@ export function deployApp(options) {
253
259
  // A real deploy has already exited if anything failed; landing here without a
254
260
  // resolved application means the deploy target was never resolved.
255
261
  if (!application) return;
256
- application = await syncApplicationTitle({
262
+ application = await syncApplicationMetadata({
257
263
  application,
258
264
  manifest,
259
- output
265
+ output,
266
+ visibility: cliConfig.app?.visibility
260
267
  });
261
268
  await shipAppDeployment({
262
269
  application,
@@ -313,7 +320,7 @@ export function deployApp(options) {
313
320
  deployDebug('User application found', application);
314
321
  if (!application) {
315
322
  deployDebug('No user application found. Creating a new one');
316
- application = await createUserApplication(organizationId, title);
323
+ application = await createUserApplication(organizationId, title, cliConfig.app?.visibility);
317
324
  deployDebug('User application created', application);
318
325
  return {
319
326
  application,
@@ -325,18 +332,34 @@ export function deployApp(options) {
325
332
  created: false
326
333
  };
327
334
  }
328
- /** Syncs the application title from the manifest when it has changed. */ async function syncApplicationTitle({ application, manifest, output }) {
335
+ /**
336
+ * Syncs application metadata on redeploy when it has changed: the title from the
337
+ * manifest and the dashboard visibility from config. Sends a single PATCH with
338
+ * only the changed fields, and skips the request entirely when nothing changed.
339
+ */ export async function syncApplicationMetadata({ application, manifest, output, visibility }) {
329
340
  const titleUpdate = resolveTitleUpdate(manifest, application);
330
- if (!titleUpdate) return application;
331
- deployDebug('Updating application title from manifest', titleUpdate);
332
- output.log(titleUpdate.from ? `Updating title from "${titleUpdate.from}" to "${titleUpdate.to}"` : `Setting application title to "${titleUpdate.to}"`);
333
- const spin = spinner('Updating application title').start();
341
+ // Treat an unset server value as `default` so a config of `default` is a no-op.
342
+ const visibilityChanged = visibility !== undefined && visibility !== (application.dashboardStatus ?? 'default');
343
+ if (!titleUpdate && !visibilityChanged) return application;
344
+ if (titleUpdate) {
345
+ deployDebug('Updating application title from manifest', titleUpdate);
346
+ output.log(titleUpdate.from ? `Updating title from "${titleUpdate.from}" to "${titleUpdate.to}"` : `Setting application title to "${titleUpdate.to}"`);
347
+ }
348
+ if (visibilityChanged) {
349
+ output.log(`Setting dashboard visibility to "${visibility}"`);
350
+ }
351
+ const spin = spinner('Updating application').start();
334
352
  try {
335
353
  const updated = await updateUserApplication({
336
354
  applicationId: application.id,
337
355
  appType: 'coreApp',
338
356
  body: {
339
- title: titleUpdate.to
357
+ ...titleUpdate ? {
358
+ title: titleUpdate.to
359
+ } : {},
360
+ ...visibilityChanged ? {
361
+ dashboardStatus: visibility
362
+ } : {}
340
363
  }
341
364
  });
342
365
  spin.succeed();
@@ -344,10 +367,10 @@ export function deployApp(options) {
344
367
  } catch (err) {
345
368
  spin.fail();
346
369
  const message = getErrorMessage(err);
347
- deployDebug('Error updating application title', {
370
+ deployDebug('Error updating application metadata', {
348
371
  message
349
372
  });
350
- output.warn(`Error updating application title: ${message}`);
373
+ output.warn(`Error updating application metadata: ${message}`);
351
374
  return application;
352
375
  }
353
376
  }
@@ -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 {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 buildExposes,\n deployConfig,\n deployCoreApp as deployWorkbenchCoreApp,\n getApplicationUrl,\n getWorkbench,\n resolveInstallationId,\n summarizeConfig,\n} from '@sanity/workbench-cli/deploy'\nimport {pack} from 'tar-fs'\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 {extractCoreAppManifest, resolveTitleUpdate} from '../manifest/extractCoreAppManifest.js'\nimport {type CoreAppManifest} from '../manifest/types.js'\nimport {createUserApplication, generateAppSlug} 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, reportExposes} from './deploymentPlan.js'\nimport {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 const dryRun = !!flags['dry-run']\n\n // A singleton (the Media Library) persists its config instead of hosting an\n // application; anything that exposes a view or service still ships one.\n const deploySingletonConfig = workbench?.deploySingletonConfig ?? false\n const deployApplication = !workbench || workbench.hasInterfaces\n\n const appTitle = workbench\n ? flags.title?.trim() || cliConfig.app?.title?.trim() || workbench.name\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 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 (deploySingletonConfig) {\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 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 await checkAppTarget(reporter, {\n appId,\n isWorkbenchApp: true,\n slug: workbench.slug,\n title: appTitle,\n })\n } else if (deployApplication) {\n ;({application, created: appCreated} = await resolveAppApplication(options, {dryRun, reporter}))\n }\n\n await checkBuild(reporter, {\n build: () =>\n buildApp({\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({isWorkbenchApp: workbench !== null, reporter, sourceDir})\n\n // Manifests aren't strictly essential, so a failure warns and continues\n let manifest: CoreAppManifest | undefined\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 // 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 config: string | undefined\n const configAppType = workbench?.config?.appType\n if (deploySingletonConfig && organizationId && workbench?.config && configAppType) {\n installationId = await resolveInstallationId({appType: configAppType, organizationId})\n config = summarizeConfig(workbench.config)\n reporter.report(\n installationId\n ? {config, message: config, status: 'pass'}\n : {\n exitCode: exitCodes.USAGE_ERROR,\n message: `No active \"${configAppType}\" installation for organization \"${organizationId}\"`,\n solution: 'Install the Media Library for the organization before deploying its config',\n status: 'fail',\n },\n )\n }\n\n // Report the exposes deploying with the application, both modes.\n const exposes = deployApplication && workbench ? reportExposes(reporter, workbench) : []\n\n // Surface the app's explicit singleton flag when set, both modes.\n if (deployApplication && workbench?.isSingleton !== undefined) {\n reporter.report({\n isSingleton: workbench.isSingleton,\n message: `Singleton: ${workbench.isSingleton}`,\n status: 'pass',\n })\n }\n\n // Dry run stops here — everything below mutates.\n if (dryRun) return\n\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 // A config-only singleton ships no application, only its config.\n if (!deployApplication) {\n if (installationId && version) {\n return {\n applicationType: 'coreApp',\n applicationVersion: version,\n ...(config ? {config} : {}),\n installationId,\n target: null,\n }\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 // Workbench apps deploy to Brett; plain coreApps use user-applications.\n if (workbench && organizationId) {\n const appId = getAppId(cliConfig)\n const slug = workbench.slug ?? generateAppSlug()\n const {applicationId} = await deployWorkbenchCoreApp({\n appId,\n interfaces: buildExposes(workbench, {\n appName: workbench.name,\n appTitle,\n exposesAppView: workbench.entry !== undefined,\n version,\n }),\n isAutoUpdating,\n isSingleton: workbench.isSingleton,\n organizationId,\n slug,\n sourceDir,\n title: appTitle,\n version,\n })\n const url = getApplicationUrl({id: applicationId, organizationId, type: 'coreApp'})\n logAppDeployed({\n applicationId,\n cliConfig,\n created: !appId,\n organizationId,\n output,\n title: appTitle,\n url,\n })\n return {\n applicationType: 'coreApp',\n applicationVersion: version,\n ...(exposes.length > 0 ? {exposes} : {}),\n ...(workbench.isSingleton === undefined ? {} : {isSingleton: workbench.isSingleton}),\n target: {\n action: appId ? 'update' : 'create',\n applicationId,\n // A redeploy ignores the slug, so only a create reports the one it used.\n ...(appId ? {} : {slug}),\n title: appTitle,\n url,\n },\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 syncApplicationTitle({application, manifest, output})\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 applicationType: 'coreApp',\n applicationVersion: version,\n target: {\n action: appCreated ? 'create' : 'update',\n applicationId: application.id,\n title: application.title ?? null,\n url: getCoreAppUrl(application.organizationId, application.id),\n },\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)\n deployDebug('User application created', application)\n return {application, created: true}\n }\n\n return {application, created: false}\n}\n\n/** Syncs the application title from the manifest when it has changed. */\nasync function syncApplicationTitle({\n application,\n manifest,\n output,\n}: {\n application: UserApplicationResolved\n manifest: CoreAppManifest | undefined\n output: DeployAppOptions['output']\n}): Promise<UserApplicationResolved> {\n const titleUpdate = resolveTitleUpdate(manifest, application)\n if (!titleUpdate) return application\n\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 const spin = spinner('Updating application title').start()\n try {\n const updated = await updateUserApplication({\n applicationId: application.id,\n appType: 'coreApp',\n body: {title: titleUpdate.to},\n })\n spin.succeed()\n return updated\n } catch (err) {\n spin.fail()\n const message = getErrorMessage(err)\n deployDebug('Error updating application title', {message})\n output.warn(`Error updating application title: ${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 = pack(dirname(sourceDir), {entries: [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","exitCodes","getErrorMessage","getCoreAppUrl","spinner","buildExposes","deployConfig","deployCoreApp","deployWorkbenchCoreApp","getApplicationUrl","getWorkbench","resolveInstallationId","summarizeConfig","pack","createDeployment","updateUserApplication","getAppId","EXTERNAL_APP_NOT_SUPPORTED","NO_ORGANIZATION_ID","buildApp","extractCoreAppManifest","resolveTitleUpdate","createUserApplication","generateAppSlug","checkAppId","checkAppTarget","checkAutoUpdates","checkBuild","checkPackageVersion","verifyOutputDir","deployDebug","listDeploymentFiles","reportExposes","runDeploy","findUserApplication","APP_PACKAGE","deployApp","options","listFiles","projectRoot","sourceDir","directory","run","runAppDeployment","type","reporter","cliConfig","flags","output","workDir","organizationId","app","appId","workbench","dryRun","deploySingletonConfig","deployApplication","hasInterfaces","appTitle","title","trim","name","assertDeployable","err","report","exitCode","USAGE_ERROR","message","solution","status","isAutoUpdating","version","moduleName","application","appCreated","external","isWorkbenchApp","slug","created","resolveAppApplication","build","autoUpdatesEnabled","calledFromDeploy","outDir","skipReason","undefined","successMessage","manifest","installationId","config","configAppType","appType","exposes","isSingleton","applicationType","applicationVersion","target","applicationId","interfaces","appName","exposesAppView","entry","url","id","logAppDeployed","length","action","syncApplicationTitle","shipAppDeployment","unattended","yes","titleUpdate","log","from","to","spin","start","updated","body","succeed","fail","warn","tarball","entries","pipe","isApp","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 {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 buildExposes,\n deployConfig,\n deployCoreApp as deployWorkbenchCoreApp,\n getApplicationUrl,\n getWorkbench,\n resolveInstallationId,\n summarizeConfig,\n} from '@sanity/workbench-cli/deploy'\nimport {pack} from 'tar-fs'\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 {\n extractCoreAppManifest,\n readIconFromPath,\n resolveTitleUpdate,\n} from '../manifest/extractCoreAppManifest.js'\nimport {type CoreAppManifest} from '../manifest/types.js'\nimport {createUserApplication, generateAppSlug} 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, reportExposes} from './deploymentPlan.js'\nimport {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 const dryRun = !!flags['dry-run']\n\n // A singleton (the Media Library) persists its config instead of hosting an\n // application; anything that exposes a view or service still ships one.\n const deploySingletonConfig = workbench?.deploySingletonConfig ?? false\n const deployApplication = !workbench || workbench.hasInterfaces\n\n const appTitle = workbench\n ? flags.title?.trim() || cliConfig.app?.title?.trim() || workbench.name\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 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 (deploySingletonConfig) {\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 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 await checkAppTarget(reporter, {\n appId,\n isWorkbenchApp: true,\n slug: workbench.slug,\n title: appTitle,\n })\n } else if (deployApplication) {\n ;({application, created: appCreated} = await resolveAppApplication(options, {dryRun, reporter}))\n }\n\n await checkBuild(reporter, {\n build: () =>\n buildApp({\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({isWorkbenchApp: workbench !== null, reporter, sourceDir})\n\n // Workbench apps ship their icon straight to Brett (below) 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) {\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 config: string | undefined\n const configAppType = workbench?.config?.appType\n if (deploySingletonConfig && organizationId && workbench?.config && configAppType) {\n installationId = await resolveInstallationId({appType: configAppType, organizationId})\n config = summarizeConfig(workbench.config)\n reporter.report(\n installationId\n ? {config, message: config, status: 'pass'}\n : {\n exitCode: exitCodes.USAGE_ERROR,\n message: `No active \"${configAppType}\" installation for organization \"${organizationId}\"`,\n solution: 'Install the Media Library for the organization before deploying its config',\n status: 'fail',\n },\n )\n }\n\n // Report the exposes deploying with the application, both modes.\n const exposes = deployApplication && workbench ? reportExposes(reporter, workbench) : []\n\n // Surface the app's explicit singleton flag when set, both modes.\n if (deployApplication && workbench?.isSingleton !== undefined) {\n reporter.report({\n isSingleton: workbench.isSingleton,\n message: `Singleton: ${workbench.isSingleton}`,\n status: 'pass',\n })\n }\n\n // Dry run stops here — everything below mutates.\n if (dryRun) return\n\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 // A config-only singleton ships no application, only its config.\n if (!deployApplication) {\n if (installationId && version) {\n return {\n applicationType: 'coreApp',\n applicationVersion: version,\n ...(config ? {config} : {}),\n installationId,\n target: null,\n }\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 // Workbench apps deploy to Brett; plain coreApps use user-applications.\n if (workbench && organizationId) {\n const appId = getAppId(cliConfig)\n const slug = workbench.slug ?? generateAppSlug()\n const {applicationId} = await deployWorkbenchCoreApp({\n appId,\n icon: workbench.icon ? await readIconFromPath(workDir, workbench.icon) : undefined,\n interfaces: buildExposes(workbench, {\n appName: workbench.name,\n appTitle,\n exposesAppView: workbench.entry !== undefined,\n version,\n }),\n isAutoUpdating,\n isSingleton: workbench.isSingleton,\n organizationId,\n slug,\n sourceDir,\n title: appTitle,\n version,\n visibility: workbench.visibility,\n })\n const url = getApplicationUrl({id: applicationId, organizationId, type: 'coreApp'})\n logAppDeployed({\n applicationId,\n cliConfig,\n created: !appId,\n organizationId,\n output,\n title: appTitle,\n url,\n })\n return {\n applicationType: 'coreApp',\n applicationVersion: version,\n ...(exposes.length > 0 ? {exposes} : {}),\n ...(workbench.isSingleton === undefined ? {} : {isSingleton: workbench.isSingleton}),\n target: {\n action: appId ? 'update' : 'create',\n applicationId,\n // A redeploy ignores the slug, so only a create reports the one it used.\n ...(appId ? {} : {slug}),\n title: appTitle,\n url,\n },\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 applicationType: 'coreApp',\n applicationVersion: version,\n target: {\n action: appCreated ? 'create' : 'update',\n applicationId: application.id,\n title: application.title ?? null,\n url: getCoreAppUrl(application.organizationId, application.id),\n },\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 = pack(dirname(sourceDir), {entries: [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","exitCodes","getErrorMessage","getCoreAppUrl","spinner","buildExposes","deployConfig","deployCoreApp","deployWorkbenchCoreApp","getApplicationUrl","getWorkbench","resolveInstallationId","summarizeConfig","pack","createDeployment","updateUserApplication","getAppId","EXTERNAL_APP_NOT_SUPPORTED","NO_ORGANIZATION_ID","buildApp","extractCoreAppManifest","readIconFromPath","resolveTitleUpdate","createUserApplication","generateAppSlug","checkAppId","checkAppTarget","checkAutoUpdates","checkBuild","checkPackageVersion","verifyOutputDir","deployDebug","listDeploymentFiles","reportExposes","runDeploy","findUserApplication","APP_PACKAGE","deployApp","options","listFiles","projectRoot","sourceDir","directory","run","runAppDeployment","type","reporter","cliConfig","flags","output","workDir","organizationId","app","appId","workbench","dryRun","deploySingletonConfig","deployApplication","hasInterfaces","appTitle","title","trim","name","assertDeployable","err","report","exitCode","USAGE_ERROR","message","solution","status","isAutoUpdating","version","moduleName","application","appCreated","external","isWorkbenchApp","slug","created","resolveAppApplication","build","autoUpdatesEnabled","calledFromDeploy","outDir","skipReason","undefined","successMessage","manifest","installationId","config","configAppType","appType","exposes","isSingleton","applicationType","applicationVersion","target","applicationId","icon","interfaces","appName","exposesAppView","entry","visibility","url","id","logAppDeployed","length","action","syncApplicationMetadata","shipAppDeployment","unattended","yes","titleUpdate","visibilityChanged","dashboardStatus","log","from","to","spin","start","updated","body","succeed","fail","warn","tarball","entries","pipe","isApp","error","clear","named"],"mappings":"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"}
@@ -10,6 +10,7 @@ import { createDeployment } from '../../services/userApplications.js';
10
10
  import { getAppId } from '../../util/appId.js';
11
11
  import { NO_ORGANIZATION_ID, NO_PROJECT_ID } from '../../util/errorMessages.js';
12
12
  import { buildStudio } from '../build/buildStudio.js';
13
+ import { readIconFromPath } from '../manifest/extractCoreAppManifest.js';
13
14
  import { createStudioUserApplication } from './createUserApplication.js';
14
15
  import { checkAutoUpdates, checkBuild, checkPackageVersion, checkStudioTarget, verifyOutputDir } from './deployChecks.js';
15
16
  import { deployDebug } from './deployDebug.js';
@@ -126,6 +127,7 @@ export function deployStudio(options) {
126
127
  if (workbench && !isExternal && organizationId) {
127
128
  const { applicationId } = await deployWorkbenchStudio({
128
129
  appId,
130
+ icon: workbench.icon ? await readIconFromPath(workDir, workbench.icon) : undefined,
129
131
  interfaces: buildExposes(workbench, {
130
132
  appName: workbench.name,
131
133
  appTitle,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/deploy/deployStudio.ts"],"sourcesContent":["import {basename, dirname} from 'node:path'\nimport {styleText} from 'node:util'\nimport {createGzip, type Gzip} from 'node:zlib'\n\nimport {formatSchemaValidation, SchemaExtractionError} from '@sanity/cli-build/_internal/extract'\nimport {exitCodes} from '@sanity/cli-core'\nimport {spinner} from '@sanity/cli-core/ux'\nimport {\n type BrettWorkspace,\n buildExposes,\n deployStudio as deployWorkbenchStudio,\n getApplicationUrl,\n getWorkbench,\n} from '@sanity/workbench-cli/deploy'\nimport {type StudioManifest} from 'sanity'\nimport {pack} from 'tar-fs'\n\nimport {createDeployment, type UserApplication} from '../../services/userApplications.js'\nimport {getAppId} from '../../util/appId.js'\nimport {NO_ORGANIZATION_ID, NO_PROJECT_ID} from '../../util/errorMessages.js'\nimport {buildStudio} from '../build/buildStudio.js'\nimport {createStudioUserApplication} from './createUserApplication.js'\nimport {\n checkAutoUpdates,\n checkBuild,\n checkPackageVersion,\n checkStudioTarget,\n type DeployCheckReporter,\n verifyOutputDir,\n} from './deployChecks.js'\nimport {deployDebug} from './deployDebug.js'\nimport {listDeploymentFiles, reportExposes} from './deploymentPlan.js'\nimport {type DeployResult, runDeploy} from './deployRunner.js'\nimport {deployStudioSchemasAndManifests} from './deployStudioSchemasAndManifests.js'\nimport {findUserApplicationForStudio} from './findUserApplication.js'\nimport {type DeployAppOptions} from './types.js'\n\nconst STUDIO_PACKAGE = 'sanity'\n\nexport function deployStudio(options: DeployAppOptions): Promise<void> {\n return runDeploy(options, {\n listFiles: ({flags, projectRoot, sourceDir}) =>\n flags.external ? Promise.resolve([]) : listDeploymentFiles(sourceDir, projectRoot.directory),\n run: runStudioDeployment,\n type: 'studio',\n })\n}\n\n/** Validates the deploy, extracts and uploads the schema, and ships the build. */\nasync function runStudioDeployment(\n options: DeployAppOptions,\n reporter: DeployCheckReporter,\n): Promise<DeployResult | void> {\n const {cliConfig, flags, output, sourceDir} = options\n const workDir = options.projectRoot.directory\n const isExternal = !!flags.external\n const workbench = getWorkbench(cliConfig)\n const isWorkbenchApp = workbench !== null\n const projectId = cliConfig.api?.projectId\n const organizationId = cliConfig.app?.organizationId\n const appId = getAppId(cliConfig)\n const dryRun = !!flags['dry-run']\n\n // A federated app deploys through Sanity's build/hosting pipeline, which\n // --external skips — fail before doing any other work.\n if (isExternal && isWorkbenchApp) {\n reporter.report({\n exitCode: exitCodes.USAGE_ERROR,\n message: 'Deploying a federated application to an external host is not yet supported',\n solution: 'Remove the --external flag to deploy to Sanity hosting',\n status: 'fail',\n })\n }\n\n const appTitle = workbench\n ? flags.title?.trim() || cliConfig.app?.title?.trim() || workbench.name\n : ''\n\n const isAutoUpdating = checkAutoUpdates(reporter, {cliConfig, flags})\n\n const version = await checkPackageVersion(reporter, {\n moduleName: STUDIO_PACKAGE,\n workDir,\n })\n\n reporter.report(\n projectId\n ? {message: `Project: ${projectId}`, status: 'pass'}\n : {\n message: NO_PROJECT_ID,\n solution: 'Add `api.projectId` to sanity.cli.ts',\n status: 'fail',\n },\n )\n\n // Workbench studios deploy to Brett (which needs the org); plain studios\n // resolve/create on user-applications, unchanged.\n let application: UserApplication | null = null\n let studioCreated = false\n if (workbench && !isExternal) {\n reporter.report(\n organizationId\n ? {message: `Organization: ${organizationId}`, status: 'pass'}\n : {\n message: NO_ORGANIZATION_ID,\n solution: 'Add `app.organizationId` to sanity.cli.ts',\n status: 'fail',\n },\n )\n await checkStudioTarget(reporter, {\n appId,\n isWorkbenchApp: true,\n studioHost: cliConfig.studioHost,\n title: appTitle,\n })\n } else {\n ;({application, created: studioCreated} = await resolveStudioApplication(options, {\n dryRun,\n reporter,\n }))\n }\n\n await checkBuild(reporter, {\n build: () =>\n buildStudio({\n autoUpdatesEnabled: isAutoUpdating,\n calledFromDeploy: true,\n cliConfig,\n flags,\n outDir: sourceDir,\n output,\n workDir,\n }),\n skipReason: studioBuildSkipReason({build: flags.build, isExternal}),\n successMessage: 'Studio built',\n })\n\n if (!isExternal) {\n await verifyOutputDir({isWorkbenchApp, reporter, sourceDir})\n }\n\n // Report the exposes deploying with the studio, both modes. External studios\n // host their own bundle, so nothing registers.\n const exposes = workbench && !isExternal ? reportExposes(reporter, workbench) : []\n\n // Dry run stops here — everything below mutates.\n if (dryRun) return\n\n // A real deploy has already exited if anything failed; landing here without a\n // resolved version means the deploy target was never resolved.\n if (!version) return\n\n const studioManifest = await uploadStudioSchema(options, {isExternal})\n // Workbench studios deploy to Brett; plain studios use user-applications.\n if (workbench && !isExternal && organizationId) {\n const {applicationId} = await deployWorkbenchStudio({\n appId,\n interfaces: buildExposes(workbench, {\n appName: workbench.name,\n appTitle,\n exposesAppView: true,\n version,\n }),\n isAutoUpdating,\n organizationId,\n output,\n projectId,\n sourceDir,\n studioHost: cliConfig.studioHost,\n title: appTitle,\n version,\n workspaces: toWorkspaces(studioManifest),\n })\n const url = getApplicationUrl({id: applicationId, organizationId, type: 'studio'})\n logWorkbenchStudioDeployed({applicationId, cliConfig, output, url})\n return {\n applicationType: 'studio',\n applicationVersion: version,\n ...(exposes.length > 0 ? {exposes} : {}),\n target: {\n action: appId ? 'update' : 'create',\n applicationId,\n title: appTitle,\n url,\n },\n }\n }\n\n if (!application) return\n const location = await shipStudioDeployment({\n application,\n isAutoUpdating,\n isExternal,\n options,\n studioManifest,\n version,\n })\n\n return {\n applicationType: 'studio',\n applicationVersion: version,\n target: {\n action: studioCreated ? 'create' : 'update',\n applicationId: application.id,\n title: application.title ?? null,\n url: location,\n },\n }\n}\n\n/**\n * Finds the application a real deploy targets, registering a studio host when\n * none is configured. A dry run resolves and reports the target read-only instead.\n */\nasync function resolveStudioApplication(\n options: DeployAppOptions,\n {dryRun, reporter}: {dryRun: boolean; reporter: DeployCheckReporter},\n): Promise<{application: UserApplication | null; created: boolean}> {\n const {cliConfig, flags, output} = options\n const isExternal = !!flags.external\n const appId = getAppId(cliConfig)\n // Sets the title on a newly registered studio; blank falls back to undefined\n const title = flags.title?.trim() || undefined\n\n if (dryRun) {\n await checkStudioTarget(reporter, {\n appId,\n isExternal,\n projectId: cliConfig.api?.projectId,\n studioHost: cliConfig.studioHost,\n title,\n urlFlag: flags.url,\n })\n return {application: null, created: false}\n }\n\n const projectId = cliConfig.api?.projectId ?? ''\n // `created` is true when a configured-but-unregistered host was just registered.\n const {application, created} = await findUserApplicationForStudio({\n appId,\n isExternal,\n output,\n projectId,\n studioHost: cliConfig.studioHost,\n title,\n unattended: !!flags.yes,\n urlFlag: flags.url,\n })\n\n if (!application) {\n if (isExternal) {\n output.log('Your project has not been registered with an external studio URL.')\n output.log('Please enter the full URL where your studio is hosted.')\n } else {\n output.log('Your project has not been assigned a studio hostname.')\n output.log('To deploy your Sanity Studio to our hosted sanity.studio service,')\n output.log('you will need one. Please enter the subdomain you want to use.')\n }\n\n const registered = await createStudioUserApplication({\n projectId,\n title,\n urlType: isExternal ? 'external' : 'internal',\n })\n deployDebug('Created user application', registered)\n return {application: registered, created: true}\n }\n\n deployDebug('Found user application', application)\n return {application, created}\n}\n\n/** Extracts the studio schema and manifest and uploads them to the schema store. */\nasync function uploadStudioSchema(\n options: DeployAppOptions,\n {isExternal}: {isExternal: boolean},\n): Promise<StudioManifest | null> {\n const {cliConfig, flags, output, projectRoot, sourceDir} = options\n\n let studioManifest: StudioManifest | null = null\n try {\n studioManifest = await deployStudioSchemasAndManifests(\n {\n configPath: projectRoot.path,\n isExternal,\n outPath: `${sourceDir}/static`,\n projectId: cliConfig.api?.projectId ?? '',\n schemaRequired: flags['schema-required'],\n verbose: flags.verbose,\n workDir: projectRoot.directory,\n },\n output,\n )\n } catch (error) {\n deployDebug('Error deploying studio schemas and manifests', error)\n if (error instanceof SchemaExtractionError) {\n output.error(formatSchemaValidation(error.validation || []), {exit: 1})\n }\n output.error(`Error deploying studio schemas and manifests: ${error}`, {exit: 1})\n }\n\n if (!studioManifest) {\n output.error('Failed to generate studio manifest. Please check your schemas and manifests.', {\n exit: 1,\n })\n }\n\n return studioManifest\n}\n\nasync function shipStudioDeployment({\n application,\n isAutoUpdating,\n isExternal,\n options,\n studioManifest,\n version,\n}: {\n application: UserApplication\n isAutoUpdating: boolean\n isExternal: boolean\n options: DeployAppOptions\n studioManifest: StudioManifest | null\n version: string\n}): Promise<string> {\n const {cliConfig, output, sourceDir} = options\n\n let tarball: Gzip | undefined\n if (!isExternal) {\n tarball = pack(dirname(sourceDir), {entries: [basename(sourceDir)]}).pipe(createGzip())\n }\n\n const spin = spinner(isExternal ? 'Registering studio' : 'Deploying to sanity.studio').start()\n let location: string\n try {\n ;({location} = await createDeployment({\n applicationId: application.id,\n isApp: false,\n isAutoUpdating,\n manifest: studioManifest,\n projectId: cliConfig.api?.projectId,\n tarball,\n version,\n }))\n } catch (error) {\n spin.fail()\n throw error\n }\n spin.succeed()\n\n const named = application.title ? ` — \"${application.title}\"` : ''\n output.log(\n isExternal\n ? `\\nSuccess! Studio registered${named}`\n : `\\nSuccess! Studio deployed to ${styleText('cyan', location)}${named}`,\n )\n\n if (getAppId(cliConfig)) return location\n\n const example = `Example:\nexport default defineCliConfig({\n //…\n deployment: {\n ${styleText('cyan', `appId: '${application.id}'`)},\n },\n //…\n})`\n output.log(`\\nAdd ${styleText('cyan', `appId: '${application.id}'`)}`)\n output.log(`to the \\`deployment\\` section in sanity.cli.js or sanity.cli.ts`)\n output.log(`to avoid prompting for application id on next deploy.`)\n output.log(`\\n${example}`)\n\n return location\n}\n\nfunction toWorkspaces(manifest: StudioManifest | null): BrettWorkspace[] {\n return (manifest?.workspaces ?? []).map((workspace) => ({\n basePath: workspace.basePath,\n dataset: workspace.dataset,\n icon: workspace.icon,\n name: workspace.name,\n projectId: workspace.projectId,\n subtitle: workspace.subtitle,\n title: workspace.title,\n }))\n}\n\n/** Renders the workbench studio's deploy result; the appId hint shows only when none is configured. */\nfunction logWorkbenchStudioDeployed({\n applicationId,\n cliConfig,\n output,\n url,\n}: {\n applicationId: string\n cliConfig: DeployAppOptions['cliConfig']\n output: DeployAppOptions['output']\n url: string\n}): void {\n output.log(`\\nSuccess! Studio deployed to ${styleText('cyan', url)}`)\n if (getAppId(cliConfig)) return\n\n output.log(`\\nAdd ${styleText('cyan', `appId: '${applicationId}'`)}`)\n output.log(`to the \\`deployment\\` section in sanity.cli.js or sanity.cli.ts`)\n output.log(`to avoid prompting for application id on next deploy.`)\n}\n\nfunction studioBuildSkipReason({build, isExternal}: {build: boolean; isExternal: boolean}) {\n if (isExternal) return 'Build skipped for externally hosted studios'\n if (!build) return 'Build skipped (--no-build) — validating existing output directory'\n return\n}\n"],"names":["basename","dirname","styleText","createGzip","formatSchemaValidation","SchemaExtractionError","exitCodes","spinner","buildExposes","deployStudio","deployWorkbenchStudio","getApplicationUrl","getWorkbench","pack","createDeployment","getAppId","NO_ORGANIZATION_ID","NO_PROJECT_ID","buildStudio","createStudioUserApplication","checkAutoUpdates","checkBuild","checkPackageVersion","checkStudioTarget","verifyOutputDir","deployDebug","listDeploymentFiles","reportExposes","runDeploy","deployStudioSchemasAndManifests","findUserApplicationForStudio","STUDIO_PACKAGE","options","listFiles","flags","projectRoot","sourceDir","external","Promise","resolve","directory","run","runStudioDeployment","type","reporter","cliConfig","output","workDir","isExternal","workbench","isWorkbenchApp","projectId","api","organizationId","app","appId","dryRun","report","exitCode","USAGE_ERROR","message","solution","status","appTitle","title","trim","name","isAutoUpdating","version","moduleName","application","studioCreated","studioHost","created","resolveStudioApplication","build","autoUpdatesEnabled","calledFromDeploy","outDir","skipReason","studioBuildSkipReason","successMessage","exposes","studioManifest","uploadStudioSchema","applicationId","interfaces","appName","exposesAppView","workspaces","toWorkspaces","url","id","logWorkbenchStudioDeployed","applicationType","applicationVersion","length","target","action","location","shipStudioDeployment","undefined","urlFlag","unattended","yes","log","registered","urlType","configPath","path","outPath","schemaRequired","verbose","error","validation","exit","tarball","entries","pipe","spin","start","isApp","manifest","fail","succeed","named","example","map","workspace","basePath","dataset","icon","subtitle"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/actions/deploy/deployStudio.ts"],"sourcesContent":["import {basename, dirname} from 'node:path'\nimport {styleText} from 'node:util'\nimport {createGzip, type Gzip} from 'node:zlib'\n\nimport {formatSchemaValidation, SchemaExtractionError} from '@sanity/cli-build/_internal/extract'\nimport {exitCodes} from '@sanity/cli-core'\nimport {spinner} from '@sanity/cli-core/ux'\nimport {\n type BrettWorkspace,\n buildExposes,\n deployStudio as deployWorkbenchStudio,\n getApplicationUrl,\n getWorkbench,\n} from '@sanity/workbench-cli/deploy'\nimport {type StudioManifest} from 'sanity'\nimport {pack} from 'tar-fs'\n\nimport {createDeployment, type UserApplication} from '../../services/userApplications.js'\nimport {getAppId} from '../../util/appId.js'\nimport {NO_ORGANIZATION_ID, NO_PROJECT_ID} from '../../util/errorMessages.js'\nimport {buildStudio} from '../build/buildStudio.js'\nimport {readIconFromPath} from '../manifest/extractCoreAppManifest.js'\nimport {createStudioUserApplication} from './createUserApplication.js'\nimport {\n checkAutoUpdates,\n checkBuild,\n checkPackageVersion,\n checkStudioTarget,\n type DeployCheckReporter,\n verifyOutputDir,\n} from './deployChecks.js'\nimport {deployDebug} from './deployDebug.js'\nimport {listDeploymentFiles, reportExposes} from './deploymentPlan.js'\nimport {type DeployResult, runDeploy} from './deployRunner.js'\nimport {deployStudioSchemasAndManifests} from './deployStudioSchemasAndManifests.js'\nimport {findUserApplicationForStudio} from './findUserApplication.js'\nimport {type DeployAppOptions} from './types.js'\n\nconst STUDIO_PACKAGE = 'sanity'\n\nexport function deployStudio(options: DeployAppOptions): Promise<void> {\n return runDeploy(options, {\n listFiles: ({flags, projectRoot, sourceDir}) =>\n flags.external ? Promise.resolve([]) : listDeploymentFiles(sourceDir, projectRoot.directory),\n run: runStudioDeployment,\n type: 'studio',\n })\n}\n\n/** Validates the deploy, extracts and uploads the schema, and ships the build. */\nasync function runStudioDeployment(\n options: DeployAppOptions,\n reporter: DeployCheckReporter,\n): Promise<DeployResult | void> {\n const {cliConfig, flags, output, sourceDir} = options\n const workDir = options.projectRoot.directory\n const isExternal = !!flags.external\n const workbench = getWorkbench(cliConfig)\n const isWorkbenchApp = workbench !== null\n const projectId = cliConfig.api?.projectId\n const organizationId = cliConfig.app?.organizationId\n const appId = getAppId(cliConfig)\n const dryRun = !!flags['dry-run']\n\n // A federated app deploys through Sanity's build/hosting pipeline, which\n // --external skips — fail before doing any other work.\n if (isExternal && isWorkbenchApp) {\n reporter.report({\n exitCode: exitCodes.USAGE_ERROR,\n message: 'Deploying a federated application to an external host is not yet supported',\n solution: 'Remove the --external flag to deploy to Sanity hosting',\n status: 'fail',\n })\n }\n\n const appTitle = workbench\n ? flags.title?.trim() || cliConfig.app?.title?.trim() || workbench.name\n : ''\n\n const isAutoUpdating = checkAutoUpdates(reporter, {cliConfig, flags})\n\n const version = await checkPackageVersion(reporter, {\n moduleName: STUDIO_PACKAGE,\n workDir,\n })\n\n reporter.report(\n projectId\n ? {message: `Project: ${projectId}`, status: 'pass'}\n : {\n message: NO_PROJECT_ID,\n solution: 'Add `api.projectId` to sanity.cli.ts',\n status: 'fail',\n },\n )\n\n // Workbench studios deploy to Brett (which needs the org); plain studios\n // resolve/create on user-applications, unchanged.\n let application: UserApplication | null = null\n let studioCreated = false\n if (workbench && !isExternal) {\n reporter.report(\n organizationId\n ? {message: `Organization: ${organizationId}`, status: 'pass'}\n : {\n message: NO_ORGANIZATION_ID,\n solution: 'Add `app.organizationId` to sanity.cli.ts',\n status: 'fail',\n },\n )\n await checkStudioTarget(reporter, {\n appId,\n isWorkbenchApp: true,\n studioHost: cliConfig.studioHost,\n title: appTitle,\n })\n } else {\n ;({application, created: studioCreated} = await resolveStudioApplication(options, {\n dryRun,\n reporter,\n }))\n }\n\n await checkBuild(reporter, {\n build: () =>\n buildStudio({\n autoUpdatesEnabled: isAutoUpdating,\n calledFromDeploy: true,\n cliConfig,\n flags,\n outDir: sourceDir,\n output,\n workDir,\n }),\n skipReason: studioBuildSkipReason({build: flags.build, isExternal}),\n successMessage: 'Studio built',\n })\n\n if (!isExternal) {\n await verifyOutputDir({isWorkbenchApp, reporter, sourceDir})\n }\n\n // Report the exposes deploying with the studio, both modes. External studios\n // host their own bundle, so nothing registers.\n const exposes = workbench && !isExternal ? reportExposes(reporter, workbench) : []\n\n // Dry run stops here — everything below mutates.\n if (dryRun) return\n\n // A real deploy has already exited if anything failed; landing here without a\n // resolved version means the deploy target was never resolved.\n if (!version) return\n\n const studioManifest = await uploadStudioSchema(options, {isExternal})\n // Workbench studios deploy to Brett; plain studios use user-applications.\n if (workbench && !isExternal && organizationId) {\n const {applicationId} = await deployWorkbenchStudio({\n appId,\n icon: workbench.icon ? await readIconFromPath(workDir, workbench.icon) : undefined,\n interfaces: buildExposes(workbench, {\n appName: workbench.name,\n appTitle,\n exposesAppView: true,\n version,\n }),\n isAutoUpdating,\n organizationId,\n output,\n projectId,\n sourceDir,\n studioHost: cliConfig.studioHost,\n title: appTitle,\n version,\n workspaces: toWorkspaces(studioManifest),\n })\n const url = getApplicationUrl({id: applicationId, organizationId, type: 'studio'})\n logWorkbenchStudioDeployed({applicationId, cliConfig, output, url})\n return {\n applicationType: 'studio',\n applicationVersion: version,\n ...(exposes.length > 0 ? {exposes} : {}),\n target: {\n action: appId ? 'update' : 'create',\n applicationId,\n title: appTitle,\n url,\n },\n }\n }\n\n if (!application) return\n const location = await shipStudioDeployment({\n application,\n isAutoUpdating,\n isExternal,\n options,\n studioManifest,\n version,\n })\n\n return {\n applicationType: 'studio',\n applicationVersion: version,\n target: {\n action: studioCreated ? 'create' : 'update',\n applicationId: application.id,\n title: application.title ?? null,\n url: location,\n },\n }\n}\n\n/**\n * Finds the application a real deploy targets, registering a studio host when\n * none is configured. A dry run resolves and reports the target read-only instead.\n */\nasync function resolveStudioApplication(\n options: DeployAppOptions,\n {dryRun, reporter}: {dryRun: boolean; reporter: DeployCheckReporter},\n): Promise<{application: UserApplication | null; created: boolean}> {\n const {cliConfig, flags, output} = options\n const isExternal = !!flags.external\n const appId = getAppId(cliConfig)\n // Sets the title on a newly registered studio; blank falls back to undefined\n const title = flags.title?.trim() || undefined\n\n if (dryRun) {\n await checkStudioTarget(reporter, {\n appId,\n isExternal,\n projectId: cliConfig.api?.projectId,\n studioHost: cliConfig.studioHost,\n title,\n urlFlag: flags.url,\n })\n return {application: null, created: false}\n }\n\n const projectId = cliConfig.api?.projectId ?? ''\n // `created` is true when a configured-but-unregistered host was just registered.\n const {application, created} = await findUserApplicationForStudio({\n appId,\n isExternal,\n output,\n projectId,\n studioHost: cliConfig.studioHost,\n title,\n unattended: !!flags.yes,\n urlFlag: flags.url,\n })\n\n if (!application) {\n if (isExternal) {\n output.log('Your project has not been registered with an external studio URL.')\n output.log('Please enter the full URL where your studio is hosted.')\n } else {\n output.log('Your project has not been assigned a studio hostname.')\n output.log('To deploy your Sanity Studio to our hosted sanity.studio service,')\n output.log('you will need one. Please enter the subdomain you want to use.')\n }\n\n const registered = await createStudioUserApplication({\n projectId,\n title,\n urlType: isExternal ? 'external' : 'internal',\n })\n deployDebug('Created user application', registered)\n return {application: registered, created: true}\n }\n\n deployDebug('Found user application', application)\n return {application, created}\n}\n\n/** Extracts the studio schema and manifest and uploads them to the schema store. */\nasync function uploadStudioSchema(\n options: DeployAppOptions,\n {isExternal}: {isExternal: boolean},\n): Promise<StudioManifest | null> {\n const {cliConfig, flags, output, projectRoot, sourceDir} = options\n\n let studioManifest: StudioManifest | null = null\n try {\n studioManifest = await deployStudioSchemasAndManifests(\n {\n configPath: projectRoot.path,\n isExternal,\n outPath: `${sourceDir}/static`,\n projectId: cliConfig.api?.projectId ?? '',\n schemaRequired: flags['schema-required'],\n verbose: flags.verbose,\n workDir: projectRoot.directory,\n },\n output,\n )\n } catch (error) {\n deployDebug('Error deploying studio schemas and manifests', error)\n if (error instanceof SchemaExtractionError) {\n output.error(formatSchemaValidation(error.validation || []), {exit: 1})\n }\n output.error(`Error deploying studio schemas and manifests: ${error}`, {exit: 1})\n }\n\n if (!studioManifest) {\n output.error('Failed to generate studio manifest. Please check your schemas and manifests.', {\n exit: 1,\n })\n }\n\n return studioManifest\n}\n\nasync function shipStudioDeployment({\n application,\n isAutoUpdating,\n isExternal,\n options,\n studioManifest,\n version,\n}: {\n application: UserApplication\n isAutoUpdating: boolean\n isExternal: boolean\n options: DeployAppOptions\n studioManifest: StudioManifest | null\n version: string\n}): Promise<string> {\n const {cliConfig, output, sourceDir} = options\n\n let tarball: Gzip | undefined\n if (!isExternal) {\n tarball = pack(dirname(sourceDir), {entries: [basename(sourceDir)]}).pipe(createGzip())\n }\n\n const spin = spinner(isExternal ? 'Registering studio' : 'Deploying to sanity.studio').start()\n let location: string\n try {\n ;({location} = await createDeployment({\n applicationId: application.id,\n isApp: false,\n isAutoUpdating,\n manifest: studioManifest,\n projectId: cliConfig.api?.projectId,\n tarball,\n version,\n }))\n } catch (error) {\n spin.fail()\n throw error\n }\n spin.succeed()\n\n const named = application.title ? ` — \"${application.title}\"` : ''\n output.log(\n isExternal\n ? `\\nSuccess! Studio registered${named}`\n : `\\nSuccess! Studio deployed to ${styleText('cyan', location)}${named}`,\n )\n\n if (getAppId(cliConfig)) return location\n\n const example = `Example:\nexport default defineCliConfig({\n //…\n deployment: {\n ${styleText('cyan', `appId: '${application.id}'`)},\n },\n //…\n})`\n output.log(`\\nAdd ${styleText('cyan', `appId: '${application.id}'`)}`)\n output.log(`to the \\`deployment\\` section in sanity.cli.js or sanity.cli.ts`)\n output.log(`to avoid prompting for application id on next deploy.`)\n output.log(`\\n${example}`)\n\n return location\n}\n\nfunction toWorkspaces(manifest: StudioManifest | null): BrettWorkspace[] {\n return (manifest?.workspaces ?? []).map((workspace) => ({\n basePath: workspace.basePath,\n dataset: workspace.dataset,\n icon: workspace.icon,\n name: workspace.name,\n projectId: workspace.projectId,\n subtitle: workspace.subtitle,\n title: workspace.title,\n }))\n}\n\n/** Renders the workbench studio's deploy result; the appId hint shows only when none is configured. */\nfunction logWorkbenchStudioDeployed({\n applicationId,\n cliConfig,\n output,\n url,\n}: {\n applicationId: string\n cliConfig: DeployAppOptions['cliConfig']\n output: DeployAppOptions['output']\n url: string\n}): void {\n output.log(`\\nSuccess! Studio deployed to ${styleText('cyan', url)}`)\n if (getAppId(cliConfig)) return\n\n output.log(`\\nAdd ${styleText('cyan', `appId: '${applicationId}'`)}`)\n output.log(`to the \\`deployment\\` section in sanity.cli.js or sanity.cli.ts`)\n output.log(`to avoid prompting for application id on next deploy.`)\n}\n\nfunction studioBuildSkipReason({build, isExternal}: {build: boolean; isExternal: boolean}) {\n if (isExternal) return 'Build skipped for externally hosted studios'\n if (!build) return 'Build skipped (--no-build) — validating existing output directory'\n return\n}\n"],"names":["basename","dirname","styleText","createGzip","formatSchemaValidation","SchemaExtractionError","exitCodes","spinner","buildExposes","deployStudio","deployWorkbenchStudio","getApplicationUrl","getWorkbench","pack","createDeployment","getAppId","NO_ORGANIZATION_ID","NO_PROJECT_ID","buildStudio","readIconFromPath","createStudioUserApplication","checkAutoUpdates","checkBuild","checkPackageVersion","checkStudioTarget","verifyOutputDir","deployDebug","listDeploymentFiles","reportExposes","runDeploy","deployStudioSchemasAndManifests","findUserApplicationForStudio","STUDIO_PACKAGE","options","listFiles","flags","projectRoot","sourceDir","external","Promise","resolve","directory","run","runStudioDeployment","type","reporter","cliConfig","output","workDir","isExternal","workbench","isWorkbenchApp","projectId","api","organizationId","app","appId","dryRun","report","exitCode","USAGE_ERROR","message","solution","status","appTitle","title","trim","name","isAutoUpdating","version","moduleName","application","studioCreated","studioHost","created","resolveStudioApplication","build","autoUpdatesEnabled","calledFromDeploy","outDir","skipReason","studioBuildSkipReason","successMessage","exposes","studioManifest","uploadStudioSchema","applicationId","icon","undefined","interfaces","appName","exposesAppView","workspaces","toWorkspaces","url","id","logWorkbenchStudioDeployed","applicationType","applicationVersion","length","target","action","location","shipStudioDeployment","urlFlag","unattended","yes","log","registered","urlType","configPath","path","outPath","schemaRequired","verbose","error","validation","exit","tarball","entries","pipe","spin","start","isApp","manifest","fail","succeed","named","example","map","workspace","basePath","dataset","subtitle"],"mappings":"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"}
@@ -1,10 +1,10 @@
1
1
  import { CLIError } from '@oclif/core/errors';
2
- import { isInteractive } from '@sanity/cli-core';
2
+ import { exitCodes } from '@sanity/cli-core';
3
3
  import { confirm } from '@sanity/cli-core/ux';
4
4
  import { oneline } from 'oneline';
5
5
  import { graphqlDebug } from './graphqlDebug.js';
6
6
  const LATEST_GENERATION = 'gen3';
7
- export async function resolveApiGeneration({ currentGeneration, force, index, output, specifiedGeneration }) {
7
+ export async function resolveApiGeneration({ currentGeneration, force, index, output, specifiedGeneration, unattended }) {
8
8
  // a) If no API is currently deployed:
9
9
  // use the specificed one from config, or use whichever generation is the latest
10
10
  // b) If an API generation is specified explicitly:
@@ -17,12 +17,12 @@ export async function resolveApiGeneration({ currentGeneration, force, index, ou
17
17
  return generation;
18
18
  }
19
19
  if (specifiedGeneration && specifiedGeneration !== currentGeneration) {
20
- if (!force && !isInteractive()) {
20
+ if (!force && unattended) {
21
21
  throw new CLIError(oneline`
22
22
  Specified generation (${specifiedGeneration}) for API at index ${index} differs from the one currently deployed (${currentGeneration}).
23
- Re-run the command with \`--force\` to force deployment.
23
+ Pass \`--force\` to continue.
24
24
  `, {
25
- exit: 1
25
+ exit: exitCodes.USAGE_ERROR
26
26
  });
27
27
  }
28
28
  output.warn(`Specified generation (${specifiedGeneration}) for API at index ${index} differs from the one currently deployed (${currentGeneration}).`);
@@ -30,7 +30,10 @@ export async function resolveApiGeneration({ currentGeneration, force, index, ou
30
30
  default: false,
31
31
  message: 'Are you sure you want to deploy?'
32
32
  });
33
- return confirmDeploy ? specifiedGeneration : undefined;
33
+ if (!confirmDeploy) {
34
+ return undefined;
35
+ }
36
+ return specifiedGeneration;
34
37
  }
35
38
  if (specifiedGeneration) {
36
39
  graphqlDebug('Using specified (%s) generation', specifiedGeneration);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/graphql/resolveApiGeneration.ts"],"sourcesContent":["import {CLIError} from '@oclif/core/errors'\nimport {isInteractive, type Output} from '@sanity/cli-core'\nimport {confirm} from '@sanity/cli-core/ux'\nimport {oneline} from 'oneline'\n\nimport {graphqlDebug} from './graphqlDebug.js'\n\nconst LATEST_GENERATION = 'gen3'\n\nexport async function resolveApiGeneration({\n currentGeneration,\n force,\n index,\n output,\n specifiedGeneration,\n}: {\n currentGeneration?: string\n force?: boolean\n index: number\n output: Output\n specifiedGeneration?: string\n}): Promise<string | undefined> {\n // a) If no API is currently deployed:\n // use the specificed one from config, or use whichever generation is the latest\n // b) If an API generation is specified explicitly:\n // use the given one, but _prompt_ if it differs from the current one\n // c) If no API generation is specified explicitly:\n // use whichever is already deployed, but warn if differs from latest\n if (!currentGeneration) {\n const generation = specifiedGeneration || LATEST_GENERATION\n graphqlDebug(\n 'There is no current generation deployed, using %s (%s)',\n generation,\n specifiedGeneration ? 'specified' : 'default',\n )\n return generation\n }\n\n if (specifiedGeneration && specifiedGeneration !== currentGeneration) {\n if (!force && !isInteractive()) {\n throw new CLIError(\n oneline`\n Specified generation (${specifiedGeneration}) for API at index ${index} differs from the one currently deployed (${currentGeneration}).\n Re-run the command with \\`--force\\` to force deployment.\n `,\n {exit: 1},\n )\n }\n\n output.warn(\n `Specified generation (${specifiedGeneration}) for API at index ${index} differs from the one currently deployed (${currentGeneration}).`,\n )\n\n const confirmDeploy =\n force ||\n (await confirm({\n default: false,\n message: 'Are you sure you want to deploy?',\n }))\n\n return confirmDeploy ? specifiedGeneration : undefined\n }\n\n if (specifiedGeneration) {\n graphqlDebug('Using specified (%s) generation', specifiedGeneration)\n return specifiedGeneration\n }\n\n graphqlDebug('Using the currently deployed version (%s)', currentGeneration)\n return currentGeneration\n}\n"],"names":["CLIError","isInteractive","confirm","oneline","graphqlDebug","LATEST_GENERATION","resolveApiGeneration","currentGeneration","force","index","output","specifiedGeneration","generation","exit","warn","confirmDeploy","default","message","undefined"],"mappings":"AAAA,SAAQA,QAAQ,QAAO,qBAAoB;AAC3C,SAAQC,aAAa,QAAoB,mBAAkB;AAC3D,SAAQC,OAAO,QAAO,sBAAqB;AAC3C,SAAQC,OAAO,QAAO,UAAS;AAE/B,SAAQC,YAAY,QAAO,oBAAmB;AAE9C,MAAMC,oBAAoB;AAE1B,OAAO,eAAeC,qBAAqB,EACzCC,iBAAiB,EACjBC,KAAK,EACLC,KAAK,EACLC,MAAM,EACNC,mBAAmB,EAOpB;IACC,sCAAsC;IACtC,mFAAmF;IACnF,mDAAmD;IACnD,wEAAwE;IACxE,mDAAmD;IACnD,wEAAwE;IACxE,IAAI,CAACJ,mBAAmB;QACtB,MAAMK,aAAaD,uBAAuBN;QAC1CD,aACE,0DACAQ,YACAD,sBAAsB,cAAc;QAEtC,OAAOC;IACT;IAEA,IAAID,uBAAuBA,wBAAwBJ,mBAAmB;QACpE,IAAI,CAACC,SAAS,CAACP,iBAAiB;YAC9B,MAAM,IAAID,SACRG,OAAO,CAAC;8BACc,EAAEQ,oBAAoB,mBAAmB,EAAEF,MAAM,0CAA0C,EAAEF,kBAAkB;;MAEvI,CAAC,EACC;gBAACM,MAAM;YAAC;QAEZ;QAEAH,OAAOI,IAAI,CACT,CAAC,sBAAsB,EAAEH,oBAAoB,mBAAmB,EAAEF,MAAM,0CAA0C,EAAEF,kBAAkB,EAAE,CAAC;QAG3I,MAAMQ,gBACJP,SACC,MAAMN,QAAQ;YACbc,SAAS;YACTC,SAAS;QACX;QAEF,OAAOF,gBAAgBJ,sBAAsBO;IAC/C;IAEA,IAAIP,qBAAqB;QACvBP,aAAa,mCAAmCO;QAChD,OAAOA;IACT;IAEAP,aAAa,6CAA6CG;IAC1D,OAAOA;AACT"}
1
+ {"version":3,"sources":["../../../src/actions/graphql/resolveApiGeneration.ts"],"sourcesContent":["import {CLIError} from '@oclif/core/errors'\nimport {exitCodes, type Output} from '@sanity/cli-core'\nimport {confirm} from '@sanity/cli-core/ux'\nimport {oneline} from 'oneline'\n\nimport {graphqlDebug} from './graphqlDebug.js'\n\nconst LATEST_GENERATION = 'gen3'\n\nexport async function resolveApiGeneration({\n currentGeneration,\n force,\n index,\n output,\n specifiedGeneration,\n unattended,\n}: {\n currentGeneration?: string\n force?: boolean\n index: number\n output: Output\n specifiedGeneration?: string\n unattended: boolean\n}): Promise<string | undefined> {\n // a) If no API is currently deployed:\n // use the specificed one from config, or use whichever generation is the latest\n // b) If an API generation is specified explicitly:\n // use the given one, but _prompt_ if it differs from the current one\n // c) If no API generation is specified explicitly:\n // use whichever is already deployed, but warn if differs from latest\n if (!currentGeneration) {\n const generation = specifiedGeneration || LATEST_GENERATION\n graphqlDebug(\n 'There is no current generation deployed, using %s (%s)',\n generation,\n specifiedGeneration ? 'specified' : 'default',\n )\n return generation\n }\n\n if (specifiedGeneration && specifiedGeneration !== currentGeneration) {\n if (!force && unattended) {\n throw new CLIError(\n oneline`\n Specified generation (${specifiedGeneration}) for API at index ${index} differs from the one currently deployed (${currentGeneration}).\n Pass \\`--force\\` to continue.\n `,\n {exit: exitCodes.USAGE_ERROR},\n )\n }\n\n output.warn(\n `Specified generation (${specifiedGeneration}) for API at index ${index} differs from the one currently deployed (${currentGeneration}).`,\n )\n\n const confirmDeploy =\n force ||\n (await confirm({\n default: false,\n message: 'Are you sure you want to deploy?',\n }))\n\n if (!confirmDeploy) {\n return undefined\n }\n\n return specifiedGeneration\n }\n\n if (specifiedGeneration) {\n graphqlDebug('Using specified (%s) generation', specifiedGeneration)\n return specifiedGeneration\n }\n\n graphqlDebug('Using the currently deployed version (%s)', currentGeneration)\n return currentGeneration\n}\n"],"names":["CLIError","exitCodes","confirm","oneline","graphqlDebug","LATEST_GENERATION","resolveApiGeneration","currentGeneration","force","index","output","specifiedGeneration","unattended","generation","exit","USAGE_ERROR","warn","confirmDeploy","default","message","undefined"],"mappings":"AAAA,SAAQA,QAAQ,QAAO,qBAAoB;AAC3C,SAAQC,SAAS,QAAoB,mBAAkB;AACvD,SAAQC,OAAO,QAAO,sBAAqB;AAC3C,SAAQC,OAAO,QAAO,UAAS;AAE/B,SAAQC,YAAY,QAAO,oBAAmB;AAE9C,MAAMC,oBAAoB;AAE1B,OAAO,eAAeC,qBAAqB,EACzCC,iBAAiB,EACjBC,KAAK,EACLC,KAAK,EACLC,MAAM,EACNC,mBAAmB,EACnBC,UAAU,EAQX;IACC,sCAAsC;IACtC,mFAAmF;IACnF,mDAAmD;IACnD,wEAAwE;IACxE,mDAAmD;IACnD,wEAAwE;IACxE,IAAI,CAACL,mBAAmB;QACtB,MAAMM,aAAaF,uBAAuBN;QAC1CD,aACE,0DACAS,YACAF,sBAAsB,cAAc;QAEtC,OAAOE;IACT;IAEA,IAAIF,uBAAuBA,wBAAwBJ,mBAAmB;QACpE,IAAI,CAACC,SAASI,YAAY;YACxB,MAAM,IAAIZ,SACRG,OAAO,CAAC;8BACc,EAAEQ,oBAAoB,mBAAmB,EAAEF,MAAM,0CAA0C,EAAEF,kBAAkB;;MAEvI,CAAC,EACC;gBAACO,MAAMb,UAAUc,WAAW;YAAA;QAEhC;QAEAL,OAAOM,IAAI,CACT,CAAC,sBAAsB,EAAEL,oBAAoB,mBAAmB,EAAEF,MAAM,0CAA0C,EAAEF,kBAAkB,EAAE,CAAC;QAG3I,MAAMU,gBACJT,SACC,MAAMN,QAAQ;YACbgB,SAAS;YACTC,SAAS;QACX;QAEF,IAAI,CAACF,eAAe;YAClB,OAAOG;QACT;QAEA,OAAOT;IACT;IAEA,IAAIA,qBAAqB;QACvBP,aAAa,mCAAmCO;QAChD,OAAOA;IACT;IAEAP,aAAa,6CAA6CG;IAC1D,OAAOA;AACT"}
@@ -1,5 +1,5 @@
1
1
  import { styleText } from 'node:util';
2
- import { subdebug } from '@sanity/cli-core';
2
+ import { exitCodes, subdebug } from '@sanity/cli-core';
3
3
  import { logSymbols, spinner } from '@sanity/cli-core/ux';
4
4
  import { frameworks } from '@vercel/frameworks';
5
5
  import deburr from 'lodash-es/deburr.js';
@@ -7,10 +7,12 @@ import { promptForConfigFiles } from '../../prompts/init/nextjs.js';
7
7
  import { getCliUser } from '../../services/user.js';
8
8
  import { CLIInitStepCompleted } from '../../telemetry/init.telemetry.js';
9
9
  import { detectFrameworkRecord } from '../../util/detectFramework.js';
10
+ import { formatCliErrorMessages } from '../../util/formatCliErrorMessages.js';
10
11
  import { getProjectDefaults } from '../../util/getProjectDefaults.js';
11
12
  import { validateSession } from '../auth/ensureAuthenticated.js';
12
13
  import { getProviderName } from '../auth/getProviderName.js';
13
14
  import { login } from '../auth/login/login.js';
15
+ import { LOGIN_REQUIRED_MESSAGE } from '../auth/login/loginInstructions.js';
14
16
  import { detectAvailableEditors } from '../mcp/detectAvailableEditors.js';
15
17
  import { setupMCP } from '../mcp/setupMCP.js';
16
18
  import { setupSkills } from '../skills/setupSkills.js';
@@ -268,24 +270,29 @@ export async function initAction(options, context) {
268
270
  }
269
271
  function checkFlagsInUnattendedMode(options, { isAppTemplate, isNextJs }) {
270
272
  debug('Unattended mode, validating required options');
271
- if (options.projectName && !options.organization) {
272
- throw new InitError('`--project-name` requires `--organization <id>` in unattended mode', 1);
273
- }
273
+ const errors = [];
274
274
  if (isAppTemplate) {
275
275
  if (!options.outputPath) {
276
- throw new InitError('`--output-path` must be specified in unattended mode', 1);
276
+ errors.push('Output path is required in unattended mode. Pass it with `--output-path <path>`.');
277
277
  }
278
- const hasProjectFlag = Boolean(options.project || options.projectName);
279
- if (!hasProjectFlag && !options.organization) {
280
- throw new InitError('The --organization flag is required for app templates in unattended mode. ' + 'Use --organization <id>, or pass --project <id> / --project-name <name>.', 1);
278
+ if (options.projectName && !options.organization) {
279
+ errors.push('Organization is required when creating a project in unattended mode. Pass it with `--organization <id>`.');
280
+ } else if (!options.project && !options.organization) {
281
+ errors.push('Project or organization is required for app templates in unattended mode. ' + 'Pass `--project <id>` or `--organization <id>`. To create a project, pass ' + '`--project-name <name>` with `--organization <id>`.');
282
+ }
283
+ } else {
284
+ if (!isNextJs && !options.bare && !options.outputPath) {
285
+ errors.push('Output path is required in unattended mode. Pass it with `--output-path <path>`.');
286
+ }
287
+ if (!options.project && !options.projectName) {
288
+ errors.push('Project is required in unattended mode. Pass it with `--project <id>` or `--project-name <name>`.');
289
+ }
290
+ if (!options.project && !options.organization) {
291
+ errors.push('Organization is required when creating a project in unattended mode. Pass it with `--organization <id>`.');
281
292
  }
282
- return;
283
- }
284
- if (!isNextJs && !options.bare && !options.outputPath) {
285
- throw new InitError('`--output-path` must be specified in unattended mode', 1);
286
293
  }
287
- if (!options.project && !options.projectName) {
288
- throw new InitError('`--project <id>` or `--project-name <name>` must be specified in unattended mode', 1);
294
+ if (errors.length > 0) {
295
+ throw new InitError(formatCliErrorMessages(errors), exitCodes.USAGE_ERROR);
289
296
  }
290
297
  }
291
298
  async function ensureAuthenticated(options, output, trace) {
@@ -301,11 +308,12 @@ async function ensureAuthenticated(options, output, trace) {
301
308
  };
302
309
  }
303
310
  if (options.unattended) {
304
- throw new InitError('Must be logged in to run this command in unattended mode, run `sanity login`', 1);
311
+ throw new InitError(LOGIN_REQUIRED_MESSAGE, exitCodes.RUNTIME_ERROR);
305
312
  }
306
313
  trace.log({
307
314
  step: 'login'
308
315
  });
316
+ output.warn(LOGIN_REQUIRED_MESSAGE);
309
317
  try {
310
318
  await login({
311
319
  output,