@sanity/runtime-cli 17.13.1-next.g13a83b0 → 17.13.1-next.g4fa31d1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -90,7 +90,7 @@ EXAMPLES
90
90
  $ sanity-run blueprints add function --name my-function --fn-type document-create --fn-type document-update --lang js
91
91
  ```
92
92
 
93
- _See code: [src/commands/blueprints/add.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g13a83b0/src/commands/blueprints/add.ts)_
93
+ _See code: [src/commands/blueprints/add.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g4fa31d1/src/commands/blueprints/add.ts)_
94
94
 
95
95
  ## `sanity-run blueprints config`
96
96
 
@@ -127,7 +127,7 @@ EXAMPLES
127
127
  $ sanity-run blueprints config --edit --project-id <projectId> --stack <name-or-id>
128
128
  ```
129
129
 
130
- _See code: [src/commands/blueprints/config.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g13a83b0/src/commands/blueprints/config.ts)_
130
+ _See code: [src/commands/blueprints/config.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g4fa31d1/src/commands/blueprints/config.ts)_
131
131
 
132
132
  ## `sanity-run blueprints deploy`
133
133
 
@@ -183,7 +183,7 @@ EXAMPLES
183
183
  $ sanity-run blueprints deploy --new-stack-name <new-name>
184
184
  ```
185
185
 
186
- _See code: [src/commands/blueprints/deploy.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g13a83b0/src/commands/blueprints/deploy.ts)_
186
+ _See code: [src/commands/blueprints/deploy.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g4fa31d1/src/commands/blueprints/deploy.ts)_
187
187
 
188
188
  ## `sanity-run blueprints destroy`
189
189
 
@@ -221,7 +221,7 @@ EXAMPLES
221
221
  $ sanity-run blueprints destroy --stack <name-or-id> --project-id <projectId> --force --no-wait
222
222
  ```
223
223
 
224
- _See code: [src/commands/blueprints/destroy.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g13a83b0/src/commands/blueprints/destroy.ts)_
224
+ _See code: [src/commands/blueprints/destroy.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g4fa31d1/src/commands/blueprints/destroy.ts)_
225
225
 
226
226
  ## `sanity-run blueprints doctor`
227
227
 
@@ -253,7 +253,7 @@ EXAMPLES
253
253
  $ sanity-run blueprints doctor --fix
254
254
  ```
255
255
 
256
- _See code: [src/commands/blueprints/doctor.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g13a83b0/src/commands/blueprints/doctor.ts)_
256
+ _See code: [src/commands/blueprints/doctor.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g4fa31d1/src/commands/blueprints/doctor.ts)_
257
257
 
258
258
  ## `sanity-run blueprints info`
259
259
 
@@ -291,7 +291,7 @@ EXAMPLES
291
291
  $ sanity-run blueprints info --organization-id <orgId> --stack <name-or-id>
292
292
  ```
293
293
 
294
- _See code: [src/commands/blueprints/info.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g13a83b0/src/commands/blueprints/info.ts)_
294
+ _See code: [src/commands/blueprints/info.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g4fa31d1/src/commands/blueprints/info.ts)_
295
295
 
296
296
  ## `sanity-run blueprints init [DIR]`
297
297
 
@@ -355,7 +355,7 @@ EXAMPLES
355
355
  $ sanity-run blueprints init old-stack --type <json|js|ts> --project-id <projectId> --stack-id <existingStackId>
356
356
  ```
357
357
 
358
- _See code: [src/commands/blueprints/init.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g13a83b0/src/commands/blueprints/init.ts)_
358
+ _See code: [src/commands/blueprints/init.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g4fa31d1/src/commands/blueprints/init.ts)_
359
359
 
360
360
  ## `sanity-run blueprints logs`
361
361
 
@@ -401,7 +401,7 @@ EXAMPLES
401
401
  $ sanity-run blueprints logs --before 2026-05-01T00:00:00Z
402
402
  ```
403
403
 
404
- _See code: [src/commands/blueprints/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g13a83b0/src/commands/blueprints/logs.ts)_
404
+ _See code: [src/commands/blueprints/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g4fa31d1/src/commands/blueprints/logs.ts)_
405
405
 
406
406
  ## `sanity-run blueprints mint-deploy-token`
407
407
 
