@sanity/cli 7.10.0 → 7.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (174) hide show
  1. package/README.md +31 -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/loginInstructions.js +19 -0
  5. package/dist/actions/auth/login/loginInstructions.js.map +1 -0
  6. package/dist/actions/build/buildApp.js +10 -7
  7. package/dist/actions/build/buildApp.js.map +1 -1
  8. package/dist/actions/build/buildStudio.js +9 -6
  9. package/dist/actions/build/buildStudio.js.map +1 -1
  10. package/dist/actions/build/types.js.map +1 -1
  11. package/dist/actions/dataset/resolveDataset.js +7 -1
  12. package/dist/actions/dataset/resolveDataset.js.map +1 -1
  13. package/dist/actions/deploy/deployApp.js +205 -157
  14. package/dist/actions/deploy/deployApp.js.map +1 -1
  15. package/dist/actions/deploy/deployChecks.js +1 -1
  16. package/dist/actions/deploy/deployChecks.js.map +1 -1
  17. package/dist/actions/deploy/deployStudio.js +127 -86
  18. package/dist/actions/deploy/deployStudio.js.map +1 -1
  19. package/dist/actions/deploy/resolveDeployTarget.js +5 -9
  20. package/dist/actions/deploy/resolveDeployTarget.js.map +1 -1
  21. package/dist/actions/dev/devAction.js +1 -2
  22. package/dist/actions/dev/devAction.js.map +1 -1
  23. package/dist/actions/dev/servers/getDevServerConfig.js +8 -2
  24. package/dist/actions/dev/servers/getDevServerConfig.js.map +1 -1
  25. package/dist/actions/graphql/resolveApiGeneration.js +9 -6
  26. package/dist/actions/graphql/resolveApiGeneration.js.map +1 -1
  27. package/dist/actions/init/bootstrapLocalTemplate.js +18 -9
  28. package/dist/actions/init/bootstrapLocalTemplate.js.map +1 -1
  29. package/dist/actions/init/createAppCliConfig.js.map +1 -1
  30. package/dist/actions/init/createCliConfig.js.map +1 -1
  31. package/dist/actions/init/initAction.js +23 -15
  32. package/dist/actions/init/initAction.js.map +1 -1
  33. package/dist/actions/manifest/extractCoreAppManifest.js +5 -3
  34. package/dist/actions/manifest/extractCoreAppManifest.js.map +1 -1
  35. package/dist/actions/migration/constants.js +10 -0
  36. package/dist/actions/migration/constants.js.map +1 -0
  37. package/dist/actions/migration/ensureApiVersionFormat.js +16 -0
  38. package/dist/actions/migration/ensureApiVersionFormat.js.map +1 -0
  39. package/dist/actions/migration/fileExists.js +13 -0
  40. package/dist/actions/migration/fileExists.js.map +1 -0
  41. package/dist/actions/migration/prettyMutationFormatter.js +155 -0
  42. package/dist/actions/migration/prettyMutationFormatter.js.map +1 -0
  43. package/dist/actions/migration/resolveMigrationScript.js +75 -0
  44. package/dist/actions/migration/resolveMigrationScript.js.map +1 -0
  45. package/dist/actions/migration/resolveMigrations.js +50 -0
  46. package/dist/actions/migration/resolveMigrations.js.map +1 -0
  47. package/dist/actions/migration/templates/index.js +7 -0
  48. package/dist/actions/migration/templates/index.js.map +1 -0
  49. package/dist/actions/migration/templates/minimalAdvanced.js +21 -0
  50. package/dist/actions/migration/templates/minimalAdvanced.js.map +1 -0
  51. package/dist/actions/migration/templates/minimalSimple.js +61 -0
  52. package/dist/actions/migration/templates/minimalSimple.js.map +1 -0
  53. package/dist/actions/migration/templates/renameField.js +20 -0
  54. package/dist/actions/migration/templates/renameField.js.map +1 -0
  55. package/dist/actions/migration/templates/renameType.js +19 -0
  56. package/dist/actions/migration/templates/renameType.js.map +1 -0
  57. package/dist/actions/migration/templates/stringToPTE.js +32 -0
  58. package/dist/actions/migration/templates/stringToPTE.js.map +1 -0
  59. package/dist/actions/migration/tree.js +111 -0
  60. package/dist/actions/migration/tree.js.map +1 -0
  61. package/dist/actions/preview/previewAction.js +33 -1
  62. package/dist/actions/preview/previewAction.js.map +1 -1
  63. package/dist/actions/schema/listSchemas.js +6 -4
  64. package/dist/actions/schema/listSchemas.js.map +1 -1
  65. package/dist/actions/tokens/validateRole.js +2 -1
  66. package/dist/actions/tokens/validateRole.js.map +1 -1
  67. package/dist/actions/undeploy/runUndeploy.js +13 -4
  68. package/dist/actions/undeploy/runUndeploy.js.map +1 -1
  69. package/dist/commands/backups/disable.js +5 -1
  70. package/dist/commands/backups/disable.js.map +1 -1
  71. package/dist/commands/backups/download.js +30 -6
  72. package/dist/commands/backups/download.js.map +1 -1
  73. package/dist/commands/backups/enable.js +5 -1
  74. package/dist/commands/backups/enable.js.map +1 -1
  75. package/dist/commands/backups/list.js +5 -1
  76. package/dist/commands/backups/list.js.map +1 -1
  77. package/dist/commands/cors/add.js +15 -7
  78. package/dist/commands/cors/add.js.map +1 -1
  79. package/dist/commands/cors/delete.js +6 -1
  80. package/dist/commands/cors/delete.js.map +1 -1
  81. package/dist/commands/datasets/alias/create.js +25 -18
  82. package/dist/commands/datasets/alias/create.js.map +1 -1
  83. package/dist/commands/datasets/alias/delete.js +15 -8
  84. package/dist/commands/datasets/alias/delete.js.map +1 -1
  85. package/dist/commands/datasets/alias/link.js +39 -17
  86. package/dist/commands/datasets/alias/link.js.map +1 -1
  87. package/dist/commands/datasets/alias/unlink.js +23 -2
  88. package/dist/commands/datasets/alias/unlink.js.map +1 -1
  89. package/dist/commands/datasets/copy.js +18 -2
  90. package/dist/commands/datasets/copy.js.map +1 -1
  91. package/dist/commands/datasets/create.js +8 -2
  92. package/dist/commands/datasets/create.js.map +1 -1
  93. package/dist/commands/datasets/delete.js +14 -17
  94. package/dist/commands/datasets/delete.js.map +1 -1
  95. package/dist/commands/datasets/embeddings/disable.js +3 -0
  96. package/dist/commands/datasets/embeddings/disable.js.map +1 -1
  97. package/dist/commands/datasets/embeddings/enable.js +5 -2
  98. package/dist/commands/datasets/embeddings/enable.js.map +1 -1
  99. package/dist/commands/datasets/embeddings/status.js +3 -0
  100. package/dist/commands/datasets/embeddings/status.js.map +1 -1
  101. package/dist/commands/datasets/export.js +27 -15
  102. package/dist/commands/datasets/export.js.map +1 -1
  103. package/dist/commands/datasets/import.js +3 -3
  104. package/dist/commands/datasets/import.js.map +1 -1
  105. package/dist/commands/datasets/visibility/get.js +2 -2
  106. package/dist/commands/datasets/visibility/get.js.map +1 -1
  107. package/dist/commands/datasets/visibility/set.js +2 -2
  108. package/dist/commands/datasets/visibility/set.js.map +1 -1
  109. package/dist/commands/docs/read.js +3 -3
  110. package/dist/commands/docs/read.js.map +1 -1
  111. package/dist/commands/documents/create.js +18 -13
  112. package/dist/commands/documents/create.js.map +1 -1
  113. package/dist/commands/documents/delete.js +3 -3
  114. package/dist/commands/documents/delete.js.map +1 -1
  115. package/dist/commands/documents/get.js +3 -3
  116. package/dist/commands/documents/get.js.map +1 -1
  117. package/dist/commands/documents/query.js +3 -3
  118. package/dist/commands/documents/query.js.map +1 -1
  119. package/dist/commands/documents/validate.js +29 -26
  120. package/dist/commands/documents/validate.js.map +1 -1
  121. package/dist/commands/graphql/deploy.js +20 -16
  122. package/dist/commands/graphql/deploy.js.map +1 -1
  123. package/dist/commands/graphql/undeploy.js +15 -18
  124. package/dist/commands/graphql/undeploy.js.map +1 -1
  125. package/dist/commands/hooks/delete.js +2 -2
  126. package/dist/commands/hooks/delete.js.map +1 -1
  127. package/dist/commands/hooks/logs.js +2 -2
  128. package/dist/commands/hooks/logs.js.map +1 -1
  129. package/dist/commands/login.js +2 -1
  130. package/dist/commands/login.js.map +1 -1
  131. package/dist/commands/media/create-aspect.js +20 -8
  132. package/dist/commands/media/create-aspect.js.map +1 -1
  133. package/dist/commands/media/delete-aspect.js +31 -16
  134. package/dist/commands/media/delete-aspect.js.map +1 -1
  135. package/dist/commands/media/deploy-aspect.js +10 -5
  136. package/dist/commands/media/deploy-aspect.js.map +1 -1
  137. package/dist/commands/media/export.js +9 -4
  138. package/dist/commands/media/export.js.map +1 -1
  139. package/dist/commands/media/import.js +6 -1
  140. package/dist/commands/media/import.js.map +1 -1
  141. package/dist/commands/migrations/create.js +150 -0
  142. package/dist/commands/migrations/create.js.map +1 -0
  143. package/dist/commands/migrations/list.js +64 -0
  144. package/dist/commands/migrations/list.js.map +1 -0
  145. package/dist/commands/migrations/run.js +306 -0
  146. package/dist/commands/migrations/run.js.map +1 -0
  147. package/dist/commands/preview.js +1 -0
  148. package/dist/commands/preview.js.map +1 -1
  149. package/dist/commands/projects/create.js +2 -1
  150. package/dist/commands/projects/create.js.map +1 -1
  151. package/dist/commands/schemas/delete.js +23 -2
  152. package/dist/commands/schemas/delete.js.map +1 -1
  153. package/dist/commands/schemas/deploy.js +6 -4
  154. package/dist/commands/schemas/deploy.js.map +1 -1
  155. package/dist/commands/schemas/extract.js +22 -1
  156. package/dist/commands/schemas/extract.js.map +1 -1
  157. package/dist/commands/schemas/list.js +8 -8
  158. package/dist/commands/schemas/list.js.map +1 -1
  159. package/dist/commands/tokens/{add.js → create.js} +25 -18
  160. package/dist/commands/tokens/create.js.map +1 -0
  161. package/dist/commands/tokens/delete.js +41 -23
  162. package/dist/commands/tokens/delete.js.map +1 -1
  163. package/dist/commands/undeploy.js +2 -7
  164. package/dist/commands/undeploy.js.map +1 -1
  165. package/dist/commands/users/invite.js +25 -3
  166. package/dist/commands/users/invite.js.map +1 -1
  167. package/dist/topicAliases.js +3 -0
  168. package/dist/topicAliases.js.map +1 -1
  169. package/dist/util/formatCliErrorMessages.js +5 -0
  170. package/dist/util/formatCliErrorMessages.js.map +1 -0
  171. package/oclif.config.js +5 -1
  172. package/oclif.manifest.json +579 -374
  173. package/package.json +7 -7
  174. package/dist/commands/tokens/add.js.map +0 -1
