@sanity/runtime-cli 11.2.5 → 12.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.
Files changed (46) hide show
  1. package/README.md +36 -38
  2. package/dist/actions/blueprints/blueprint.d.ts +3 -0
  3. package/dist/actions/blueprints/blueprint.js +26 -14
  4. package/dist/actions/blueprints/config.d.ts +34 -3
  5. package/dist/actions/blueprints/config.js +67 -14
  6. package/dist/actions/blueprints/stacks.d.ts +1 -2
  7. package/dist/actions/blueprints/stacks.js +2 -3
  8. package/dist/commands/blueprints/config.d.ts +0 -1
  9. package/dist/commands/blueprints/config.js +4 -12
  10. package/dist/commands/blueprints/deploy.js +1 -1
  11. package/dist/commands/blueprints/destroy.js +3 -3
  12. package/dist/commands/blueprints/info.js +2 -2
  13. package/dist/commands/blueprints/init.d.ts +1 -0
  14. package/dist/commands/blueprints/init.js +4 -0
  15. package/dist/commands/blueprints/logs.js +2 -2
  16. package/dist/commands/blueprints/plan.js +1 -0
  17. package/dist/config.d.ts +2 -1
  18. package/dist/config.js +8 -1
  19. package/dist/cores/blueprints/config.d.ts +1 -1
  20. package/dist/cores/blueprints/config.js +92 -78
  21. package/dist/cores/blueprints/deploy.js +8 -8
  22. package/dist/cores/blueprints/destroy.d.ts +1 -0
  23. package/dist/cores/blueprints/destroy.js +22 -26
  24. package/dist/cores/blueprints/doctor.js +24 -72
  25. package/dist/cores/blueprints/info.d.ts +1 -0
  26. package/dist/cores/blueprints/info.js +5 -4
  27. package/dist/cores/blueprints/init.d.ts +1 -1
  28. package/dist/cores/blueprints/init.js +50 -78
  29. package/dist/cores/blueprints/logs.d.ts +1 -0
  30. package/dist/cores/blueprints/logs.js +7 -7
  31. package/dist/cores/blueprints/plan.d.ts +3 -0
  32. package/dist/cores/blueprints/plan.js +5 -4
  33. package/dist/cores/blueprints/stacks.d.ts +1 -0
  34. package/dist/cores/blueprints/stacks.js +1 -2
  35. package/dist/cores/functions/add.js +58 -70
  36. package/dist/cores/functions/logs.js +2 -4
  37. package/dist/cores/index.js +3 -3
  38. package/dist/utils/display/blueprints-formatting.js +8 -3
  39. package/dist/utils/display/errors.js +2 -2
  40. package/dist/utils/display/presenters.d.ts +2 -0
  41. package/dist/utils/display/presenters.js +7 -0
  42. package/dist/utils/display/prompt.d.ts +14 -2
  43. package/dist/utils/display/prompt.js +60 -41
  44. package/dist/utils/types.d.ts +0 -1
  45. package/oclif.manifest.json +19 -26
  46. package/package.json +6 -8
@@ -1,23 +1,20 @@
1
1
  import { cwd } from 'node:process';
2
2
  import chalk from 'chalk';
3
- import inquirer from 'inquirer';
4
- import ora from 'ora';
5
3
  import { findBlueprintFile, readLocalBlueprint, } from '../../actions/blueprints/blueprint.js';
6
- import { createStack, getStack } from '../../actions/blueprints/stacks.js';
7
- import { getProject } from '../../actions/sanity/projects.js';
4
+ import { getStack } from '../../actions/blueprints/stacks.js';
8
5
  import config from '../../config.js';
9
- import { capitalize, check, indent, niceId, severe, warn } from '../../utils/display/presenters.js';
6
+ import { capitalize, check, filePathRelativeToCwd, indent, niceId, severe, unsure, } from '../../utils/display/presenters.js';
10
7
  import { validTokenOrErrorMessage } from '../../utils/validated-token.js';
