@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.
- package/README.md +35 -16
- package/dist/actions/blueprints/config.d.ts +1 -1
- package/dist/actions/blueprints/config.js +2 -11
- package/dist/actions/blueprints/index.js +14 -5
- package/dist/actions/blueprints/stacks.d.ts +5 -3
- package/dist/actions/blueprints/stacks.js +11 -4
- package/dist/actions/sanity/projects.d.ts +4 -2
- package/dist/actions/sanity/projects.js +5 -2
- package/dist/commands/blueprints/doctor.d.ts +10 -0
- package/dist/commands/blueprints/doctor.js +28 -0
- package/dist/cores/blueprints/config.js +11 -4
- package/dist/cores/blueprints/deploy.js +10 -6
- package/dist/cores/blueprints/destroy.js +2 -2
- package/dist/cores/blueprints/doctor.d.ts +9 -0
- package/dist/cores/blueprints/doctor.js +188 -0
- package/dist/cores/blueprints/init.js +17 -8
- package/dist/cores/blueprints/plan.js +4 -1
- package/dist/cores/blueprints/stacks.js +1 -1
- package/dist/cores/index.d.ts +4 -1
- package/dist/cores/index.js +1 -1
- package/dist/utils/display/prompt.js +3 -2
- package/dist/utils/get-headers.d.ts +2 -2
- package/dist/utils/get-headers.js +5 -13
- package/dist/utils/types.d.ts +6 -3
- package/dist/utils/validate/resource.js +3 -3
- package/oclif.manifest.json +37 -1
- package/package.json +2 -1
- package/dist/server/static/api.d.ts +0 -24
- package/dist/server/static/components/api-base.d.ts +0 -20
- package/dist/server/static/components/clear-button.d.ts +0 -6
- package/dist/server/static/components/codemirror-theme.d.ts +0 -6
- package/dist/server/static/components/console-panel.d.ts +0 -1
- package/dist/server/static/components/fetch-button.d.ts +0 -7
- package/dist/server/static/components/filters.d.ts +0 -1
- package/dist/server/static/components/function-list.d.ts +0 -1
- package/dist/server/static/components/help-button.d.ts +0 -3
- package/dist/server/static/components/network-spinner.d.ts +0 -1
- package/dist/server/static/components/payload-panel.d.ts +0 -1
- package/dist/server/static/components/response-panel.d.ts +0 -1
- package/dist/server/static/components/rule-panel.d.ts +0 -1
- package/dist/server/static/components/run-panel.d.ts +0 -1
- package/dist/server/static/components/select-dropdown.d.ts +0 -1
- package/dist/server/static/components/toggle-switch.d.ts +0 -11
- package/dist/server/static/hot-reload.d.ts +0 -1
- package/dist/server/static/vendor/vendor.bundle.d.ts +0 -2008
- 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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
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
|
-
|
|
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
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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 {
|
|
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,
|
|
28
|
+
export declare function createEmptyStack({ token, scopeType, scopeId, name, projectBased, }: {
|
|
28
29
|
token: string;
|
|
29
|
-
|
|
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,
|
|
69
|
+
export async function createEmptyStack({ token, scopeType, scopeId, name, projectBased = true, }) {
|
|
66
70
|
const stackMutation = {
|
|
67
71
|
name,
|
|
68
|
-
|
|
72
|
+
scopeType,
|
|
73
|
+
scopeId,
|
|
69
74
|
useProjectBasedId: projectBased,
|
|
70
75
|
document: { resources: [] },
|
|
71
76
|
};
|
|
72
|
-
const
|
|
73
|
-
|
|
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,
|
|
44
|
+
export declare function getProject({ token, scopeId, scopeType, }: {
|
|
44
45
|
token: string;
|
|
45
|
-
|
|
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,
|
|
52
|
-
|
|
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
|
|
174
|
-
|
|
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({
|
|
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,
|
|
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
|
+
}
|