@sanity/runtime-cli 13.2.1 → 13.2.3
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 +18 -18
- package/dist/actions/blueprints/blueprint.d.ts +17 -1
- package/dist/actions/blueprints/blueprint.js +44 -12
- package/dist/actions/blueprints/logs-streaming.js +4 -4
- package/dist/actions/blueprints/resources.js +2 -2
- package/dist/cores/blueprints/config.js +2 -2
- package/dist/cores/blueprints/deploy.js +5 -5
- package/dist/cores/blueprints/destroy.js +6 -6
- package/dist/cores/blueprints/doctor.js +55 -57
- package/dist/cores/blueprints/init.js +11 -11
- package/dist/cores/blueprints/logs.js +4 -4
- package/dist/cores/blueprints/plan.js +4 -4
- package/dist/cores/blueprints/stacks.js +2 -2
- package/dist/cores/functions/add.js +8 -8
- package/dist/cores/functions/env/add.js +2 -2
- package/dist/cores/functions/env/remove.js +2 -2
- package/dist/cores/functions/logs.js +15 -15
- package/dist/server/static/api.js +22 -2
- package/dist/server/static/components/run-panel.js +3 -5
- package/dist/utils/display/blueprints-formatting.js +19 -17
- package/dist/utils/display/logs-formatting.js +3 -3
- package/dist/utils/display/presenters.js +8 -8
- package/dist/utils/display/prompt.js +5 -5
- package/dist/utils/display/resources-formatting.js +3 -3
- package/dist/utils/style-text.d.ts +2 -0
- package/dist/utils/style-text.js +44 -0
- package/dist/utils/traced-fetch.js +3 -3
- package/oclif.manifest.json +1 -1
- package/package.json +2 -3
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { confirm } from '@inquirer/prompts';
|
|
4
|
-
import chalk from 'chalk';
|
|
5
4
|
import { findBlueprintFile, readLocalBlueprint, writeBlueprintToDisk, } from '../../actions/blueprints/blueprint.js';
|
|
6
5
|
import { writeConfigFile } from '../../actions/blueprints/config.js';
|
|
7
6
|
import { createEmptyStack } from '../../actions/blueprints/stacks.js';
|
|
@@ -12,6 +11,7 @@ import { getProject } from '../../actions/sanity/projects.js';
|
|
|
12
11
|
import { BLUEPRINT_CONFIG_DIR, BLUEPRINT_CONFIG_FILE } from '../../config.js';
|
|
13
12
|
import { check, filePathRelativeToCwd, labeledId, warn } from '../../utils/display/presenters.js';
|
|
14
13
|
import { promptForBlueprintType, promptForProject, promptForStack, } from '../../utils/display/prompt.js';
|
|
14
|
+
import { styleText } from '../../utils/style-text.js';
|
|
15
15
|
import { blueprintConfigCore } from './config.js';
|
|
16
16
|
const SCOPE_PROJECT = 'project';
|
|
17
17
|
const SCOPE_ORGANIZATION = 'organization';
|
|
@@ -155,7 +155,7 @@ async function handleExampleInitialization(options) {
|
|
|
155
155
|
}
|
|
156
156
|
const { files, dir: newDir, instructions } = addedExample;
|
|
157
157
|
for (const filePath of Object.keys(files)) {
|
|
158
|
-
log(check(`${
|
|
158
|
+
log(check(`${styleText('bold', 'Created:')} ${newDir}/${filePath}`));
|
|
159
159
|
}
|
|
160
160
|
const discoveredBlueprint = findBlueprintFile(exampleDir);
|
|
161
161
|
if (!discoveredBlueprint) {
|
|
@@ -163,8 +163,8 @@ async function handleExampleInitialization(options) {
|
|
|
163
163
|
}
|
|
164
164
|
const { blueprintFilePath } = discoveredBlueprint;
|
|
165
165
|
writeConfigFile(blueprintFilePath, { projectId: resolvedProjectId, stackId: stack.id });
|
|
166
|
-
log(check(`${
|
|
167
|
-
log(`\n Run "${
|
|
166
|
+
log(check(`${styleText('bold', 'Configured:')} ${exampleDir}/${BLUEPRINT_CONFIG_DIR}/${BLUEPRINT_CONFIG_FILE}`));
|
|
167
|
+
log(`\n Run "${styleText(['bold', 'magenta'], `cd ${exampleDir} && npm i`)}" and check out the README`);
|
|
168
168
|
if (instructions) {
|
|
169
169
|
log('');
|
|
170
170
|
log(instructions);
|
|
@@ -271,27 +271,27 @@ export async function createBlueprintFiles(params) {
|
|
|
271
271
|
const blueprintFilePath = join(blueprintDir, blueprintFileName);
|
|
272
272
|
writeBlueprintToDisk({ blueprintFilePath });
|
|
273
273
|
if (userProvidedDirName) {
|
|
274
|
-
log(check(`${
|
|
274
|
+
log(check(`${styleText('bold', 'New folder created:')} ${userProvidedDirName}/`));
|
|
275
275
|
}
|
|
276
276
|
const displayPath = userProvidedDirName || '.';
|
|
277
|
-
log(check(`${
|
|
277
|
+
log(check(`${styleText('bold', 'Created Blueprint:')} ${displayPath}/${blueprintFileName}`));
|
|
278
278
|
writeConfigFile(blueprintFilePath, {
|
|
279
279
|
stackId,
|
|
280
280
|
...(scopeType === SCOPE_ORGANIZATION ? { organizationId: scopeId } : { projectId: scopeId }),
|
|
281
281
|
});
|
|
282
|
-
log(check(`${
|
|
282
|
+
log(check(`${styleText('bold', 'Added configuration:')} ${displayPath}/${BLUEPRINT_CONFIG_DIR}/${BLUEPRINT_CONFIG_FILE}`));
|
|
283
283
|
const gitignoreResult = writeGitignoreFile(blueprintFilePath);
|
|
284
284
|
if (gitignoreResult.action === 'created') {
|
|
285
|
-
log(check(`${
|
|
285
|
+
log(check(`${styleText('bold', 'Added .gitignore:')} ${displayPath}/.gitignore`));
|
|
286
286
|
}
|
|
287
287
|
else if (gitignoreResult.action === 'updated') {
|
|
288
|
-
log(check(`${
|
|
288
|
+
log(check(`${styleText('bold', 'Updated .gitignore:')} ${displayPath}/.gitignore`));
|
|
289
289
|
}
|
|
290
290
|
if (blueprintExtension !== 'json') {
|
|
291
291
|
const blueprintsPackage = '@sanity/blueprints';
|
|
292
292
|
try {
|
|
293
293
|
await writeOrUpdateNodeDependency(blueprintFilePath, blueprintsPackage, log);
|
|
294
|
-
log(check(`${
|
|
294
|
+
log(check(`${styleText('bold', 'Added dependency:')} ${blueprintsPackage}`));
|
|
295
295
|
}
|
|
296
296
|
catch {
|
|
297
297
|
log.warn(warn(`Unable to add ${blueprintsPackage} to your project.`));
|
|
@@ -303,6 +303,6 @@ export async function createBlueprintFiles(params) {
|
|
|
303
303
|
if (blueprintExtension !== 'json')
|
|
304
304
|
nextStepParts.push('npm install');
|
|
305
305
|
nextStepParts.push(`${bin} blueprints --help`);
|
|
306
|
-
log(`\n Run "${
|
|
306
|
+
log(`\n Run "${styleText(['bold', 'magenta'], nextStepParts.join(' && '))}" to get started`);
|
|
307
307
|
return { success: true };
|
|
308
308
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import chalk from 'chalk';
|
|
2
1
|
import { getLogs, getRecentLogs } from '../../actions/blueprints/logs.js';
|
|
3
2
|
import { setupLogStreaming } from '../../actions/blueprints/logs-streaming.js';
|
|
4
3
|
import { formatTitle } from '../../utils/display/blueprints-formatting.js';
|
|
5
4
|
import { formatLogEntry, formatLogsByDay, organizeLogsByDay, } from '../../utils/display/logs-formatting.js';
|
|
6
5
|
import { niceId } from '../../utils/display/presenters.js';
|
|
6
|
+
import { styleText } from '../../utils/style-text.js';
|
|
7
7
|
export async function blueprintLogsCore(options) {
|
|
8
8
|
const { log, auth, stackId, deployedStack, flags } = options;
|
|
9
9
|
const { watch = false, verbose: _verbose = false } = flags;
|
|
@@ -12,7 +12,7 @@ export async function blueprintLogsCore(options) {
|
|
|
12
12
|
if (watch) {
|
|
13
13
|
const { ok, logs, error } = await getLogs(stackId, auth, log);
|
|
14
14
|
if (!ok) {
|
|
15
|
-
spinner.fail(`${
|
|
15
|
+
spinner.fail(`${styleText('red', 'Failed')} to retrieve logs`);
|
|
16
16
|
log.error(`Error: ${error || 'Unknown error'}`);
|
|
17
17
|
return { success: false, error: error || 'Failed to retrieve logs' };
|
|
18
18
|
}
|
|
@@ -44,7 +44,7 @@ export async function blueprintLogsCore(options) {
|
|
|
44
44
|
// Regular non-streaming logs
|
|
45
45
|
const { ok, logs, error } = await getLogs(stackId, auth, log);
|
|
46
46
|
if (!ok) {
|
|
47
|
-
spinner.fail(`${
|
|
47
|
+
spinner.fail(`${styleText('red', 'Failed')} to retrieve Stack deployment logs`);
|
|
48
48
|
log.error(`Error: ${error || 'Unknown error'}`);
|
|
49
49
|
return { success: false, error: error || 'Failed to retrieve logs' };
|
|
50
50
|
}
|
|
@@ -53,7 +53,7 @@ export async function blueprintLogsCore(options) {
|
|
|
53
53
|
return { success: true };
|
|
54
54
|
}
|
|
55
55
|
spinner.succeed(`${formatTitle('Blueprint', deployedStack.name)} Logs`);
|
|
56
|
-
log(`Found ${
|
|
56
|
+
log(`Found ${styleText('bold', logs.length.toString())} log entries for Stack deployment ${niceId(stackId)}\n`);
|
|
57
57
|
// Organize and format logs by day
|
|
58
58
|
const logsByDay = organizeLogsByDay(logs);
|
|
59
59
|
log(formatLogsByDay(logsByDay));
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import chalk from 'chalk';
|
|
2
1
|
import { getStack } from '../../actions/blueprints/stacks.js';
|
|
3
2
|
import { formatResourceTree, stackDeployDiff } from '../../utils/display/blueprints-formatting.js';
|
|
3
|
+
import { styleText } from '../../utils/style-text.js';
|
|
4
4
|
export async function blueprintPlanCore(options) {
|
|
5
5
|
const { bin = 'sanity', log, blueprint, token, flags } = options;
|
|
6
6
|
const { verbose: _verbose = false } = flags;
|
|
7
7
|
const { scopeType, scopeId, stackId, parsedBlueprint, fileInfo } = blueprint;
|
|
8
|
-
log(`${
|
|
8
|
+
log(`${styleText(['bold', 'blueBright'], 'Blueprint Stack deployment plan')} ${styleText('dim', `(${fileInfo.fileName})`)}`);
|
|
9
9
|
log(formatResourceTree(parsedBlueprint.resources));
|
|
10
10
|
if (token && scopeType && scopeId && stackId) {
|
|
11
11
|
const stackResponse = await getStack({
|
|
@@ -14,7 +14,7 @@ export async function blueprintPlanCore(options) {
|
|
|
14
14
|
logger: log,
|
|
15
15
|
});
|
|
16
16
|
if (!stackResponse.ok) {
|
|
17
|
-
log(
|
|
17
|
+
log(styleText('dim', 'Unable to retrieve live Stack deployment for comparison'));
|
|
18
18
|
}
|
|
19
19
|
else {
|
|
20
20
|
const diff = stackDeployDiff(parsedBlueprint, stackResponse.stack);
|
|
@@ -22,6 +22,6 @@ export async function blueprintPlanCore(options) {
|
|
|
22
22
|
log(diff);
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
|
-
log(`\n Run "${
|
|
25
|
+
log(`\n Run "${styleText(['bold', 'magenta'], `${bin} blueprints deploy`)}" to deploy these Stack changes`);
|
|
26
26
|
return { success: true };
|
|
27
27
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import chalk from 'chalk';
|
|
2
1
|
import { listStacks } from '../../actions/blueprints/stacks.js';
|
|
3
2
|
import { formatStacksListing } from '../../utils/display/blueprints-formatting.js';
|
|
4
3
|
import { capitalize, niceId } from '../../utils/display/presenters.js';
|
|
4
|
+
import { styleText } from '../../utils/style-text.js';
|
|
5
5
|
export async function blueprintStacksCore(options) {
|
|
6
6
|
const { log, token, blueprint, flags } = options;
|
|
7
7
|
const { scopeType: blueprintScopeType, scopeId: blueprintScopeId, stackId: blueprintStackId, } = blueprint;
|
|
@@ -32,7 +32,7 @@ export async function blueprintStacksCore(options) {
|
|
|
32
32
|
log('No stacks found');
|
|
33
33
|
return { success: true };
|
|
34
34
|
}
|
|
35
|
-
log(`${
|
|
35
|
+
log(`${styleText('bold', capitalize(scopeType))} ${niceId(scopeId)} ${styleText('bold', 'Stacks')}:\n`);
|
|
36
36
|
log(formatStacksListing(stacks, blueprintStackId));
|
|
37
37
|
return { success: true };
|
|
38
38
|
}
|
|
@@ -3,11 +3,11 @@ import { dirname, join } from 'node:path';
|
|
|
3
3
|
import { cwd } from 'node:process';
|
|
4
4
|
import { checkbox, confirm, input, select } from '@inquirer/prompts';
|
|
5
5
|
import { highlight } from 'cardinal';
|
|
6
|
-
import chalk from 'chalk';
|
|
7
6
|
import { createFunctionResource } from '../../actions/blueprints/resources.js';
|
|
8
7
|
import { verifyExampleExists, writeExample } from '../../actions/sanity/examples.js';
|
|
9
8
|
import { SANITY_FUNCTION_MEDIA_LIBRARY_ASSET, SANITY_FUNCTION_SCHEDULE } from '../../constants.js';
|
|
10
9
|
import { check, indent, warn } from '../../utils/display/presenters.js';
|
|
10
|
+
import { styleText } from '../../utils/style-text.js';
|
|
11
11
|
import { validateFunctionName } from '../../utils/validate/resource.js';
|
|
12
12
|
const generateFunctionBlueprintResourceTemplate = (fnName, eventNames) => {
|
|
13
13
|
const definer = eventNames[0].substring(0, eventNames[0].lastIndexOf('-')) === 'document'
|
|
@@ -61,11 +61,11 @@ export async function functionAddCore(options) {
|
|
|
61
61
|
const { files, dir, instructions, functionConfig } = addedExample;
|
|
62
62
|
const newDir = dir.replace(root, '').replace(/^[/\\]+/, '');
|
|
63
63
|
for (const filePath of Object.keys(files)) {
|
|
64
|
-
log(check(`${
|
|
64
|
+
log(check(`${styleText('bold', 'Created:')} ${newDir}/${filePath}`));
|
|
65
65
|
}
|
|
66
66
|
if (functionConfig) {
|
|
67
67
|
log('');
|
|
68
|
-
log(
|
|
68
|
+
log(styleText('bold', `Add the following to ${blueprint.fileInfo.fileName}:`));
|
|
69
69
|
const configString = JSON.stringify(functionConfig, null, 2);
|
|
70
70
|
if (blueprint.fileInfo.extension === '.json') {
|
|
71
71
|
log(indent(highlight(configString)));
|
|
@@ -111,7 +111,7 @@ export async function functionAddCore(options) {
|
|
|
111
111
|
if (flagResourceName && !validateFunctionName(flagResourceName)) {
|
|
112
112
|
return {
|
|
113
113
|
success: false,
|
|
114
|
-
error: `Invalid function name: "${
|
|
114
|
+
error: `Invalid function name: "${styleText('bold', flagResourceName)}"`,
|
|
115
115
|
};
|
|
116
116
|
}
|
|
117
117
|
try {
|
|
@@ -119,7 +119,7 @@ export async function functionAddCore(options) {
|
|
|
119
119
|
if (blueprint.parsedBlueprint.resources?.some((r) => r.name === fnName)) {
|
|
120
120
|
return {
|
|
121
121
|
success: false,
|
|
122
|
-
error: `Function "${
|
|
122
|
+
error: `Function "${styleText('bold', fnName)}" already exists.`,
|
|
123
123
|
};
|
|
124
124
|
}
|
|
125
125
|
let fnTypes;
|
|
@@ -176,7 +176,7 @@ export async function functionAddCore(options) {
|
|
|
176
176
|
installCommand = addHelpers ? await promptForInstallCommand() : null;
|
|
177
177
|
}
|
|
178
178
|
if (installCommand)
|
|
179
|
-
log(`${
|
|
179
|
+
log(`${styleText('magenta', 'Installing')} with ${installCommand}...`);
|
|
180
180
|
const { filePath, resourceAdded, resource } = await createFunctionResource({
|
|
181
181
|
blueprintFilePath,
|
|
182
182
|
name: fnName,
|
|
@@ -187,7 +187,7 @@ export async function functionAddCore(options) {
|
|
|
187
187
|
}, log);
|
|
188
188
|
log(`\nCreated function: ${filePath.replace(root, '')}`);
|
|
189
189
|
if (!resourceAdded) {
|
|
190
|
-
log(`\n${
|
|
190
|
+
log(`\n${styleText('bold', 'Add the Resource to your Blueprint:')}`);
|
|
191
191
|
switch (blueprint.fileInfo.extension) {
|
|
192
192
|
case '.ts':
|
|
193
193
|
case '.js':
|
|
@@ -201,7 +201,7 @@ export async function functionAddCore(options) {
|
|
|
201
201
|
}
|
|
202
202
|
}
|
|
203
203
|
else {
|
|
204
|
-
log(`Function "${
|
|
204
|
+
log(`Function "${styleText('bold', fnName)}" added to Blueprint file.`);
|
|
205
205
|
}
|
|
206
206
|
return { success: true };
|
|
207
207
|
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import chalk from 'chalk';
|
|
2
1
|
import { update } from '../../../actions/functions/env/update.js';
|
|
3
2
|
import { findFunctionInStack } from '../../../utils/find-function.js';
|
|
3
|
+
import { styleText } from '../../../utils/style-text.js';
|
|
4
4
|
export async function functionEnvAddCore(options) {
|
|
5
5
|
const { args, log } = options;
|
|
6
6
|
const spinner = log.ora(`Updating "${args.key}" environment variable in "${args.name}"`).start();
|
|
7
7
|
const { externalId } = findFunctionInStack(options.deployedStack, args.name);
|
|
8
8
|
const result = await update(externalId, args.key, args.value, options.auth, options.log);
|
|
9
9
|
if (!result.ok) {
|
|
10
|
-
spinner.fail(`${
|
|
10
|
+
spinner.fail(`${styleText('red', 'Failed')} to update ${args.key}`);
|
|
11
11
|
return {
|
|
12
12
|
success: false,
|
|
13
13
|
error: result.error || 'Unknown error',
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import chalk from 'chalk';
|
|
2
1
|
import { remove } from '../../../actions/functions/env/remove.js';
|
|
3
2
|
import { findFunctionInStack } from '../../../utils/find-function.js';
|
|
3
|
+
import { styleText } from '../../../utils/style-text.js';
|
|
4
4
|
export async function functionEnvRemoveCore(options) {
|
|
5
5
|
const { args, log } = options;
|
|
6
6
|
const spinner = log.ora(`Removing "${args.key}" environment variable in "${args.name}"`).start();
|
|
7
7
|
const { externalId } = findFunctionInStack(options.deployedStack, args.name);
|
|
8
8
|
const result = await remove(externalId, args.key, options.auth, options.log);
|
|
9
9
|
if (!result.ok) {
|
|
10
|
-
spinner.fail(`${
|
|
10
|
+
spinner.fail(`${styleText('red', 'Failed')} to remove ${args.key}`);
|
|
11
11
|
return { success: false, error: result.error || 'Unknown error' };
|
|
12
12
|
}
|
|
13
13
|
spinner.succeed(`Removal of ${args.key} succeeded`);
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { confirm } from '@inquirer/prompts';
|
|
2
|
-
import chalk from 'chalk';
|
|
3
2
|
import { deleteLogs as deleteLogsAction, logs as getLogsAction, streamLogs as streamLogsAction, } from '../../actions/functions/logs.js';
|
|
4
3
|
import { formatTitle } from '../../utils/display/blueprints-formatting.js';
|
|
5
4
|
import { niceId } from '../../utils/display/presenters.js';
|
|
6
5
|
import { findFunctionInStack, getFunctionNames } from '../../utils/find-function.js';
|
|
6
|
+
import { styleText } from '../../utils/style-text.js';
|
|
7
7
|
export async function functionLogsCore(options) {
|
|
8
8
|
const { args, flags, log, error, auth, deployedStack, blueprint, helpText } = options;
|
|
9
9
|
const { name } = args;
|
|
@@ -27,16 +27,16 @@ export async function functionLogsCore(options) {
|
|
|
27
27
|
async function deleteLogs({ name, externalId, auth, force, log, }) {
|
|
28
28
|
if (!force) {
|
|
29
29
|
const certain = await confirm({
|
|
30
|
-
message: `Are you sure you want to delete ${
|
|
30
|
+
message: `Are you sure you want to delete ${styleText('bold', 'all')} logs for function ${styleText('yellow', name)}?`,
|
|
31
31
|
default: false,
|
|
32
32
|
});
|
|
33
33
|
if (!certain)
|
|
34
34
|
return { success: true };
|
|
35
35
|
}
|
|
36
|
-
const spinner = log.ora(`Deleting logs for function ${
|
|
36
|
+
const spinner = log.ora(`Deleting logs for function ${styleText('yellow', name)}`).start();
|
|
37
37
|
const { ok, error } = await deleteLogsAction(externalId, auth, log);
|
|
38
38
|
if (!ok) {
|
|
39
|
-
spinner.fail(`${
|
|
39
|
+
spinner.fail(`${styleText('red', 'Failed')} to delete logs`);
|
|
40
40
|
return { success: false, error: error || 'Unknown error' };
|
|
41
41
|
}
|
|
42
42
|
spinner.succeed('Logs deleted');
|
|
@@ -47,18 +47,18 @@ async function streamLogs({ name, externalId, auth, log, }) {
|
|
|
47
47
|
try {
|
|
48
48
|
spinner.stop();
|
|
49
49
|
log(`Streaming log session for function ${niceId(name)}`);
|
|
50
|
-
log(`Watching for new logs... ${
|
|
50
|
+
log(`Watching for new logs... ${styleText('bold', 'ctrl+c')} to stop`);
|
|
51
51
|
let alreadyOpened = false;
|
|
52
52
|
const onOpen = () => {
|
|
53
53
|
if (alreadyOpened)
|
|
54
|
-
log(`${
|
|
54
|
+
log(`${styleText('green', 'Reconnected')}`);
|
|
55
55
|
alreadyOpened = true;
|
|
56
56
|
};
|
|
57
57
|
const renderLog = (logEntry) => {
|
|
58
58
|
const { time, level, message } = logEntry;
|
|
59
59
|
log(formatLog(time, level, message, true));
|
|
60
60
|
};
|
|
61
|
-
streamLogsAction(externalId, auth, renderLog, onOpen, (error) => log.error(`${
|
|
61
|
+
streamLogsAction(externalId, auth, renderLog, onOpen, (error) => log.error(`${styleText('red', 'Error:')} ${error}`), log);
|
|
62
62
|
// Return a special key for streaming mode
|
|
63
63
|
return {
|
|
64
64
|
success: true,
|
|
@@ -76,7 +76,7 @@ async function getLogs({ name, externalId, auth, limit, json, utc, log, }) {
|
|
|
76
76
|
const spinner = log.ora(`Finding logs for function "${name}"`).start();
|
|
77
77
|
const { ok, error, logs, total } = await getLogsAction(externalId, { limit }, auth, log);
|
|
78
78
|
if (!ok) {
|
|
79
|
-
spinner.fail(`${
|
|
79
|
+
spinner.fail(`${styleText('red', 'Failed')} to retrieve logs`);
|
|
80
80
|
return { success: false, error: error || 'Unknown error' };
|
|
81
81
|
}
|
|
82
82
|
const filteredLogs = logs.filter((entry) => entry.level && entry.message);
|
|
@@ -86,9 +86,9 @@ async function getLogs({ name, externalId, auth, limit, json, utc, log, }) {
|
|
|
86
86
|
}
|
|
87
87
|
spinner.succeed(`${formatTitle('Function', name)} Logs`);
|
|
88
88
|
if (!json) {
|
|
89
|
-
log(`Found ${
|
|
89
|
+
log(`Found ${styleText('bold', String(total))} log entries for function ${styleText('yellow', name)}`);
|
|
90
90
|
if (logs.length < total) {
|
|
91
|
-
log(`Here are the last ${
|
|
91
|
+
log(`Here are the last ${styleText('bold', filteredLogs.length.toString())} entries`);
|
|
92
92
|
}
|
|
93
93
|
log('\n');
|
|
94
94
|
for (const { time, level, message } of filteredLogs) {
|
|
@@ -106,16 +106,16 @@ function formatLog(time, level, message, utc) {
|
|
|
106
106
|
? date.toISOString().slice(0, 19).split('T')
|
|
107
107
|
: [date.toLocaleDateString(), date.toLocaleTimeString()];
|
|
108
108
|
return [
|
|
109
|
-
|
|
110
|
-
|
|
109
|
+
styleText('bold', dateString),
|
|
110
|
+
styleText(['bold', 'blue'], timeString),
|
|
111
111
|
logLevel(level.toUpperCase()),
|
|
112
112
|
message,
|
|
113
113
|
].join(' ');
|
|
114
114
|
}
|
|
115
115
|
function logLevel(level) {
|
|
116
116
|
if (level === 'ERROR')
|
|
117
|
-
return
|
|
117
|
+
return styleText('red', level);
|
|
118
118
|
if (level === 'WARN')
|
|
119
|
-
return
|
|
120
|
-
return
|
|
119
|
+
return styleText('yellow', level);
|
|
120
|
+
return styleText('green', level);
|
|
121
121
|
}
|
|
@@ -82,7 +82,17 @@ function projects() {
|
|
|
82
82
|
return fetch('/projects')
|
|
83
83
|
.then((response) => response.json())
|
|
84
84
|
.then(async (projects) => {
|
|
85
|
-
store.projects = projects
|
|
85
|
+
store.projects = projects.sort((a, b) => {
|
|
86
|
+
const nameA = a.displayName.toUpperCase()
|
|
87
|
+
const nameB = b.displayName.toUpperCase()
|
|
88
|
+
if (nameA < nameB) {
|
|
89
|
+
return -1
|
|
90
|
+
}
|
|
91
|
+
if (nameA > nameB) {
|
|
92
|
+
return 1
|
|
93
|
+
}
|
|
94
|
+
return 0
|
|
95
|
+
})
|
|
86
96
|
store.selectedProject = store.defaultProject ? store.defaultProject : projects[0].id
|
|
87
97
|
await datasets(store.selectedProject)
|
|
88
98
|
})
|
|
@@ -98,7 +108,17 @@ function datasets(selectedProject) {
|
|
|
98
108
|
return fetch(`/datasets?project=${selectedProject}`)
|
|
99
109
|
.then((response) => response.json())
|
|
100
110
|
.then((datasets) => {
|
|
101
|
-
store.datasets = datasets
|
|
111
|
+
store.datasets = datasets.sort((a, b) => {
|
|
112
|
+
const nameA = a.name.toUpperCase()
|
|
113
|
+
const nameB = b.name.toUpperCase()
|
|
114
|
+
if (nameA < nameB) {
|
|
115
|
+
return -1
|
|
116
|
+
}
|
|
117
|
+
if (nameA > nameB) {
|
|
118
|
+
return 1
|
|
119
|
+
}
|
|
120
|
+
return 0
|
|
121
|
+
})
|
|
102
122
|
store.selectedDataset = datasets[0].name
|
|
103
123
|
})
|
|
104
124
|
.catch(() => {
|
|
@@ -78,11 +78,9 @@ class RunPanel extends ApiBaseElement {
|
|
|
78
78
|
this.api.invoke({context, event, metadata})
|
|
79
79
|
}
|
|
80
80
|
createPayloadText = (doc) => {
|
|
81
|
-
if (doc
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
if (doc.children) {
|
|
85
|
-
return doc.children.map((child) => child.text.join('')).join('') || '{}'
|
|
81
|
+
if (doc) {
|
|
82
|
+
const payload = doc.toString().trim()
|
|
83
|
+
return payload ? payload : '{}'
|
|
86
84
|
}
|
|
87
85
|
return '{}'
|
|
88
86
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { treeify } from 'array-treeify';
|
|
2
|
-
import chalk from 'chalk';
|
|
3
2
|
import { SANITY_ACCESS_ROBOT, SANITY_ACCESS_ROLE, SANITY_FUNCTION_DOCUMENT, SANITY_FUNCTION_MEDIA_LIBRARY_ASSET, SANITY_FUNCTION_SCHEDULE, SANITY_PROJECT_CORS, SANITY_PROJECT_DATASET, SANITY_PROJECT_WEBHOOK, } from '../../constants.js';
|
|
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';
|
|
6
6
|
import { niceId } from './presenters.js';
|
|
@@ -54,22 +54,22 @@ const categoryByLabel = Object.values(RESOURCE_CATEGORIES).reduce((acc, curr) =>
|
|
|
54
54
|
return acc;
|
|
55
55
|
}, {});
|
|
56
56
|
function resourceName(res, displayNameAttribute) {
|
|
57
|
-
const nameParts = [
|
|
57
|
+
const nameParts = [styleText(['bold', 'green'], res.name)];
|
|
58
58
|
const displayName = displayNameAttribute &&
|
|
59
59
|
displayNameAttribute in res &&
|
|
60
60
|
typeof res[displayNameAttribute] === 'string' &&
|
|
61
61
|
res[displayNameAttribute];
|
|
62
62
|
if (displayName && displayName !== res.name)
|
|
63
|
-
nameParts.push(
|
|
63
|
+
nameParts.push(styleText('green', `"${displayName}"`));
|
|
64
64
|
return nameParts.join(' ');
|
|
65
65
|
}
|
|
66
66
|
function deployedResourceName(res, displayNameAttribute, _verbose = false) {
|
|
67
|
-
const nameParts = [
|
|
67
|
+
const nameParts = [styleText(['bold', 'green'], res.name)];
|
|
68
68
|
const displayName = displayNameAttribute &&
|
|
69
69
|
typeof res.parameters[displayNameAttribute] === 'string' &&
|
|
70
70
|
res.parameters[displayNameAttribute];
|
|
71
71
|
if (displayName && displayName !== res.name)
|
|
72
|
-
nameParts.push(
|
|
72
|
+
nameParts.push(styleText('green', `"${displayName}"`));
|
|
73
73
|
// if (verbose)
|
|
74
74
|
nameParts.push(idList(res));
|
|
75
75
|
return nameParts.join(' ');
|
|
@@ -85,7 +85,7 @@ function idList(res) {
|
|
|
85
85
|
return ids.length > 0 ? ids.join(' ') : '';
|
|
86
86
|
}
|
|
87
87
|
export function formatTitle(title, name) {
|
|
88
|
-
return `${
|
|
88
|
+
return `${styleText(['bold', 'blue'], title)} ${styleText('bold', `"${name}"`)}`;
|
|
89
89
|
}
|
|
90
90
|
function categorizeResources(resources) {
|
|
91
91
|
const categorized = {};
|
|
@@ -108,13 +108,15 @@ function categorizeResources(resources) {
|
|
|
108
108
|
return categorized;
|
|
109
109
|
}
|
|
110
110
|
function buildOutputTree(resources, createName, mapToResource, verbose = false) {
|
|
111
|
-
const output = [
|
|
111
|
+
const output = [
|
|
112
|
+
`${styleText(['bold', 'underline'], 'Resources')} [${resources.length}]`,
|
|
113
|
+
];
|
|
112
114
|
const children = [];
|
|
113
115
|
const categorized = categorizeResources(resources);
|
|
114
116
|
for (const category of Object.values(categoryByLabel)) {
|
|
115
117
|
const catResources = categorized[category.label];
|
|
116
118
|
if (catResources && catResources.length > 0) {
|
|
117
|
-
children.push(`${
|
|
119
|
+
children.push(`${styleText('bold', category.label)} [${catResources.length}]`);
|
|
118
120
|
const details = [];
|
|
119
121
|
for (const res of catResources) {
|
|
120
122
|
details.push(createName(category, res, verbose));
|
|
@@ -126,9 +128,9 @@ function buildOutputTree(resources, createName, mapToResource, verbose = false)
|
|
|
126
128
|
}
|
|
127
129
|
}
|
|
128
130
|
if (categorized['Other Resources'] && categorized['Other Resources'].length > 0) {
|
|
129
|
-
children.push(`${
|
|
131
|
+
children.push(`${styleText('bold', 'Other Resources')} [${categorized['Other Resources'].length}]`);
|
|
130
132
|
const otherResourcesOutput = categorized['Other Resources'].map((other) => {
|
|
131
|
-
return `${
|
|
133
|
+
return `${styleText('yellow', other.name ?? 'unnamed')} ${styleText('dim', other.type)}`;
|
|
132
134
|
});
|
|
133
135
|
children.push(otherResourcesOutput);
|
|
134
136
|
}
|
|
@@ -152,9 +154,9 @@ export function formatStackInfo(stack, isCurrentStack = false) {
|
|
|
152
154
|
const isProjectBasedStack = isStack && stack.id === `ST-${stack.scopeId}`;
|
|
153
155
|
const output = [];
|
|
154
156
|
if (isStack) {
|
|
155
|
-
let stackName =
|
|
157
|
+
let stackName = styleText('bold', `"${stack.name}"`);
|
|
156
158
|
if (isCurrentStack)
|
|
157
|
-
stackName = `${
|
|
159
|
+
stackName = `${styleText('blue', stackName)} (current)`;
|
|
158
160
|
if (isProjectBasedStack)
|
|
159
161
|
stackName += ' (project-based)';
|
|
160
162
|
output.push(`${stackName} ${niceId(stack.id)}`);
|
|
@@ -180,15 +182,15 @@ export function formatStackInfo(stack, isCurrentStack = false) {
|
|
|
180
182
|
if (operation.id)
|
|
181
183
|
operationOutput.push(`Recent Operation ${niceId(operation.id)}:`);
|
|
182
184
|
if (operation.status) {
|
|
183
|
-
const operationColor = operation.status === 'COMPLETED' ?
|
|
185
|
+
const operationColor = operation.status === 'COMPLETED' ? 'green' : 'red';
|
|
184
186
|
const status = operation.status || 'UNKNOWN';
|
|
185
|
-
operationOutput.push(`Status: ${operationColor
|
|
187
|
+
operationOutput.push(`Status: ${styleText(operationColor, status)}`);
|
|
186
188
|
}
|
|
187
189
|
if (operation.createdAt)
|
|
188
190
|
operationOutput.push(`Started: ${formatDate(operation.createdAt)}`);
|
|
189
191
|
if (operation.status === 'COMPLETED' && operation.completedAt && operation.createdAt) {
|
|
190
192
|
operationOutput.push(`Completed: ${formatDate(operation.completedAt)}`);
|
|
191
|
-
operationOutput.push(`Duration: ${
|
|
193
|
+
operationOutput.push(`Duration: ${styleText('yellow', formatDuration(operation.createdAt, operation.completedAt))}`);
|
|
192
194
|
}
|
|
193
195
|
infoOutput.push(operationOutput);
|
|
194
196
|
}
|
|
@@ -225,10 +227,10 @@ export function stackDeployDiff(localBlueprint, deployedStack) {
|
|
|
225
227
|
return null;
|
|
226
228
|
const output = [];
|
|
227
229
|
if (added.length > 0) {
|
|
228
|
-
output.push(` ${
|
|
230
|
+
output.push(` ${styleText(['bold', 'greenBright'], '++')} ${added.map(({ name }) => styleText(['bgGreen', 'whiteBright'], `"${name}"`)).join(' ')}`);
|
|
229
231
|
}
|
|
230
232
|
if (removed.length > 0) {
|
|
231
|
-
output.push(` ${
|
|
233
|
+
output.push(` ${styleText(['bold', 'redBright'], '--')} ${removed.map(({ name }) => styleText(['bgRed', 'whiteBright'], `"${name}"`)).join(' ')}`);
|
|
232
234
|
}
|
|
233
235
|
return output.join('\n');
|
|
234
236
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { treeify } from 'array-treeify';
|
|
2
|
-
import
|
|
2
|
+
import { styleText } from '../style-text.js';
|
|
3
3
|
export function formatLogEntry(log, withDate = true, isNewest = false) {
|
|
4
4
|
const date = new Date(log.timestamp);
|
|
5
5
|
const time = date.toLocaleTimeString();
|
|
6
6
|
const day = date.toLocaleDateString();
|
|
7
|
-
return `${isNewest ? `${
|
|
7
|
+
return `${isNewest ? `${styleText('green', '>')} ` : ''}${withDate ? `${day} ` : ''}${styleText('dim', time)} ${log.message}`;
|
|
8
8
|
}
|
|
9
9
|
export function organizeLogsByDay(logs) {
|
|
10
10
|
const logsByDay = new Map();
|
|
@@ -23,7 +23,7 @@ export function formatLogsByDay(logsByDay) {
|
|
|
23
23
|
return new Date(a).getTime() - new Date(b).getTime();
|
|
24
24
|
});
|
|
25
25
|
for (const day of sortedDays) {
|
|
26
|
-
output.push(`${
|
|
26
|
+
output.push(`${styleText('blue', 'Date:')} ${styleText('bold', day)}`);
|
|
27
27
|
const dayLogs = logsByDay.get(day) || [];
|
|
28
28
|
dayLogs.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
|
|
29
29
|
const dayLogsOutput = dayLogs.map((log) => formatLogEntry(log, false));
|
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
import { cwd } from 'node:process';
|
|
2
|
-
import
|
|
2
|
+
import { styleText } from '../style-text.js';
|
|
3
3
|
export function check(str) {
|
|
4
|
-
return `${
|
|
4
|
+
return `${styleText('bold', styleText('green', '✔︎'))} ${str}`;
|
|
5
5
|
}
|
|
6
6
|
export function info(str) {
|
|
7
|
-
return `${
|
|
7
|
+
return `${styleText(['bold', 'blue'], 'ℹ︎')} ${str}`;
|
|
8
8
|
}
|
|
9
9
|
export function warn(str) {
|
|
10
|
-
return `${
|
|
10
|
+
return `${styleText(['bold', 'yellow'], '▶︎')} ${str}`;
|
|
11
11
|
}
|
|
12
12
|
export function unsure(str) {
|
|
13
|
-
return `${
|
|
13
|
+
return `${styleText(['bold', 'cyan'], '?')} ${str}`;
|
|
14
14
|
}
|
|
15
15
|
export function severe(str) {
|
|
16
|
-
return `${
|
|
16
|
+
return `${styleText(['bold', 'red'], '✘')} ${str}`;
|
|
17
17
|
}
|
|
18
18
|
export function niceId(id) {
|
|
19
19
|
if (!id)
|
|
20
20
|
return '';
|
|
21
|
-
return `<${
|
|
21
|
+
return `<${styleText('yellow', id)}>`;
|
|
22
22
|
}
|
|
23
23
|
export function indent(str, spaces = 2) {
|
|
24
24
|
const pad = ' '.repeat(spaces);
|
|
@@ -34,5 +34,5 @@ export function filePathRelativeToCwd(filePath) {
|
|
|
34
34
|
return filePath.replace(cwd(), '.');
|
|
35
35
|
}
|
|
36
36
|
export function labeledId(label, id) {
|
|
37
|
-
return `${
|
|
37
|
+
return `${styleText('blue', capitalize(label || 'unknown'))} ${niceId(id || 'unknown')}`;
|
|
38
38
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { confirm, input, Separator, select } from '@inquirer/prompts';
|
|
2
|
-
import chalk from 'chalk';
|
|
3
2
|
import { createEmptyStack, listStacks } from '../../actions/blueprints/stacks.js';
|
|
4
3
|
import { groupProjectsByOrganization } from '../../actions/sanity/projects.js';
|
|
4
|
+
import { styleText } from '../style-text.js';
|
|
5
5
|
import { niceId } from './presenters.js';
|
|
6
6
|
export async function promptForBlueprintType() {
|
|
7
7
|
return await select({
|
|
@@ -91,11 +91,11 @@ export async function promptForStack({ projectId, token, logger, }) {
|
|
|
91
91
|
let pickedStackId = NEW_STACK_ID;
|
|
92
92
|
if (stacks.length > 0) {
|
|
93
93
|
const stackChoices = [];
|
|
94
|
-
stackChoices.push(new Separator(
|
|
95
|
-
stackChoices.push({ name:
|
|
96
|
-
stackChoices.push(new Separator(
|
|
94
|
+
stackChoices.push(new Separator(styleText('underline', 'Create a new Stack:')));
|
|
95
|
+
stackChoices.push({ name: styleText('bold', 'New Stack ✨'), value: NEW_STACK_ID });
|
|
96
|
+
stackChoices.push(new Separator(styleText('underline', 'Use an existing Stack:')));
|
|
97
97
|
stackChoices.push(...stacks.map((s) => ({
|
|
98
|
-
name: `"${s.name}" ${niceId(s.id)} ${
|
|
98
|
+
name: `"${s.name}" ${niceId(s.id)} ${styleText('dim', `(${s.resources.length} res)`)}`,
|
|
99
99
|
value: s.id,
|
|
100
100
|
})));
|
|
101
101
|
pickedStackId = await select({
|