@@ -446,7 +446,7 @@ EXAMPLES
446
446
  $ sanity-run blueprints mint-deploy-token --organization-id <orgId>
447
447
  ```
448
448
 
449
- _See code: [src/commands/blueprints/mint-deploy-token.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g13a83b0/src/commands/blueprints/mint-deploy-token.ts)_
449
+ _See code: [src/commands/blueprints/mint-deploy-token.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g4fa31d1/src/commands/blueprints/mint-deploy-token.ts)_
450
450
 
451
451
  ## `sanity-run blueprints plan`
452
452
 
@@ -479,7 +479,7 @@ EXAMPLES
479
479
  $ sanity-run blueprints plan --organization-id <orgId> --stack <name-or-id>
480
480
  ```
481
481
 
482
- _See code: [src/commands/blueprints/plan.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g13a83b0/src/commands/blueprints/plan.ts)_
482
+ _See code: [src/commands/blueprints/plan.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g4fa31d1/src/commands/blueprints/plan.ts)_
483
483
 
484
484
  ## `sanity-run blueprints promote`
485
485
 
@@ -515,7 +515,7 @@ EXAMPLES
515
515
  $ sanity-run blueprints promote --new-stack-name <new-name>
516
516
  ```
517
517
 
518
- _See code: [src/commands/blueprints/promote.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g13a83b0/src/commands/blueprints/promote.ts)_
518
+ _See code: [src/commands/blueprints/promote.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g4fa31d1/src/commands/blueprints/promote.ts)_
519
519
 
520
520
  ## `sanity-run blueprints stacks`
521
521
 
@@ -556,7 +556,7 @@ EXAMPLES
556
556
  $ sanity-run blueprints stacks --organization-id <organizationId> --include-projects
557
557
  ```
558
558
 
559
- _See code: [src/commands/blueprints/stacks.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g13a83b0/src/commands/blueprints/stacks.ts)_
559
+ _See code: [src/commands/blueprints/stacks.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g4fa31d1/src/commands/blueprints/stacks.ts)_
560
560
 
561
561
  ## `sanity-run functions add`
562
562
 
@@ -608,7 +608,7 @@ EXAMPLES
608
608
  $ sanity-run functions add --name my-function --type document-create --type document-update --lang js
609
609
  ```
610
610
 
611
- _See code: [src/commands/functions/add.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g13a83b0/src/commands/functions/add.ts)_
611
+ _See code: [src/commands/functions/add.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g4fa31d1/src/commands/functions/add.ts)_
612
612
 
613
613
  ## `sanity-run functions dev`
614
614
 
@@ -643,7 +643,7 @@ EXAMPLES
643
643
  $ sanity-run functions dev --timeout 60
644
644
  ```
645
645
 
646
- _See code: [src/commands/functions/dev.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g13a83b0/src/commands/functions/dev.ts)_
646
+ _See code: [src/commands/functions/dev.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g4fa31d1/src/commands/functions/dev.ts)_
647
647
 
648
648
  ## `sanity-run functions env add NAME KEY VALUE`
649
649
 
@@ -676,7 +676,7 @@ EXAMPLES
676
676
  $ sanity-run functions env add --stack <name-or-id> MyFunction API_URL https://api.example.com/
677
677
  ```
678
678
 
679
- _See code: [src/commands/functions/env/add.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g13a83b0/src/commands/functions/env/add.ts)_
679
+ _See code: [src/commands/functions/env/add.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g4fa31d1/src/commands/functions/env/add.ts)_
680
680
 
681
681
  ## `sanity-run functions env list NAME`
682
682
 
@@ -706,7 +706,7 @@ EXAMPLES
706
706
  $ sanity-run functions env list --stack <name-or-id> MyFunction
707
707
  ```
708
708
 
709
- _See code: [src/commands/functions/env/list.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g13a83b0/src/commands/functions/env/list.ts)_
709
+ _See code: [src/commands/functions/env/list.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g4fa31d1/src/commands/functions/env/list.ts)_
710
710
 
711
711
  ## `sanity-run functions env remove NAME KEY`
712
712
 
@@ -738,7 +738,7 @@ EXAMPLES
738
738
  $ sanity-run functions env remove --stack <name-or-id> MyFunction API_URL
