@sanity/runtime-cli 14.8.6 → 14.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -30
- package/dist/baseCommands.d.ts +21 -8
- package/dist/baseCommands.js +54 -15
- package/dist/commands/blueprints/add.js +3 -3
- package/dist/commands/blueprints/config.js +4 -4
- package/dist/commands/blueprints/deploy.js +5 -5
- package/dist/commands/blueprints/destroy.js +5 -5
- package/dist/commands/blueprints/doctor.d.ts +1 -1
- package/dist/commands/blueprints/doctor.js +7 -5
- package/dist/commands/blueprints/info.js +5 -5
- package/dist/commands/blueprints/init.js +4 -4
- package/dist/commands/blueprints/logs.js +6 -6
- package/dist/commands/blueprints/plan.js +5 -5
- package/dist/commands/blueprints/promote.js +8 -6
- package/dist/commands/blueprints/stacks.js +5 -5
- package/dist/commands/functions/add.js +3 -3
- package/dist/commands/functions/build.js +4 -4
- package/dist/commands/functions/dev.js +5 -5
- package/dist/commands/functions/env/add.js +4 -4
- package/dist/commands/functions/env/list.js +4 -4
- package/dist/commands/functions/env/remove.js +4 -4
- package/dist/commands/functions/logs.js +4 -4
- package/dist/commands/functions/test.js +4 -4
- package/dist/constants.d.ts +1 -0
- package/dist/constants.js +1 -0
- package/dist/cores/blueprints/config.js +0 -1
- package/dist/cores/blueprints/deploy.js +29 -4
- package/dist/cores/blueprints/destroy.js +18 -3
- package/dist/cores/blueprints/doctor.js +9 -2
- package/dist/cores/blueprints/plan.js +18 -10
- package/dist/cores/blueprints/promote.js +11 -3
- package/dist/cores/blueprints/stacks.js +14 -3
- package/dist/cores/functions/test.js +7 -1
- package/dist/cores/index.d.ts +6 -0
- package/dist/cores/index.js +0 -3
- package/dist/utils/display/blueprints-formatting.js +2 -1
- package/dist/utils/display/resources-formatting.js +8 -3
- package/dist/utils/invoke-local.js +1 -1
- package/dist/utils/types.d.ts +2 -2
- package/oclif.manifest.json +13 -10
- package/package.json +1 -1
|
@@ -2,7 +2,7 @@ import { LocalBlueprintCommand, stackFlag, unhide } from '../../baseCommands.js'
|
|
|
2
2
|
import { blueprintPlanCore } from '../../cores/blueprints/plan.js';
|
|
3
3
|
import { Logger } from '../../utils/logger.js';
|
|
4
4
|
export default class PlanCommand extends LocalBlueprintCommand {
|
|
5
|
-
static summary = '
|
|
5
|
+
static summary = 'Preview changes that will be applied to the remote Stack';
|
|
6
6
|
static description = `Use this command to preview what changes will be applied to your remote Stack before deploying. This is a safe, read-only operation—no resources are created, modified, or deleted.
|
|
7
7
|
|
|
8
8
|
Run 'blueprints plan' after making local changes to your Blueprint manifest to verify the expected diff. When ready, run 'blueprints deploy' to apply changes.`;
|
|
@@ -11,7 +11,7 @@ Run 'blueprints plan' after making local changes to your Blueprint manifest to v
|
|
|
11
11
|
stack: unhide(stackFlag),
|
|
12
12
|
};
|
|
13
13
|
async run() {
|
|
14
|
-
const
|
|
14
|
+
const result = await blueprintPlanCore({
|
|
15
15
|
bin: this.config.bin,
|
|
16
16
|
log: Logger(this.log.bind(this), this.flags),
|
|
17
17
|
token: this.sanityToken,
|
|
@@ -19,8 +19,8 @@ Run 'blueprints plan' after making local changes to your Blueprint manifest to v
|
|
|
19
19
|
validateResources: this.flags['validate-resources'],
|
|
20
20
|
flags: this.flags,
|
|
21
21
|
});
|
|
22
|
-
if (!success)
|
|
23
|
-
this.
|
|
24
|
-
return json;
|
|
22
|
+
if (!result.success)
|
|
23
|
+
this.coreError(result);
|
|
24
|
+
return result.json;
|
|
25
25
|
}
|
|
26
26
|
}
|
|
@@ -3,8 +3,10 @@ import { DeployedStackCommand } from '../../baseCommands.js';
|
|
|
3
3
|
import { blueprintPromoteCore } from '../../cores/blueprints/promote.js';
|
|
4
4
|
import { Logger } from '../../utils/logger.js';
|
|
5
5
|
export default class PromoteCommand extends DeployedStackCommand {
|
|
6
|
-
static summary = 'Promote a Stack
|
|
7
|
-
static description = `
|
|
6
|
+
static summary = 'Promote a Stack from project scope to organization scope';
|
|
7
|
+
static description = `Promotes a deployed Stack to organization scope, enabling management of org-level resources. Promotion cannot be reversed.
|
|
8
|
+
|
|
9
|
+
Your local Blueprint configuration will be updated to reflect the new scope.`;
|
|
8
10
|
static hidden = true;
|
|
9
11
|
static examples = [
|
|
10
12
|
'<%= config.bin %> <%= command.id %>',
|
|
@@ -21,7 +23,7 @@ export default class PromoteCommand extends DeployedStackCommand {
|
|
|
21
23
|
}),
|
|
22
24
|
};
|
|
23
25
|
async run() {
|
|
24
|
-
const
|
|
26
|
+
const result = await blueprintPromoteCore({
|
|
25
27
|
bin: this.config.bin,
|
|
26
28
|
log: Logger(this.log.bind(this), this.flags),
|
|
27
29
|
token: this.sanityToken,
|
|
@@ -34,8 +36,8 @@ export default class PromoteCommand extends DeployedStackCommand {
|
|
|
34
36
|
validateResources: this.flags['validate-resources'],
|
|
35
37
|
flags: this.flags,
|
|
36
38
|
});
|
|
37
|
-
if (!success)
|
|
38
|
-
this.
|
|
39
|
-
return json;
|
|
39
|
+
if (!result.success)
|
|
40
|
+
this.coreError(result);
|
|
41
|
+
return result.json;
|
|
40
42
|
}
|
|
41
43
|
}
|
|
@@ -3,7 +3,7 @@ import { LocalBlueprintCommand, organizationIdFlagConfig, projectIdFlagConfig, }
|
|
|
3
3
|
import { blueprintStacksCore } from '../../cores/blueprints/stacks.js';
|
|
4
4
|
import { Logger } from '../../utils/logger.js';
|
|
5
5
|
export default class StacksCommand extends LocalBlueprintCommand {
|
|
6
|
-
static summary =
|
|
6
|
+
static summary = 'List remote Stack deployments for your project or organization';
|
|
7
7
|
static description = `Shows all Stacks associated with a project or organization. By default, lists Stacks scoped to the local Blueprint.
|
|
8
8
|
|
|
9
9
|
Use this to discover existing Stacks you can scope a local Blueprint to (using 'blueprints config --edit'), or to audit what's deployed across your project.`;
|
|
@@ -17,7 +17,7 @@ Use this to discover existing Stacks you can scope a local Blueprint to (using '
|
|
|
17
17
|
'organization-id': Flags.string({ ...organizationIdFlagConfig, exclusive: ['project-id'] }),
|
|
18
18
|
};
|
|
19
19
|
async run() {
|
|
20
|
-
const
|
|
20
|
+
const result = await blueprintStacksCore({
|
|
21
21
|
bin: this.config.bin,
|
|
22
22
|
log: Logger(this.log.bind(this), this.flags),
|
|
23
23
|
token: this.sanityToken,
|
|
@@ -25,8 +25,8 @@ Use this to discover existing Stacks you can scope a local Blueprint to (using '
|
|
|
25
25
|
validateResources: this.flags['validate-resources'],
|
|
26
26
|
flags: this.flags,
|
|
27
27
|
});
|
|
28
|
-
if (!success)
|
|
29
|
-
this.
|
|
30
|
-
return json;
|
|
28
|
+
if (!result.success)
|
|
29
|
+
this.coreError(result);
|
|
30
|
+
return result.json;
|
|
31
31
|
}
|
|
32
32
|
}
|
|
@@ -61,14 +61,14 @@ After adding, use 'functions dev' to test locally, then 'blueprints deploy' to p
|
|
|
61
61
|
}),
|
|
62
62
|
};
|
|
63
63
|
async run() {
|
|
64
|
-
const
|
|
64
|
+
const result = await functionAddCore({
|
|
65
65
|
bin: this.config.bin,
|
|
66
66
|
log: Logger(this.log.bind(this), this.flags),
|
|
67
67
|
blueprint: this.blueprint,
|
|
68
68
|
validateResources: this.flags['validate-resources'],
|
|
69
69
|
flags: this.flags,
|
|
70
70
|
});
|
|
71
|
-
if (!success)
|
|
72
|
-
this.
|
|
71
|
+
if (!result.success)
|
|
72
|
+
this.coreError(result);
|
|
73
73
|
}
|
|
74
74
|
}
|
|
@@ -19,7 +19,7 @@ export default class BuildCommand extends LocalBlueprintCommand {
|
|
|
19
19
|
'out-dir': Flags.string({ char: 'o', description: 'Output directory for zip files' }),
|
|
20
20
|
};
|
|
21
21
|
async run() {
|
|
22
|
-
const
|
|
22
|
+
const result = await functionBuildCore({
|
|
23
23
|
bin: this.config.bin,
|
|
24
24
|
log: Logger(this.log.bind(this), this.flags),
|
|
25
25
|
args: { name: this.args.name },
|
|
@@ -27,8 +27,8 @@ export default class BuildCommand extends LocalBlueprintCommand {
|
|
|
27
27
|
blueprint: this.blueprint,
|
|
28
28
|
validateResources: this.flags['validate-resources'],
|
|
29
29
|
});
|
|
30
|
-
if (!success)
|
|
31
|
-
this.
|
|
32
|
-
return json;
|
|
30
|
+
if (!result.success)
|
|
31
|
+
this.coreError(result);
|
|
32
|
+
return result.json;
|
|
33
33
|
}
|
|
34
34
|
}
|
|
@@ -34,15 +34,15 @@ To invoke a function with the CLI, use 'functions test'.`;
|
|
|
34
34
|
};
|
|
35
35
|
async run() {
|
|
36
36
|
const { flags } = await this.parse(DevCommand);
|
|
37
|
-
const
|
|
37
|
+
const result = await functionDevCore({
|
|
38
38
|
bin: this.config.bin,
|
|
39
39
|
log: Logger(this.log.bind(this), this.flags),
|
|
40
40
|
validateResources: this.flags['validate-resources'],
|
|
41
41
|
flags,
|
|
42
42
|
});
|
|
43
|
-
if (!success)
|
|
44
|
-
this.
|
|
45
|
-
if (streaming)
|
|
46
|
-
await streaming;
|
|
43
|
+
if (!result.success)
|
|
44
|
+
this.coreError(result);
|
|
45
|
+
if (result.streaming)
|
|
46
|
+
await result.streaming;
|
|
47
47
|
}
|
|
48
48
|
}
|
|
@@ -16,7 +16,7 @@ Environment variables are useful for API keys, configuration values, and other s
|
|
|
16
16
|
'<%= config.bin %> <%= command.id %> MyFunction API_URL https://api.example.com/',
|
|
17
17
|
];
|
|
18
18
|
async run() {
|
|
19
|
-
const
|
|
19
|
+
const result = await functionEnvAddCore({
|
|
20
20
|
bin: this.config.bin,
|
|
21
21
|
log: Logger(this.log.bind(this), this.flags),
|
|
22
22
|
args: this.args,
|
|
@@ -29,8 +29,8 @@ Environment variables are useful for API keys, configuration values, and other s
|
|
|
29
29
|
stackId: this.stackId,
|
|
30
30
|
validateResources: this.flags['validate-resources'],
|
|
31
31
|
});
|
|
32
|
-
if (!success)
|
|
33
|
-
this.
|
|
34
|
-
return json;
|
|
32
|
+
if (!result.success)
|
|
33
|
+
this.coreError(result);
|
|
34
|
+
return result.json;
|
|
35
35
|
}
|
|
36
36
|
}
|
|
@@ -12,7 +12,7 @@ Use 'functions env add' to set variables or 'functions env remove' to delete the
|
|
|
12
12
|
};
|
|
13
13
|
static examples = ['<%= config.bin %> <%= command.id %> MyFunction'];
|
|
14
14
|
async run() {
|
|
15
|
-
const
|
|
15
|
+
const result = await functionEnvListCore({
|
|
16
16
|
bin: this.config.bin,
|
|
17
17
|
log: Logger(this.log.bind(this), this.flags),
|
|
18
18
|
args: this.args,
|
|
@@ -25,8 +25,8 @@ Use 'functions env add' to set variables or 'functions env remove' to delete the
|
|
|
25
25
|
stackId: this.stackId,
|
|
26
26
|
validateResources: this.flags['validate-resources'],
|
|
27
27
|
});
|
|
28
|
-
if (!success)
|
|
29
|
-
this.
|
|
30
|
-
return json;
|
|
28
|
+
if (!result.success)
|
|
29
|
+
this.coreError(result);
|
|
30
|
+
return result.json;
|
|
31
31
|
}
|
|
32
32
|
}
|
|
@@ -13,7 +13,7 @@ Use 'functions env list' to see current variables before removing.`;
|
|
|
13
13
|
};
|
|
14
14
|
static examples = ['<%= config.bin %> <%= command.id %> MyFunction API_URL'];
|
|
15
15
|
async run() {
|
|
16
|
-
const
|
|
16
|
+
const result = await functionEnvRemoveCore({
|
|
17
17
|
bin: this.config.bin,
|
|
18
18
|
log: Logger(this.log.bind(this), this.flags),
|
|
19
19
|
args: this.args,
|
|
@@ -26,8 +26,8 @@ Use 'functions env list' to see current variables before removing.`;
|
|
|
26
26
|
stackId: this.stackId,
|
|
27
27
|
validateResources: this.flags['validate-resources'],
|
|
28
28
|
});
|
|
29
|
-
if (!success)
|
|
30
|
-
this.
|
|
31
|
-
return json;
|
|
29
|
+
if (!result.success)
|
|
30
|
+
this.coreError(result);
|
|
31
|
+
return result.json;
|
|
32
32
|
}
|
|
33
33
|
}
|
|
@@ -48,7 +48,7 @@ Use --watch (-w) to stream logs in real-time. Use --delete to clear all logs for
|
|
|
48
48
|
}),
|
|
49
49
|
};
|
|
50
50
|
async run() {
|
|
51
|
-
const
|
|
51
|
+
const result = await functionLogsCore({
|
|
52
52
|
bin: this.config.bin,
|
|
53
53
|
log: Logger(this.log.bind(this), this.flags),
|
|
54
54
|
error: (msg, options) => this.error(msg, options),
|
|
@@ -64,8 +64,8 @@ Use --watch (-w) to stream logs in real-time. Use --delete to clear all logs for
|
|
|
64
64
|
helpText: LogsCommand.getHelpText(this.config.bin, 'functions logs'),
|
|
65
65
|
validateResources: this.flags['validate-resources'],
|
|
66
66
|
});
|
|
67
|
-
if (!success)
|
|
68
|
-
this.
|
|
69
|
-
return json;
|
|
67
|
+
if (!result.success)
|
|
68
|
+
this.coreError(result);
|
|
69
|
+
return result.json;
|
|
70
70
|
}
|
|
71
71
|
}
|
|
@@ -159,7 +159,7 @@ Provide test data via --data (inline JSON), --file (JSON file), or --document-id
|
|
|
159
159
|
' --document-id-before and --document-id-after');
|
|
160
160
|
}
|
|
161
161
|
}
|
|
162
|
-
const
|
|
162
|
+
const result = await functionTestCore({
|
|
163
163
|
bin: this.config.bin,
|
|
164
164
|
log: Logger(this.log.bind(this), this.flags),
|
|
165
165
|
error: (msg, options) => this.error(msg, options),
|
|
@@ -169,8 +169,8 @@ Provide test data via --data (inline JSON), --file (JSON file), or --document-id
|
|
|
169
169
|
helpText: TestCommand.getHelpText(this.config.bin, 'functions test'),
|
|
170
170
|
validateResources: this.flags['validate-resources'],
|
|
171
171
|
});
|
|
172
|
-
if (!success)
|
|
173
|
-
this.
|
|
174
|
-
return json;
|
|
172
|
+
if (!result.success)
|
|
173
|
+
this.coreError(result);
|
|
174
|
+
return result.json;
|
|
175
175
|
}
|
|
176
176
|
}
|
package/dist/constants.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export declare const SANITY_FUNCTION_PREFIX = "sanity.function.";
|
|
|
4
4
|
export declare const SANITY_FUNCTION_DOCUMENT = "sanity.function.document";
|
|
5
5
|
export declare const SANITY_FUNCTION_MEDIA_LIBRARY_ASSET = "sanity.function.media-library.asset";
|
|
6
6
|
export declare const SANITY_FUNCTION_SCHEDULED = "sanity.function.cron";
|
|
7
|
+
export declare const SANITY_FUNCTION_SYNC_TAG_INVALIDATE = "sanity.function.sync-tag-invalidate";
|
|
7
8
|
export declare const SANITY_PROJECT = "sanity.project";
|
|
8
9
|
export declare const SANITY_PROJECT_CORS = "sanity.project.cors";
|
|
9
10
|
export declare const SANITY_PROJECT_DATASET = "sanity.project.dataset";
|
package/dist/constants.js
CHANGED
|
@@ -4,6 +4,7 @@ export const SANITY_FUNCTION_PREFIX = 'sanity.function.';
|
|
|
4
4
|
export const SANITY_FUNCTION_DOCUMENT = 'sanity.function.document';
|
|
5
5
|
export const SANITY_FUNCTION_MEDIA_LIBRARY_ASSET = 'sanity.function.media-library.asset';
|
|
6
6
|
export const SANITY_FUNCTION_SCHEDULED = 'sanity.function.cron';
|
|
7
|
+
export const SANITY_FUNCTION_SYNC_TAG_INVALIDATE = 'sanity.function.sync-tag-invalidate';
|
|
7
8
|
export const SANITY_PROJECT = 'sanity.project';
|
|
8
9
|
export const SANITY_PROJECT_CORS = 'sanity.project.cors';
|
|
9
10
|
export const SANITY_PROJECT_DATASET = 'sanity.project.dataset';
|
|
@@ -111,7 +111,6 @@ function printConfig(options) {
|
|
|
111
111
|
const { projectId, organizationId, stackId, updatedAt } = config;
|
|
112
112
|
const scopeType = projectId ? 'project' : 'organization';
|
|
113
113
|
const scopeId = projectId ? projectId : organizationId;
|
|
114
|
-
log.verbose(JSON.stringify(config));
|
|
115
114
|
log(`${styleText('bold', `${configLabel} configuration:`)}`);
|
|
116
115
|
log(` Deployment: ${labeledId('stack', stackId)}`);
|
|
117
116
|
log(` Scoped to: ${labeledId(scopeType, scopeId)}`);
|
|
@@ -25,7 +25,11 @@ export async function blueprintDeployCore(options) {
|
|
|
25
25
|
if (operationStatus === 'QUEUED' || operationStatus === 'IN_PROGRESS') {
|
|
26
26
|
return {
|
|
27
27
|
success: false,
|
|
28
|
-
error: 'A Stack operation is already in progress.
|
|
28
|
+
error: 'A Stack operation is already in progress.',
|
|
29
|
+
suggestions: [
|
|
30
|
+
`Run \`npx ${bin} blueprints info\` to check operation status.`,
|
|
31
|
+
'Wait for the current operation to complete, then try again.',
|
|
32
|
+
],
|
|
29
33
|
};
|
|
30
34
|
}
|
|
31
35
|
const resources = [...blueprint.resources];
|
|
@@ -56,7 +60,14 @@ export async function blueprintDeployCore(options) {
|
|
|
56
60
|
});
|
|
57
61
|
if (!deployOk) {
|
|
58
62
|
spinner.fail(`${styleText('red', 'Failed')} to update Stack deployment`);
|
|
59
|
-
return {
|
|
63
|
+
return {
|
|
64
|
+
success: false,
|
|
65
|
+
error: deployError || 'Failed to update Stack deployment',
|
|
66
|
+
suggestions: [
|
|
67
|
+
`Run \`npx ${bin} blueprints plan\` to preview changes before deploying.`,
|
|
68
|
+
`Run \`npx ${bin} blueprints doctor\` to check your configuration.`,
|
|
69
|
+
],
|
|
70
|
+
};
|
|
60
71
|
}
|
|
61
72
|
spinner.stop().clear();
|
|
62
73
|
if (noWait) {
|
|
@@ -88,7 +99,14 @@ export async function blueprintDeployCore(options) {
|
|
|
88
99
|
if (!ok) {
|
|
89
100
|
if (logStreamCleanup)
|
|
90
101
|
logStreamCleanup();
|
|
91
|
-
return {
|
|
102
|
+
return {
|
|
103
|
+
success: false,
|
|
104
|
+
error: 'Failed to check Stack deployment status',
|
|
105
|
+
suggestions: [
|
|
106
|
+
'The deployment may still be running on Sanity servers.',
|
|
107
|
+
`Run \`npx ${bin} blueprints info\` to check status.`,
|
|
108
|
+
],
|
|
109
|
+
};
|
|
92
110
|
}
|
|
93
111
|
const operation = currentStack.recentOperation;
|
|
94
112
|
if (!operation) {
|
|
@@ -99,7 +117,14 @@ export async function blueprintDeployCore(options) {
|
|
|
99
117
|
if (operation.status === 'FAILED') {
|
|
100
118
|
if (logStreamCleanup)
|
|
101
119
|
logStreamCleanup();
|
|
102
|
-
return {
|
|
120
|
+
return {
|
|
121
|
+
success: false,
|
|
122
|
+
error: 'Stack deployment failed',
|
|
123
|
+
suggestions: [
|
|
124
|
+
`Run \`npx ${bin} blueprints logs\` to review deployment logs.`,
|
|
125
|
+
`Run \`npx ${bin} blueprints plan\` to identify issues with your Blueprint.`,
|
|
126
|
+
],
|
|
127
|
+
};
|
|
103
128
|
}
|
|
104
129
|
if (operation.status === 'COMPLETED') {
|
|
105
130
|
if (logStreamCleanup)
|
|
@@ -55,8 +55,16 @@ export async function blueprintDestroyCore(options) {
|
|
|
55
55
|
return { success: false, error: blueprintStack.error || 'Failed to get Stack' };
|
|
56
56
|
stack = blueprintStack.stack;
|
|
57
57
|
}
|
|
58
|
-
if (!stack)
|
|
59
|
-
return {
|
|
58
|
+
if (!stack) {
|
|
59
|
+
return {
|
|
60
|
+
success: false,
|
|
61
|
+
error: 'Stack deployment not found',
|
|
62
|
+
suggestions: [
|
|
63
|
+
`Run \`npx ${bin} blueprints stacks\` to list available Stacks.`,
|
|
64
|
+
`Run \`npx ${bin} blueprints doctor\` to check your configuration.`,
|
|
65
|
+
],
|
|
66
|
+
};
|
|
67
|
+
}
|
|
60
68
|
const destroySpinner = log.ora({
|
|
61
69
|
text: `Destroying Stack deployment "${styleText('bold', stack.name)}" ${niceId(stack.id)}...`,
|
|
62
70
|
color: 'red',
|
|
@@ -122,7 +130,14 @@ export async function blueprintDestroyCore(options) {
|
|
|
122
130
|
if (operation.status === 'FAILED') {
|
|
123
131
|
if (logStreamCleanup)
|
|
124
132
|
logStreamCleanup();
|
|
125
|
-
return {
|
|
133
|
+
return {
|
|
134
|
+
success: false,
|
|
135
|
+
error: 'Stack destruction failed',
|
|
136
|
+
suggestions: [
|
|
137
|
+
`Run \`npx ${bin} blueprints logs\` to review destruction logs.`,
|
|
138
|
+
`Run \`npx ${bin} blueprints info\` to view current Stack status.`,
|
|
139
|
+
],
|
|
140
|
+
};
|
|
126
141
|
}
|
|
127
142
|
if (!idleMessageShown && Date.now() - lastLogAt > 60_000) {
|
|
128
143
|
log(`No new activity for 60 seconds. The destruction is still running on Sanity servers.`);
|
|
@@ -284,6 +284,7 @@ export async function blueprintDoctorCore(options) {
|
|
|
284
284
|
return {
|
|
285
285
|
success: false,
|
|
286
286
|
error: `${errorMessage}. Unable to fix: Missing authentication token`,
|
|
287
|
+
suggestions: ['Run `npx @sanity/cli login` to authenticate, then try again.'],
|
|
287
288
|
data: { diagnostics: flatDiagnostics },
|
|
288
289
|
};
|
|
289
290
|
}
|
|
@@ -291,6 +292,7 @@ export async function blueprintDoctorCore(options) {
|
|
|
291
292
|
return {
|
|
292
293
|
success: false,
|
|
293
294
|
error: `${errorMessage}. Unable to fix: ${tokenOrError.error.message}`,
|
|
295
|
+
suggestions: ['Run `npx @sanity/cli login` to re-authenticate.'],
|
|
294
296
|
data: { diagnostics: flatDiagnostics },
|
|
295
297
|
};
|
|
296
298
|
}
|
|
@@ -298,6 +300,7 @@ export async function blueprintDoctorCore(options) {
|
|
|
298
300
|
return {
|
|
299
301
|
success: false,
|
|
300
302
|
error: `${errorMessage}. Unable to fix: Blueprint is missing or invalid`,
|
|
303
|
+
suggestions: [`Run \`npx ${bin} blueprints init\` to create a new Blueprint.`],
|
|
301
304
|
data: { diagnostics: flatDiagnostics },
|
|
302
305
|
};
|
|
303
306
|
}
|
|
@@ -310,6 +313,10 @@ export async function blueprintDoctorCore(options) {
|
|
|
310
313
|
flags: { edit: true, verbose: v },
|
|
311
314
|
});
|
|
312
315
|
}
|
|
313
|
-
|
|
314
|
-
|
|
316
|
+
return {
|
|
317
|
+
success: false,
|
|
318
|
+
error: errorMessage,
|
|
319
|
+
suggestions: [`Run \`npx ${bin} blueprints doctor --fix\` to fix configuration issues.`],
|
|
320
|
+
data: { diagnostics: flatDiagnostics },
|
|
321
|
+
};
|
|
315
322
|
}
|
|
@@ -9,13 +9,17 @@ export async function blueprintPlanCore(options) {
|
|
|
9
9
|
log(formatResourceTree(resources));
|
|
10
10
|
if (!token || !scopeType || !scopeId) {
|
|
11
11
|
log(styleText('dim', 'Unable to retrieve live Stack deployment for comparison'));
|
|
12
|
-
|
|
13
|
-
?
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
12
|
+
return !token
|
|
13
|
+
? {
|
|
14
|
+
success: false,
|
|
15
|
+
error: 'Missing authentication token',
|
|
16
|
+
suggestions: [`Run \`npx ${bin} login\` to authenticate.`],
|
|
17
|
+
}
|
|
18
|
+
: {
|
|
19
|
+
success: false,
|
|
20
|
+
error: 'Missing Blueprint configuration',
|
|
21
|
+
suggestions: [`Run \`npx ${bin} blueprints doctor --fix\` to fix your configuration.`],
|
|
22
|
+
};
|
|
19
23
|
}
|
|
20
24
|
const stackId = flags.stack
|
|
21
25
|
? await resolveStackIdByNameOrId(flags.stack, { token, scopeType, scopeId }, log)
|
|
@@ -24,7 +28,8 @@ export async function blueprintPlanCore(options) {
|
|
|
24
28
|
log(styleText('dim', 'Unable to retrieve live Stack deployment for comparison'));
|
|
25
29
|
return {
|
|
26
30
|
success: false,
|
|
27
|
-
error:
|
|
31
|
+
error: 'Missing Stack deployment configuration',
|
|
32
|
+
suggestions: [`Run \`npx ${bin} blueprints doctor --fix\` to fix your configuration.`],
|
|
28
33
|
};
|
|
29
34
|
}
|
|
30
35
|
const auth = { token, scopeType, scopeId };
|
|
@@ -48,12 +53,15 @@ export async function blueprintPlanCore(options) {
|
|
|
48
53
|
log(` ${styleText(['bold', 'red'], '✘')} ${msg}`);
|
|
49
54
|
}
|
|
50
55
|
}
|
|
51
|
-
log(`\n Fix the issues above before running "${styleText(['bold', 'magenta'], `npx ${bin} blueprints deploy`)}"`);
|
|
52
56
|
}
|
|
53
57
|
else {
|
|
54
58
|
log(styleText('dim', '\nUnable to retrieve deployment plan from server'));
|
|
55
59
|
}
|
|
56
|
-
return {
|
|
60
|
+
return {
|
|
61
|
+
success: false,
|
|
62
|
+
error: 'Deployment plan has problems',
|
|
63
|
+
suggestions: [`Fix the issues above, then run \`npx ${bin} blueprints deploy\`.`],
|
|
64
|
+
};
|
|
57
65
|
}
|
|
58
66
|
log('');
|
|
59
67
|
log(formatDeploymentPlan(planResponse.deploymentPlan));
|
|
@@ -3,13 +3,13 @@ import { patchConfigFile } from '../../actions/blueprints/config.js';
|
|
|
3
3
|
import { promoteStack } from '../../actions/blueprints/stacks.js';
|
|
4
4
|
import { niceId } from '../../utils/display/presenters.js';
|
|
5
5
|
export async function blueprintPromoteCore(options) {
|
|
6
|
-
const { log, stackId, auth, flags, deployedStack, blueprint } = options;
|
|
6
|
+
const { bin = 'sanity', log, stackId, auth, flags, deployedStack, blueprint } = options;
|
|
7
7
|
let message = `"${deployedStack.name}" ${niceId(deployedStack.id)}`;
|
|
8
8
|
if (deployedStack.scopeType === 'organization') {
|
|
9
9
|
message = `Stack ${message} is already org-scoped. Promote again?`;
|
|
10
10
|
}
|
|
11
11
|
else {
|
|
12
|
-
message = `
|
|
12
|
+
message = `Promote Stack ${message} from project to organization scope? You will need admin access to your organization.`;
|
|
13
13
|
}
|
|
14
14
|
if (!flags.force) {
|
|
15
15
|
const confirmed = await confirm({ message });
|
|
@@ -22,7 +22,12 @@ export async function blueprintPromoteCore(options) {
|
|
|
22
22
|
const { ok, error, stack } = await promoteStack({ stackId, auth, logger: log });
|
|
23
23
|
if (!ok) {
|
|
24
24
|
spinner.fail('Failed to promote Stack');
|
|
25
|
-
|
|
25
|
+
const suggestions = [];
|
|
26
|
+
if (error && /access|permission|forbidden/i.test(error)) {
|
|
27
|
+
suggestions.push('Verify you have organization admin access.');
|
|
28
|
+
}
|
|
29
|
+
suggestions.push(`Run \`npx ${bin} blueprints info\` to check the current Stack scope.`);
|
|
30
|
+
return { success: false, error: error || 'Failed to promote Stack', suggestions };
|
|
26
31
|
}
|
|
27
32
|
spinner.stop().clear();
|
|
28
33
|
log(`Stack "${stack.name}" ${niceId(stack.id)} promoted successfully`);
|
|
@@ -39,6 +44,9 @@ export async function blueprintPromoteCore(options) {
|
|
|
39
44
|
return {
|
|
40
45
|
success: false,
|
|
41
46
|
error: 'Stack promoted successfully but failed to update local Blueprint configuration. No config file found.',
|
|
47
|
+
suggestions: [
|
|
48
|
+
`Run \`npx ${bin} blueprints config --edit\` to update your local configuration.`,
|
|
49
|
+
],
|
|
42
50
|
};
|
|
43
51
|
}
|
|
44
52
|
return { success: true, json: { stack }, data: { stack } };
|
|
@@ -21,15 +21,26 @@ export async function blueprintStacksCore(options) {
|
|
|
21
21
|
scopeId = flagProjectId;
|
|
22
22
|
}
|
|
23
23
|
if (!scopeType || !scopeId) {
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
return {
|
|
25
|
+
success: false,
|
|
26
|
+
error: 'Unable to determine scope for Blueprint Stacks',
|
|
27
|
+
suggestions: ['Run in a Blueprint directory or provide a project with --project-id.'],
|
|
28
|
+
};
|
|
26
29
|
}
|
|
27
30
|
try {
|
|
28
31
|
const spinner = log.ora('Fetching Stacks...').start();
|
|
29
32
|
const { ok, stacks, error } = await listStacks({ token, scopeType, scopeId }, log);
|
|
30
33
|
if (!ok) {
|
|
31
34
|
spinner.fail('Failed to list Stacks');
|
|
32
|
-
|
|
35
|
+
const suggestions = [];
|
|
36
|
+
if (error && /access|permission|forbidden/i.test(error)) {
|
|
37
|
+
suggestions.push('Verify you have access to this organization or project.', `Try a different scope with --project-id or --organization-id.`);
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
success: false,
|
|
41
|
+
error: error || 'Failed to list stacks',
|
|
42
|
+
suggestions: suggestions.length ? suggestions : undefined,
|
|
43
|
+
};
|
|
33
44
|
}
|
|
34
45
|
spinner.stop().clear();
|
|
35
46
|
if (!stacks || stacks.length === 0) {
|
|
@@ -142,9 +142,15 @@ export async function functionTestCore(options) {
|
|
|
142
142
|
});
|
|
143
143
|
if (error) {
|
|
144
144
|
spinner.fail('Function execution failed.');
|
|
145
|
+
const errorMessage = error.stack || error.message || error.name;
|
|
146
|
+
const isTimeout = error.message?.includes('Timeout');
|
|
145
147
|
return {
|
|
146
148
|
success: false,
|
|
147
|
-
error:
|
|
149
|
+
error: errorMessage,
|
|
150
|
+
ref: isTimeout ? 'https://www.sanity.io/docs/help/functions-timeout' : undefined,
|
|
151
|
+
suggestions: isTimeout
|
|
152
|
+
? ['Increase the timeout in your Blueprint function configuration.']
|
|
153
|
+
: undefined,
|
|
148
154
|
};
|
|
149
155
|
}
|
|
150
156
|
spinner.succeed('Function execution succeeded.');
|
package/dist/cores/index.d.ts
CHANGED
|
@@ -35,6 +35,12 @@ export type CoreResult = {
|
|
|
35
35
|
success: false;
|
|
36
36
|
/** The error message, if the operation failed. */
|
|
37
37
|
error: string;
|
|
38
|
+
/** Actionable suggestions displayed to the user via oclif's PrettyPrintableError. */
|
|
39
|
+
suggestions?: string[];
|
|
40
|
+
/** A URL for more information about the error. */
|
|
41
|
+
ref?: string;
|
|
42
|
+
/** A machine-readable error code. */
|
|
43
|
+
code?: string;
|
|
38
44
|
streaming?: never;
|
|
39
45
|
json?: never;
|
|
40
46
|
} | {
|
package/dist/cores/index.js
CHANGED
|
@@ -42,7 +42,6 @@ export async function initDeployedBlueprintConfig(config) {
|
|
|
42
42
|
}
|
|
43
43
|
const { scopeType, scopeId, stackId: blueprintStackId } = config.blueprint;
|
|
44
44
|
if (!scopeType || !scopeId) {
|
|
45
|
-
config.log(`Incomplete configuration. Run \`${config.bin} blueprints doctor\` for diagnostics.`);
|
|
46
45
|
return { ok: false, error: 'Missing scope configuration for Blueprint' };
|
|
47
46
|
}
|
|
48
47
|
const auth = { token: config.token, scopeType, scopeId };
|
|
@@ -51,14 +50,12 @@ export async function initDeployedBlueprintConfig(config) {
|
|
|
51
50
|
stackId = await resolveStackIdByNameOrId(config.stackOverride, auth, config.log);
|
|
52
51
|
}
|
|
53
52
|
if (!stackId) {
|
|
54
|
-
config.log(`Incomplete configuration. Run \`${config.bin} blueprints doctor\` for diagnostics.`);
|
|
55
53
|
return { ok: false, error: 'Missing Stack deployment configuration for Blueprint' };
|
|
56
54
|
}
|
|
57
55
|
const spinner = config.log.ora('Loading Stack deployment...').start();
|
|
58
56
|
const stackResponse = await getStack({ stackId, auth, logger: config.log });
|
|
59
57
|
if (!stackResponse.ok) {
|
|
60
58
|
spinner.fail('Could not load Stack deployment');
|
|
61
|
-
config.log(`Run \`${config.bin} blueprints doctor\` for diagnostics.`);
|
|
62
59
|
return { ok: false, error: 'Missing Stack deployment' };
|
|
63
60
|
}
|
|
64
61
|
spinner.stop().clear();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { treeify } from 'array-treeify';
|
|
2
|
-
import { SANITY_ACCESS_ROBOT, SANITY_ACCESS_ROLE, SANITY_FUNCTION_DOCUMENT, SANITY_FUNCTION_MEDIA_LIBRARY_ASSET, SANITY_FUNCTION_SCHEDULED, SANITY_PROJECT, SANITY_PROJECT_CORS, SANITY_PROJECT_DATASET, SANITY_PROJECT_WEBHOOK, } from '../../constants.js';
|
|
2
|
+
import { SANITY_ACCESS_ROBOT, SANITY_ACCESS_ROLE, SANITY_FUNCTION_DOCUMENT, SANITY_FUNCTION_MEDIA_LIBRARY_ASSET, SANITY_FUNCTION_SCHEDULED, SANITY_FUNCTION_SYNC_TAG_INVALIDATE, SANITY_PROJECT, SANITY_PROJECT_CORS, SANITY_PROJECT_DATASET, SANITY_PROJECT_WEBHOOK, } from '../../constants.js';
|
|
3
3
|
import { styleText } from '../style-text.js';
|
|
4
4
|
import { isCorsOriginResource, isDatasetResource, isRobotResource, isRoleResource, isWebhookResource, } from '../types.js';
|
|
5
5
|
import { formatDate, formatDuration } from './dates.js';
|
|
@@ -28,6 +28,7 @@ const RESOURCE_CATEGORIES = {
|
|
|
28
28
|
[SANITY_FUNCTION_DOCUMENT]: functionCategory,
|
|
29
29
|
[SANITY_FUNCTION_MEDIA_LIBRARY_ASSET]: functionCategory,
|
|
30
30
|
[SANITY_FUNCTION_SCHEDULED]: functionCategory,
|
|
31
|
+
[SANITY_FUNCTION_SYNC_TAG_INVALIDATE]: functionCategory,
|
|
31
32
|
[SANITY_PROJECT]: {
|
|
32
33
|
label: 'Projects',
|
|
33
34
|
displayNameAttribute: 'displayName',
|