@sanity/runtime-cli 12.0.0 → 12.1.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 CHANGED
@@ -20,7 +20,7 @@ $ npm install -g @sanity/runtime-cli
20
20
  $ sanity-run COMMAND
21
21
  running command...
22
22
  $ sanity-run (--version)
23
- @sanity/runtime-cli/12.0.0 linux-x64 node-v24.11.1
23
+ @sanity/runtime-cli/12.1.0 linux-x64 node-v24.11.1
24
24
  $ sanity-run --help [COMMAND]
25
25
  USAGE
26
26
  $ sanity-run COMMAND
@@ -92,7 +92,7 @@ EXAMPLES
92
92
  $ sanity-run blueprints add function --name my-function --fn-type document-create --fn-type document-update --lang js
93
93
  ```
94
94
 
95
- _See code: [src/commands/blueprints/add.ts](https://github.com/sanity-io/runtime-cli/blob/v12.0.0/src/commands/blueprints/add.ts)_
95
+ _See code: [src/commands/blueprints/add.ts](https://github.com/sanity-io/runtime-cli/blob/v12.1.0/src/commands/blueprints/add.ts)_
96
96
 
97
97
  ## `sanity-run blueprints config`
98
98
 
@@ -121,7 +121,7 @@ EXAMPLES
121
121
  $ sanity-run blueprints config --edit --project-id <projectId> --stack-id <stackId>
122
122
  ```
123
123
 
