@sanity/runtime-cli 10.10.0 → 10.11.1

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 (46) hide show
  1. package/README.md +35 -16
  2. package/dist/actions/blueprints/config.d.ts +1 -1
  3. package/dist/actions/blueprints/config.js +2 -11
  4. package/dist/actions/blueprints/index.js +14 -5
  5. package/dist/actions/blueprints/stacks.d.ts +5 -3
  6. package/dist/actions/blueprints/stacks.js +11 -4
  7. package/dist/actions/sanity/projects.d.ts +4 -2
  8. package/dist/actions/sanity/projects.js +5 -2
  9. package/dist/commands/blueprints/doctor.d.ts +10 -0
  10. package/dist/commands/blueprints/doctor.js +28 -0
  11. package/dist/cores/blueprints/config.js +11 -4
  12. package/dist/cores/blueprints/deploy.js +10 -6
  13. package/dist/cores/blueprints/destroy.js +2 -2
  14. package/dist/cores/blueprints/doctor.d.ts +9 -0
  15. package/dist/cores/blueprints/doctor.js +188 -0
  16. package/dist/cores/blueprints/init.js +17 -8
  17. package/dist/cores/blueprints/plan.js +4 -1
  18. package/dist/cores/blueprints/stacks.js +1 -1
  19. package/dist/cores/index.d.ts +4 -1
  20. package/dist/cores/index.js +1 -1
  21. package/dist/utils/display/prompt.js +3 -2
  22. package/dist/utils/get-headers.d.ts +2 -2
  23. package/dist/utils/get-headers.js +5 -13
  24. package/dist/utils/types.d.ts +6 -3
  25. package/dist/utils/validate/resource.js +3 -3
  26. package/oclif.manifest.json +37 -1
  27. package/package.json +2 -1
  28. package/dist/server/static/api.d.ts +0 -24
  29. package/dist/server/static/components/api-base.d.ts +0 -20
  30. package/dist/server/static/components/clear-button.d.ts +0 -6
  31. package/dist/server/static/components/codemirror-theme.d.ts +0 -6
  32. package/dist/server/static/components/console-panel.d.ts +0 -1
  33. package/dist/server/static/components/fetch-button.d.ts +0 -7
  34. package/dist/server/static/components/filters.d.ts +0 -1
  35. package/dist/server/static/components/function-list.d.ts +0 -1
  36. package/dist/server/static/components/help-button.d.ts +0 -3
  37. package/dist/server/static/components/network-spinner.d.ts +0 -1
  38. package/dist/server/static/components/payload-panel.d.ts +0 -1
  39. package/dist/server/static/components/response-panel.d.ts +0 -1
  40. package/dist/server/static/components/rule-panel.d.ts +0 -1
  41. package/dist/server/static/components/run-panel.d.ts +0 -1
  42. package/dist/server/static/components/select-dropdown.d.ts +0 -1
  43. package/dist/server/static/components/toggle-switch.d.ts +0 -11
  44. package/dist/server/static/hot-reload.d.ts +0 -1
  45. package/dist/server/static/vendor/vendor.bundle.d.ts +0 -2008
  46. package/dist/utils/child-process-wrapper.d.ts +0 -1
package/README.md CHANGED
@@ -20,7 +20,7 @@ $ npm install -g @sanity/runtime-cli
20
20
  $ sanity-run COMMAND
21
21
  running command...
22
22
  $ sanity-run (--version)
23
- @sanity/runtime-cli/10.10.0 linux-x64 node-v22.20.0
23
+ @sanity/runtime-cli/10.11.1 linux-x64 node-v22.20.0
24
24
  $ sanity-run --help [COMMAND]
25
25
  USAGE
26
26
  $ sanity-run COMMAND