739
739
  ```
740
740
 
741
- _See code: [src/commands/functions/env/remove.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g13a83b0/src/commands/functions/env/remove.ts)_
741
+ _See code: [src/commands/functions/env/remove.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g4fa31d1/src/commands/functions/env/remove.ts)_
742
742
 
743
743
  ## `sanity-run functions logs [NAME]`
744
744
 
@@ -778,7 +778,7 @@ EXAMPLES
778
778
  $ sanity-run functions logs <name> --delete
779
779
  ```
780
780
 
781
- _See code: [src/commands/functions/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g13a83b0/src/commands/functions/logs.ts)_
781
+ _See code: [src/commands/functions/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g4fa31d1/src/commands/functions/logs.ts)_
782
782
 
783
783
  ## `sanity-run functions test [NAME]`
784
784
 
@@ -836,7 +836,7 @@ EXAMPLES
836
836
  $ sanity-run functions test <name> --event update --data-before '{ "title": "before" }' --data-after '{ "title": "after" }'
837
837
  ```
838
838
 
839
- _See code: [src/commands/functions/test.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g13a83b0/src/commands/functions/test.ts)_
839
+ _See code: [src/commands/functions/test.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g4fa31d1/src/commands/functions/test.ts)_
840
840
 
841
841
  ## `sanity-run help [COMMAND]`
842
842
 
@@ -8,6 +8,7 @@ type PreDeployFailure = {
8
8
  code?: string;
9
9
  exitCode?: number;
10
10
  suggestions?: string[];
11
+ requestId?: string;
11
12
  };
12
13
  export type PreDeployResult = PreDeployFailure | {
13
14
  success: true;
@@ -1,9 +1,9 @@
1
1
  import { SANITY_FUNCTION_PREFIX } from '../../constants.js';
2
2
  import { resolveDeployedResources } from '../../utils/blueprints/resolve-deployed-resources.js';
3
+ import { BUNDLE_SPECS, prepareBundleAsset, } from '../../utils/bundles/prepare-asset.js';
3
4
  import { CODE_OPERATION_UNCONFIRMED, EXIT_OPERATION_UNCONFIRMED } from '../../utils/exit-codes.js';
4
5
  import { prepareAsset as prepareFunctionAsset } from '../../utils/functions/prepare-asset.js';
5
6
  import { runCommand } from '../../utils/package-manager.js';
6
- import { prepareStudioAsset } from '../../utils/studios/prepare-asset.js';
7
7
  import { setupLogPolling } from './logs-polling.js';
8
8
  import { getOperationStateInfo } from './operations-state.js';
9
9
  import { processAssets } from './process-assets.js';
@@ -13,9 +13,9 @@ import { updateStack } from './stacks.js';
13
13
  */
14
14
  const preDeployConfigs = [
15
15
  {
16
- resourceType: 'sanity.studio',
16
+ resourceType: (type) => type in BUNDLE_SPECS,
17
17
  async prepareAsset(options) {
18
- return prepareStudioAsset({
18
+ return prepareBundleAsset({
19
19
  resource: options.resource,
20
20
  blueprintFileDir: options.blueprintFileDir,
21
21
  });
@@ -114,12 +114,13 @@ async function preDeployStack(options) {
114
114
  preDeploy: true,
115
115
  document: { resources },
116
116
  };
117
- const { ok: deployOk, stack, error: deployError, } = await updateStack({ stackId, stackMutation, auth, fetchFn });
117
+ const { ok: deployOk, stack, error: deployError, requestId, } = await updateStack({ stackId, stackMutation, auth, fetchFn });
118
118
  if (!deployOk) {
119
119
  options.onPreDeployStackFail?.();
120
120
  return {
121
121
  success: false,
122
122
  error: deployError || 'Failed to complete Stack pre-deployment',
123
+ requestId,
123
124
  suggestions: [
124
125
  `Run \`${runCommand(bin)} blueprints plan\` to preview changes before deploying.`,
125
126
  `Run \`${runCommand(bin)} blueprints doctor\` to check your configuration.`,
