@sanity/runtime-cli 7.6.7 → 8.0.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 +65 -25
- package/bin/dev.cmd +1 -1
- package/bin/dev.js +1 -1
- package/dist/actions/blueprints/blueprint.d.ts +20 -2
- package/dist/actions/blueprints/blueprint.js +88 -35
- package/dist/actions/blueprints/resources.js +1 -13
- package/dist/actions/blueprints/stacks.d.ts +6 -0
- package/dist/actions/blueprints/stacks.js +17 -3
- package/dist/commands/blueprints/add.d.ts +1 -1
- package/dist/commands/blueprints/add.js +2 -5
- package/dist/commands/blueprints/config.js +1 -3
- package/dist/commands/blueprints/destroy.js +1 -4
- package/dist/commands/blueprints/info.js +1 -3
- package/dist/commands/blueprints/init.js +2 -6
- package/dist/commands/blueprints/stacks.d.ts +1 -2
- package/dist/commands/blueprints/stacks.js +3 -5
- package/dist/cores/blueprints/add.js +26 -7
- package/dist/cores/blueprints/config.js +3 -28
- package/dist/cores/blueprints/init.js +45 -75
- package/dist/cores/blueprints/plan.js +3 -3
- package/dist/cores/blueprints/stacks.d.ts +1 -1
- package/dist/cores/blueprints/stacks.js +2 -2
- package/dist/utils/display/blueprints-formatting.js +3 -3
- package/dist/utils/display/presenters.d.ts +1 -0
- package/dist/utils/display/presenters.js +6 -3
- package/dist/utils/display/prompt.d.ts +4 -0
- package/dist/utils/display/prompt.js +44 -1
- package/dist/utils/other/npmjs.d.ts +1 -0
- package/dist/utils/other/npmjs.js +13 -0
- package/oclif.manifest.json +18 -19
- package/package.json +6 -7
- package/dist/utils/format-error.d.ts +0 -4
- package/dist/utils/format-error.js +0 -9
- package/dist/utils/is-dependency.d.ts +0 -1
- package/dist/utils/is-dependency.js +0 -7
|
@@ -5,13 +5,11 @@ export default class InfoCommand extends DeployedBlueprintCommand {
|
|
|
5
5
|
static description = 'Show information about a Blueprint deployment';
|
|
6
6
|
static examples = [
|
|
7
7
|
'<%= config.bin %> <%= command.id %>',
|
|
8
|
-
|
|
9
|
-
// '<%= config.bin %> <%= command.id %> --id ST-a1b2c3',
|
|
8
|
+
'<%= config.bin %> <%= command.id %> --stack-id <stackId>',
|
|
10
9
|
];
|
|
11
10
|
static flags = {
|
|
12
11
|
id: Flags.string({
|
|
13
12
|
description: 'Stack ID to show info for (defaults to current stack)',
|
|
14
|
-
hidden: true, // LAUNCH LIMIT: 1 Stack per Project
|
|
15
13
|
}),
|
|
16
14
|
};
|
|
17
15
|
async run() {
|
|
@@ -7,10 +7,8 @@ export default class InitCommand extends Command {
|
|
|
7
7
|
'<%= config.bin %> <%= command.id %>',
|
|
8
8
|
'<%= config.bin %> <%= command.id %> [directory]',
|
|
9
9
|
'<%= config.bin %> <%= command.id %> --blueprint-type <json|js|ts>',
|
|
10
|
-
'<%= config.bin %> <%= command.id %> --blueprint-type <json|js|ts> --project-id <projectId>',
|
|
11
|
-
|
|
12
|
-
// '<%= config.bin %> <%= command.id %> --blueprint-type <json|js|ts> --project-id <projectId> --stack-id <stackId>',
|
|
13
|
-
// '<%= config.bin %> <%= command.id %> --blueprint-type <json|js|ts> --project-id <projectId> --stack-name <stackName>',
|
|
10
|
+
'<%= config.bin %> <%= command.id %> --blueprint-type <json|js|ts> --project-id <projectId> --stack-id <stackId>',
|
|
11
|
+
'<%= config.bin %> <%= command.id %> --blueprint-type <json|js|ts> --stack-name <stackName>',
|
|
14
12
|
];
|
|
15
13
|
static args = {
|
|
16
14
|
dir: Args.string({
|
|
@@ -35,13 +33,11 @@ export default class InitCommand extends Command {
|
|
|
35
33
|
aliases: ['stack', 'stackId'],
|
|
36
34
|
dependsOn: ['project-id'],
|
|
37
35
|
exclusive: ['stack-name'],
|
|
38
|
-
hidden: true, // LAUNCH LIMIT: 1 Stack per Project
|
|
39
36
|
}),
|
|
40
37
|
'stack-name': Flags.string({
|
|
41
38
|
description: 'Name to use for a NEW Stack',
|
|
42
39
|
aliases: ['name'],
|
|
43
40
|
exclusive: ['stack-id'],
|
|
44
|
-
hidden: true, // LAUNCH LIMIT: 1 Stack per Project
|
|
45
41
|
}),
|
|
46
42
|
};
|
|
47
43
|
async run() {
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { BlueprintCommand } from '../../baseCommands.js';
|
|
2
2
|
export default class StacksCommand extends BlueprintCommand<typeof StacksCommand> {
|
|
3
|
-
static hidden: boolean;
|
|
4
3
|
static description: string;
|
|
5
4
|
static examples: string[];
|
|
6
5
|
static flags: {
|
|
7
|
-
|
|
6
|
+
'project-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
8
7
|
};
|
|
9
8
|
run(): Promise<void>;
|
|
10
9
|
}
|
|
@@ -2,17 +2,15 @@ import { Flags } from '@oclif/core';
|
|
|
2
2
|
import { BlueprintCommand } from '../../baseCommands.js';
|
|
3
3
|
import { blueprintStacksCore } from '../../cores/blueprints/stacks.js';
|
|
4
4
|
export default class StacksCommand extends BlueprintCommand {
|
|
5
|
-
// LAUNCH LIMIT: 1 Stack per Project - hide stacks command
|
|
6
|
-
static hidden = true;
|
|
7
5
|
static description = 'List all Blueprint stacks';
|
|
8
6
|
static examples = [
|
|
9
7
|
'<%= config.bin %> <%= command.id %>',
|
|
10
|
-
'<%= config.bin %> <%= command.id %> --projectId
|
|
8
|
+
'<%= config.bin %> <%= command.id %> --project-id <projectId>',
|
|
11
9
|
];
|
|
12
10
|
static flags = {
|
|
13
|
-
|
|
11
|
+
'project-id': Flags.string({
|
|
14
12
|
description: 'Project ID to show stacks for',
|
|
15
|
-
|
|
13
|
+
aliases: ['projectId', 'project'],
|
|
16
14
|
}),
|
|
17
15
|
};
|
|
18
16
|
async run() {
|
|
@@ -1,9 +1,21 @@
|
|
|
1
1
|
import { cwd } from 'node:process';
|
|
2
|
+
import { highlight } from 'cardinal';
|
|
2
3
|
import chalk from 'chalk';
|
|
3
|
-
import highlight from 'color-json';
|
|
4
4
|
import inquirer from 'inquirer';
|
|
5
5
|
import { createFunctionResource } from '../../actions/blueprints/resources.js';
|
|
6
6
|
import { validateFunctionName } from '../../utils/validate/resource.js';
|
|
7
|
+
const FUNCTION_BLUEPRINT_RESOURCE_TEMPLATE = `
|
|
8
|
+
import {defineBlueprint, defineDocumentFunction} from '@sanity/blueprints'
|
|
9
|
+
// update imports ↑
|
|
10
|
+
|
|
11
|
+
export default defineBlueprint({
|
|
12
|
+
// ...
|
|
13
|
+
resources: [
|
|
14
|
+
// ...
|
|
15
|
+
defineDocumentFunction({name: '{{fnName}}'}), // ← add this line
|
|
16
|
+
],
|
|
17
|
+
})
|
|
18
|
+
`;
|
|
7
19
|
export async function blueprintAddCore(options) {
|
|
8
20
|
const { bin = 'sanity', log, blueprint, args, flags } = options;
|
|
9
21
|
const { type: resourceType } = args;
|
|
@@ -89,17 +101,24 @@ export async function blueprintAddCore(options) {
|
|
|
89
101
|
});
|
|
90
102
|
log(`\nCreated function: ${filePath.replace(cwd(), '')}`);
|
|
91
103
|
if (!resourceAdded) {
|
|
92
|
-
// print the resource
|
|
93
|
-
log('
|
|
94
|
-
|
|
104
|
+
// print the resource definition for manual addition
|
|
105
|
+
log(`\n${chalk.bold('Add the Resource to your Blueprint:')}`);
|
|
106
|
+
switch (blueprint.fileInfo.extension) {
|
|
107
|
+
case '.ts':
|
|
108
|
+
log(highlight(FUNCTION_BLUEPRINT_RESOURCE_TEMPLATE.replace('{{fnName}}', fnName)));
|
|
109
|
+
break;
|
|
110
|
+
case '.js':
|
|
111
|
+
log(highlight(FUNCTION_BLUEPRINT_RESOURCE_TEMPLATE.replace('{{fnName}}', fnName)));
|
|
112
|
+
break;
|
|
113
|
+
default:
|
|
114
|
+
log(highlight(JSON.stringify(resource, null, 2)));
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
95
117
|
}
|
|
96
118
|
else {
|
|
97
119
|
// added to blueprint.json
|
|
98
120
|
log(`Function "${chalk.bold(fnName)}" added to Blueprint file.`);
|
|
99
121
|
}
|
|
100
|
-
if (fnLang === 'ts') {
|
|
101
|
-
log(chalk.dim('Add "functions/**/.build/**" to your .gitignore.'));
|
|
102
|
-
}
|
|
103
122
|
return { success: true };
|
|
104
123
|
}
|
|
105
124
|
catch (err) {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import { highlight } from 'cardinal';
|
|
1
2
|
import chalk from 'chalk';
|
|
2
|
-
import highlight from 'color-json';
|
|
3
3
|
import inquirer from 'inquirer';
|
|
4
4
|
import ora from 'ora';
|
|
5
5
|
import { BLUEPRINT_CONFIG_FILE, BLUEPRINT_DIR, writeConfigFile, } from '../../actions/blueprints/blueprint.js';
|
|
6
|
-
import { createStack, getStack
|
|
6
|
+
import { createStack, getStack } from '../../actions/blueprints/stacks.js';
|
|
7
7
|
import { getProject } from '../../actions/sanity/projects.js';
|
|
8
8
|
import { niceId, warn } from '../../utils/display/presenters.js';
|
|
9
9
|
import { promptForProject } from '../../utils/display/prompt.js';
|
|
@@ -67,7 +67,7 @@ export async function blueprintConfigCore(options) {
|
|
|
67
67
|
// LAUNCH LIMIT: 1 Stack per Project - configStackId is always inferred from projectId if not set in config JSON
|
|
68
68
|
let updatedStackId = flagStackId ?? // flag first
|
|
69
69
|
configStackId ?? // existing config second
|
|
70
|
-
`ST-${updatedProjectId}`;
|
|
70
|
+
`ST-${updatedProjectId}`; //?? LAUNCH LIMIT: 1 Stack per Project - project-based third
|
|
71
71
|
// (await promptForStackId({projectId: updatedProjectId, knownStackId: configStackId})) // prompt for stackId
|
|
72
72
|
const isProjectBasedId = updatedStackId === `ST-${updatedProjectId}`;
|
|
73
73
|
log(`\n${chalk.bold('New configuration:')}`);
|
|
@@ -135,31 +135,6 @@ export async function blueprintConfigCore(options) {
|
|
|
135
135
|
return { success: false, error: 'Unknown error' };
|
|
136
136
|
}
|
|
137
137
|
}
|
|
138
|
-
async function promptForStackId({ token, projectId, knownStackId, }) {
|
|
139
|
-
const auth = { token, projectId };
|
|
140
|
-
// get stacks for selected project
|
|
141
|
-
const { ok: stacksOk, stacks, error: stacksError } = await listStacks(auth);
|
|
142
|
-
if (!stacksOk)
|
|
143
|
-
throw new Error(stacksError ?? 'Unknown error listing stacks');
|
|
144
|
-
if (stacks.length > 0) {
|
|
145
|
-
const stackChoices = stacks.map((s) => ({
|
|
146
|
-
name: `"${s.name}" ${niceId(s.id)} ${chalk.dim(`(${s.resources.length} res)`)}`,
|
|
147
|
-
value: s.id,
|
|
148
|
-
}));
|
|
149
|
-
stackChoices.push({ name: 'Unset Stack association', value: 'unset' });
|
|
150
|
-
const { pickedStackId } = await inquirer.prompt([
|
|
151
|
-
{
|
|
152
|
-
type: 'list',
|
|
153
|
-
name: 'pickedStackId',
|
|
154
|
-
message: 'Select a stack:',
|
|
155
|
-
choices: stackChoices,
|
|
156
|
-
default: knownStackId,
|
|
157
|
-
},
|
|
158
|
-
]);
|
|
159
|
-
return pickedStackId === 'unset' ? undefined : pickedStackId;
|
|
160
|
-
}
|
|
161
|
-
return undefined;
|
|
162
|
-
}
|
|
163
138
|
async function testConfigAndReport({ token, stackId, projectId, }) {
|
|
164
139
|
const spinner = ora('Testing the configuration...').start();
|
|
165
140
|
const { ok, error } = await getStack({
|
|
@@ -2,18 +2,18 @@ import { join } from 'node:path';
|
|
|
2
2
|
import { cwd } from 'node:process';
|
|
3
3
|
import chalk from 'chalk';
|
|
4
4
|
import inquirer from 'inquirer';
|
|
5
|
-
import { BLUEPRINT_CONFIG_FILE, BLUEPRINT_DIR, findBlueprintFile, writeBlueprintToDisk, writeConfigFile, } from '../../actions/blueprints/blueprint.js';
|
|
6
|
-
import {
|
|
5
|
+
import { BLUEPRINT_CONFIG_FILE, BLUEPRINT_DIR, findBlueprintFile, writeBlueprintToDisk, writeConfigFile, writeGitignoreFile, writeOrUpdateNodeDependency, } from '../../actions/blueprints/blueprint.js';
|
|
6
|
+
import { createEmptyStack, getStack } from '../../actions/blueprints/stacks.js';
|
|
7
7
|
import { getProject } from '../../actions/sanity/projects.js';
|
|
8
|
-
import {
|
|
9
|
-
import { promptForProject } from '../../utils/display/prompt.js';
|
|
8
|
+
import { check, warn } from '../../utils/display/presenters.js';
|
|
9
|
+
import { promptForProject, promptForStackId } from '../../utils/display/prompt.js';
|
|
10
10
|
const LAUNCH_LIMIT_STACK_PER_PROJECT = true;
|
|
11
11
|
export async function blueprintInitCore(options) {
|
|
12
|
-
const { log, token, args, flags } = options;
|
|
12
|
+
const { bin = 'sanity', log, token, args, flags } = options;
|
|
13
13
|
try {
|
|
14
14
|
const { 'blueprint-type': flagBlueprintType, 'project-id': flagProjectId, 'stack-id': flagStackId, 'stack-name': flagStackName, dir: flagDir, } = flags;
|
|
15
15
|
const { dir: argDir } = args;
|
|
16
|
-
const
|
|
16
|
+
const providedDir = argDir || flagDir;
|
|
17
17
|
const here = cwd();
|
|
18
18
|
const dir = argDir || flagDir || here;
|
|
19
19
|
const existingBlueprint = findBlueprintFile(dir);
|
|
@@ -30,6 +30,7 @@ export async function blueprintInitCore(options) {
|
|
|
30
30
|
const pickedProject = await promptForProject({ token });
|
|
31
31
|
projectId = pickedProject.projectId;
|
|
32
32
|
}
|
|
33
|
+
log('');
|
|
33
34
|
if (flagStackName) {
|
|
34
35
|
// using --stack-name gets around "LAUNCH LIMIT: 1 Stack per Project"
|
|
35
36
|
const stack = await createEmptyStack({
|
|
@@ -51,17 +52,40 @@ export async function blueprintInitCore(options) {
|
|
|
51
52
|
stackId = await promptForStackId({ projectId, token });
|
|
52
53
|
}
|
|
53
54
|
}
|
|
54
|
-
const fileName = `blueprint.${blueprintExtension}`;
|
|
55
|
+
const fileName = `sanity.blueprint.${blueprintExtension}`;
|
|
55
56
|
const filePath = join(dir, fileName);
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
writeBlueprintToDisk({
|
|
58
|
+
blueprintFilePath: filePath,
|
|
59
|
+
// content: {resources: [] /*projectId, stackId*/}, // TODO: in the future maybe set config in blueprint
|
|
60
|
+
});
|
|
61
|
+
if (providedDir)
|
|
62
|
+
log(check(`${chalk.bold('New folder created:')} ${providedDir}/`));
|
|
63
|
+
log(check(`${chalk.bold('Created Blueprint:')} ${providedDir ?? '.'}/${fileName}`));
|
|
60
64
|
writeConfigFile({ blueprintFilePath: filePath, projectId, stackId });
|
|
61
|
-
log(
|
|
62
|
-
|
|
63
|
-
|
|
65
|
+
log(check(`${chalk.bold('Added configuration:')} ${providedDir ?? '.'}/${BLUEPRINT_DIR}/${BLUEPRINT_CONFIG_FILE}`));
|
|
66
|
+
writeGitignoreFile({ blueprintFilePath: filePath });
|
|
67
|
+
log(check(`${chalk.bold('Added .gitignore:')} ${providedDir ?? '.'}/.gitignore`));
|
|
68
|
+
if (blueprintExtension !== 'json') {
|
|
69
|
+
try {
|
|
70
|
+
// check for || create package.json and add @sanity/blueprints to dependencies
|
|
71
|
+
await writeOrUpdateNodeDependency({
|
|
72
|
+
blueprintFilePath: filePath,
|
|
73
|
+
dependency: '@sanity/blueprints',
|
|
74
|
+
});
|
|
75
|
+
log(check(`${chalk.bold('Added dependency:')} @sanity/blueprints`));
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
log(warn('Unable to add @sanity/blueprints to your project.'));
|
|
79
|
+
}
|
|
64
80
|
}
|
|
81
|
+
const nextStepParts = [];
|
|
82
|
+
if (providedDir)
|
|
83
|
+
nextStepParts.push(`cd ./${providedDir}`);
|
|
84
|
+
if (blueprintExtension !== 'json')
|
|
85
|
+
nextStepParts.push('npm install');
|
|
86
|
+
nextStepParts.push(`${bin} blueprints --help`);
|
|
87
|
+
const nextStep = `Run \`${nextStepParts.join(' && ')}\``;
|
|
88
|
+
log(`\n ${chalk.dim(nextStep)} to get started`);
|
|
65
89
|
return { success: true };
|
|
66
90
|
}
|
|
67
91
|
catch (error) {
|
|
@@ -75,72 +99,17 @@ async function promptForBlueprintType() {
|
|
|
75
99
|
{
|
|
76
100
|
type: 'list',
|
|
77
101
|
name: 'pickedBlueprintsType',
|
|
78
|
-
message: 'Choose a
|
|
102
|
+
message: 'Choose a Blueprint file type:',
|
|
79
103
|
choices: [
|
|
104
|
+
{ name: 'TypeScript', value: 'ts' },
|
|
105
|
+
{ name: 'JavaScript', value: 'js' },
|
|
80
106
|
{ name: 'JSON', value: 'json' },
|
|
81
|
-
{ name: 'TypeScript', value: 'ts', disabled: '(Coming soon)' },
|
|
82
|
-
{ name: 'JavaScript', value: 'js', disabled: '(Coming soon)' },
|
|
83
107
|
],
|
|
84
|
-
default: '
|
|
108
|
+
default: 'ts',
|
|
85
109
|
},
|
|
86
110
|
]);
|
|
87
111
|
return pickedBlueprintsType;
|
|
88
112
|
}
|
|
89
|
-
async function promptForStackId({ projectId, token, }) {
|
|
90
|
-
const { ok: stacksOk, error: stacksErr, stacks } = await listStacks({ token, projectId });
|
|
91
|
-
if (!stacksOk) {
|
|
92
|
-
throw new Error(stacksErr || 'Failed to list Stacks');
|
|
93
|
-
}
|
|
94
|
-
const stackChoices = [
|
|
95
|
-
{ name: chalk.bold('✨ Create a new Stack'), value: 'new' },
|
|
96
|
-
];
|
|
97
|
-
if (stacks.length > 0) {
|
|
98
|
-
stackChoices.push(new inquirer.Separator(chalk.underline('Use an existing Stack:')));
|
|
99
|
-
stackChoices.push(...stacks.map((s) => ({
|
|
100
|
-
name: `"${s.name}" ${niceId(s.id)} ${chalk.dim(`(${s.resources.length} res)`)}`,
|
|
101
|
-
value: s.id,
|
|
102
|
-
})));
|
|
103
|
-
}
|
|
104
|
-
const { pickedStackId } = await inquirer.prompt([
|
|
105
|
-
{
|
|
106
|
-
type: 'list',
|
|
107
|
-
name: 'pickedStackId',
|
|
108
|
-
message: 'Select an existing deployment or create a new one:',
|
|
109
|
-
choices: stackChoices,
|
|
110
|
-
},
|
|
111
|
-
]);
|
|
112
|
-
if (pickedStackId === 'new') {
|
|
113
|
-
const { stackName } = await inquirer.prompt([
|
|
114
|
-
{
|
|
115
|
-
type: 'input',
|
|
116
|
-
name: 'stackName',
|
|
117
|
-
message: 'Enter a name for your Stack:',
|
|
118
|
-
validate: (input) => input.length > 0 || 'Stack name is required',
|
|
119
|
-
},
|
|
120
|
-
]);
|
|
121
|
-
const stack = await createEmptyStack({
|
|
122
|
-
token,
|
|
123
|
-
projectId,
|
|
124
|
-
name: stackName,
|
|
125
|
-
});
|
|
126
|
-
return stack.id;
|
|
127
|
-
}
|
|
128
|
-
return pickedStackId;
|
|
129
|
-
}
|
|
130
|
-
async function createEmptyStack({ token, projectId, name, projectBased = true, }) {
|
|
131
|
-
const stackPayload = {
|
|
132
|
-
name,
|
|
133
|
-
projectId,
|
|
134
|
-
useProjectBasedId: projectBased,
|
|
135
|
-
document: { resources: [] },
|
|
136
|
-
};
|
|
137
|
-
const auth = { token, projectId };
|
|
138
|
-
const response = await createStack({ stackPayload, auth });
|
|
139
|
-
if (!response.ok) {
|
|
140
|
-
throw new Error(response.error || 'Failed to create new Stack');
|
|
141
|
-
}
|
|
142
|
-
return response.stack;
|
|
143
|
-
}
|
|
144
113
|
// LAUNCH LIMIT: 1 Stack per Project - create exclusive stack for project
|
|
145
114
|
async function createProjectBasedStack(auth, token, log) {
|
|
146
115
|
const { projectId } = auth;
|
|
@@ -155,8 +124,9 @@ async function createProjectBasedStack(auth, token, log) {
|
|
|
155
124
|
const { stack: existingStack, ok: stackOk } = await getStack({ stackId: inferredStackId, auth });
|
|
156
125
|
// if existing stack, return stack
|
|
157
126
|
if (stackOk && existingStack) {
|
|
158
|
-
log(
|
|
159
|
-
log(
|
|
127
|
+
log(warn(`"${projectDisplayName}" has an existing deployment.`));
|
|
128
|
+
log(warn(`Deploying an empty Blueprint ${chalk.bold.red('will override the existing deployment!')}`));
|
|
129
|
+
log('');
|
|
160
130
|
return existingStack;
|
|
161
131
|
}
|
|
162
132
|
// if not, create a stack
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { getStack } from '../../actions/blueprints/stacks.js';
|
|
3
|
-
import { formatResourceTree,
|
|
3
|
+
import { formatResourceTree, stackDeployDiff } from '../../utils/display/blueprints-formatting.js';
|
|
4
4
|
export async function blueprintPlanCore(options) {
|
|
5
5
|
const { bin = 'sanity', log, blueprint, token } = options;
|
|
6
6
|
const { projectId, stackId, parsedBlueprint, fileInfo } = blueprint;
|
|
7
|
-
log(`${
|
|
7
|
+
log(`${chalk.bold.blueBright('Blueprint Deployment Plan')} ${chalk.dim(`(${fileInfo.fileName})`)}`);
|
|
8
8
|
log(formatResourceTree(parsedBlueprint.resources));
|
|
9
9
|
if (token && projectId && stackId) {
|
|
10
10
|
const stackResponse = await getStack({ stackId, auth: { token, projectId } });
|
|
@@ -19,6 +19,6 @@ export async function blueprintPlanCore(options) {
|
|
|
19
19
|
log(chalk.dim('No changes detected to live deployment'));
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
|
-
log(chalk.dim(`Run ${bin} blueprints deploy to deploy these changes`));
|
|
22
|
+
log(chalk.dim(`Run "${bin} blueprints deploy" to deploy these changes`));
|
|
23
23
|
return { success: true };
|
|
24
24
|
}
|
|
@@ -4,7 +4,7 @@ export interface BlueprintStacksOptions extends CoreConfig {
|
|
|
4
4
|
token: string;
|
|
5
5
|
blueprint: ReadBlueprintResult;
|
|
6
6
|
flags: {
|
|
7
|
-
|
|
7
|
+
'project-id'?: string;
|
|
8
8
|
};
|
|
9
9
|
}
|
|
10
10
|
export declare function blueprintStacksCore(options: BlueprintStacksOptions): Promise<CoreResult>;
|
|
@@ -5,9 +5,9 @@ import { niceId } from '../../utils/display/presenters.js';
|
|
|
5
5
|
export async function blueprintStacksCore(options) {
|
|
6
6
|
const { log, token, blueprint, flags } = options;
|
|
7
7
|
const { projectId: blueprintProjectId, stackId: blueprintStackId } = blueprint;
|
|
8
|
-
const projectId = flags
|
|
8
|
+
const projectId = flags['project-id'] || blueprintProjectId;
|
|
9
9
|
if (!projectId) {
|
|
10
|
-
log('Run in a Blueprint directory or provide a Project with --
|
|
10
|
+
log('Run in a Blueprint directory or provide a Project with --project-id');
|
|
11
11
|
return { success: false, error: 'No Project ID provided' };
|
|
12
12
|
}
|
|
13
13
|
try {
|
|
@@ -9,7 +9,7 @@ export function formatTitle(title, name) {
|
|
|
9
9
|
export function formatResourceTree(resources) {
|
|
10
10
|
if (!resources || resources.length === 0)
|
|
11
11
|
return ' Zero resources';
|
|
12
|
-
const output = [`${chalk.
|
|
12
|
+
const output = [`${chalk.bold.underline('Resources')} [${resources.length}]`];
|
|
13
13
|
const functionResources = resources.filter((r) => r.type?.startsWith('sanity.function.'));
|
|
14
14
|
const otherResources = resources.filter((r) => !r.type?.startsWith('sanity.function.'));
|
|
15
15
|
const hasOtherResources = otherResources.length > 0;
|
|
@@ -17,12 +17,12 @@ export function formatResourceTree(resources) {
|
|
|
17
17
|
const fnsOutput = [`${chalk.bold('Functions')} [${functionResources.length}]`];
|
|
18
18
|
const fnDetails = [];
|
|
19
19
|
for (const fn of functionResources) {
|
|
20
|
-
const name = chalk.green(fn.displayName || fn.name);
|
|
20
|
+
const name = chalk.bold.green(fn.displayName || fn.name);
|
|
21
21
|
const ids = [
|
|
22
22
|
'id' in fn && fn.id ? `${niceId(fn.id)}` : '',
|
|
23
23
|
'externalId' in fn && fn.externalId ? `<${niceId(fn.externalId)}>` : '',
|
|
24
24
|
].join(' ');
|
|
25
|
-
fnDetails.push(
|
|
25
|
+
fnDetails.push(`${name} ${ids}`);
|
|
26
26
|
if ('parameters' in fn && fn.parameters) {
|
|
27
27
|
fnDetails.push(arrayifyStackFunction(fn));
|
|
28
28
|
}
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
+
export function check(str) {
|
|
3
|
+
return `${chalk.bold(chalk.green('✔︎'))} ${str}`;
|
|
4
|
+
}
|
|
2
5
|
export function info(str) {
|
|
3
|
-
return `${chalk.blue('
|
|
6
|
+
return `${chalk.bold.blue('ℹ︎')} ${str}`;
|
|
4
7
|
}
|
|
5
8
|
export function warn(str) {
|
|
6
|
-
return `${chalk.yellow('
|
|
9
|
+
return `${chalk.bold.yellow('▶︎')} ${str}`;
|
|
7
10
|
}
|
|
8
11
|
export function severe(str) {
|
|
9
|
-
return `${chalk.red('
|
|
12
|
+
return `${chalk.bold.red('✘')} ${str}`;
|
|
10
13
|
}
|
|
11
14
|
export function niceId(id) {
|
|
12
15
|
if (!id)
|
|
@@ -12,3 +12,7 @@ export declare function promptForProject({ token, knownOrganizationId, knownProj
|
|
|
12
12
|
projectId: string;
|
|
13
13
|
displayName: string;
|
|
14
14
|
}>;
|
|
15
|
+
export declare function promptForStackId({ projectId, token, }: {
|
|
16
|
+
projectId: string;
|
|
17
|
+
token: string;
|
|
18
|
+
}): Promise<string>;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
1
2
|
import inquirer from 'inquirer';
|
|
3
|
+
import { createEmptyStack, listStacks } from '../../actions/blueprints/stacks.js';
|
|
2
4
|
import { groupProjectsByOrganization } from '../../actions/sanity/projects.js';
|
|
3
5
|
import { niceId } from './presenters.js';
|
|
4
6
|
/**
|
|
@@ -44,10 +46,51 @@ export async function promptForProject({ token, knownOrganizationId, knownProjec
|
|
|
44
46
|
{
|
|
45
47
|
type: 'list',
|
|
46
48
|
name: 'pickedProject',
|
|
47
|
-
message: '
|
|
49
|
+
message: 'Choose a Sanity Project:',
|
|
48
50
|
choices: projectChoices,
|
|
49
51
|
default: knownProjectId,
|
|
50
52
|
},
|
|
51
53
|
]);
|
|
52
54
|
return pickedProject;
|
|
53
55
|
}
|
|
56
|
+
export async function promptForStackId({ projectId, token, }) {
|
|
57
|
+
const { ok: stacksOk, error: stacksErr, stacks } = await listStacks({ token, projectId });
|
|
58
|
+
if (!stacksOk) {
|
|
59
|
+
throw new Error(stacksErr || 'Failed to list Stacks');
|
|
60
|
+
}
|
|
61
|
+
const stackChoices = [
|
|
62
|
+
{ name: chalk.bold('✨ Create a new Stack'), value: 'new' },
|
|
63
|
+
];
|
|
64
|
+
if (stacks.length > 0) {
|
|
65
|
+
stackChoices.push(new inquirer.Separator(chalk.underline('Use an existing Stack:')));
|
|
66
|
+
stackChoices.push(...stacks.map((s) => ({
|
|
67
|
+
name: `"${s.name}" ${niceId(s.id)} ${chalk.dim(`(${s.resources.length} res)`)}`,
|
|
68
|
+
value: s.id,
|
|
69
|
+
})));
|
|
70
|
+
}
|
|
71
|
+
const { pickedStackId } = await inquirer.prompt([
|
|
72
|
+
{
|
|
73
|
+
type: 'list',
|
|
74
|
+
name: 'pickedStackId',
|
|
75
|
+
message: 'Select an existing deployment or create a new one:',
|
|
76
|
+
choices: stackChoices,
|
|
77
|
+
},
|
|
78
|
+
]);
|
|
79
|
+
if (pickedStackId === 'new') {
|
|
80
|
+
const { stackName } = await inquirer.prompt([
|
|
81
|
+
{
|
|
82
|
+
type: 'input',
|
|
83
|
+
name: 'stackName',
|
|
84
|
+
message: 'Enter a name for your Stack:',
|
|
85
|
+
validate: (input) => input.length > 0 || 'Stack name is required',
|
|
86
|
+
},
|
|
87
|
+
]);
|
|
88
|
+
const stack = await createEmptyStack({
|
|
89
|
+
token,
|
|
90
|
+
projectId,
|
|
91
|
+
name: stackName,
|
|
92
|
+
});
|
|
93
|
+
return stack.id;
|
|
94
|
+
}
|
|
95
|
+
return pickedStackId;
|
|
96
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getLatestNpmVersion(pkg: string): Promise<string>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export async function getLatestNpmVersion(pkg) {
|
|
2
|
+
const url = `https://registry.npmjs.org/${pkg}/latest`;
|
|
3
|
+
try {
|
|
4
|
+
const res = await fetch(url);
|
|
5
|
+
if (!res.ok)
|
|
6
|
+
throw new Error(`Failed to fetch version for ${pkg}`);
|
|
7
|
+
const data = await res.json();
|
|
8
|
+
return data.version;
|
|
9
|
+
}
|
|
10
|
+
catch (error) {
|
|
11
|
+
return 'latest';
|
|
12
|
+
}
|
|
13
|
+
}
|