124
- _See code: [src/commands/blueprints/config.ts](https://github.com/sanity-io/runtime-cli/blob/v12.0.0/src/commands/blueprints/config.ts)_
124
+ _See code: [src/commands/blueprints/config.ts](https://github.com/sanity-io/runtime-cli/blob/v12.1.0/src/commands/blueprints/config.ts)_
125
125
 
126
126
  ## `sanity-run blueprints deploy`
127
127
 
@@ -143,7 +143,7 @@ EXAMPLES
143
143
  $ sanity-run blueprints deploy --no-wait
144
144
  ```
145
145
 
146
- _See code: [src/commands/blueprints/deploy.ts](https://github.com/sanity-io/runtime-cli/blob/v12.0.0/src/commands/blueprints/deploy.ts)_
146
+ _See code: [src/commands/blueprints/deploy.ts](https://github.com/sanity-io/runtime-cli/blob/v12.1.0/src/commands/blueprints/deploy.ts)_
147
147
 
148
148
  ## `sanity-run blueprints destroy`
149
149
 
@@ -170,7 +170,7 @@ EXAMPLES
170
170
  $ sanity-run blueprints destroy --stack-id <stackId> --project-id <projectId> --force --no-wait
171
171
  ```
172
172
 
173
- _See code: [src/commands/blueprints/destroy.ts](https://github.com/sanity-io/runtime-cli/blob/v12.0.0/src/commands/blueprints/destroy.ts)_
173
+ _See code: [src/commands/blueprints/destroy.ts](https://github.com/sanity-io/runtime-cli/blob/v12.1.0/src/commands/blueprints/destroy.ts)_
174
174
 
175
175
  ## `sanity-run blueprints doctor`
176
176
 
@@ -188,7 +188,7 @@ DESCRIPTION
188
188
  Diagnose potential issues with Blueprint configuration
189
189
  ```
190
190
 
191
- _See code: [src/commands/blueprints/doctor.ts](https://github.com/sanity-io/runtime-cli/blob/v12.0.0/src/commands/blueprints/doctor.ts)_
191
+ _See code: [src/commands/blueprints/doctor.ts](https://github.com/sanity-io/runtime-cli/blob/v12.1.0/src/commands/blueprints/doctor.ts)_
192
192
 
193
193
  ## `sanity-run blueprints info`
194
194
 
@@ -207,14 +207,14 @@ DESCRIPTION
207
207
  EXAMPLES
208
208
  $ sanity-run blueprints info
209
209
 
210
- $ sanity-run blueprints info --stack-id <stackId>
210
+ $ sanity-run blueprints info --id <stackId>
211
211
  ```
212
212
 
213
- _See code: [src/commands/blueprints/info.ts](https://github.com/sanity-io/runtime-cli/blob/v12.0.0/src/commands/blueprints/info.ts)_
213
+ _See code: [src/commands/blueprints/info.ts](https://github.com/sanity-io/runtime-cli/blob/v12.1.0/src/commands/blueprints/info.ts)_
214
214
 
215
215
  ## `sanity-run blueprints init [DIR]`
216
216
 
217
- Initialize a new Blueprint
217
+ Initialize a new Blueprint Stack deployment
218
218
 
219
219
  ```
220
220
  USAGE
@@ -236,7 +236,7 @@ FLAGS
236
236
  --verbose Verbose output
237
237
 
238
238
  DESCRIPTION
239
- Initialize a new Blueprint
239
+ Initialize a new Blueprint Stack deployment
240
240
 
241
241
  EXAMPLES
242
242
  $ sanity-run blueprints init
@@ -250,7 +250,7 @@ EXAMPLES
250
250
  $ sanity-run blueprints init --blueprint-type <json|js|ts> --stack-name <stackName>
251
251
  ```
252
252
 
253
- _See code: [src/commands/blueprints/init.ts](https://github.com/sanity-io/runtime-cli/blob/v12.0.0/src/commands/blueprints/init.ts)_
253
+ _See code: [src/commands/blueprints/init.ts](https://github.com/sanity-io/runtime-cli/blob/v12.1.0/src/commands/blueprints/init.ts)_
254
254
 
255
255
  ## `sanity-run blueprints logs`
256
256
 
@@ -272,7 +272,7 @@ EXAMPLES
272
272
  $ sanity-run blueprints logs --watch
273
273
  ```
274
274
 
275
- _See code: [src/commands/blueprints/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v12.0.0/src/commands/blueprints/logs.ts)_
275
+ _See code: [src/commands/blueprints/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v12.1.0/src/commands/blueprints/logs.ts)_
276
276
 
277
277
  ## `sanity-run blueprints plan`
278
278
 
@@ -289,11 +289,11 @@ EXAMPLES
289
289
  $ sanity-run blueprints plan
290
290
  ```
291
291
 
292
- _See code: [src/commands/blueprints/plan.ts](https://github.com/sanity-io/runtime-cli/blob/v12.0.0/src/commands/blueprints/plan.ts)_
292
+ _See code: [src/commands/blueprints/plan.ts](https://github.com/sanity-io/runtime-cli/blob/v12.1.0/src/commands/blueprints/plan.ts)_
293
293
 
294
294
  ## `sanity-run blueprints stacks`
295
295
 
296
- List all Blueprint stacks
296
+ List all Blueprint Stacks
297
297
 
298
298
  ```
299
299
  USAGE
@@ -304,7 +304,7 @@ FLAGS
304
304
  --project-id=<value> Project ID to show stacks for
305
305
 
306
306
  DESCRIPTION
307
- List all Blueprint stacks
307
+ List all Blueprint Stacks
308
308
 
309
309
  EXAMPLES
310
310
  $ sanity-run blueprints stacks
@@ -314,7 +314,7 @@ EXAMPLES
314
314
  $ sanity-run blueprints stacks --organization-id <organizationId>
315
315
  ```
316
316
 
317
- _See code: [src/commands/blueprints/stacks.ts](https://github.com/sanity-io/runtime-cli/blob/v12.0.0/src/commands/blueprints/stacks.ts)_
317
+ _See code: [src/commands/blueprints/stacks.ts](https://github.com/sanity-io/runtime-cli/blob/v12.1.0/src/commands/blueprints/stacks.ts)_
318
318
 
319
319
  ## `sanity-run functions add`
320
320
 
@@ -356,7 +356,7 @@ EXAMPLES
356
356
  $ sanity-run functions add --name my-function --type document-create --type document-update --lang js
357
357
  ```
358
358
 
359
- _See code: [src/commands/functions/add.ts](https://github.com/sanity-io/runtime-cli/blob/v12.0.0/src/commands/functions/add.ts)_
359
+ _See code: [src/commands/functions/add.ts](https://github.com/sanity-io/runtime-cli/blob/v12.1.0/src/commands/functions/add.ts)_
360
360
 
361
361
  ## `sanity-run functions dev`
362
362
 
@@ -379,7 +379,7 @@ EXAMPLES
379
379
  $ sanity-run functions dev --host 127.0.0.1 --port 8974
380
380
  ```
381
381
 
382
- _See code: [src/commands/functions/dev.ts](https://github.com/sanity-io/runtime-cli/blob/v12.0.0/src/commands/functions/dev.ts)_
382
+ _See code: [src/commands/functions/dev.ts](https://github.com/sanity-io/runtime-cli/blob/v12.1.0/src/commands/functions/dev.ts)_
383
383
 
384
384
  ## `sanity-run functions env add NAME KEY VALUE`
385
385
 
@@ -401,7 +401,7 @@ EXAMPLES
401
401
  $ sanity-run functions env add MyFunction API_URL https://api.example.com/
402
402
  ```
403
403
 
404
- _See code: [src/commands/functions/env/add.ts](https://github.com/sanity-io/runtime-cli/blob/v12.0.0/src/commands/functions/env/add.ts)_
404
+ _See code: [src/commands/functions/env/add.ts](https://github.com/sanity-io/runtime-cli/blob/v12.1.0/src/commands/functions/env/add.ts)_
405
405
 
406
406
  ## `sanity-run functions env list NAME`
407
407
 
@@ -421,7 +421,7 @@ EXAMPLES
421
421
  $ sanity-run functions env list MyFunction
422
422
  ```
423
423
 
424
- _See code: [src/commands/functions/env/list.ts](https://github.com/sanity-io/runtime-cli/blob/v12.0.0/src/commands/functions/env/list.ts)_
424
+ _See code: [src/commands/functions/env/list.ts](https://github.com/sanity-io/runtime-cli/blob/v12.1.0/src/commands/functions/env/list.ts)_
425
425
 
426
426
  ## `sanity-run functions env remove NAME KEY`
427
427
 
@@ -442,7 +442,7 @@ EXAMPLES
442
442
  $ sanity-run functions env remove MyFunction API_URL
443
443
  ```
444
444
 
445
- _See code: [src/commands/functions/env/remove.ts](https://github.com/sanity-io/runtime-cli/blob/v12.0.0/src/commands/functions/env/remove.ts)_
445
+ _See code: [src/commands/functions/env/remove.ts](https://github.com/sanity-io/runtime-cli/blob/v12.1.0/src/commands/functions/env/remove.ts)_
446
446
 
447
447
  ## `sanity-run functions logs NAME`
448
448
 
@@ -476,7 +476,7 @@ EXAMPLES
476
476
  $ sanity-run functions logs <name> --delete
477
477
  ```
478
478
 
479
- _See code: [src/commands/functions/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v12.0.0/src/commands/functions/logs.ts)_
479
+ _See code: [src/commands/functions/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v12.1.0/src/commands/functions/logs.ts)_
480
480
 
481
481
  ## `sanity-run functions test NAME`
482
482
 
@@ -525,7 +525,7 @@ EXAMPLES
525
525
  $ sanity-run functions test <name> --event update --data-before '{ "title": "before" }' --data-after '{ "title": "after" }'
526
526
  ```
527
527
 
528
- _See code: [src/commands/functions/test.ts](https://github.com/sanity-io/runtime-cli/blob/v12.0.0/src/commands/functions/test.ts)_
528
+ _See code: [src/commands/functions/test.ts](https://github.com/sanity-io/runtime-cli/blob/v12.1.0/src/commands/functions/test.ts)_
529
529
 
530
530
  ## `sanity-run help [COMMAND]`
531
531
 
@@ -1,7 +1,7 @@
1
1
  import { type Blueprint } from '@sanity/blueprints-parser';
2
2
  import type { BlueprintParserError, Resource } from '../../utils/types.js';
3
3
  import { type ScopeType } from '../../utils/types.js';
4
- import { type BlueprintsConfig } from './config.js';
4
+ import { type LocatedBlueprintsConfig } from './config.js';
5
5
  declare const SUPPORTED_FILE_EXTENSIONS: readonly [".json", ".js", ".mjs", ".ts"];
6
6
  type BlueprintFileExtension = (typeof SUPPORTED_FILE_EXTENSIONS)[number];
7
7
  export declare const JSON_BLUEPRINT_CONTENT: {
@@ -29,7 +29,7 @@ export declare function findBlueprintFile(blueprintPath?: string): FileInfo | nu
29
29
  /** Result of the blueprint read operation */
30
30
  export interface ReadBlueprintResult {
31
31
  fileInfo: FileInfo;
32
- blueprintConfig: BlueprintsConfig | null;
32
+ blueprintConfig: LocatedBlueprintsConfig | null;
33
33
  rawBlueprint: Record<string, unknown>;
34
34
  parsedBlueprint: Blueprint;
35
35
  errors: BlueprintParserError[];
@@ -5,12 +5,14 @@ export interface ConfigUpdate {
5
5
  stackId?: string;
6
6
  }
7
7
  export interface BlueprintsConfig extends ConfigUpdate {
8
- configPath: string;
9
8
  blueprintConfigVersion?: typeof BLUEPRINT_CONFIG_VERSION;
10
9
  runtimeCliVersion?: typeof RUNTIME_CLI_VERSION;
11
10
  updatedAt?: number;
12
11
  }
13
- export declare function readConfigFile(blueprintFilePath?: string): BlueprintsConfig | null;
12
+ export interface LocatedBlueprintsConfig extends BlueprintsConfig {
13
+ configPath: string;
14
+ }
15
+ export declare function readConfigFile(blueprintFilePath?: string): LocatedBlueprintsConfig | null;
14
16
  /**
15
17
  * Create or update the config file to disk.
16
18
  * One of organizationId or projectId must be provided. Not both.
@@ -21,8 +23,7 @@ export declare function readConfigFile(blueprintFilePath?: string): BlueprintsCo
21
23
  * @param options.projectId - the project ID
22
24
  * @param options.stackId - the stack ID
23
25
  */
24
- export declare function writeConfigFile(options: {
25
- blueprintFilePath?: string;
26
+ export declare function writeConfigFile(blueprintFilePath: string, options: {
26
27
  stackId?: string;
27
28
  } & ({
28
29
  organizationId: string;
@@ -30,7 +31,7 @@ export declare function writeConfigFile(options: {
30
31
  } | {
31
32
  projectId: string;
32
33
  organizationId?: string;
33
- })): void;
34
+ })): BlueprintsConfig;
34
35
  /**
35
36
  * Update the config file with the given properties.
36
37
  * Config file must already exist.
@@ -41,7 +42,7 @@ export declare function writeConfigFile(options: {
41
42
  * @param updateableProperties.projectId - the project ID
42
43
  * @param updateableProperties.stackId - the stack ID
43
44
  */
44
- export declare function patchConfigFile(blueprintFilePath: string, updateableProperties: ConfigUpdate): void;
45
+ export declare function patchConfigFile(blueprintFilePath: string, updateableProperties: ConfigUpdate): BlueprintsConfig;
45
46
  /**
46
47
  * Find and write an organizationId to the config file by getting it from the projectId
47
48
  * @throws {Error} if unable to fetch project
@@ -28,8 +28,8 @@ export function readConfigFile(blueprintFilePath) {
28
28
  * @param options.projectId - the project ID
29
29
  * @param options.stackId - the stack ID
30
30
  */
31
- export function writeConfigFile(options) {
32
- const { blueprintFilePath, organizationId, projectId, stackId } = options;
31
+ export function writeConfigFile(blueprintFilePath, options) {
32
+ const { organizationId, projectId, stackId } = options;
33
33
  const blueprintDir = blueprintFilePath ? dirname(blueprintFilePath) : cwd();
34
34
  const configDir = join(blueprintDir, BLUEPRINT_CONFIG_DIR);
35
35
  const configPath = join(configDir, BLUEPRINT_CONFIG_FILE);
@@ -49,6 +49,7 @@ export function writeConfigFile(options) {
49
49
  config.runtimeCliVersion = RUNTIME_CLI_VERSION;
50
50
  config.updatedAt = Date.now();
51
51
  writeFileSync(configPath, JSON.stringify(config, null, 2));
52
+ return config;
52
53
  }
53
54
  /**
54
55
  * Update the config file with the given properties.
@@ -66,13 +67,14 @@ export function patchConfigFile(blueprintFilePath, updateableProperties) {
66
67
  throw new Error('No config file found');
67
68
  const { configPath, ...existingConfigProperties } = existingConfig;
68
69
  const newConfig = {
69
- blueprintConfigVersion: BLUEPRINT_CONFIG_VERSION, // don't overwrite the version
70
+ blueprintConfigVersion: BLUEPRINT_CONFIG_VERSION, // patch doesn't overwrite versions
71
+ runtimeCliVersion: RUNTIME_CLI_VERSION,
70
72
  ...existingConfigProperties,
71
73
  ...updateableProperties,
72
74
  updatedAt: Date.now(),
73
- runtimeCliVersion: RUNTIME_CLI_VERSION,
74
75
  };
75
76
  writeFileSync(configPath, JSON.stringify(newConfig, null, 2));
77
+ return newConfig;
76
78
  }
77
79
  /**
78
80
  * Find and write an organizationId to the config file by getting it from the projectId
@@ -97,7 +99,7 @@ export async function backfillOrganizationId({ blueprintFilePath, projectId, })
97
99
  }
98
100
  if (!organizationId)
99
101
  throw new Error('No organizationId found');
100
- writeConfigFile({ blueprintFilePath, organizationId });
102
+ patchConfigFile(blueprintFilePath, { organizationId });
101
103
  return organizationId;
102
104
  }
103
105
  export async function backfillProjectBasedStackId({ blueprintFilePath, projectId, }) {
@@ -117,7 +119,7 @@ export async function backfillProjectBasedStackId({ blueprintFilePath, projectId
117
119
  stacks[0].scopeType === 'project' &&
118
120
  stacks[0].id === possibleStackId) {
119
121
  // jackpot
120
- writeConfigFile({ blueprintFilePath, projectId, stackId: possibleStackId });
122
+ patchConfigFile(blueprintFilePath, { projectId, stackId: possibleStackId });
121
123
  return possibleStackId;
122
124
  }
123
125
  return undefined;
@@ -17,11 +17,13 @@ export default class DestroyCommand extends BlueprintCommand {
17
17
  description: 'Project associated with the Stack',
18
18
  aliases: ['projectId', 'project'],
19
19
  dependsOn: ['stack-id', 'force'],
20
+ exclusive: ['organization-id'],
20
21
  }),
21
22
  'organization-id': Flags.string({
22
23
  description: 'Organization associated with the Stack',
23
24
  aliases: ['organizationId', 'organization', 'org'],
24
25
  dependsOn: ['stack-id', 'force'],
26
+ exclusive: ['project-id'],
25
27
  }),
26
28
  'stack-id': Flags.string({
27
29
  description: 'Stack ID to destroy (defaults to current Stack)',
@@ -5,7 +5,7 @@ export default class InfoCommand extends DeployedBlueprintCommand {
5
5
  static description = 'Show information about a Blueprint Stack deployment';
6
6
  static examples = [
7
7
  '<%= config.bin %> <%= command.id %>',
8
- '<%= config.bin %> <%= command.id %> --stack-id <stackId>',
8
+ '<%= config.bin %> <%= command.id %> --id <stackId>',
9
9
  ];
10
10
  static flags = {
11
11
  id: Flags.string({
@@ -2,7 +2,7 @@ import { Args, Command, Flags } from '@oclif/core';
2
2
  import { blueprintInitCore } from '../../cores/blueprints/init.js';
3
3
  import { validTokenOrErrorMessage } from '../../utils/validated-token.js';
4
4
  export default class InitCommand extends Command {
5
- static description = 'Initialize a new Blueprint';
5
+ static description = 'Initialize a new Blueprint Stack deployment';
6
6
  static examples = [
7
7
  '<%= config.bin %> <%= command.id %>',
8
8
  '<%= config.bin %> <%= command.id %> [directory]',
@@ -2,7 +2,7 @@ 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
- static description = 'List all Blueprint stacks';
5
+ static description = 'List all Blueprint Stacks';
6
6
  static examples = [
7
7
  '<%= config.bin %> <%= command.id %>',
8
8
  '<%= config.bin %> <%= command.id %> --project-id <projectId>',
package/dist/config.js CHANGED
@@ -1,13 +1,23 @@
1
1
  import { readFileSync } from 'node:fs';
2
- import { dirname, join } from 'node:path';
3
2
  import { env } from 'node:process';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { findUpSync } from 'find-up';
4
5
  import getToken from './utils/get-token.js';
5
6
  export const BLUEPRINT_CONFIG_VERSION = 'v2025-05-08';
6
7
  export const BLUEPRINT_CONFIG_DIR = '.sanity';
7
8
  export const BLUEPRINT_CONFIG_FILE = 'blueprint.config.json';
8
9
  export let RUNTIME_CLI_VERSION;
9
10
  try {
10
- RUNTIME_CLI_VERSION = JSON.parse(readFileSync(join(dirname(import.meta.url), '..', 'package.json'), 'utf8')).version;
11
+ const packageJsonPath = findUpSync('package.json', {
12
+ cwd: fileURLToPath(new URL('.', import.meta.url)),
13
+ type: 'file',
14
+ });
15
+ if (packageJsonPath) {
16
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
17
+ if (packageJson.name === '@sanity/runtime-cli') {
18
+ RUNTIME_CLI_VERSION = packageJson.version;
19
+ }
20
+ }
11
21
  }
12
22
  catch { }
13
23
  const nodeEnv = env.NODE_ENV?.toLowerCase() ?? 'production';
@@ -1,15 +1,13 @@
1
- import { highlight } from 'cardinal';
2
1
  import chalk from 'chalk';
3
2
  import { patchConfigFile, writeConfigFile, } from '../../actions/blueprints/config.js';
4
- import { BLUEPRINT_CONFIG_DIR, BLUEPRINT_CONFIG_FILE } from '../../config.js';
5
- import { capitalize, filePathRelativeToCwd, niceId, warn } from '../../utils/display/presenters.js';
3
+ import { filePathRelativeToCwd, labeledId, warn } from '../../utils/display/presenters.js';
6
4
  import { promptForProject, promptForStack } from '../../utils/display/prompt.js';
7
5
  export async function blueprintConfigCore(options) {
8
6
  const { bin = 'sanity', blueprint, log, token, flags } = options;
9
7
  const { edit: editConfig = false, 'project-id': flagProjectId, 'organization-id': flagOrganizationId, 'stack-id': flagStackId, verbose: v = false, } = flags;
8
+ const providedConfigFlag = [flagProjectId, flagStackId, flagOrganizationId].some(Boolean);
10
9
  const { stackId: configStackId, scopeType: configScopeType, scopeId: configScopeId, blueprintConfig, fileInfo, } = blueprint;
11
10
  const blueprintFilePath = fileInfo.blueprintFilePath;
12
- const configPath = blueprintConfig?.configPath;
13
11
  if (!configStackId && !configScopeType && !configScopeId) {
14
12
  log(warn('Incomplete configuration.'));
15
13
  if (!editConfig) {
@@ -18,19 +16,10 @@ export async function blueprintConfigCore(options) {
18
16
  return { success: true }; // not necessarily fatal
19
17
  }
20
18
  }
21
- log(chalk.bold('Current Blueprint configuration:'));
22
- if (configPath) {
23
- if (v)
24
- log(` File: ${filePathRelativeToCwd(configPath)}`);
25
- }
26
- log(` Deployment: ${chalk.blue('Stack')} ${niceId(configStackId || 'unknown')}`);
27
- log(` Scoped to: ${chalk.blue(capitalize(configScopeType || 'unknown'))} ${niceId(configScopeId || 'unknown')}`);
28
- if (blueprintConfig?.updatedAt) {
29
- if (v)
30
- log(` Updated: ${new Date(blueprintConfig.updatedAt).toLocaleString()}`);
31
- }
19
+ if (blueprintConfig)
20
+ printConfig({ configLabel: 'Current', log, config: blueprintConfig, v });
32
21
  // passing new config without --edit flag is not allowed
33
- if ((flagProjectId || flagOrganizationId || flagStackId) && !editConfig) {
22
+ if (providedConfigFlag && !editConfig) {
34
23
  log('To update the configuration, use the --edit flag.');
35
24
  return { success: true };
36
25
  }
@@ -39,10 +28,9 @@ export async function blueprintConfigCore(options) {
39
28
  return { success: true };
40
29
  }
41
30
  else {
42
- // if a config property flag was passed, set the value and return success
43
- // do not try to validate correctness of combined flags; this should not be interactive
44
- const providedConfigFlag = [flagProjectId, flagStackId, flagOrganizationId].some(Boolean);
45
31
  if (providedConfigFlag) {
32
+ // if a config property flag was passed, set the value and return success
33
+ // do not try to validate correctness of combined flags; this should not be interactive
46
34
  const configUpdate = {};
47
35
  if (flagProjectId)
48
36
  configUpdate.projectId = flagProjectId;
@@ -51,19 +39,16 @@ export async function blueprintConfigCore(options) {
51
39
  if (flagOrganizationId)
52
40
  configUpdate.organizationId = flagOrganizationId;
53
41
  try {
54
- patchConfigFile(blueprintFilePath, configUpdate);
42
+ const newConfig = patchConfigFile(blueprintFilePath, configUpdate);
43
+ printConfig({ configLabel: 'Updated', log, config: newConfig, v });
44
+ return { success: true };
55
45
  }
56
46
  catch {
57
47
  return { success: false, error: 'Unable to update configuration.' };
58
48
  }
59
- log('\nConfiguration updated.');
60
- return { success: true };
61
- }
62
- // organization-based Blueprints are not yet supported for interactive editing
63
- if (configScopeType === 'organization') {
64
- return { success: false, error: 'Only project-based Blueprints are supported.' };
65
49
  }
66
- // otherwise, prompt for values interactively
50
+ // prompt for values interactively
51
+ // do not yet offer organization as scope option
67
52
  let updatedProjectId = flagProjectId;
68
53
  if (!updatedProjectId) {
69
54
  const pickedProject = await promptForProject({
@@ -83,21 +68,33 @@ export async function blueprintConfigCore(options) {
83
68
  return { success: false, error: 'Stack is required.' };
84
69
  try {
85
70
  // update or create config JSON
86
- writeConfigFile({ blueprintFilePath, projectId: updatedProjectId, stackId: updatedStackId });
87
- log(`\n${chalk.bold('New configuration:')}`);
88
- log(` Deployment: ${chalk.blue('Stack')} ${niceId(updatedStackId)}`);
89
- log(` Scoped to: ${chalk.blue('Project')} ${niceId(updatedProjectId)}`);
90
- log('');
91
- log('Configuration updated.');
71
+ const newConfig = await writeConfigFile(blueprintFilePath, {
72
+ projectId: updatedProjectId,
73
+ stackId: updatedStackId,
74
+ });
75
+ printConfig({ configLabel: 'Updated', log, config: newConfig, v });
92
76
  return { success: true };
93
77
  }
94
78
  catch {
95
- log(`Unable to update config. These values should be set in ${BLUEPRINT_CONFIG_DIR}/${BLUEPRINT_CONFIG_FILE}`);
96
- log(highlight(JSON.stringify({ metadata: { projectId: updatedProjectId, stackId: updatedStackId } }, null, 2)));
97
- return {
98
- success: false,
99
- error: `Be sure to update your ${BLUEPRINT_CONFIG_DIR}/${BLUEPRINT_CONFIG_FILE}`,
100
- };
79
+ return { success: false, error: 'Unable to update configuration!' };
101
80
  }
102
81
  }
103
82
  }
83
+ function printConfig(options) {
84
+ const { configLabel, log, config, v = false } = options;
85
+ const { projectId, organizationId, stackId, updatedAt } = config;
86
+ const scopeType = projectId ? 'project' : 'organization';
87
+ const scopeId = projectId ? projectId : organizationId;
88
+ if (v)
89
+ log(JSON.stringify(config));
90
+ log(`${chalk.bold(`${configLabel} configuration:`)}`);
91
+ log(` Deployment: ${labeledId('stack', stackId)}`);
92
+ log(` Scoped to: ${labeledId(scopeType, scopeId)}`);
93
+ if (updatedAt)
94
+ log(` Updated: ${new Date(updatedAt).toLocaleString()}`);
95
+ if ('configPath' in config) {
96
+ const { configPath } = config;
97
+ if (configPath)
98
+ log(` File: ${filePathRelativeToCwd(configPath)}`);
99
+ }
100
+ }
@@ -33,11 +33,13 @@ export declare function resolveScopeAndStack(params: {
33
33
  organizationId: string | undefined;
34
34
  stackId: string | undefined;
35
35
  stackName: string | undefined;
36
+ log: (message: string) => void;
36
37
  token: string;
37
38
  }): Promise<ResolvedScope>;
38
39
  export declare function determineBlueprintExtension(params: {
39
40
  requestedType: string | undefined;
40
41
  blueprintDir: string;
42
+ log: (message: string) => void;
41
43
  }): Promise<string>;
42
44
  export declare function createBlueprintFiles(params: {
43
45
  blueprintDir: string;
@@ -9,7 +9,7 @@ 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
11
  import { BLUEPRINT_CONFIG_DIR, BLUEPRINT_CONFIG_FILE } from '../../config.js';
12
- import { check, filePathRelativeToCwd, warn } from '../../utils/display/presenters.js';
12
+ import { check, filePathRelativeToCwd, labeledId, warn } from '../../utils/display/presenters.js';
13
13
  import { promptForBlueprintType, promptForProject, promptForStack, } from '../../utils/display/prompt.js';
14
14
  import { blueprintConfigCore } from './config.js';
15
15
  const SCOPE_PROJECT = 'project';
@@ -20,6 +20,7 @@ export async function blueprintInitCore(options) {
20
20
  const { dir: argDir } = args;
21
21
  const userProvidedDirName = argDir || flagDir;
22
22
  const blueprintDir = userProvidedDirName || '.';
23
+ const flagProvidedConfig = [flagProjectId, flagOrganizationId, flagStackId].some(Boolean);
23
24
  const validationError = validateFlags({
24
25
  stackId: flagStackId,
25
26
  stackName: flagStackName,
@@ -29,15 +30,30 @@ export async function blueprintInitCore(options) {
29
30
  if (validationError)
30
31
  return validationError;
31
32
  try {
33
+ // look for existing blueprint file and maybe re-configure it
32
34
  const existingBlueprintFile = findBlueprintFile(blueprintDir);
33
35
  if (existingBlueprintFile) {
34
36
  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.' };
37
+ if (flagExample) {
38
+ return {
39
+ success: false,
40
+ error: 'Flag --example cannot be used with an existing Blueprint.',
41
+ };
42
+ }
43
+ if (flagStackName) {
44
+ return {
45
+ success: false,
46
+ error: 'Flag --stack-name cannot be used with an existing Blueprint.',
47
+ };
48
+ }
49
+ if (!flagProvidedConfig) {
50
+ const overwrite = await confirm({
51
+ message: 'Would you like to re-configure deployment for this Blueprint?',
52
+ default: true,
53
+ });
54
+ if (!overwrite)
55
+ return { success: false, error: 'Initialization cancelled.' };
56
+ }
41
57
  const existingBlueprint = await readLocalBlueprint(existingBlueprintFile.blueprintFilePath);
42
58
  return blueprintConfigCore({
43
59
  blueprint: existingBlueprint,
@@ -68,11 +84,13 @@ export async function blueprintInitCore(options) {
68
84
  organizationId: flagOrganizationId,
69
85
  stackId: flagStackId,
70
86
  stackName: flagStackName,
87
+ log,
71
88
  token,
72
89
  });
73
90
  const blueprintExtension = await determineBlueprintExtension({
74
91
  requestedType: flagBlueprintType,
75
92
  blueprintDir,
93
+ log,
76
94
  });
77
95
  return createBlueprintFiles({
78
96
  blueprintDir,
@@ -87,7 +105,6 @@ export async function blueprintInitCore(options) {
87
105
  }
88
106
  catch (error) {
89
107
  const errorMessage = error instanceof Error ? error.message : String(error);
90
- log(`Error: ${errorMessage}`);
91
108
  return { success: false, error: errorMessage };
92
109
  }
93
110
  }
@@ -136,7 +153,7 @@ async function handleExampleInitialization(options) {
136
153
  return { success: false, error: 'Failed to find blueprint file.' };
137
154
  }
138
155
  const { blueprintFilePath } = discoveredBlueprint;
139
- writeConfigFile({ blueprintFilePath, projectId: resolvedProjectId, stackId: stack.id });
156
+ writeConfigFile(blueprintFilePath, { projectId: resolvedProjectId, stackId: stack.id });
140
157
  log(check(`${chalk.bold('Configured:')} ${exampleDir}/${BLUEPRINT_CONFIG_DIR}/${BLUEPRINT_CONFIG_FILE}`));
141
158
  log(`\n Run "${chalk.bold.magenta(`cd ${exampleDir} && npm i`)}" and check out the README`);
142
159
  if (instructions) {
@@ -146,7 +163,7 @@ async function handleExampleInitialization(options) {
146
163
  return { success: true };
147
164
  }
148
165
  export async function resolveScopeAndStack(params) {
149
- const { projectId, organizationId, stackId, stackName, token } = params;
166
+ const { projectId, organizationId, stackId, stackName, log, token } = params;
150
167
  let scopeType = SCOPE_PROJECT;
151
168
  let scopeId;
152
169
  if (projectId) {
@@ -159,7 +176,9 @@ export async function resolveScopeAndStack(params) {
159
176
  }
160
177
  let resolvedStackId = stackId;
161
178
  if (!resolvedStackId && stackName && scopeType && scopeId) {
179
+ // sending stackName will assume you want to create a new stack
162
180
  // essentially the only way to create an org-scoped stack
181
+ log(`\nCreating new Stack "${stackName}" scoped to ${labeledId(scopeType, scopeId)}`);
163
182
  const stack = await createEmptyStack({
164
183
  token,
165
184
  scopeType,
@@ -169,11 +188,13 @@ export async function resolveScopeAndStack(params) {
169
188
  resolvedStackId = stack.id;
170
189
  }
171
190
  if (!scopeId) {
191
+ log('\nBlueprints are associated with a Sanity Project. Please select one:');
172
192
  const pickedProject = await promptForProject({ token });
173
193
  scopeType = SCOPE_PROJECT;
174
194
  scopeId = pickedProject.projectId;
175
195
  }
176
196
  if (!resolvedStackId) {
197
+ log('\nBlueprints are deployed to a "Stack".');
177
198
  const { stackId } = await promptForStack({ projectId: scopeId, token });
178
199
  resolvedStackId = stackId;
179
200
  }
@@ -184,11 +205,14 @@ export async function resolveScopeAndStack(params) {
184
205
  };
185
206
  }
186
207
  export async function determineBlueprintExtension(params) {
187
- const { requestedType, blueprintDir } = params;
208
+ const { requestedType, blueprintDir, log } = params;
188
209
  let extension = requestedType;
189
- if (!extension)
210
+ if (!extension) {
211
+ log('\nBlueprint files are authored locally to create resources in your Stack.');
190
212
  extension = await promptForBlueprintType();
213
+ }
191
214
  if (extension === 'js') {
215
+ // do we need to use .mjs or .js?
192
216
  const packageJsonPath = join(blueprintDir, 'package.json');
193
217
  const packageExists = existsSync(packageJsonPath);
194
218
  if (packageExists) {
@@ -209,6 +233,7 @@ export async function createBlueprintFiles(params) {
209
233
  if (!blueprintExtension) {
210
234
  return { success: false, error: 'Blueprint type is required.' };
211
235
  }
236
+ log(`\nCreating local Blueprint setup...`);
212
237
  const blueprintFileName = `sanity.blueprint.${blueprintExtension}`;
213
238
  const blueprintFilePath = join(blueprintDir, blueprintFileName);
214
239
  writeBlueprintToDisk({ blueprintFilePath });
@@ -217,8 +242,7 @@ export async function createBlueprintFiles(params) {
217
242
  }
218
243
  const displayPath = userProvidedDirName || '.';
219
244
  log(check(`${chalk.bold('Created Blueprint:')} ${displayPath}/${blueprintFileName}`));
220
- writeConfigFile({
221
- blueprintFilePath,
245
+ writeConfigFile(blueprintFilePath, {
222
246
  stackId,
223
247
  ...(scopeType === SCOPE_ORGANIZATION ? { organizationId: scopeId } : { projectId: scopeId }),
224
248
  });
@@ -7,3 +7,4 @@ export declare function niceId(id: string | undefined): string;
7
7
  export declare function indent(str: string, spaces?: number): string;
8
8
  export declare function capitalize(str: string): string;
9
9
  export declare function filePathRelativeToCwd(filePath: string): string;
10
+ export declare function labeledId(label: string | undefined, id: string | undefined): string;
@@ -33,3 +33,6 @@ export function capitalize(str) {
33
33
  export function filePathRelativeToCwd(filePath) {
34
34
  return filePath.replace(cwd(), '.');
35
35
  }
36
+ export function labeledId(label, id) {
37
+ return `${chalk.blue(capitalize(label || 'unknown'))} ${niceId(id || 'unknown')}`;
38
+ }
@@ -84,24 +84,25 @@ export async function promptForStack({ projectId, token, }) {
84
84
  throw new Error(stacksErr || 'Failed to list Stacks');
85
85
  }
86
86
  const newStackValue = { id: 'new', name: 'new' };
87
- const stackChoices = [];
88
- stackChoices.push(new Separator(chalk.underline('Create a new Stack:')));
89
- stackChoices.push({ name: chalk.bold('New Stack ✨'), value: newStackValue });
87
+ let pickedStackId = newStackValue;
90
88
  if (stacks.length > 0) {
89
+ const stackChoices = [];
90
+ stackChoices.push(new Separator(chalk.underline('Create a new Stack:')));
91
+ stackChoices.push({ name: chalk.bold('New Stack ✨'), value: newStackValue });
91
92
  stackChoices.push(new Separator(chalk.underline('Use an existing Stack:')));
92
93
  stackChoices.push(...stacks.map((s) => ({
93
94
  name: `"${s.name}" ${niceId(s.id)} ${chalk.dim(`(${s.resources.length} res)`)}`,
94
95
  value: { id: s.id, name: s.name },
95
96
  })));
97
+ pickedStackId = await select({
98
+ message: 'Select a deployment Stack:',
99
+ choices: stackChoices,
100
+ default: newStackValue,
101
+ });
96
102
  }
97
- const pickedStackId = await select({
98
- message: 'Select an existing deployment or create a new one:',
99
- choices: stackChoices,
100
- default: newStackValue,
101
- });
102
103
  if (pickedStackId.id === 'new') {
103
104
  const stackName = await input({
104
- message: 'Enter a name for your Stack:',
105
+ message: 'Enter a name for your new Stack:',
105
106
  validate: (input) => input.length > 0 || 'Stack name is required',
106
107
  });
107
108
  const stack = await createEmptyStack({
@@ -50,7 +50,7 @@ export async function validTokenOrErrorMessage(maybeToken) {
50
50
  ok: false,
51
51
  error: {
52
52
  e,
53
- message: `Authentication server error: "${e.cause}". Try again later`,
53
+ message: `Server error: "${e.cause}". Try logging in again with \`npx @sanity/cli login\``,
54
54
  },
55
55
  };
56
56
  default:
@@ -318,6 +318,9 @@
318
318
  "force"
319
319
  ],
320
320
  "description": "Project associated with the Stack",
321
+ "exclusive": [
322
+ "organization-id"
323
+ ],
321
324
  "name": "project-id",
322
325
  "hasDynamicHelp": false,
323
326
  "multiple": false,
@@ -334,6 +337,9 @@
334
337
  "force"
335
338
  ],
336
339
  "description": "Organization associated with the Stack",
340
+ "exclusive": [
341
+ "project-id"
342
+ ],
337
343
  "name": "organization-id",
338
344
  "hasDynamicHelp": false,
339
345
  "multiple": false,
@@ -415,7 +421,7 @@
415
421
  "description": "Show information about a Blueprint Stack deployment",
416
422
  "examples": [
417
423
  "<%= config.bin %> <%= command.id %>",
418
- "<%= config.bin %> <%= command.id %> --stack-id <stackId>"
424
+ "<%= config.bin %> <%= command.id %> --id <stackId>"
419
425
  ],
420
426
  "flags": {
421
427
  "verbose": {
@@ -457,7 +463,7 @@
457
463
  "name": "dir"
458
464
  }
459
465
  },
460
- "description": "Initialize a new Blueprint",
466
+ "description": "Initialize a new Blueprint Stack deployment",
461
467
  "examples": [
462
468
  "<%= config.bin %> <%= command.id %>",
463
469
  "<%= config.bin %> <%= command.id %> [directory]",
@@ -657,7 +663,7 @@
657
663
  "blueprints:stacks": {
658
664
  "aliases": [],
659
665
  "args": {},
660
- "description": "List all Blueprint stacks",
666
+ "description": "List all Blueprint Stacks",
661
667
  "examples": [
662
668
  "<%= config.bin %> <%= command.id %>",
663
669
  "<%= config.bin %> <%= command.id %> --project-id <projectId>",
@@ -1410,5 +1416,5 @@
1410
1416
  ]
1411
1417
  }
1412
1418
  },
1413
- "version": "12.0.0"
1419
+ "version": "12.1.0"
1414
1420
  }
package/package.json CHANGED
@@ -1,11 +1,14 @@
1
1
  {
2
2
  "name": "@sanity/runtime-cli",
3
3
  "description": "Sanity's Runtime CLI for Blueprints and Functions",
4
- "version": "12.0.0",
4
+ "version": "12.1.0",
5
5
  "author": "Sanity Runtime Team",
6
6
  "type": "module",
7
7
  "license": "MIT",
8
- "repository": "sanity-io/runtime-cli",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/sanity-io/runtime-cli.git"
11
+ },
9
12
  "bugs": "https://github.com/sanity-io/runtime-cli/issues",
10
13
  "homepage": "https://github.com/sanity-io/runtime-cli",
11
14
  "main": "dist/index.js",
@@ -53,7 +56,7 @@
53
56
  "./oclif.manifest.json"
54
57
  ],
55
58
  "bin": {
56
- "sanity-run": "./bin/run.js"
59
+ "sanity-run": "bin/run.js"
57
60
  },
58
61
  "scripts": {
59
62
  "build": "rollup -c && npm run build:ts && npm run build:static && npm run build:oclif",