@@ -5,14 +5,14 @@ import { exitCodes } from '@sanity/cli-core';
5
5
  import { getErrorMessage } from '@sanity/cli-core/errors';
6
6
  import { getCoreAppUrl } from '@sanity/cli-core/util';
7
7
  import { spinner } from '@sanity/cli-core/ux';
8
- import { buildExposes, deployConfig, deployCoreApp as deployWorkbenchCoreApp, getApplicationUrl, getWorkbench, resolveInstallationId, summarizeConfig } from '@sanity/workbench-cli/deploy';
8
+ import { buildExposes, createCoreApp, deployConfig, deployWorkbenchApp, getApplicationUrl, getWorkbench, resolveInstallationId, summarizeConfig } from '@sanity/workbench-cli/deploy';
9
9
  import { pack } from 'tar-fs';
10
10
  import { createDeployment, updateUserApplication } from '../../services/userApplications.js';
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';
15
- import { createUserApplication, generateAppSlug } from './createUserApplication.js';
14
+ import { extractCoreAppManifest, readIconFromPath, resolveTitleUpdate } from '../manifest/extractCoreAppManifest.js';
15
+ import { createUserApplication } from './createUserApplication.js';
16
16
  import { checkAppId, checkAppTarget, checkAutoUpdates, checkBuild, checkPackageVersion, verifyOutputDir } from './deployChecks.js';