11
8
  const diagLookup = {
12
9
  online: 'Online',
13
10
  tokenPresent: 'Auth token present',
14
11
  tokenValid: 'Auth token valid',
15
- configFilePresent: 'Blueprints config file present',
16
- configFileValid: 'Blueprints config file valid',
12
+ configFilePresent: 'Blueprint config file present',
13
+ configFileValid: 'Blueprint config file valid',
17
14
  blueprintPresent: 'Blueprint file present',
18
15
  blueprintValid: 'Blueprint file valid',
19
- stackReady: 'Deployment "Stack" ready',
20
- userHasAccess: 'User has access to "Stack"',
16
+ stackReady: 'Stack deployment ready',
17
+ userHasAccess: 'User has access to deployed "Stack"',
21
18
  };
22
19
  export async function blueprintDoctorCore(options) {
23
20
  const { log, token, flags: { verbose: v, path: p }, } = options;
@@ -27,15 +24,12 @@ export async function blueprintDoctorCore(options) {
27
24
  const here = cwd();
28
25
  const path = p || here;
29
26
  if (v)
30
- log(`Checking ${path}`);
27
+ log(`Checking ${filePathRelativeToCwd(path)}`);
31
28
  // 3 states: null == unknown, true == good, false == bad
32
29
  const diagnostics = {};
33
30
  for (const key in diagLookup) {
34
31
  diagnostics[key] = null;
35
32
  }
36
- let spinner;
37
- if (!v)
38
- spinner = ora('Checking environment').start();
39
33
  // ONLINE
40
34
  try {
41
35
  const res = await fetch(config.apiUrl);
@@ -45,14 +39,12 @@ export async function blueprintDoctorCore(options) {
45
39
  diagnostics.online = res.ok;
46
40
  }
47
41
  else {
48
- if (v)
49
- yikes(`Failed to ping ${config.apiUrl}: ${res.status} ${res.statusText}`);
42
+ yikes(`Failed to ping ${config.apiUrl}: ${res.status} ${res.statusText}`);
50
43
  diagnostics.online = false;
51
44
  }
52
45
  }
53
46
  catch {
54
- if (v)
55
- yikes(`Failed to ping ${config.apiUrl}`);
47
+ yikes(`Failed to ping ${config.apiUrl}`);
56
48
  }
57
49
  // TOKEN
58
50
  if (token) {
@@ -62,8 +54,7 @@ export async function blueprintDoctorCore(options) {
62
54
  diagnostics.tokenValid = true;
63
55
  }
64
56
  else {
65
- if (v)
66
- yikes(`Token error: ${tokenOrError.error}`);
57
+ yikes(`Token error: ${tokenOrError.error}`);
67
58
  diagnostics.tokenValid = false;
68
59
  }
69
60
  }
@@ -136,35 +127,34 @@ export async function blueprintDoctorCore(options) {
136
127
  diagnostics.userHasAccess = true;
137
128
  }
138
129
  else if (stackResponse.response?.status === 404) {
139
- if (v)
140
- yikes(`Deployment "Stack" <${stackId}> not found`);
130
+ yikes(`Deployment "Stack" <${stackId}> not found`);
141
131
  diagnostics.stackReady = false;
142
132
  }
143
133
  else if (stackResponse.response?.status === 403 || stackResponse.response?.status === 401) {
144
- if (v)
145
- yikes(`User does not have access to "Stack" <${stackId}>`);
134
+ yikes(`User does not have access to "Stack" <${stackId}>`);
146
135
  diagnostics.userHasAccess = false;
147
136
  }
148
137
  else {
149
- if (v)
150
- yikes(`Unknown error with "Stack" <${stackId}>: ${stackResponse.error}`);
138
+ yikes(`Unknown error with "Stack" <${stackId}>: ${stackResponse.error}`);
151
139
  }
152
140
  }
153
141
  else {
154
- if (v)
155
- yikes('Unable to check deployment "Stack" status.');
142
+ if (!diagnostics.online)
143
+ yikes('Unable to connect to Sanity API.');
144
+ if (!diagnostics.tokenValid)
145
+ yikes('Invalid authentication token.');
146
+ if (!stackId)
147
+ yikes(`Blueprints configuration is missing a Stack ID`);
148
+ if (!projectId)
149
+ yikes(`Blueprints configuration is missing a Project ID`);
156
150
  }
157
151
  }