@@ -33,6 +33,7 @@ USAGE
33
33
  * [`sanity-run blueprints config`](#sanity-run-blueprints-config)
34
34
  * [`sanity-run blueprints deploy`](#sanity-run-blueprints-deploy)
35
35
  * [`sanity-run blueprints destroy`](#sanity-run-blueprints-destroy)
36
+ * [`sanity-run blueprints doctor`](#sanity-run-blueprints-doctor)
36
37
  * [`sanity-run blueprints info`](#sanity-run-blueprints-info)
37
38
  * [`sanity-run blueprints init [DIR]`](#sanity-run-blueprints-init-dir)
38
39
  * [`sanity-run blueprints logs`](#sanity-run-blueprints-logs)
@@ -88,7 +89,7 @@ EXAMPLES
88
89
  $ sanity-run blueprints add function --name my-function --fn-type document-create --fn-type document-update --lang js
89
90
  ```
90
91
 
91
- _See code: [src/commands/blueprints/add.ts](https://github.com/sanity-io/runtime-cli/blob/v10.10.0/src/commands/blueprints/add.ts)_
92
+ _See code: [src/commands/blueprints/add.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.1/src/commands/blueprints/add.ts)_
92
93
 
93
94
  ## `sanity-run blueprints config`
94
95
 
@@ -119,7 +120,7 @@ EXAMPLES
119
120
  $ sanity-run blueprints config --edit --project-id <projectId> --stack-id <stackId>
120
121
  ```
121
122
 
122
- _See code: [src/commands/blueprints/config.ts](https://github.com/sanity-io/runtime-cli/blob/v10.10.0/src/commands/blueprints/config.ts)_
123
+ _See code: [src/commands/blueprints/config.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.1/src/commands/blueprints/config.ts)_
123
124
 
124
125
  ## `sanity-run blueprints deploy`
125
126
 
@@ -141,7 +142,7 @@ EXAMPLES
141
142
  $ sanity-run blueprints deploy --no-wait
142
143
  ```
143
144
 
144
- _See code: [src/commands/blueprints/deploy.ts](https://github.com/sanity-io/runtime-cli/blob/v10.10.0/src/commands/blueprints/deploy.ts)_
145
+ _See code: [src/commands/blueprints/deploy.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.1/src/commands/blueprints/deploy.ts)_
145
146
 
146
147
  ## `sanity-run blueprints destroy`
147
148
 
@@ -166,7 +167,25 @@ EXAMPLES
166
167
  $ sanity-run blueprints destroy --stack-id <stackId> --project-id <projectId> --force --no-wait
167
168
  ```
168
169
 
169
- _See code: [src/commands/blueprints/destroy.ts](https://github.com/sanity-io/runtime-cli/blob/v10.10.0/src/commands/blueprints/destroy.ts)_
170
+ _See code: [src/commands/blueprints/destroy.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.1/src/commands/blueprints/destroy.ts)_
171
+
172
+ ## `sanity-run blueprints doctor`
173
+
174
+ Diagnose potential issues with Blueprint configuration
175
+
176
+ ```
177
+ USAGE
178
+ $ sanity-run blueprints doctor [--verbose] [--path <value>]
179
+
180
+ FLAGS
181
+ --path=<value> Path to the Blueprint configuration file
182
+ --verbose Provide detailed information about issues
183
+
184
+ DESCRIPTION
185
+ Diagnose potential issues with Blueprint configuration
186
+ ```
187
+
188
+ _See code: [src/commands/blueprints/doctor.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.1/src/commands/blueprints/doctor.ts)_
170
189
 
171
190
  ## `sanity-run blueprints info`
172
191
 
@@ -188,7 +207,7 @@ EXAMPLES
188
207
  $ sanity-run blueprints info --stack-id <stackId>
189
208
  ```
190
209
 
191
- _See code: [src/commands/blueprints/info.ts](https://github.com/sanity-io/runtime-cli/blob/v10.10.0/src/commands/blueprints/info.ts)_
210
+ _See code: [src/commands/blueprints/info.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.1/src/commands/blueprints/info.ts)_
192
211
 
193
212
  ## `sanity-run blueprints init [DIR]`
194
213
 
@@ -226,7 +245,7 @@ EXAMPLES
226
245
  $ sanity-run blueprints init --blueprint-type <json|js|ts> --stack-name <stackName>
227
246
  ```
228
247
 
229
- _See code: [src/commands/blueprints/init.ts](https://github.com/sanity-io/runtime-cli/blob/v10.10.0/src/commands/blueprints/init.ts)_
248
+ _See code: [src/commands/blueprints/init.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.1/src/commands/blueprints/init.ts)_
230
249
 
231
250
  ## `sanity-run blueprints logs`
232
251
 
@@ -248,7 +267,7 @@ EXAMPLES
248
267
  $ sanity-run blueprints logs --watch
249
268
  ```
250
269
 
251
- _See code: [src/commands/blueprints/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v10.10.0/src/commands/blueprints/logs.ts)_
270
+ _See code: [src/commands/blueprints/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.1/src/commands/blueprints/logs.ts)_
252
271
 
253
272
  ## `sanity-run blueprints plan`
254
273
 
@@ -265,7 +284,7 @@ EXAMPLES
265
284
  $ sanity-run blueprints plan
266
285
  ```
267
286
 
268
- _See code: [src/commands/blueprints/plan.ts](https://github.com/sanity-io/runtime-cli/blob/v10.10.0/src/commands/blueprints/plan.ts)_
287
+ _See code: [src/commands/blueprints/plan.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.1/src/commands/blueprints/plan.ts)_
269
288
 
270
289
  ## `sanity-run blueprints stacks`
271
290
 
@@ -287,7 +306,7 @@ EXAMPLES
287
306
  $ sanity-run blueprints stacks --project-id <projectId>
288
307
  ```
289
308
 
290
- _See code: [src/commands/blueprints/stacks.ts](https://github.com/sanity-io/runtime-cli/blob/v10.10.0/src/commands/blueprints/stacks.ts)_
309
+ _See code: [src/commands/blueprints/stacks.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.1/src/commands/blueprints/stacks.ts)_
291
310
 
292
311
  ## `sanity-run functions dev`
293
312
 
@@ -309,7 +328,7 @@ EXAMPLES
309
328
  $ sanity-run functions dev --port 8974
310
329
  ```
311
330
 
312
- _See code: [src/commands/functions/dev.ts](https://github.com/sanity-io/runtime-cli/blob/v10.10.0/src/commands/functions/dev.ts)_
331
+ _See code: [src/commands/functions/dev.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.1/src/commands/functions/dev.ts)_
313
332
 
314
333
  ## `sanity-run functions env add NAME KEY VALUE`
315
334
 
@@ -331,7 +350,7 @@ EXAMPLES
331
350
  $ sanity-run functions env add MyFunction API_URL https://api.example.com/
332
351
  ```
333
352
 
334
- _See code: [src/commands/functions/env/add.ts](https://github.com/sanity-io/runtime-cli/blob/v10.10.0/src/commands/functions/env/add.ts)_
353
+ _See code: [src/commands/functions/env/add.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.1/src/commands/functions/env/add.ts)_
335
354
 
336
355
  ## `sanity-run functions env list NAME`
337
356
 
@@ -351,7 +370,7 @@ EXAMPLES
351
370
  $ sanity-run functions env list MyFunction
352
371
  ```
353
372
 
354
- _See code: [src/commands/functions/env/list.ts](https://github.com/sanity-io/runtime-cli/blob/v10.10.0/src/commands/functions/env/list.ts)_
373
+ _See code: [src/commands/functions/env/list.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.1/src/commands/functions/env/list.ts)_
355
374
 
356
375
  ## `sanity-run functions env remove NAME KEY`
357
376
 
@@ -372,7 +391,7 @@ EXAMPLES
372
391
  $ sanity-run functions env remove MyFunction API_URL
373
392
  ```
374
393
 
375
- _See code: [src/commands/functions/env/remove.ts](https://github.com/sanity-io/runtime-cli/blob/v10.10.0/src/commands/functions/env/remove.ts)_
394
+ _See code: [src/commands/functions/env/remove.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.1/src/commands/functions/env/remove.ts)_
376
395
 
377
396
  ## `sanity-run functions logs NAME`
378
397
 
@@ -406,7 +425,7 @@ EXAMPLES
406
425
  $ sanity-run functions logs <name> --delete
407
426
  ```
408
427
 
409
- _See code: [src/commands/functions/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v10.10.0/src/commands/functions/logs.ts)_
428
+ _See code: [src/commands/functions/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.1/src/commands/functions/logs.ts)_
410
429
 
411
430
  ## `sanity-run functions test NAME`
412
431
 
@@ -453,7 +472,7 @@ EXAMPLES
453
472
  $ sanity-run functions test <name> --event update --data-before '{ "title": "before" }' --data-after '{ "title": "after" }'
454
473
  ```
455
474
 
456
- _See code: [src/commands/functions/test.ts](https://github.com/sanity-io/runtime-cli/blob/v10.10.0/src/commands/functions/test.ts)_
475
+ _See code: [src/commands/functions/test.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.1/src/commands/functions/test.ts)_
457
476
 
458
477
  ## `sanity-run help [COMMAND]`
459
478
 
@@ -4,7 +4,7 @@ export interface BlueprintsConfig {
4
4
  projectId?: string;
5
5
  stackId?: string;
6
6
  }
7
- export declare function readConfigFile(blueprintFilePath: string): BlueprintsConfig | null;
7
+ export declare function readConfigFile(blueprintFilePath?: string): BlueprintsConfig | null;
8
8
  export declare function writeConfigFile({ blueprintFilePath, organizationId, projectId, stackId, }: {
9
9
  blueprintFilePath?: string;
10
10
  stackId?: string;
@@ -3,7 +3,7 @@ import { dirname, join } from 'node:path';
3
3
  import { cwd } from 'node:process';
4
4
  import { BLUEPRINT_CONFIG_FILE, BLUEPRINT_CONFIG_VERSION, BLUEPRINT_DIR } from '../../config.js';
5
5
  export function readConfigFile(blueprintFilePath) {
6
- const blueprintDir = dirname(blueprintFilePath);
6
+ const blueprintDir = blueprintFilePath ? dirname(blueprintFilePath) : cwd();
7
7
  const configPath = join(blueprintDir, BLUEPRINT_DIR, BLUEPRINT_CONFIG_FILE);
8
8
  if (existsSync(configPath)) {
9
9
  try {
@@ -14,16 +14,7 @@ export function readConfigFile(blueprintFilePath) {
14
14
  return null;
15
15
  }
16
16
  }
17
- const configFilePath = join(cwd(), BLUEPRINT_DIR, BLUEPRINT_CONFIG_FILE);
18
- if (!existsSync(configFilePath))
19
- return null;
20
- try {
21
- const config = JSON.parse(readFileSync(configFilePath, 'utf8'));
22
- return config || null;
23
- }
24
- catch {
25
- return null;
26
- }
17
+ return null;
27
18
  }
28
19
  export function writeConfigFile({ blueprintFilePath, organizationId, projectId, stackId, }) {
29
20
  const blueprintDir = blueprintFilePath ? dirname(blueprintFilePath) : cwd();
@@ -33,11 +33,20 @@ export async function getBlueprintAndStack({ token, blueprintPath, }) {
33
33
  issues.push({ code: 'NO_STACK_ID', message: 'Stack ID not found' });
34
34
  return { localBlueprint, issues };
35
35
  }
36
- const auth = { token, projectId };
37
- const { error, ok, stack: deployedStack } = await getStack({ stackId, auth });
38
- if (!ok) {
39
- issues.push({ code: 'NO_STACK', message: error || 'Unknown error' });
36
+ const stackResponse = await getStack({
37
+ stackId,
38
+ auth: {
39
+ scopeType: 'project',
40
+ scopeId: projectId,
41
+ token,
42
+ },
43
+ });
44
+ if (!stackResponse.ok) {
45
+ issues.push({ code: 'NO_STACK', message: stackResponse.error || 'Unknown error' });
40
46
  return { localBlueprint, issues };
41
47
  }
42
- return { localBlueprint: localBlueprint, deployedStack };
48
+ return {
49
+ localBlueprint: localBlueprint,
50
+ deployedStack: stackResponse.stack,
51
+ };
43
52
  }
@@ -1,4 +1,4 @@
1
- import type { AuthParams, Stack, StackMutation } from '../../utils/types.js';
1
+ import type { AuthParams, ScopeType, Stack, StackMutation } from '../../utils/types.js';
2
2
  export declare const stacksUrl: string;
3
3
  interface ListStacksResponse {
4
4
  ok: boolean;
@@ -10,6 +10,7 @@ interface GetStackResponse {
10
10
  ok: boolean;
11
11
  error: string | null;
12
12
  stack: Stack;
13
+ response?: Response;
13
14
  }
14
15
  export declare function getStack({ stackId, auth, }: {
15
16
  stackId: string;
@@ -24,9 +25,10 @@ export declare function createStack({ stackMutation, auth, }: {
24
25
  stackMutation: StackMutation;
25
26
  auth: AuthParams;
26
27
  }): Promise<CreateStackResponse>;
27
- export declare function createEmptyStack({ token, projectId, name, projectBased, }: {
28
+ export declare function createEmptyStack({ token, scopeType, scopeId, name, projectBased, }: {
28
29
  token: string;
29
- projectId: string;
30
+ scopeType: ScopeType;
31
+ scopeId: string;
30
32
  name: string;
31
33
  projectBased?: boolean;
32
34
  }): Promise<Stack>;
@@ -2,6 +2,7 @@ import config from '../../config.js';
2
2
  import getHeaders from '../../utils/get-headers.js';
3
3
  const { apiUrl } = config;
4
4
  export const stacksUrl = `${apiUrl}vX/blueprints/stacks`;
5
+ /** Discriminate between Resource and Resource with parameters */
5
6
  function hasParameters(obj) {
6
7
  return (typeof obj === 'object' &&
7
8
  obj !== null &&
@@ -9,6 +10,7 @@ function hasParameters(obj) {
9
10
  typeof obj.parameters === 'object' &&
10
11
  obj.parameters !== null);
11
12
  }
13
+ /** Flatten Resource with parameters */
12
14
  function flattenResource(resource) {
13
15
  if (hasParameters(resource)) {
14
16
  const { parameters, ...rest } = resource;
@@ -16,6 +18,7 @@ function flattenResource(resource) {
16
18
  }
17
19
  return resource;
18
20
  }
21
+ /** Flatten a Stack's resources */
19
22
  function flattenStackResources(stack) {
20
23
  if (stack && Array.isArray(stack.resources)) {
21
24
  return {
@@ -47,6 +50,7 @@ export async function getStack({ stackId, auth, }) {
47
50
  ok: response.ok,
48
51
  error: response.ok ? null : data.message,
49
52
  stack: response.ok ? flattenStackResources(data) : data,
53
+ response,
50
54
  };
51
55
  }
52
56
  export async function createStack({ stackMutation, auth, }) {
@@ -62,15 +66,18 @@ export async function createStack({ stackMutation, auth, }) {
62
66
  stack: response.ok ? flattenStackResources(data) : data,
63
67
  };
64
68
  }
65
- export async function createEmptyStack({ token, projectId, name, projectBased = true, }) {
69
+ export async function createEmptyStack({ token, scopeType, scopeId, name, projectBased = true, }) {
66
70
  const stackMutation = {
67
71
  name,
68
- projectId,
72
+ scopeType,
73
+ scopeId,
69
74
  useProjectBasedId: projectBased,
70
75
  document: { resources: [] },
71
76
  };
72
- const auth = { token, projectId };
73
- const response = await createStack({ stackMutation, auth });
77
+ const response = await createStack({
78
+ stackMutation,
79
+ auth: { token, scopeType, scopeId },
80
+ });
74
81
  if (!response.ok) {
75
82
  throw new Error(response.error || 'Failed to create new Stack');
76
83
  }
@@ -1,3 +1,4 @@
1
+ import type { ScopeType } from '../../utils/types.js';
1
2
  export declare const projectsApiPath: string;
2
3
  export declare const orgsApiPath: string;
3
4
  export interface Project {
@@ -40,8 +41,9 @@ interface GetProjectResponse {
40
41
  error: string | null;
41
42
  project: Project;
42
43
  }
43
- export declare function getProject({ token, projectId, }: {
44
+ export declare function getProject({ token, scopeId, scopeType, }: {
44
45
  token: string;
45
- projectId: string;
46
+ scopeId: string;
47
+ scopeType: ScopeType;
46
48
  }): Promise<GetProjectResponse>;
47
49
  export {};
@@ -48,8 +48,11 @@ export async function groupProjectsByOrganization({ token, }) {
48
48
  organizations: orgsWithProjects,
49
49
  };
50
50
  }
51
- export async function getProject({ token, projectId, }) {
52
- const response = await fetch(`${projectsApiPath}/${projectId}`, {
51
+ export async function getProject({ token, scopeId, scopeType, }) {
52
+ if (scopeType !== 'project') {
53
+ throw new Error('Scope type must be project');
54
+ }
55
+ const response = await fetch(`${projectsApiPath}/${scopeId}`, {
53
56
  method: 'GET',
54
57
  headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
55
58
  });
@@ -0,0 +1,10 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class DoctorCommand extends Command {
3
+ static description: string;
4
+ static examples: never[];
5
+ static flags: {
6
+ verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
7
+ path: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
8
+ };
9
+ run(): Promise<void>;
10
+ }
@@ -0,0 +1,28 @@
1
+ import { Command, Flags } from '@oclif/core';
2
+ import config from '../../config.js';
3
+ import { blueprintDoctorCore } from '../../cores/blueprints/doctor.js';
4
+ export default class DoctorCommand extends Command {
5
+ static description = 'Diagnose potential issues with Blueprint configuration';
6
+ static examples = [];
7
+ static flags = {
8
+ verbose: Flags.boolean({
9
+ description: 'Provide detailed information about issues',
10
+ default: false,
11
+ }),
12
+ path: Flags.string({
13
+ description: 'Path to the Blueprint configuration file',
14
+ }),
15
+ };
16
+ async run() {
17
+ const { flags } = await this.parse(DoctorCommand);
18
+ const { token } = config;
19
+ const { success, error } = await blueprintDoctorCore({
20
+ bin: this.config.bin,
21
+ log: (message) => this.log(message),
22
+ token,
23
+ flags,
24
+ });
25
+ if (!success)
26
+ this.error(error);
27
+ }
28
+ }
@@ -140,7 +140,7 @@ async function testConfigAndReport({ token, stackId, projectId, }) {
140
140
  const spinner = ora('Testing the configuration...').start();
141
141
  const { ok, error } = await getStack({
142
142
  stackId,
143
- auth: { token, projectId },
143
+ auth: { token, scopeType: 'project', scopeId: projectId },
144
144
  });
145
145
  if (!ok) {
146
146
  spinner.fail('Configuration test failed.');
@@ -151,7 +151,7 @@ async function testConfigAndReport({ token, stackId, projectId, }) {
151
151
  return { ok, error };
152
152
  }
153
153
  async function startReinitializeStack({ token, projectId, }) {
154
- const auth = { token, projectId };
154
+ const auth = { token, scopeType: 'project', scopeId: projectId };
155
155
  // stack id IS ST-${projectId} – it has already been checked and doesn't exist
156
156
  const { confirm } = await inquirer.prompt([
157
157
  {
@@ -170,8 +170,15 @@ async function startReinitializeStack({ token, projectId, }) {
170
170
  };
171
171
  }
172
172
  const projectDisplayName = project.displayName;
173
- const stackMutation = { name: projectDisplayName, projectId, document: { resources: [] } };
174
- const response = await createStack({ stackMutation, auth });
173
+ const response = await createStack({
174
+ stackMutation: {
175
+ name: projectDisplayName,
176
+ scopeType: 'project',
177
+ scopeId: projectId,
178
+ document: { resources: [] },
179
+ },
180
+ auth,
181
+ });
175
182
  if (!response.ok)
176
183
  return { ok: false, error: response.error || 'Failed to create new Stack' };
177
184
  return {
@@ -46,14 +46,18 @@ export async function blueprintDeployCore(options) {
46
46
  }
47
47
  }
48
48
  }
49
- const stackMutation = {
50
- projectId,
51
- name: deployedStack.name,
52
- document: { resources: validResources },
53
- };
54
49
  const spinner = ora('Deploying...').start();
55
50
  const isoNow = new Date().toISOString();
56
- const { ok: deployOk, stack, error: deployError, } = await updateStack({ stackId, stackMutation, auth });
51
+ const { ok: deployOk, stack, error: deployError, } = await updateStack({
52
+ stackId,
53
+ stackMutation: {
54
+ scopeType: 'project',
55
+ scopeId: projectId,
56
+ name: deployedStack.name,
57
+ document: { resources: validResources },
58
+ },
59
+ auth,
60
+ });
57
61
  if (!deployOk) {
58
62
  spinner.fail(`${chalk.red('Failed')} to update deployment`);
59
63
  return { success: false, error: deployError || 'Failed to update deployment' };
@@ -12,7 +12,7 @@ export async function blueprintDestroyCore(options) {
12
12
  if (flagProjectId && flagStackId && force) {
13
13
  const { ok, error, stack } = await destroyStack({
14
14
  stackId: flagStackId,
15
- auth: { token, projectId: flagProjectId },
15
+ auth: { token, scopeType: 'project', scopeId: flagProjectId },
16
16
  });
17
17
  if (!ok)
18
18
  return { success: false, error: error || 'Failed to destroy deployment' };
@@ -22,7 +22,7 @@ export async function blueprintDestroyCore(options) {
22
22
  const { projectId, stackId } = blueprint;
23
23
  if (!projectId)
24
24
  return { success: false, error: 'Project ID is required' };
25
- const auth = { token, projectId };
25
+ const auth = { token, scopeType: 'project', scopeId: projectId };
26
26
  let stack;
27
27
  try {
28
28
  if (flagStackId) {
@@ -0,0 +1,9 @@
1
+ import type { CoreConfig, CoreResult } from '../index.js';
2
+ export interface BlueprintDoctorOptions extends CoreConfig {
3
+ token: string | null;
4
+ flags: {
5
+ verbose: boolean;
6
+ path: string | undefined;
7
+ };
8
+ }
9
+ export declare function blueprintDoctorCore(options: BlueprintDoctorOptions): Promise<CoreResult>;
@@ -0,0 +1,188 @@
1
+ import { cwd } from 'node:process';
2
+ import chalk from 'chalk';
3
+ import ora from 'ora';
4
+ import { findBlueprintFile, readLocalBlueprint, } from '../../actions/blueprints/blueprint.js';
5
+ import { getStack } from '../../actions/blueprints/stacks.js';
6
+ import config from '../../config.js';
7
+ import { check, indent, niceId, severe, warn } from '../../utils/display/presenters.js';
8
+ import { validTokenOrErrorMessage } from '../../utils/validated-token.js';
9
+ const diagLookup = {
10
+ online: 'Online',
11
+ tokenPresent: 'Auth token present',
12
+ tokenValid: 'Auth token valid',
13
+ configFilePresent: 'Blueprints config file present',
14
+ configFileValid: 'Blueprints config file valid',
15
+ blueprintPresent: 'Blueprint file present',
16
+ blueprintValid: 'Blueprint file valid',
17
+ stackReady: 'Deployment "Stack" ready',
18
+ userHasAccess: 'User has access to "Stack"',
19
+ };
20
+ export async function blueprintDoctorCore(options) {
21
+ const { log, token, flags: { verbose: v, path: p }, } = options;
22
+ const yikes = (s) => {
23
+ log(chalk.bgRedBright.whiteBright.bold(` ${s} `));
24
+ };
25
+ const here = cwd();
26
+ const path = p || here;
27
+ if (v)
28
+ log(`Checking ${path}`);
29
+ // 3 states: null == unknown, true == good, false == bad
30
+ const diagnostics = {};
31
+ for (const key in diagLookup) {
32
+ diagnostics[key] = null;
33
+ }
34
+ let spinner;
35
+ if (!v)
36
+ spinner = ora('Checking environment').start();
37
+ // ONLINE
38
+ try {
39
+ const res = await fetch(config.apiUrl);
40
+ if (res.ok) {
41
+ if (v)
42
+ log(`Successfully pinged ${config.apiUrl}`);
43
+ diagnostics.online = res.ok;
44
+ }
45
+ else {
46
+ if (v)
47
+ yikes(`Failed to ping ${config.apiUrl}: ${res.status} ${res.statusText}`);
48
+ diagnostics.online = false;
49
+ }
50
+ }
51
+ catch {
52
+ if (v)
53
+ yikes(`Failed to ping ${config.apiUrl}`);
54
+ }
55
+ // TOKEN
56
+ if (token) {
57
+ diagnostics.tokenPresent = true;
58
+ const tokenOrError = await validTokenOrErrorMessage(token);
59
+ if (tokenOrError.ok) {
60
+ diagnostics.tokenValid = true;
61
+ }
62
+ else {
63
+ if (v)
64
+ yikes(`Token error: ${tokenOrError.error}`);
65
+ diagnostics.tokenValid = false;
66
+ }
67
+ }
68
+ else {
69
+ diagnostics.tokenPresent = false;
70
+ }
71
+ // BLUEPRINT file
72
+ const blueprintFile = findBlueprintFile(path);
73
+ if (blueprintFile?.blueprintFilePath) {
74
+ if (v)
75
+ log(`Found blueprint file at ${blueprintFile.blueprintFilePath.replace(here, '.')}`);
76
+ diagnostics.blueprintPresent = true;
77
+ }
78
+ else {
79
+ diagnostics.blueprintPresent = false;
80
+ }
81
+ let blueprint;
82
+ try {
83
+ blueprint = await readLocalBlueprint(path);
84
+ if (blueprint.errors.length === 0) {
85
+ if (v)
86
+ log(`Blueprint has no errors`);
87
+ diagnostics.blueprintValid = true;
88
+ }
89
+ else {
90
+ if (v)
91
+ log(`Blueprint errors: \n${blueprint.errors.join('\n ')}`);
92
+ diagnostics.blueprintValid = false;
93
+ }
94
+ }
95
+ catch {
96
+ if (v)
97
+ yikes(`Unable to read blueprint`);
98
+ diagnostics.blueprintValid = false;
99
+ }
100
+ if (blueprint) {
101
+ const { configPath, scopeType, scopeId, stackId, projectId } = blueprint;
102
+ // CONFIG file
103
+ if (configPath) {
104
+ if (v)
105
+ log(`Found config file at ${configPath.replace(here, '.')}`);
106
+ diagnostics.configFilePresent = true;
107
+ if (scopeType && scopeId && stackId) {
108
+ diagnostics.configFileValid = true;
109
+ if (v) {
110
+ const capitalizedScopeType = scopeType.charAt(0).toUpperCase() + scopeType.slice(1);
111
+ const configOutput = [
112
+ `${capitalizedScopeType}: ${niceId(scopeId)}`,
113
+ `Deployment: ${niceId(stackId)}`,
114
+ ].join('\n');
115
+ log(indent(configOutput));
116
+ }
117
+ }
118
+ else {
119
+ diagnostics.configFileValid = false;
120
+ }
121
+ }
122
+ else {
123
+ diagnostics.configFilePresent = false;
124
+ }
125
+ // STACK + ACCESS
126
+ if (diagnostics.online && diagnostics.tokenValid && token && stackId && projectId) {
127
+ const stackResponse = await getStack({
128
+ auth: { token, scopeType: 'project', scopeId: projectId },
129
+ stackId,
130
+ });
131
+ if (stackResponse.ok) {
132
+ if (v)
133
+ log(`Deployment "Stack" ${niceId(stackId)} ready`);
134
+ diagnostics.stackReady = true;
135
+ diagnostics.userHasAccess = true;
136
+ }
137
+ else if (stackResponse.response?.status === 404) {
138
+ if (v)
139
+ yikes(`Deployment "Stack" <${stackId}> not found`);
140
+ diagnostics.stackReady = false;
141
+ }
142
+ else if (stackResponse.response?.status === 403 || stackResponse.response?.status === 401) {
143
+ if (v)
144
+ yikes(`User does not have access to "Stack" <${stackId}>`);
145
+ diagnostics.userHasAccess = false;
146
+ }
147
+ else {
148
+ if (v)
149
+ yikes(`Unknown error with "Stack" <${stackId}>: ${stackResponse.error}`);
150
+ }
151
+ }
152
+ else {
153
+ if (v)
154
+ yikes('Unable to check deployment "Stack" status.');
155
+ }
156
+ }
157
+ if (spinner)
158
+ spinner.stop();
159
+ if (v)
160
+ log('');
161
+ let allGood = true;
162
+ for (const [key, value] of Object.entries(diagnostics)) {
163
+ switch (value) {
164
+ case true:
165
+ if (v)
166
+ log(check(diagLookup[key]));
167
+ break;
168
+ case false:
169
+ allGood = false;
170
+ log(severe(diagLookup[key]));
171
+ break;
172
+ case null:
173
+ allGood = false;
174
+ log(warn(diagLookup[key]));
175
+ break;
176
+ default:
177
+ allGood = false;
178
+ log(severe(`${key} is ${value}`));
179
+ }
180
+ }
181
+ if (allGood) {
182
+ log(chalk.bold.green('All checks passed'));
183
+ return { success: true, data: { diagnostics } };
184
+ }
185
+ else {
186
+ return { success: false, error: 'One or more checks failed', data: { diagnostics } };
187
+ }
188
+ }