17
17
  import { deployDebug } from './deployDebug.js';
18
18
  import { listDeploymentFiles, reportExposes } from './deploymentPlan.js';
@@ -103,188 +103,236 @@ export function deployApp(options) {
103
103
  reporter
104
104
  }));
105
105
  }
106
- await checkBuild(reporter, {
107
- build: ()=>buildApp({
108
- autoUpdatesEnabled: isAutoUpdating,
109
- calledFromDeploy: true,
110
- cliConfig,
111
- flags,
112
- outDir: sourceDir,
113
- output,
114
- workDir
115
- }),
116
- skipReason: flags.build ? undefined : 'Build skipped (--no-build) — validating existing output directory',
117
- successMessage: 'App built'
118
- });
119
- await verifyOutputDir({
120
- isWorkbenchApp: workbench !== null,
121
- reporter,
122
- sourceDir
123
- });
124
- // Manifests aren't strictly essential, so a failure warns and continues
125
- let manifest;
126
- try {
127
- manifest = await extractCoreAppManifest({
128
- workDir
129
- });
130
- } catch (err) {
131
- deployDebug('Error extracting app manifest', err);
106
+ // A first deploy mints the app id and the build inlines it; --no-build would
107
+ // ship an existing bundle carrying a different id, so it can't be a first deploy.
108
+ if (deployApplication && workbench && !appId && !flags.external && !flags.build) {
132
109
  reporter.report({
133
- message: `Error extracting app manifest: ${getErrorMessage(err)}`,
134
- status: 'warn'
135
- });
136
- }
137
- // Resolve the installation in both modes so the report — dry-run and real —
138
- // shows whether the config is deployable; a missing one fails the deploy here.
139
- let installationId;
140
- let config;
141
- const configAppType = workbench?.config?.appType;
142
- if (deploySingletonConfig && organizationId && workbench?.config && configAppType) {
143
- installationId = await resolveInstallationId({
144
- appType: configAppType,
145
- organizationId
146
- });
147
- config = summarizeConfig(workbench.config);
148
- reporter.report(installationId ? {
149
- config,
150
- message: config,
151
- status: 'pass'
152
- } : {
153
110
  exitCode: exitCodes.USAGE_ERROR,
154
- message: `No active "${configAppType}" installation for organization "${organizationId}"`,
155
- solution: 'Install the Media Library for the organization before deploying its config',
111
+ message: 'A first deploy cannot skip the build (--no-build)',
112
+ solution: 'Drop --no-build so the new application id is inlined into the build',
156
113
  status: 'fail'
157
114
  });
158
115
  }
159
- // Report the exposes deploying with the application, both modes.
160
- const exposes = deployApplication && workbench ? reportExposes(reporter, workbench) : [];
161
- // Surface the app's explicit singleton flag when set, both modes.
162
- if (deployApplication && workbench?.isSingleton !== undefined) {
163
- reporter.report({
116
+ // Read up front so a bad icon path fails before we create or build.
117
+ const appIcon = !dryRun && workbench?.icon ? await readIconFromPath(workDir, workbench.icon) : undefined;
118
+ // Create the app before the build so the bundle carries its real id. A
119
+ // redeploy already has it from `deployment.appId`; a dry run skips creation.
120
+ let applicationId = appId;
121
+ let applicationCreated = false;
122
+ let rollbackApp;
123
+ if (!dryRun && deployApplication && workbench && organizationId && !applicationId) {
124
+ ;
125
+ ({ applicationId, rollback: rollbackApp } = await createCoreApp({
164
126
  isSingleton: workbench.isSingleton,
165
- message: `Singleton: ${workbench.isSingleton}`,
166
- status: 'pass'
167
- });
168
- }
169
- // Dry run stops here — everything below mutates.
170
- if (dryRun) return;
171
- if (installationId && version && configAppType && organizationId) {
172
- await deployConfig({
173
- appType: configAppType,
174
- installationId,
175
127
  organizationId,
176
- output,
177
- sourceDir,
178
- version
179
- });
128
+ slug: workbench.slug,
129
+ title: appTitle,
130
+ visibility: workbench.visibility
131
+ }));
132
+ applicationCreated = true;
180
133
  }
181
- // A config-only singleton ships no application, only its config.
182
- if (!deployApplication) {
183
- if (installationId && version) {
134
+ // A record created above is stranded at its slug (and blocks retries) if any
135
+ // step before it fully deploys fails, so undo the creation on failure.
136
+ try {
137
+ await checkBuild(reporter, {
138
+ build: ()=>buildApp({
139
+ applicationId: workbench ? applicationId : undefined,
140
+ autoUpdatesEnabled: isAutoUpdating,
141
+ calledFromDeploy: true,
142
+ cliConfig,
143
+ flags,
144
+ outDir: sourceDir,
145
+ output,
146
+ workDir
147
+ }),
148
+ skipReason: flags.build ? undefined : 'Build skipped (--no-build) — validating existing output directory',
149
+ successMessage: 'App built'
150
+ });
151
+ await verifyOutputDir({
152
+ isWorkbenchApp: workbench !== null,
153
+ reporter,
154
+ sourceDir
155
+ });
156
+ // Workbench apps ship their icon straight to Brett (below) and don't read the
157
+ // core-app manifest; only plain core-apps do. Manifests aren't strictly
158
+ // essential, so a failure warns and continues.
159
+ let manifest;
160
+ if (!workbench) {
161
+ try {
162
+ manifest = await extractCoreAppManifest({
163
+ workDir
164
+ });
165
+ } catch (err) {
166
+ deployDebug('Error extracting app manifest', err);
167
+ reporter.report({
168
+ message: `Error extracting app manifest: ${getErrorMessage(err)}`,
169
+ status: 'warn'
170
+ });
171
+ }
172
+ }
173
+ // Resolve the installation in both modes so the report — dry-run and real —
174
+ // shows whether the config is deployable; a missing one fails the deploy here.
175
+ let installationId;
176
+ let config;
177
+ const configAppType = workbench?.config?.appType;
178
+ if (deploySingletonConfig && organizationId && workbench?.config && configAppType) {
179
+ installationId = await resolveInstallationId({
180
+ appType: configAppType,
181
+ organizationId
182
+ });
183
+ config = summarizeConfig(workbench.config);
184
+ reporter.report(installationId ? {
185
+ config,
186
+ message: config,
187
+ status: 'pass'
188
+ } : {
189
+ exitCode: exitCodes.USAGE_ERROR,
190
+ message: `No active "${configAppType}" installation for organization "${organizationId}"`,
191
+ solution: 'Install the Media Library for the organization before deploying its config',
192
+ status: 'fail'
193
+ });
194
+ }
195
+ // Report the exposes deploying with the application, both modes.
196
+ const exposes = deployApplication && workbench ? reportExposes(reporter, workbench) : [];
197
+ // Surface the app's explicit singleton flag when set, both modes.
198
+ if (deployApplication && workbench?.isSingleton !== undefined) {
199
+ reporter.report({
200
+ isSingleton: workbench.isSingleton,
201
+ message: `Singleton: ${workbench.isSingleton}`,
202
+ status: 'pass'
203
+ });
204
+ }
205
+ // Applied after the app is live (see below) so a failed deploy never leaves
206
+ // the org's installation config without its application.
207
+ const deployApplicationConfig = async ()=>{
208
+ if (installationId && version && configAppType && organizationId) {
209
+ await deployConfig({
210
+ appType: configAppType,
211
+ installationId,
212
+ organizationId,
213
+ output,
214
+ sourceDir,
215
+ version
216
+ });
217
+ }
218
+ };
219
+ // Dry run stops here — everything below mutates.
220
+ if (dryRun) return;
221
+ // A config-only singleton ships no application, only its config.
222
+ if (!deployApplication) {
223
+ await deployApplicationConfig();
224
+ if (installationId && version) {
225
+ return {
226
+ applicationType: 'coreApp',
227
+ applicationVersion: version,
228
+ ...config ? {
229
+ config
230
+ } : {},
231
+ installationId,
232
+ target: null
233
+ };
234
+ }
235
+ return;
236
+ }
237
+ // A real deploy already exited on a version-resolution failure; this narrows the type.
238
+ if (!version) return;
239
+ // The app was created (or resolved from `deployment.appId`) before the build,
240
+ // so this only ships the deployment; plain coreApps use user-applications below.
241
+ if (workbench && organizationId && applicationId) {
242
+ await deployWorkbenchApp({
243
+ applicationId,
244
+ icon: appIcon,
245
+ interfaces: buildExposes(workbench, {
246
+ appName: workbench.name,
247
+ appTitle,
248
+ exposesAppView: workbench.entry !== undefined,
249
+ version
250
+ }),
251
+ isAutoUpdating,
252
+ // Once the deployment is live, a metadata-sync or later config failure
253
+ // must not delete the app.
254
+ onDeployed: ()=>{
255
+ rollbackApp = undefined;
256
+ },
257
+ sourceDir,
258
+ title: appTitle,
259
+ version,
260
+ visibility: workbench.visibility
261
+ });
262
+ await deployApplicationConfig();
263
+ const url = getApplicationUrl({
264
+ id: applicationId,
265
+ organizationId,
266
+ type: 'coreApp'
267
+ });
268
+ logAppDeployed({
269
+ applicationId,
270
+ cliConfig,
271
+ created: applicationCreated,
272
+ organizationId,
273
+ output,
274
+ title: appTitle,
275
+ url
276
+ });
184
277
  return {
185
278
  applicationType: 'coreApp',
186
279
  applicationVersion: version,
187
- ...config ? {
188
- config
280
+ ...exposes.length > 0 ? {
281
+ exposes
189
282
  } : {},
190
- installationId,
191
- target: null
283
+ ...workbench.isSingleton === undefined ? {} : {
284
+ isSingleton: workbench.isSingleton
285
+ },
286
+ target: {
287
+ action: applicationCreated ? 'create' : 'update',
288
+ applicationId,
289
+ // A redeploy targets an existing app; only a create reports the slug.
290
+ ...applicationCreated ? {
291
+ slug: workbench.slug
292
+ } : {},
293
+ title: appTitle,
294
+ url
295
+ }
192
296
  };
193
297
  }
194
- return;
195
- }
196
- // A real deploy already exited on a version-resolution failure; this narrows the type.
197
- if (!version) return;
198
- // Workbench apps deploy to Brett; plain coreApps use user-applications.
199
- if (workbench && organizationId) {
200
- const appId = getAppId(cliConfig);
201
- const slug = workbench.slug ?? generateAppSlug();
202
- const { applicationId } = await deployWorkbenchCoreApp({
203
- appId,
204
- interfaces: buildExposes(workbench, {
205
- appName: workbench.name,
206
- appTitle,
207
- exposesAppView: workbench.entry !== undefined,
208
- version
209
- }),
298
+ // A real deploy has already exited if anything failed; landing here without a
299
+ // resolved application means the deploy target was never resolved.
300
+ if (!application) return;
301
+ application = await syncApplicationMetadata({
302
+ application,
303
+ manifest,
304
+ output,
305
+ visibility: cliConfig.app?.visibility
306
+ });
307
+ await shipAppDeployment({
308
+ application,
210
309
  isAutoUpdating,
211
- isSingleton: workbench.isSingleton,
212
- organizationId,
213
- slug,
310
+ manifest,
214
311
  sourceDir,
215
- title: appTitle,
216
- version,
217
- visibility: workbench.visibility
218
- });
219
- const url = getApplicationUrl({
220
- id: applicationId,
221
- organizationId,
222
- type: 'coreApp'
312
+ version
223
313
  });
224
314
  logAppDeployed({
225
- applicationId,
315
+ applicationId: application.id,
226
316
  cliConfig,
227
- created: !appId,
228
- organizationId,
317
+ created: appCreated,
318
+ organizationId: application.organizationId,
229
319
  output,
230
- title: appTitle,
231
- url
320
+ title: application.title
232
321
  });
233
322
  return {
234
323
  applicationType: 'coreApp',
235
324
  applicationVersion: version,
236
- ...exposes.length > 0 ? {
237
- exposes
238
- } : {},
239
- ...workbench.isSingleton === undefined ? {} : {
240
- isSingleton: workbench.isSingleton
241
- },
242
325
  target: {
243
- action: appId ? 'update' : 'create',
244
- applicationId,
245
- // A redeploy ignores the slug, so only a create reports the one it used.
246
- ...appId ? {} : {
247
- slug
248
- },
249
- title: appTitle,
250
- url
326
+ action: appCreated ? 'create' : 'update',
327
+ applicationId: application.id,
328
+ title: application.title ?? null,
329
+ url: getCoreAppUrl(application.organizationId, application.id)
251
330
  }
252
331
  };
332
+ } catch (err) {
333
+ await rollbackApp?.();
334
+ throw err;
253
335
  }
254
- // A real deploy has already exited if anything failed; landing here without a
255
- // resolved application means the deploy target was never resolved.
256
- if (!application) return;
257
- application = await syncApplicationMetadata({
258
- application,
259
- manifest,
260
- output,
261
- visibility: cliConfig.app?.visibility
262
- });
263
- await shipAppDeployment({
264
- application,
265
- isAutoUpdating,
266
- manifest,
267
- sourceDir,
268
- version
269
- });
270
- logAppDeployed({
271
- applicationId: application.id,
272
- cliConfig,
273
- created: appCreated,
274
- organizationId: application.organizationId,
275
- output,
276
- title: application.title
277
- });
278
- return {
279
- applicationType: 'coreApp',
280
- applicationVersion: version,
281
- target: {
282
- action: appCreated ? 'create' : 'update',
283
- applicationId: application.id,
284
- title: application.title ?? null,
285
- url: getCoreAppUrl(application.organizationId, application.id)
286
- }
287
- };
288
336
  }
289
337
  /**
290
338
  * Finds the application a real deploy targets, creating one when none is
@@ -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 {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 {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 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","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","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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"}
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 createCoreApp,\n deployConfig,\n deployWorkbenchApp,\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} 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 // A first deploy mints the app id and the build inlines it; --no-build would\n // ship an existing bundle carrying a different id, so it can't be a first deploy.\n if (deployApplication && workbench && !appId && !flags.external && !flags.build) {\n reporter.report({\n exitCode: exitCodes.USAGE_ERROR,\n message: 'A first deploy cannot skip the build (--no-build)',\n solution: 'Drop --no-build so the new application id is inlined into the build',\n status: 'fail',\n })\n }\n\n // Read up front so a bad icon path fails before we create or build.\n const appIcon =\n !dryRun && workbench?.icon ? await readIconFromPath(workDir, workbench.icon) : undefined\n\n // Create the app before the build so the bundle carries its real id. A\n // redeploy already has it from `deployment.appId`; a dry run skips creation.\n let applicationId = appId\n let applicationCreated = false\n let rollbackApp: (() => Promise<void>) | undefined\n if (!dryRun && deployApplication && workbench && organizationId && !applicationId) {\n ;({applicationId, rollback: rollbackApp} = await createCoreApp({\n isSingleton: workbench.isSingleton,\n organizationId,\n slug: workbench.slug,\n title: appTitle,\n visibility: workbench.visibility,\n }))\n applicationCreated = true\n }\n\n // A record created above is stranded at its slug (and blocks retries) if any\n // step before it fully deploys fails, so undo the creation on failure.\n try {\n await checkBuild(reporter, {\n build: () =>\n buildApp({\n applicationId: workbench ? applicationId : undefined,\n autoUpdatesEnabled: isAutoUpdating,\n calledFromDeploy: true,\n cliConfig,\n flags,\n outDir: sourceDir,\n output,\n workDir,\n }),\n skipReason: flags.build\n ? undefined\n : 'Build skipped (--no-build) — validating existing output directory',\n successMessage: 'App built',\n })\n\n await verifyOutputDir({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:\n '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 // Applied after the app is live (see below) so a failed deploy never leaves\n // the org's installation config without its application.\n const deployApplicationConfig = async (): Promise<void> => {\n if (installationId && version && configAppType && organizationId) {\n await deployConfig({\n appType: configAppType,\n installationId,\n organizationId,\n output,\n sourceDir,\n version,\n })\n }\n }\n\n // Dry run stops here — everything below mutates.\n if (dryRun) return\n\n // A config-only singleton ships no application, only its config.\n if (!deployApplication) {\n await deployApplicationConfig()\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 // The app was created (or resolved from `deployment.appId`) before the build,\n // so this only ships the deployment; plain coreApps use user-applications below.\n if (workbench && organizationId && applicationId) {\n await deployWorkbenchApp({\n applicationId,\n icon: appIcon,\n interfaces: buildExposes(workbench, {\n appName: workbench.name,\n appTitle,\n exposesAppView: workbench.entry !== undefined,\n version,\n }),\n isAutoUpdating,\n // Once the deployment is live, a metadata-sync or later config failure\n // must not delete the app.\n onDeployed: () => {\n rollbackApp = undefined\n },\n sourceDir,\n title: appTitle,\n version,\n visibility: workbench.visibility,\n })\n await deployApplicationConfig()\n const url = getApplicationUrl({id: applicationId, organizationId, type: 'coreApp'})\n logAppDeployed({\n applicationId,\n cliConfig,\n created: applicationCreated,\n organizationId,\n output,\n title: appTitle,\n url,\n })\n return {\n applicationType: 'coreApp',\n applicationVersion: version,\n ...(exposes.length > 0 ? {exposes} : {}),\n ...(workbench.isSingleton === undefined ? {} : {isSingleton: workbench.isSingleton}),\n target: {\n action: applicationCreated ? 'create' : 'update',\n applicationId,\n // A redeploy targets an existing app; only a create reports the slug.\n ...(applicationCreated ? {slug: workbench.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 } catch (err) {\n await rollbackApp?.()\n throw err\n }\n}\n\n/**\n * Finds the application a real deploy targets, creating one when none is\n * configured. A dry run resolves and reports the target read-only instead.\n */\nasync function resolveAppApplication(\n options: DeployAppOptions,\n {dryRun, reporter}: {dryRun: boolean; reporter: DeployCheckReporter},\n): Promise<{application: UserApplicationResolved | null; created: boolean}> {\n const {cliConfig, flags, output} = options\n const organizationId = cliConfig.app?.organizationId ?? ''\n // Create name from --title or `app.title` config; blank falls back to the prompt\n const title = flags.title?.trim() || cliConfig.app?.title?.trim() || undefined\n\n if (dryRun) {\n await checkAppTarget(reporter, {appId: getAppId(cliConfig), organizationId, title})\n return {application: null, created: false}\n }\n\n let application = await findUserApplication({\n cliConfig,\n organizationId,\n output,\n title,\n unattended: !!flags.yes,\n })\n deployDebug('User application found', application)\n\n if (!application) {\n deployDebug('No user application found. Creating a new one')\n application = await createUserApplication(organizationId, title, cliConfig.app?.visibility)\n deployDebug('User application created', application)\n return {application, created: true}\n }\n\n return {application, created: false}\n}\n\n/**\n * Syncs application metadata on redeploy when it has changed: the title from the\n * manifest and the dashboard visibility from config. Sends a single PATCH with\n * only the changed fields, and skips the request entirely when nothing changed.\n */\nexport async function syncApplicationMetadata({\n application,\n manifest,\n output,\n visibility,\n}: {\n application: UserApplicationResolved\n manifest: CoreAppManifest | undefined\n output: DeployAppOptions['output']\n visibility: AppVisibility | undefined\n}): Promise<UserApplicationResolved> {\n const titleUpdate = resolveTitleUpdate(manifest, application)\n // Treat an unset server value as `default` so a config of `default` is a no-op.\n const visibilityChanged =\n visibility !== undefined && visibility !== (application.dashboardStatus ?? 'default')\n\n if (!titleUpdate && !visibilityChanged) return application\n\n if (titleUpdate) {\n deployDebug('Updating application title from manifest', titleUpdate)\n output.log(\n titleUpdate.from\n ? `Updating title from \"${titleUpdate.from}\" to \"${titleUpdate.to}\"`\n : `Setting application title to \"${titleUpdate.to}\"`,\n )\n }\n if (visibilityChanged) {\n output.log(`Setting dashboard visibility to \"${visibility}\"`)\n }\n\n const spin = spinner('Updating application').start()\n try {\n const updated = await updateUserApplication({\n applicationId: application.id,\n appType: 'coreApp',\n body: {\n ...(titleUpdate ? {title: titleUpdate.to} : {}),\n ...(visibilityChanged ? {dashboardStatus: visibility} : {}),\n },\n })\n spin.succeed()\n return updated\n } catch (err) {\n spin.fail()\n const message = getErrorMessage(err)\n deployDebug('Error updating application metadata', {message})\n output.warn(`Error updating application metadata: ${message}`)\n return application\n }\n}\n\nasync function shipAppDeployment({\n application,\n isAutoUpdating,\n manifest,\n sourceDir,\n version,\n}: {\n application: UserApplication\n isAutoUpdating: boolean\n manifest: CoreAppManifest | undefined\n sourceDir: string\n version: string\n}): Promise<void> {\n const tarball = 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","createCoreApp","deployConfig","deployWorkbenchApp","getApplicationUrl","getWorkbench","resolveInstallationId","summarizeConfig","pack","createDeployment","updateUserApplication","getAppId","EXTERNAL_APP_NOT_SUPPORTED","NO_ORGANIZATION_ID","buildApp","extractCoreAppManifest","readIconFromPath","resolveTitleUpdate","createUserApplication","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","appIcon","icon","undefined","applicationId","applicationCreated","rollbackApp","rollback","isSingleton","visibility","autoUpdatesEnabled","calledFromDeploy","outDir","skipReason","successMessage","manifest","installationId","config","configAppType","appType","exposes","deployApplicationConfig","applicationType","applicationVersion","target","interfaces","appName","exposesAppView","entry","onDeployed","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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"}
@@ -293,7 +293,7 @@ export function describeAppTargetError(err, organizationId) {
293
293
  const { title } = options;
294
294
  const resolve = options.isWorkbenchApp ? resolveWorkbenchStudio({
295
295
  appId: options.appId,
296
- studioHost: options.studioHost
296
+ slug: options.slug
297
297
  }) : resolveStudioDeployTarget(options);
298
298
  // Workbench studios always deploy to Sanity hosting, never an external URL.
299
299
  const isExternal = options.isWorkbenchApp ? false : options.isExternal;