@@ -162,6 +163,7 @@ async function preDeployStack(options) {
162
163
  return {
163
164
  success: false,
164
165
  error: `Stack pre-deployment was accepted but completion could not be confirmed${outcome.error ? ` (${outcome.error})` : ''}.`,
166
+ requestId,
165
167
  code: CODE_OPERATION_UNCONFIRMED,
166
168
  exitCode: EXIT_OPERATION_UNCONFIRMED,
167
169
  suggestions: [
@@ -175,6 +177,7 @@ async function preDeployStack(options) {
175
177
  return {
176
178
  success: false,
177
179
  error: 'Stack pre-deployment failed',
180
+ requestId,
178
181
  suggestions: [
179
182
  ...outcome.logHints,
180
183
  'Review the pre-deployment output above for error details.',
@@ -1,6 +1,6 @@
1
1
  import type { Blueprint } from '@sanity/blueprints-parser';
2
2
  import type { Logger } from '../../utils/logger.js';
3
- import type { AuthParams, ScopeType, Stack, StackMutation, StackSummary } from '../../utils/types.js';
3
+ import type { AuthParams, ScopeType, Stack, StackMutation, StackSummary, UpdatedStack } from '../../utils/types.js';
4
4
  export declare const stacksUrl: string;
5
5
  type ListStacksResponse = {
6
6
  ok: true;
@@ -46,14 +46,15 @@ export declare function createEmptyStack({ token, scopeType, scopeId, name, logg
46
46
  type UpdateStackResponse = {
47
47
  ok: true;
48
48
  error: null;
49
- stack: Stack & {
50
- operationId: string;
51
- changeCount?: number;
52
- };
49
+ stack: UpdatedStack;
50
+ requestId?: string;
51
+ response?: Response;
53
52
  } | {
54
53
  ok: false;
55
54
  error: string;
56
55
  stack?: unknown;
56
+ requestId?: string;
57
+ response?: Response;
57
58
  };
58
59
  export declare function updateStack({ stackId, stackMutation, auth, fetchFn, }: {
59
60
  stackId: string;
@@ -1,5 +1,6 @@
1
1
  import { blueprintsUrl } from '../../config.js';
2
2
  import getHeaders from '../../utils/get-headers.js';
3
+ import { getRequestId } from '../../utils/request-id.js';
3
4
  import { createTracedFetch } from '../../utils/traced-fetch.js';
4
5
  export const stacksUrl = blueprintsUrl('stacks');
5
6
  export async function listStacks(auth, logger) {
@@ -91,6 +92,28 @@ export async function createEmptyStack({ token, scopeType, scopeId, name, logger
91
92
  }
92
93
  return response.stack;
93
94
  }
95
+ async function parseOperationResponse(response) {
96
+ let data;
97
+ try {
98
+ data = await response.json();
99
+ }
100
+ catch {
101
+ return {
102
+ ok: false,
103
+ error: `HTTP ${response.status} ${response.statusText}`.trim(),
104
+ requestId: getRequestId(response),
105
+ response,
106
+ };
107
+ }
108
+ const body = data;
109
+ return {
110
+ ok: response.ok,
111
+ error: response.ok ? null : String(body?.message ?? `HTTP ${response.status}`),
112
+ stack: data,
113
+ requestId: getRequestId(response, data),
114
+ response,
115
+ };
116
+ }
94
117
  export async function updateStack({ stackId, stackMutation, auth, fetchFn, }) {
95
118
  try {
96
119
  const response = await fetchFn(`${stacksUrl}/${stackId}`, {
@@ -98,12 +121,7 @@ export async function updateStack({ stackId, stackMutation, auth, fetchFn, }) {
98
121
  headers: getHeaders(auth),
99
122
  body: JSON.stringify(stackMutation),
100
123
  });
101
- const data = await response.json();
102
- return {
103
- ok: response.ok,
104
- error: response.ok ? null : data.message,
105
- stack: data,
106
- };
124
+ return await parseOperationResponse(response);
107
125
  }
108
126
  catch (error) {
109
127
  return {
@@ -183,12 +201,7 @@ export async function destroyStack({ stackId, auth, logger, }) {
183
201
  method: 'DELETE',
184
202
  headers: getHeaders(auth),
185
203
  });
186
- const data = await response.json();
187
- return {
188
- ok: response.ok,
189
- error: response.ok ? null : data.message,
190
- stack: data,
191
- };
204
+ return await parseOperationResponse(response);
192
205
  }
193
206
  catch (error) {
194
207
  return {
@@ -1,5 +1,5 @@
1
1
  // * https://oclif.io/docs/base_class
2
- import { Command, CommandHelp, Flags as OclifFlags } from '@oclif/core';
2
+ import { Command, CommandHelp, Errors, Flags as OclifFlags } from '@oclif/core';
3
3
  import { findBlueprintFile, loadBlueprintFile, parseBlueprintContent, } from './actions/blueprints/blueprint.js';
4
4
  import { backfillProjectBasedStackId, readConfigFile, } from './actions/blueprints/config.js';
5
5
  import { resolveIds } from './actions/blueprints/resolve.js';
@@ -8,6 +8,7 @@ import config from './config.js';
8
8
  import { CI_SETUP_DOCS_URL } from './constants.js';
9
9
  import { presentBlueprintParserErrors } from './utils/display/errors.js';
10
10
  import { Logger } from './utils/logger.js';
11
+ import { withRequestId } from './utils/request-id.js';
11
12
  import { styleText } from './utils/style-text.js';
12
13
  import { createTracedFetch } from './utils/traced-fetch.js';
13
14
  import { validTokenOrErrorMessage } from './utils/validated-token.js';
@@ -135,12 +136,16 @@ export class RuntimeCommand extends Command {
135
136
  * forwarding suggestions, ref, or code to oclif's PrettyPrintableError rendering.
136
137
  */
137
138
  coreError(result) {
138
- this.error(result.error, {
139
+ const error = new Errors.CLIError(withRequestId(result.error, result.requestId), {
139
140
  suggestions: result.suggestions,
140
141
  ref: result.ref,
141
142
  code: result.code,
142
143
  exit: result.exitCode,
143
144
  });
145
+ // oclif's toErrorJson spreads own enumerable properties into the --json error
146
+ if (result.requestId)
147
+ Object.assign(error, { requestId: result.requestId });
148
+ throw error;
144
149
  }
145
150
  /**
146
151
  * Renders any actionable items the user can take that don't warrant throwing an error.
@@ -13,6 +13,8 @@ export declare const SANITY_PROJECT_CORS = "sanity.project.cors";
13
13
  export declare const SANITY_PROJECT_DATASET = "sanity.project.dataset";
14
14
  export declare const SANITY_PROJECT_WEBHOOK = "sanity.project.webhook";
15
15
  export declare const SANITY_STUDIO = "sanity.studio";
16
+ export declare const SANITY_APPLICATION = "sanity.application";
17
+ export declare const SANITY_INSTALLATION_CONFIG = "sanity.installation.config";
16
18
  export declare const EVENT_DOCUMENT_PUBLISH = "document-publish";
17
19
  export declare const EVENT_DOCUMENT_CREATE = "document-create";
18
20
  export declare const EVENT_DOCUMENT_UPDATE = "document-update";
package/dist/constants.js CHANGED
@@ -12,6 +12,8 @@ export const SANITY_PROJECT_CORS = 'sanity.project.cors';
12
12
  export const SANITY_PROJECT_DATASET = 'sanity.project.dataset';
13
13
  export const SANITY_PROJECT_WEBHOOK = 'sanity.project.webhook';
14
14
  export const SANITY_STUDIO = 'sanity.studio';
15
+ export const SANITY_APPLICATION = 'sanity.application';
16
+ export const SANITY_INSTALLATION_CONFIG = 'sanity.installation.config';
15
17
  export const EVENT_DOCUMENT_PUBLISH = 'document-publish';
16
18
  export const EVENT_DOCUMENT_CREATE = 'document-create';
17
19
  export const EVENT_DOCUMENT_UPDATE = 'document-update';
@@ -6,6 +6,7 @@ import { checkUserPermission } from '../../actions/sanity/access.js';
6
6
  import { getClientMetadata } from '../../utils/blueprints/deploy-metadata.js';
7
7
  import { extractDurableConfig } from '../../utils/blueprints/extract-durable-config.js';
8
8
  import { createHintCollector } from '../../utils/blueprints/hints.js';
9
+ import { stampInstallationConfigVersion } from '../../utils/blueprints/stamp-installation-config-version.js';
9
10
  import { createWaitFor } from '../../utils/blueprints/wait-for.js';
10
11
  import { formatStudioUrls } from '../../utils/display/blueprints-formatting.js';
11
12
  import { check, niceId, severe } from '../../utils/display/presenters.js';
@@ -42,6 +43,7 @@ export async function blueprintDeployCore(options) {
42
43
  }
43
44
  const resources = [...blueprint.resources];
44
45
  await extractDurableConfig(resources, blueprintFileDir);
46
+ await stampInstallationConfigVersion(resources, blueprintFileDir);
45
47
  let spinner;
46
48
  const preDeployResult = await preDeploy({
47
49
  scopeType,
@@ -80,7 +82,7 @@ export async function blueprintDeployCore(options) {
80
82
  resources: preDeployResult.resourceMetadata,
81
83
  };
82
84
  const deploySpinner = logger.ora('Deploying...').start();
83
- const { ok: deployOk, stack, error: deployError, } = await updateStack({
85
+ const { ok: deployOk, stack, error: deployError, requestId, } = await updateStack({
84
86
  stackId,
85
87
  stackMutation: {
86
88
  scopeType,
@@ -102,6 +104,7 @@ export async function blueprintDeployCore(options) {
102
104
  return {
103
105
  success: false,
104
106
  error: deployError || 'Failed to update Stack deployment',
107
+ requestId,
105
108
  suggestions: [
106
109
  ...hints.getSuggestions(),
107
110
  `Run \`${runCommand(bin)} blueprints plan\` to preview changes before deploying.`,
@@ -110,6 +113,8 @@ export async function blueprintDeployCore(options) {
110
113
  };
111
114
  }
112
115
  deploySpinner.stop().clear();
116
+ if (requestId)
117
+ logger.verbose(styleText('dim', `Request ID: ${requestId}`));
113
118
  const legacyPermissionsNoticePromise = CHECK_LEGACY_DEPLOY_PERMISSION
114
119
  ? checkLegacyDeployPermission({
115
120
  auth,
@@ -121,11 +126,13 @@ export async function blueprintDeployCore(options) {
121
126
  if (noWait) {
122
127
  logger(styleText(['bold', 'green'], 'Stack deployment started!'));
123
128
  logger(`Use \`${runCommand(bin)} blueprints info\` to check status`);
129
+ if (requestId && !verbose)
130
+ logger(styleText('dim', `Request ID: ${requestId}`));
124
131
  const legacyWarning = await legacyPermissionsNoticePromise;
125
132
  const warnings = [...(legacyWarning ? [legacyWarning] : []), ...workspaceWarnings];
126
133
  return {
127
134
  success: true,
128
- json: { stackId, resources },
135
+ json: { stackId, resources, requestId },
129
136
  data: { resources },
130
137
  warnings: warnings.length ? warnings : undefined,
131
138
  };
@@ -149,7 +156,7 @@ export async function blueprintDeployCore(options) {
149
156
  const warnings = [...(legacyWarning ? [legacyWarning] : []), ...workspaceWarnings];
150
157
  return {
151
158
  success: true,
152
- json: { stackId, resources },
159
+ json: { stackId, resources, requestId },
153
160
  data: { resources },
154
161
  warnings: warnings.length ? warnings : undefined,
155
162
  };
@@ -158,6 +165,7 @@ export async function blueprintDeployCore(options) {
158
165
  return {
159
166
  success: false,
160
167
  error: `Stack deployment was accepted but completion could not be confirmed${outcome.error ? ` (${outcome.error})` : ''}.`,
168
+ requestId,
161
169
  code: CODE_OPERATION_UNCONFIRMED,
162
170
  exitCode: EXIT_OPERATION_UNCONFIRMED,
163
171
  suggestions: [
@@ -170,6 +178,7 @@ export async function blueprintDeployCore(options) {
170
178
  return {
171
179
  success: false,
172
180
  error: 'Stack deployment failed',
181
+ requestId,
173
182
  suggestions: [
174
183
  ...outcome.logHints,
175
184
  'Review the deployment output above for error details.',
@@ -19,22 +19,21 @@ export async function blueprintDestroyCore(options) {
19
19
  }
20
20
  const auth = { token, scopeType, scopeId };
21
21
  const resolvedId = await resolveStackIdByNameOrId(flagStack, auth, log);
22
- const { ok, error, stack } = await destroyStack({
22
+ const { ok, error, stack, requestId } = await destroyStack({
23
23
  stackId: resolvedId,
24
24
  auth,
25
25
  logger: log,
26
26
  });
27
- if (!ok)
28
- return { success: false, error: error || 'Failed to destroy Stack deployment' };
29
- clearLocalStackIdFromConfig(blueprintConfig, stack.id, log);
30
- if (noWait) {
31
- log(styleText(['bold', 'magenta'], 'Stack destruction started!'));
32
- return { success: true, json: { stackId: stack.id, stackName: stack.name } };
27
+ if (!ok) {
28
+ return { success: false, error: error || 'Failed to destroy Stack deployment', requestId };
33
29
  }
34
- return waitForDestruction({
30
+ clearLocalStackIdFromConfig(blueprintConfig, stack.id, log);
31
+ return afterDestroyAccepted({
35
32
  stackId: stack.id,
36
33
  stackName: stack.name,
37
34
  operationId: stack.operationId,
35
+ requestId,
36
+ noWait,
38
37
  auth,
39
38
  log,
40
39
  bin,
@@ -98,25 +97,23 @@ export async function blueprintDestroyCore(options) {
98
97
  else {
99
98
  destroySpinner.start();
100
99
  }
101
- const { ok, error, stack: destroyedStack, } = await destroyStack({
100
+ const { ok, error, stack: destroyedStack, requestId, } = await destroyStack({
102
101
  stackId: stack.id,
103
102
  auth,
104
103
  logger: log,
105
104
  });
106
105
  if (!ok) {
107
106
  destroySpinner.fail('Failed to destroy Stack deployment');
108
- return { success: false, error: error || 'Failed to destroy Stack deployment' };
107
+ return { success: false, error: error || 'Failed to destroy Stack deployment', requestId };
109
108
  }
110
109
  destroySpinner.stop().clear();
111
110
  clearLocalStackIdFromConfig(blueprintConfig, stack.id, log);
112
- if (noWait) {
113
- log(styleText(['bold', 'magenta'], 'Stack destruction started!'));
114
- return { success: true, json: { stackId: stack.id, stackName: stack.name } };
115
- }
116
- return waitForDestruction({
111
+ return afterDestroyAccepted({
117
112
  stackId: stack.id,
118
113
  stackName: stack.name,
119
114
  operationId: destroyedStack.operationId,
115
+ requestId,
116
+ noWait,
120
117
  auth,
121
118
  log,
122
119
  bin,
@@ -141,8 +138,20 @@ function clearLocalStackIdFromConfig(blueprintConfig, destroyedStackId, log) {
141
138
  log(styleText('yellow', 'Could not update .sanity/blueprint.config.json. Remove stackId manually.'));
142
139
  }
143
140
  }
141
+ function afterDestroyAccepted(options) {
142
+ const { stackId, stackName, requestId, noWait, log, verbose = false } = options;
143
+ if (requestId)
144
+ log.verbose(styleText('dim', `Request ID: ${requestId}`));
145
+ if (noWait) {
146
+ log(styleText(['bold', 'magenta'], 'Stack destruction started!'));
147
+ if (requestId && !verbose)
148
+ log(styleText('dim', `Request ID: ${requestId}`));
149
+ return { success: true, json: { stackId, stackName, requestId } };
150
+ }
151
+ return waitForDestruction(options);
152
+ }
144
153
  async function waitForDestruction(options) {
145
- const { stackId, stackName, operationId, auth, log, bin, verbose = false } = options;
154
+ const { stackId, stackName, operationId, requestId, auth, log, bin, verbose = false } = options;
146
155
  log(styleText('dim', 'Stack destruction progress:'));
147
156
  log('');
148
157
  const outcome = await waitForOperation({
@@ -157,12 +166,13 @@ async function waitForDestruction(options) {
157
166
  });
158
167
  if (outcome.type === 'completed') {
159
168
  log(styleText(['bold', 'magenta'], 'Stack destruction completed!'));
160
- return { success: true, json: { stackId, stackName } };
169
+ return { success: true, json: { stackId, stackName, requestId } };
161
170
  }
162
171
  if (outcome.type === 'unconfirmed') {
163
172
  return {
164
173
  success: false,
165
174
  error: `Stack destruction was accepted but completion could not be confirmed${outcome.error ? ` (${outcome.error})` : ''}.`,
175
+ requestId,
166
176
  code: CODE_OPERATION_UNCONFIRMED,
167
177
  exitCode: EXIT_OPERATION_UNCONFIRMED,
168
178
  suggestions: [
@@ -175,6 +185,7 @@ async function waitForDestruction(options) {
175
185
  return {
176
186
  success: false,
177
187
  error: 'Stack destruction failed',
188
+ requestId,
178
189
  suggestions: [
179
190
  ...outcome.logHints,
180
191
  'Review the destruction output above for error details.',
@@ -2,6 +2,7 @@ import { dirname } from 'node:path';
2
2
  import { planStack, resolveStackIdByNameOrId } from '../../actions/blueprints/stacks.js';
3
3
  import { extractDurableConfig } from '../../utils/blueprints/extract-durable-config.js';
4
4
  import { createHintCollector } from '../../utils/blueprints/hints.js';
5
+ import { stampInstallationConfigVersion } from '../../utils/blueprints/stamp-installation-config-version.js';
5
6
  import { formatDeploymentPlan, formatResourceTree, hasActionableChanges, } from '../../utils/display/blueprints-formatting.js';
6
7
  import { runCommand } from '../../utils/package-manager.js';
7
8
  import { styleText } from '../../utils/style-text.js';
@@ -12,6 +13,7 @@ export async function blueprintPlanCore(options) {
12
13
  const { scopeType, scopeId, stackId: blueprintStackId, parsedBlueprint, resources, fileInfo, } = blueprint;
13
14
  log(`${styleText(['bold', 'blueBright'], 'Local Blueprint')} ${styleText('dim', `(${fileInfo.fileName})`)}`);
14
15
  await extractDurableConfig(resources, dirname(fileInfo.blueprintFilePath));
16
+ await stampInstallationConfigVersion(resources, dirname(fileInfo.blueprintFilePath));
15
17
  log(formatResourceTree(resources));
16
18
  if (!token || !scopeType || !scopeId) {
17
19
  log(styleText('dim', 'Unable to retrieve live Stack deployment for comparison'));
@@ -39,6 +39,8 @@ export type CoreResult = {
39
39
  ref?: string;
40
40
  /** A machine-readable error code. */
41
41
  code?: string;
42
+ /** Request ID of the API call that failed, for support. */
43
+ requestId?: string;
42
44
  /**
43
45
  * The user cancelled a prompt. A calling core reads it to keep its own message.
44
46
  * Not printed: `code` would surface as `Code:` in the command output.
@@ -0,0 +1,9 @@
1
+ import type { BlueprintResource } from '@sanity/blueprints';
2
+ /**
3
+ * Stamps the installed `sanity` version onto each media-library config resource
4
+ * before pre-deploy. The version is a label Brett stores on the config snapshot,
5
+ * mirroring what `sanity deploy` sends for a media-library config; it is not what
6
+ * the runtime loads. Other installation config types are left alone: the
7
+ * media-library tie to the `sanity` package is specific to it.
8
+ */
9
+ export declare const stampInstallationConfigVersion: (resources: BlueprintResource[], blueprintFileDir: string) => Promise<void>;
@@ -0,0 +1,28 @@
1
+ import { resolve } from 'node:path';
2
+ import { getLocalPackageVersion } from '@sanity/cli-core/package-manager';
3
+ import { SANITY_INSTALLATION_CONFIG } from '../../constants.js';
4
+ /**
5
+ * Stamps the installed `sanity` version onto each media-library config resource
6
+ * before pre-deploy. The version is a label Brett stores on the config snapshot,
7
+ * mirroring what `sanity deploy` sends for a media-library config; it is not what
8
+ * the runtime loads. Other installation config types are left alone: the
9
+ * media-library tie to the `sanity` package is specific to it.
10
+ */
11
+ export const stampInstallationConfigVersion = async (resources, blueprintFileDir) => {
12
+ for (const resource of resources) {
13
+ if (resource.type !== SANITY_INSTALLATION_CONFIG)
14
+ continue;
15
+ const config = resource;
16
+ if (config.appType !== 'media-library')
17
+ continue;
18
+ // Update values not included in the blueprint.
19
+ if (config.version !== undefined)
20
+ continue;
21
+ const workDir = resolve(blueprintFileDir, config.root);
22
+ const version = await getLocalPackageVersion('sanity', workDir);
23
+ if (!version) {
24
+ throw new Error(`Unable to determine the installed 'sanity' version for installation config resource '${config.name}'; is 'sanity' installed in '${config.root}'?`);
25
+ }
26
+ config.version = version;
27
+ }
28
+ };