@sanity/runtime-cli 13.4.1 → 14.0.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 +43 -35
- package/dist/actions/blueprints/config.d.ts +3 -7
- package/dist/actions/blueprints/config.js +1 -1
- package/dist/actions/blueprints/logs-streaming.d.ts +1 -0
- package/dist/actions/blueprints/logs-streaming.js +1 -0
- package/dist/actions/blueprints/stacks.d.ts +1 -0
- package/dist/actions/blueprints/stacks.js +11 -0
- package/dist/baseCommands.d.ts +2 -0
- package/dist/baseCommands.js +6 -1
- package/dist/commands/blueprints/config.d.ts +1 -1
- package/dist/commands/blueprints/config.js +5 -5
- package/dist/commands/blueprints/deploy.d.ts +1 -0
- package/dist/commands/blueprints/deploy.js +5 -2
- package/dist/commands/blueprints/destroy.d.ts +1 -1
- package/dist/commands/blueprints/destroy.js +6 -6
- package/dist/commands/blueprints/doctor.js +5 -1
- package/dist/commands/blueprints/info.d.ts +1 -1
- package/dist/commands/blueprints/info.js +4 -4
- package/dist/commands/blueprints/init.js +1 -1
- package/dist/commands/blueprints/logs.d.ts +1 -0
- package/dist/commands/blueprints/logs.js +2 -1
- package/dist/commands/blueprints/plan.d.ts +3 -0
- package/dist/commands/blueprints/plan.js +4 -1
- package/dist/commands/functions/logs.d.ts +1 -0
- package/dist/commands/functions/logs.js +2 -1
- package/dist/cores/blueprints/config.d.ts +1 -1
- package/dist/cores/blueprints/config.js +27 -6
- package/dist/cores/blueprints/deploy.js +36 -3
- package/dist/cores/blueprints/destroy.d.ts +1 -1
- package/dist/cores/blueprints/destroy.js +30 -15
- package/dist/cores/blueprints/doctor.js +184 -90
- package/dist/cores/blueprints/info.d.ts +1 -3
- package/dist/cores/blueprints/info.js +5 -20
- package/dist/cores/blueprints/init.js +1 -1
- package/dist/cores/blueprints/plan.d.ts +1 -0
- package/dist/cores/blueprints/plan.js +20 -15
- package/dist/cores/index.d.ts +1 -0
- package/dist/cores/index.js +12 -7
- package/oclif.manifest.json +81 -24
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LocalBlueprintCommand } from '../../baseCommands.js';
|
|
1
|
+
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 {
|
|
@@ -7,6 +7,9 @@ export default class PlanCommand extends LocalBlueprintCommand {
|
|
|
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.`;
|
|
9
9
|
static examples = ['<%= config.bin %> <%= command.id %>'];
|
|
10
|
+
static flags = {
|
|
11
|
+
stack: unhide(stackFlag),
|
|
12
|
+
};
|
|
10
13
|
async run() {
|
|
11
14
|
const { success, error } = await blueprintPlanCore({
|
|
12
15
|
bin: this.config.bin,
|
|
@@ -7,6 +7,7 @@ export default class LogsCommand extends DeployedStackCommand<typeof LogsCommand
|
|
|
7
7
|
};
|
|
8
8
|
static examples: string[];
|
|
9
9
|
static flags: {
|
|
10
|
+
stack: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
11
|
limit: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
12
|
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
13
|
utc: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Args, Flags } from '@oclif/core';
|
|
2
|
-
import { DeployedStackCommand } from '../../baseCommands.js';
|
|
2
|
+
import { DeployedStackCommand, stackFlag, unhide } from '../../baseCommands.js';
|
|
3
3
|
import { functionLogsCore } from '../../cores/functions/logs.js';
|
|
4
4
|
import { Logger } from '../../utils/logger.js';
|
|
5
5
|
export default class LogsCommand extends DeployedStackCommand {
|
|
@@ -17,6 +17,7 @@ Use --watch (-w) to stream logs in real-time. Use --delete to clear all logs for
|
|
|
17
17
|
'<%= config.bin %> <%= command.id %> <name> --delete',
|
|
18
18
|
];
|
|
19
19
|
static flags = {
|
|
20
|
+
stack: unhide(stackFlag),
|
|
20
21
|
limit: Flags.integer({
|
|
21
22
|
char: 'l',
|
|
22
23
|
description: 'Total number of log entries to retrieve',
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { patchConfigFile, writeConfigFile, } from '../../actions/blueprints/config.js';
|
|
2
|
+
import { resolveStackIdByNameOrId } from '../../actions/blueprints/stacks.js';
|
|
2
3
|
import { filePathRelativeToCwd, labeledId, warn } from '../../utils/display/presenters.js';
|
|
3
4
|
import { promptForProject, promptForStack } from '../../utils/display/prompt.js';
|
|
4
5
|
import { styleText } from '../../utils/style-text.js';
|
|
5
6
|
export async function blueprintConfigCore(options) {
|
|
6
7
|
const { bin = 'sanity', blueprint, log, token, flags } = options;
|
|
7
|
-
const { edit: editConfig = false, 'project-id': flagProjectId, 'organization-id': flagOrganizationId,
|
|
8
|
-
const providedConfigFlag = [flagProjectId,
|
|
8
|
+
const { edit: editConfig = false, 'project-id': flagProjectId, 'organization-id': flagOrganizationId, stack: flagStack, verbose: _v = false, } = flags;
|
|
9
|
+
const providedConfigFlag = [flagProjectId, flagStack, flagOrganizationId].some(Boolean);
|
|
9
10
|
const { stackId: configStackId, scopeType: configScopeType, scopeId: configScopeId, blueprintConfig, fileInfo, } = blueprint;
|
|
10
11
|
const blueprintFilePath = fileInfo.blueprintFilePath;
|
|
11
12
|
if (!configStackId && !configScopeType && !configScopeId) {
|
|
@@ -34,8 +35,16 @@ export async function blueprintConfigCore(options) {
|
|
|
34
35
|
const configUpdate = {};
|
|
35
36
|
if (flagProjectId)
|
|
36
37
|
configUpdate.projectId = flagProjectId;
|
|
37
|
-
if (
|
|
38
|
-
|
|
38
|
+
if (flagStack) {
|
|
39
|
+
const scopeType = flagProjectId ? 'project' : configScopeType;
|
|
40
|
+
const scopeId = flagProjectId || configScopeId;
|
|
41
|
+
if (scopeType && scopeId) {
|
|
42
|
+
configUpdate.stackId = await resolveStackIdByNameOrId(flagStack, { token, scopeType, scopeId }, log);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
configUpdate.stackId = flagStack;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
39
48
|
if (flagOrganizationId)
|
|
40
49
|
configUpdate.organizationId = flagOrganizationId;
|
|
41
50
|
try {
|
|
@@ -44,7 +53,16 @@ export async function blueprintConfigCore(options) {
|
|
|
44
53
|
return { success: true };
|
|
45
54
|
}
|
|
46
55
|
catch {
|
|
47
|
-
|
|
56
|
+
// fallback to writeConfigFile if patchConfigFile fails
|
|
57
|
+
// creates a new config file with the given properties
|
|
58
|
+
try {
|
|
59
|
+
const newConfig = writeConfigFile(blueprintFilePath, configUpdate);
|
|
60
|
+
printConfig({ configLabel: 'Updated', log, config: newConfig });
|
|
61
|
+
return { success: true };
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return { success: false, error: 'Unable to update configuration.' };
|
|
65
|
+
}
|
|
48
66
|
}
|
|
49
67
|
}
|
|
50
68
|
// prompt for values interactively
|
|
@@ -60,7 +78,10 @@ export async function blueprintConfigCore(options) {
|
|
|
60
78
|
}
|
|
61
79
|
if (!updatedProjectId)
|
|
62
80
|
return { success: false, error: 'Project ID is required.' };
|
|
63
|
-
let updatedStackId
|
|
81
|
+
let updatedStackId;
|
|
82
|
+
if (flagStack) {
|
|
83
|
+
updatedStackId = await resolveStackIdByNameOrId(flagStack, { token, scopeType: 'project', scopeId: updatedProjectId }, log);
|
|
84
|
+
}
|
|
64
85
|
if (!updatedStackId) {
|
|
65
86
|
const pickedStack = await promptForStack({ projectId: updatedProjectId, token, logger: log });
|
|
66
87
|
updatedStackId = pickedStack.stackId;
|
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
import { setTimeout } from 'node:timers/promises';
|
|
1
|
+
import { setTimeout as sleep } from 'node:timers/promises';
|
|
2
2
|
import { stashAsset } from '../../actions/blueprints/assets.js';
|
|
3
3
|
import { setupLogStreaming } from '../../actions/blueprints/logs-streaming.js';
|
|
4
4
|
import { getStack, updateStack } from '../../actions/blueprints/stacks.js';
|
|
5
5
|
import { niceId } from '../../utils/display/presenters.js';
|
|
6
6
|
import { styleText } from '../../utils/style-text.js';
|
|
7
7
|
import { isLocalFunctionCollection, isLocalFunctionResource } from '../../utils/types.js';
|
|
8
|
+
const DEFAULT_ASSET_TIMEOUT = 60;
|
|
9
|
+
const assetTimeoutS = Number(process.env.SANITY_ASSET_TIMEOUT) || DEFAULT_ASSET_TIMEOUT;
|
|
10
|
+
const assetTimeoutMs = assetTimeoutS * 1000;
|
|
11
|
+
const warnTimeoutMs = assetTimeoutMs / 2;
|
|
8
12
|
export async function blueprintDeployCore(options) {
|
|
9
13
|
const { bin = 'sanity', log, auth, stackId, scopeType, scopeId, deployedStack, blueprint, flags, } = options;
|
|
10
14
|
const { verbose } = flags;
|
|
@@ -33,7 +37,26 @@ export async function blueprintDeployCore(options) {
|
|
|
33
37
|
log('Processing function assets...');
|
|
34
38
|
for (const resource of allFunctionResources) {
|
|
35
39
|
const fnSpinner = log.ora({ text: `Processing ${resource.name}...`, prefixText: ' ' }).start();
|
|
36
|
-
const
|
|
40
|
+
const warnTimer = setTimeout(() => {
|
|
41
|
+
fnSpinner.text = `Still processing ${resource.name}, this can take a moment...`;
|
|
42
|
+
}, warnTimeoutMs);
|
|
43
|
+
let result;
|
|
44
|
+
try {
|
|
45
|
+
result = await Promise.race([
|
|
46
|
+
stashAsset({ resource, auth, logger: log }),
|
|
47
|
+
sleep(assetTimeoutMs).then(() => {
|
|
48
|
+
throw new Error(`Processing ${resource.name} timed out after ${assetTimeoutS}s`);
|
|
49
|
+
}),
|
|
50
|
+
]);
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
54
|
+
fnSpinner.fail(msg);
|
|
55
|
+
return { success: false, error: msg };
|
|
56
|
+
}
|
|
57
|
+
finally {
|
|
58
|
+
clearTimeout(warnTimer);
|
|
59
|
+
}
|
|
37
60
|
if (result.success && result.assetId) {
|
|
38
61
|
resource.src = result.assetId;
|
|
39
62
|
if (isLocalFunctionCollection(resource)) {
|
|
@@ -102,12 +125,17 @@ export async function blueprintDeployCore(options) {
|
|
|
102
125
|
log(styleText('dim', 'Stack deployment progress:'));
|
|
103
126
|
let logStreamCleanup = null;
|
|
104
127
|
try {
|
|
128
|
+
let lastLogAt = Date.now();
|
|
129
|
+
let idleMessageShown = false;
|
|
105
130
|
logStreamCleanup = await setupLogStreaming({
|
|
106
131
|
stackId: stack.id,
|
|
107
132
|
after: isoNow,
|
|
108
133
|
auth,
|
|
109
134
|
log,
|
|
110
135
|
verbose,
|
|
136
|
+
onActivity: () => {
|
|
137
|
+
lastLogAt = Date.now();
|
|
138
|
+
},
|
|
111
139
|
});
|
|
112
140
|
while (true) {
|
|
113
141
|
const { ok, stack: currentStack } = await getStack({ stackId: stack.id, auth, logger: log });
|
|
@@ -133,7 +161,12 @@ export async function blueprintDeployCore(options) {
|
|
|
133
161
|
log(styleText(['bold', 'green'], 'Stack deployment completed!'));
|
|
134
162
|
return { success: true, data: { resources } };
|
|
135
163
|
}
|
|
136
|
-
|
|
164
|
+
if (!idleMessageShown && Date.now() - lastLogAt > 60_000) {
|
|
165
|
+
log(`No new activity for 60 seconds. The deployment is still running on Sanity servers.`);
|
|
166
|
+
log(`You can safely exit and check status later with \`${bin} blueprints info\`.`);
|
|
167
|
+
idleMessageShown = true;
|
|
168
|
+
}
|
|
169
|
+
await sleep(1500);
|
|
137
170
|
}
|
|
138
171
|
}
|
|
139
172
|
catch (error) {
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { setTimeout } from 'node:timers/promises';
|
|
1
|
+
import { setTimeout as sleep } from 'node:timers/promises';
|
|
2
2
|
import { confirm } from '@inquirer/prompts';
|
|
3
3
|
import { setupLogStreaming } from '../../actions/blueprints/logs-streaming.js';
|
|
4
|
-
import { destroyStack, getStack } from '../../actions/blueprints/stacks.js';
|
|
4
|
+
import { destroyStack, getStack, resolveStackIdByNameOrId } from '../../actions/blueprints/stacks.js';
|
|
5
5
|
import { niceId } from '../../utils/display/presenters.js';
|
|
6
6
|
import { styleText } from '../../utils/style-text.js';
|
|
7
7
|
export async function blueprintDestroyCore(options) {
|
|
8
|
-
const { log, token, blueprint, flags } = options;
|
|
9
|
-
const { force = false, 'project-id': flagProjectId, 'organization-id': flagOrganizationId,
|
|
8
|
+
const { bin = 'sanity', log, token, blueprint, flags } = options;
|
|
9
|
+
const { force = false, 'project-id': flagProjectId, 'organization-id': flagOrganizationId, stack: flagStack, 'no-wait': noWait = false, verbose: _verbose = false, } = flags;
|
|
10
10
|
// 3-flag combo: just destroy it
|
|
11
|
-
if ((flagProjectId || flagOrganizationId) &&
|
|
11
|
+
if ((flagProjectId || flagOrganizationId) && flagStack && force) {
|
|
12
12
|
let scopeType;
|
|
13
13
|
let scopeId;
|
|
14
14
|
if (flagOrganizationId) {
|
|
@@ -22,9 +22,11 @@ export async function blueprintDestroyCore(options) {
|
|
|
22
22
|
else {
|
|
23
23
|
return { success: false, error: 'Unable to determine scope for Blueprint Destroy' };
|
|
24
24
|
}
|
|
25
|
+
const auth = { token, scopeType, scopeId };
|
|
26
|
+
const resolvedId = await resolveStackIdByNameOrId(flagStack, auth, log);
|
|
25
27
|
const { ok, error, stack } = await destroyStack({
|
|
26
|
-
stackId:
|
|
27
|
-
auth
|
|
28
|
+
stackId: resolvedId,
|
|
29
|
+
auth,
|
|
28
30
|
logger: log,
|
|
29
31
|
});
|
|
30
32
|
if (!ok)
|
|
@@ -36,13 +38,16 @@ export async function blueprintDestroyCore(options) {
|
|
|
36
38
|
if (!scopeType || !scopeId)
|
|
37
39
|
return { success: false, error: 'Scope is required' };
|
|
38
40
|
const auth = { token, scopeType, scopeId };
|
|
41
|
+
const resolvedStackId = flagStack
|
|
42
|
+
? await resolveStackIdByNameOrId(flagStack, auth, log)
|
|
43
|
+
: undefined;
|
|
39
44
|
let stack;
|
|
40
45
|
try {
|
|
41
|
-
if (
|
|
42
|
-
const
|
|
43
|
-
if (!
|
|
44
|
-
return { success: false, error:
|
|
45
|
-
stack =
|
|
46
|
+
if (resolvedStackId) {
|
|
47
|
+
const overrideStack = await getStack({ stackId: resolvedStackId, auth, logger: log });
|
|
48
|
+
if (!overrideStack.ok)
|
|
49
|
+
return { success: false, error: overrideStack.error || 'Failed to get Stack' };
|
|
50
|
+
stack = overrideStack.stack;
|
|
46
51
|
}
|
|
47
52
|
else if (stackId) {
|
|
48
53
|
const blueprintStack = await getStack({ stackId, auth, logger: log });
|
|
@@ -70,10 +75,10 @@ export async function blueprintDestroyCore(options) {
|
|
|
70
75
|
let i = 5;
|
|
71
76
|
while (i >= 0) {
|
|
72
77
|
destroySpinner.text = `Destroying Stack deployment in ${styleText('bold', (i--).toString())} seconds...`;
|
|
73
|
-
await
|
|
78
|
+
await sleep(1000);
|
|
74
79
|
}
|
|
75
80
|
destroySpinner.text = 'Destroying Stack deployment 💥';
|
|
76
|
-
await
|
|
81
|
+
await sleep(500);
|
|
77
82
|
}
|
|
78
83
|
else {
|
|
79
84
|
destroySpinner.start();
|
|
@@ -92,11 +97,16 @@ export async function blueprintDestroyCore(options) {
|
|
|
92
97
|
log(styleText('dim', 'Stack destruction progress:'));
|
|
93
98
|
let logStreamCleanup = null;
|
|
94
99
|
try {
|
|
100
|
+
let lastLogAt = Date.now();
|
|
101
|
+
let idleMessageShown = false;
|
|
95
102
|
logStreamCleanup = await setupLogStreaming({
|
|
96
103
|
stackId: stack.id,
|
|
97
104
|
after: isoNow,
|
|
98
105
|
auth,
|
|
99
106
|
log,
|
|
107
|
+
onActivity: () => {
|
|
108
|
+
lastLogAt = Date.now();
|
|
109
|
+
},
|
|
100
110
|
});
|
|
101
111
|
while (true) {
|
|
102
112
|
const { ok, stack: currentStack } = await getStack({ stackId: stack.id, auth, logger: log });
|
|
@@ -114,7 +124,12 @@ export async function blueprintDestroyCore(options) {
|
|
|
114
124
|
logStreamCleanup();
|
|
115
125
|
return { success: false, error: 'Stack destruction failed' };
|
|
116
126
|
}
|
|
117
|
-
|
|
127
|
+
if (!idleMessageShown && Date.now() - lastLogAt > 60_000) {
|
|
128
|
+
log(`No new activity for 60 seconds. The destruction is still running on Sanity servers.`);
|
|
129
|
+
log(`You can safely exit and check status later with \`${bin} blueprints info\`.`);
|
|
130
|
+
idleMessageShown = true;
|
|
131
|
+
}
|
|
132
|
+
await sleep(1500);
|
|
118
133
|
}
|
|
119
134
|
}
|
|
120
135
|
catch (error) {
|