158
- if (spinner)
159
- spinner.stop();
160
- if (v)
161
- log('');
152
+ log('');
162
153
  let allGood = true;
163
154
  for (const [key, value] of Object.entries(diagnostics)) {
164
155
  switch (value) {
165
156
  case true:
166
- if (v)
167
- log(check(diagLookup[key]));
157
+ log(check(diagLookup[key]));
168
158
  break;
169
159
  case false:
170
160
  allGood = false;
@@ -172,7 +162,7 @@ export async function blueprintDoctorCore(options) {
172
162
  break;
173
163
  case null:
174
164
  allGood = false;
175
- log(warn(diagLookup[key]));
165
+ log(unsure(diagLookup[key]));
176
166
  break;
177
167
  default:
178
168
  allGood = false;
@@ -187,41 +177,3 @@ export async function blueprintDoctorCore(options) {
187
177
  return { success: false, error: 'One or more checks failed', data: { diagnostics } };
188
178
  }
189
179
  }
190
- // copied from old config --edit --test flow
191
- async function _startReinitializeStack({ token, projectId, }) {
192
- const auth = { token, scopeType: 'project', scopeId: projectId };
193
- // stack id IS ST-${projectId} – it has already been checked and doesn't exist
194
- const { confirm } = await inquirer.prompt([
195
- {
196
- type: 'confirm',
197
- name: 'confirm',
198
- message: `Do you want to create a ${chalk.blue('new')}, empty Blueprint deployment with the ${chalk.blue('existing')} configuration?`,
199
- },
200
- ]);
201
- if (!confirm)
202
- return { ok: false, error: 'Reinitialization cancelled' };
203
- const { ok: projectOk, project, error: projectError } = await getProject(auth);
204
- if (!projectOk) {
205
- return {
206
- ok: false,
207
- error: projectError || 'Failed to find Project while creating Stack',
208
- };
209
- }
210
- const projectDisplayName = project.displayName;
211
- const response = await createStack({
212
- stackMutation: {
213
- name: projectDisplayName,
214
- scopeType: 'project',
215
- scopeId: projectId,
216
- document: { resources: [] },
217
- },
218
- auth,
219
- });
220
- if (!response.ok)
221
- return { ok: false, error: response.error || 'Failed to create new Stack' };
222
- return {
223
- ok: true,
224
- stackId: response.stack.id,
225
- projectDisplayName,
226
- };
227
- }
@@ -6,6 +6,7 @@ export interface BlueprintInfoOptions extends CoreConfig {
6
6
  deployedStack: Stack;
7
7
  flags: {
8
8
  id?: string;
9
+ verbose?: boolean;
9
10
  };
10
11
  }
11
12
  export declare function blueprintInfoCore(options: BlueprintInfoOptions): Promise<CoreResult>;
@@ -3,16 +3,17 @@ import { formatResourceTree, formatStackInfo } from '../../utils/display/bluepri
3
3
  import { niceId } from '../../utils/display/presenters.js';
4
4
  export async function blueprintInfoCore(options) {
5
5
  const { log, auth, stackId, flags, deployedStack } = options;
6
+ const { id: flagStackId, verbose: _verbose = false } = flags;
6
7
  try {
7
- const targetStackId = flags.id || stackId;
8
+ const targetStackId = flagStackId || stackId;
8
9
  let stack = deployedStack;
9
- if (flags.id) {
10
+ if (flagStackId) {
10
11
  const existingStackResponse = await getStack({ stackId: targetStackId, auth });
11
12
  if (!existingStackResponse.ok) {
12
- log(`Could not retrieve deployment info for ${niceId(targetStackId)}`);
13
+ log(`Could not retrieve Stack deployment info for ${niceId(targetStackId)}`);
13
14
  return {
14
15
  success: false,
15
- error: existingStackResponse.error || 'Failed to retrieve stack',
16
+ error: existingStackResponse.error || 'Failed to retrieve Stack deployment',
16
17
  };
17
18
  }
18
19
  stack = existingStackResponse.stack;
@@ -13,6 +13,7 @@ export interface BlueprintInitOptions extends CoreConfig {
13
13
  'organization-id'?: string;
14
14
  'stack-id'?: string;
15
15
  'stack-name'?: string;
16
+ verbose?: boolean;
16
17
  };
17
18
  }
18
19
  export declare function blueprintInitCore(options: BlueprintInitOptions): Promise<CoreResult>;
@@ -33,7 +34,6 @@ export declare function resolveScopeAndStack(params: {
33
34
  stackId: string | undefined;
34
35
  stackName: string | undefined;
35
36
  token: string;
36
- log: (message: string) => void;
37
37
  }): Promise<ResolvedScope>;
38
38
  export declare function determineBlueprintExtension(params: {
39
39
  requestedType: string | undefined;
@@ -1,38 +1,58 @@
1
1
  import { existsSync, readFileSync } from 'node:fs';
2
2
  import { join } from 'node:path';
3
+ import { confirm } from '@inquirer/prompts';
3
4
  import chalk from 'chalk';
4
- import inquirer from 'inquirer';
5
- import { findBlueprintFile, writeBlueprintToDisk } from '../../actions/blueprints/blueprint.js';
5
+ import { findBlueprintFile, readLocalBlueprint, writeBlueprintToDisk, } from '../../actions/blueprints/blueprint.js';
6
6
  import { writeConfigFile } from '../../actions/blueprints/config.js';
7
- import { createEmptyStack, getStack } from '../../actions/blueprints/stacks.js';
7
+ import { createEmptyStack } from '../../actions/blueprints/stacks.js';
8
8
  import { writeGitignoreFile } from '../../actions/git.js';
9
9
  import { writeOrUpdateNodeDependency } from '../../actions/node.js';
10
10
  import { verifyExampleExists, writeExample } from '../../actions/sanity/examples.js';
11
- import { getProject } from '../../actions/sanity/projects.js';
12
- import { BLUEPRINT_CONFIG_FILE, BLUEPRINT_DIR } from '../../config.js';
13
- import { check, warn } from '../../utils/display/presenters.js';
14
- import { promptForProject } from '../../utils/display/prompt.js';
11
+ import { BLUEPRINT_CONFIG_DIR, BLUEPRINT_CONFIG_FILE } from '../../config.js';
12
+ import { check, filePathRelativeToCwd, warn } from '../../utils/display/presenters.js';
13
+ import { promptForBlueprintType, promptForProject, promptForStack, } from '../../utils/display/prompt.js';
14
+ import { blueprintConfigCore } from './config.js';
15
15
  const SCOPE_PROJECT = 'project';
16
16
  const SCOPE_ORGANIZATION = 'organization';
17
17
  export async function blueprintInitCore(options) {
18
18
  const { bin = 'sanity', log, token, args, flags } = options;
19
+ const { dir: flagDir, example: flagExample, 'blueprint-type': flagBlueprintType, 'project-id': flagProjectId, 'organization-id': flagOrganizationId, 'stack-id': flagStackId, 'stack-name': flagStackName, verbose: v = false, } = flags;
20
+ const { dir: argDir } = args;
21
+ const userProvidedDirName = argDir || flagDir;
22
+ const blueprintDir = userProvidedDirName || '.';
23
+ const validationError = validateFlags({
24
+ stackId: flagStackId,
25
+ stackName: flagStackName,
26
+ organizationId: flagOrganizationId,
27
+ projectId: flagProjectId,
28
+ });
29
+ if (validationError)
30
+ return validationError;
19
31
  try {
20
- const { dir: flagDir, example: flagExample, 'blueprint-type': flagBlueprintType, 'project-id': flagProjectId, 'organization-id': flagOrganizationId, 'stack-id': flagStackId, 'stack-name': flagStackName, } = flags;
21
- const { dir: argDir } = args;
22
- const userProvidedDirName = argDir || flagDir;
23
- const blueprintDir = userProvidedDirName || '.';
24
- const existingBlueprint = findBlueprintFile(blueprintDir);
25
- if (existingBlueprint) {
26
- return { success: false, error: 'Existing Blueprint found.' };
32
+ const existingBlueprintFile = findBlueprintFile(blueprintDir);
33
+ if (existingBlueprintFile) {
34
+ log(warn(`Existing Blueprint found: ${filePathRelativeToCwd(existingBlueprintFile.blueprintFilePath)}`));
35
+ const overwrite = await confirm({
36
+ message: 'Would you like to re-configure deployment for this Blueprint?',
37
+ default: true,
38
+ });
39
+ if (!overwrite)
40
+ return { success: false, error: 'Initialization cancelled.' };
41
+ const existingBlueprint = await readLocalBlueprint(existingBlueprintFile.blueprintFilePath);
42
+ return blueprintConfigCore({
43
+ blueprint: existingBlueprint,
44
+ bin,
45
+ log,
46
+ token,
47
+ flags: {
48
+ edit: true,
49
+ 'project-id': flagProjectId,
50
+ 'organization-id': flagOrganizationId,
51
+ 'stack-id': flagStackId,
52
+ verbose: v,
53
+ },
54
+ });
27
55
  }
28
- const validationError = validateFlags({
29
- stackId: flagStackId,
30
- stackName: flagStackName,
31
- organizationId: flagOrganizationId,
32
- projectId: flagProjectId,
33
- });
34
- if (validationError)
35
- return validationError;
36
56
  if (flagExample) {
37
57
  return handleExampleInitialization({
38
58
  exampleName: flagExample,
@@ -49,7 +69,6 @@ export async function blueprintInitCore(options) {
49
69
  stackId: flagStackId,
50
70
  stackName: flagStackName,
51
71
  token,
52
- log,
53
72
  });
54
73
  const blueprintExtension = await determineBlueprintExtension({
55
74
  requestedType: flagBlueprintType,
@@ -95,7 +114,6 @@ async function handleExampleInitialization(options) {
95
114
  scopeType: SCOPE_PROJECT,
96
115
  scopeId: resolvedProjectId,
97
116
  name: `example-${exampleName}`,
98
- projectBased: false,
99
117
  });
100
118
  const exampleDir = userProvidedDirName || join(blueprintDir, exampleName);
101
119
  if (existsSync(exampleDir)) {
@@ -119,7 +137,7 @@ async function handleExampleInitialization(options) {
119
137
  }
120
138
  const { blueprintFilePath } = discoveredBlueprint;
121
139
  writeConfigFile({ blueprintFilePath, projectId: resolvedProjectId, stackId: stack.id });
122
- log(check(`${chalk.bold('Configured:')} ${exampleDir}/${BLUEPRINT_DIR}/${BLUEPRINT_CONFIG_FILE}`));
140
+ log(check(`${chalk.bold('Configured:')} ${exampleDir}/${BLUEPRINT_CONFIG_DIR}/${BLUEPRINT_CONFIG_FILE}`));
123
141
  log(`\n Run "${chalk.bold.magenta(`cd ${exampleDir} && npm i`)}" and check out the README`);
124
142
  if (instructions) {
125
143
  log('');
@@ -128,7 +146,7 @@ async function handleExampleInitialization(options) {
128
146
  return { success: true };
129
147
  }
130
148
  export async function resolveScopeAndStack(params) {
131
- const { projectId, organizationId, stackId, stackName, token, log } = params;
149
+ const { projectId, organizationId, stackId, stackName, token } = params;
132
150
  let scopeType = SCOPE_PROJECT;
133
151
  let scopeId;
134
152
  if (projectId) {
@@ -147,7 +165,6 @@ export async function resolveScopeAndStack(params) {
147
165
  scopeType,
148
166
  scopeId,
149
167
  name: stackName,
150
- projectBased: false,
151
168
  });
152
169
  resolvedStackId = stack.id;
153
170
  }
@@ -157,7 +174,8 @@ export async function resolveScopeAndStack(params) {
157
174
  scopeId = pickedProject.projectId;
158
175
  }
159
176
  if (!resolvedStackId) {
160
- await getOrCreateProjectBasedStack({ token, projectId: scopeId, log });
177
+ const { stackId } = await promptForStack({ projectId: scopeId, token });
178
+ resolvedStackId = stackId;
161
179
  }
162
180
  return {
163
181
  scopeType,
@@ -167,7 +185,9 @@ export async function resolveScopeAndStack(params) {
167
185
  }
168
186
  export async function determineBlueprintExtension(params) {
169
187
  const { requestedType, blueprintDir } = params;
170
- const extension = requestedType || (await promptForBlueprintType());
188
+ let extension = requestedType;
189
+ if (!extension)
190
+ extension = await promptForBlueprintType();
171
191
  if (extension === 'js') {
172
192
  const packageJsonPath = join(blueprintDir, 'package.json');
173
193
  const packageExists = existsSync(packageJsonPath);
@@ -202,7 +222,7 @@ export async function createBlueprintFiles(params) {
202
222
  stackId,
203
223
  ...(scopeType === SCOPE_ORGANIZATION ? { organizationId: scopeId } : { projectId: scopeId }),
204
224
  });
205
- log(check(`${chalk.bold('Added configuration:')} ${displayPath}/${BLUEPRINT_DIR}/${BLUEPRINT_CONFIG_FILE}`));
225
+ log(check(`${chalk.bold('Added configuration:')} ${displayPath}/${BLUEPRINT_CONFIG_DIR}/${BLUEPRINT_CONFIG_FILE}`));
206
226
  writeGitignoreFile(blueprintFilePath);
207
227
  log(check(`${chalk.bold('Added .gitignore:')} ${displayPath}/.gitignore`));
208
228
  if (blueprintExtension !== 'json') {
@@ -224,51 +244,3 @@ export async function createBlueprintFiles(params) {
224
244
  log(`\n Run "${chalk.bold.magenta(nextStepParts.join(' && '))}" to get started`);
225
245
  return { success: true };
226
246
  }
227
- async function promptForBlueprintType() {
228
- const { pickedBlueprintsType } = await inquirer.prompt([
229
- {
230
- type: 'list',
231
- name: 'pickedBlueprintsType',
232
- message: 'Choose a Blueprint file type:',
233
- choices: [
234
- { name: 'TypeScript', value: 'ts' },
235
- { name: 'JavaScript', value: 'js' },
236
- { name: 'JSON', value: 'json' },
237
- ],
238
- default: 'ts',
239
- },
240
- ]);
241
- return pickedBlueprintsType;
242
- }
243
- // LAUNCH LIMIT: 1 Stack per Project - create exclusive stack for project
244
- async function getOrCreateProjectBasedStack(params) {
245
- const { projectId, token, log } = params;
246
- const { ok: projectOk, project } = await getProject({
247
- token,
248
- scopeType: SCOPE_PROJECT,
249
- scopeId: projectId,
250
- });
251
- if (!projectOk) {
252
- throw new Error('Failed to find Project while creating Stack');
253
- }
254
- // check if project has a stack
255
- const { stack: existingStack, ok: stackOk } = await getStack({
256
- auth: { token, scopeType: SCOPE_PROJECT, scopeId: projectId },
257
- stackId: `ST-${projectId}`,
258
- });
259
- // if existing stack, return stack
260
- if (stackOk && existingStack) {
261
- log(warn(`"${project.displayName}" has an existing deployment.`));
262
- log(warn(`Deploying an empty Blueprint ${chalk.bold.red('will override the existing deployment!')}`));
263
- log('');
264
- return existingStack;
265
- }
266
- // if not, create a stack
267
- const stack = await createEmptyStack({
268
- token,
269
- scopeType: SCOPE_PROJECT,
270
- scopeId: projectId,
271
- name: project.displayName,
272
- });
273
- return stack;
274
- }
@@ -6,6 +6,7 @@ export interface BlueprintLogsOptions extends CoreConfig {
6
6
  deployedStack: Stack;
7
7
  flags: {
8
8
  watch?: boolean;
9
+ verbose?: boolean;
9
10
  };
10
11
  }
11
12
  export declare function blueprintLogsCore(options: BlueprintLogsOptions): Promise<CoreResult>;
@@ -7,8 +7,8 @@ import { formatLogEntry, formatLogsByDay, organizeLogsByDay, } from '../../utils
7
7
  import { niceId } from '../../utils/display/presenters.js';
8
8
  export async function blueprintLogsCore(options) {
9
9
  const { log, auth, stackId, deployedStack, flags } = options;
10
- const { watch = false } = flags;
11
- const spinner = ora(`Fetching recent logs for deployment ${niceId(stackId)}`).start();
10
+ const { watch = false, verbose: _verbose = false } = flags;
11
+ const spinner = ora(`Fetching recent logs for Stack deployment ${niceId(stackId)}`).start();
12
12
  try {
13
13
  if (watch) {
14
14
  const { ok, logs, error } = await getLogs(stackId, auth);
@@ -27,7 +27,7 @@ export async function blueprintLogsCore(options) {
27
27
  }
28
28
  }
29
29
  else {
30
- log(`No recent logs found for deployment ${niceId(stackId)}`);
30
+ log(`No recent logs found for Stack deployment ${niceId(stackId)}`);
31
31
  }
32
32
  // Set up streaming log display
33
33
  await setupLogStreaming({
@@ -45,23 +45,23 @@ export async function blueprintLogsCore(options) {
45
45
  // Regular non-streaming logs
46
46
  const { ok, logs, error } = await getLogs(stackId, auth);
47
47
  if (!ok) {
48
- spinner.fail(`${chalk.red('Failed')} to retrieve logs`);
48
+ spinner.fail(`${chalk.red('Failed')} to retrieve Stack deployment logs`);
49
49
  log(`Error: ${error || 'Unknown error'}`);
50
50
  return { success: false, error: error || 'Failed to retrieve logs' };
51
51
  }
52
52
  if (logs.length === 0) {
53
- spinner.info(`No logs found for deployment ${stackId}`);
53
+ spinner.info(`No logs found for Stack deployment ${stackId}`);
54
54
  return { success: true };
55
55
  }
56
56
  spinner.succeed(`${formatTitle('Blueprint', deployedStack.name)} Logs`);
57
- log(`Found ${chalk.bold(logs.length.toString())} log entries for deployment ${niceId(stackId)}\n`);
57
+ log(`Found ${chalk.bold(logs.length.toString())} log entries for Stack deployment ${niceId(stackId)}\n`);
58
58
  // Organize and format logs by day
59
59
  const logsByDay = organizeLogsByDay(logs);
60
60
  log(formatLogsByDay(logsByDay));
61
61
  return { success: true };
62
62
  }
63
63
  catch (err) {
64
- spinner.fail('Failed to retrieve logs');
64
+ spinner.fail('Failed to retrieve Stack deployment logs');
65
65
  const errorMessage = err instanceof Error ? err.message : String(err);
66
66
  log(`Error: ${errorMessage}`);
67
67
  return { success: false, error: errorMessage };
@@ -3,5 +3,8 @@ import type { CoreConfig, CoreResult } from '../index.js';
3
3
  export interface BlueprintPlanOptions extends CoreConfig {
4
4
  blueprint: ReadBlueprintResult;
5
5
  token?: string;
6
+ flags: {
7
+ verbose?: boolean;
8
+ };
6
9
  }
7
10
  export declare function blueprintPlanCore(options: BlueprintPlanOptions): Promise<CoreResult>;
@@ -2,9 +2,10 @@ import chalk from 'chalk';
2
2
  import { getStack } from '../../actions/blueprints/stacks.js';
3
3
  import { formatResourceTree, stackDeployDiff } from '../../utils/display/blueprints-formatting.js';
4
4
  export async function blueprintPlanCore(options) {
5
- const { bin = 'sanity', log, blueprint, token } = options;
5
+ const { bin = 'sanity', log, blueprint, token, flags } = options;
6
+ const { verbose: _verbose = false } = flags;
6
7
  const { scopeType, scopeId, stackId, parsedBlueprint, fileInfo } = blueprint;
7
- log(`${chalk.bold.blueBright('Blueprint Deployment Plan')} ${chalk.dim(`(${fileInfo.fileName})`)}`);
8
+ log(`${chalk.bold.blueBright('Blueprint Stack deployment plan')} ${chalk.dim(`(${fileInfo.fileName})`)}`);
8
9
  log(formatResourceTree(parsedBlueprint.resources));
9
10
  if (token && scopeType && scopeId && stackId) {
10
11
  const stackResponse = await getStack({
@@ -12,7 +13,7 @@ export async function blueprintPlanCore(options) {
12
13
  stackId,
13
14
  });
14
15
  if (!stackResponse.ok) {
15
- log(chalk.dim('Unable to retrieve live deployment for comparison'));
16
+ log(chalk.dim('Unable to retrieve live Stack deployment for comparison'));
16
17
  }
17
18
  else {
18
19
  const diff = stackDeployDiff(parsedBlueprint, stackResponse.stack);
@@ -20,6 +21,6 @@ export async function blueprintPlanCore(options) {
20
21
  log(diff);
21
22
  }
22
23
  }
23
- log(`\n Run "${chalk.bold.magenta(`${bin} blueprints deploy`)}" to deploy these changes`);
24
+ log(`\n Run "${chalk.bold.magenta(`${bin} blueprints deploy`)}" to deploy these Stack changes`);
24
25
  return { success: true };
25
26
  }
@@ -6,6 +6,7 @@ export interface BlueprintStacksOptions extends CoreConfig {
6
6
  flags: {
7
7
  'project-id'?: string;
8
8
  'organization-id'?: string;
9
+ verbose?: boolean;
9
10
  };
10
11
  }
11
12
  export declare function blueprintStacksCore(options: BlueprintStacksOptions): Promise<CoreResult>;
@@ -5,8 +5,7 @@ import { capitalize, niceId } from '../../utils/display/presenters.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;
8
- const flagProjectId = flags['project-id'];
9
- const flagOrganizationId = flags['organization-id'];
8
+ const { 'project-id': flagProjectId, 'organization-id': flagOrganizationId, verbose: _verbose = false, } = flags;
10
9
  if (flagOrganizationId && flagProjectId) {
11
10
  log('Cannot specify both --organization-id and --project-id');
12
11
  return { success: false, error: 'Cannot specify both --organization-id and --project-id' };