@sanity/runtime-cli 4.5.1 → 5.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md 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/4.5.1 linux-x64 node-v22.15.0
23
+ @sanity/runtime-cli/5.0.1 linux-x64 node-v22.15.0
24
24
  $ sanity-run --help [COMMAND]
25
25
  USAGE
26
26
  $ sanity-run COMMAND
@@ -48,32 +48,37 @@ USAGE
48
48
 
49
49
  ## `sanity-run blueprints add TYPE`
50
50
 
51
- Add a resource to a Blueprint
51
+ Add a (function) resource to a Blueprint
52
52
 
53
53
  ```
54
54
  USAGE
55
- $ sanity-run blueprints add TYPE [--function-type document-publish -n <value>]
55
+ $ sanity-run blueprints add TYPE [--fn-type document-publish -n <value>] [--language ts|js] [--javascript]
56
56
 
57
57
  ARGUMENTS
58
58
  TYPE (function) Type of resource to add (e.g. function)
59
59
 
60
60
  FLAGS
61
- -n, --name=<value> Name of the resource to add
62
- --function-type=<option> Type of function to add (e.g. document-publish)
63
- <options: document-publish>
61
+ -n, --name=<value> Name of the resource to add
62
+ --fn-type=<option> Type of new function
63
+ <options: document-publish>
64
+ --javascript Use JavaScript instead of TypeScript
65
+ --language=<option> [default: ts] Language of the new function
66
+ <options: ts|js>
64
67
 
65
68
  DESCRIPTION
66
- Add a resource to a Blueprint
69
+ Add a (function) resource to a Blueprint
67
70
 
68
71
  EXAMPLES
69
72
  $ sanity-run blueprints add function
70
73
 
71
74
  $ sanity-run blueprints add function --name my-function
72
75
 
73
- $ sanity-run blueprints add function --name my-function --function-type document-publish
76
+ $ sanity-run blueprints add function --name my-function --fn-type document-publish
77
+
78
+ $ sanity-run blueprints add function --name my-function --fn-type document-publish --lang js
74
79
  ```
75
80
 
76
- _See code: [src/commands/blueprints/add.ts](https://github.com/sanity-io/runtime-cli/blob/v4.5.1/src/commands/blueprints/add.ts)_
81
+ _See code: [src/commands/blueprints/add.ts](https://github.com/sanity-io/runtime-cli/blob/v5.0.1/src/commands/blueprints/add.ts)_
77
82
 
78
83
  ## `sanity-run blueprints config`
79
84
 
@@ -101,7 +106,7 @@ EXAMPLES
101
106
  $ sanity-run blueprints config --edit --project-id <projectId>
102
107
  ```
103
108
 
104
- _See code: [src/commands/blueprints/config.ts](https://github.com/sanity-io/runtime-cli/blob/v4.5.1/src/commands/blueprints/config.ts)_
109
+ _See code: [src/commands/blueprints/config.ts](https://github.com/sanity-io/runtime-cli/blob/v5.0.1/src/commands/blueprints/config.ts)_
105
110
 
106
111
  ## `sanity-run blueprints deploy`
107
112
 
@@ -123,11 +128,11 @@ EXAMPLES
123
128
  $ sanity-run blueprints deploy --no-wait
124
129
  ```
125
130
 
126
- _See code: [src/commands/blueprints/deploy.ts](https://github.com/sanity-io/runtime-cli/blob/v4.5.1/src/commands/blueprints/deploy.ts)_
131
+ _See code: [src/commands/blueprints/deploy.ts](https://github.com/sanity-io/runtime-cli/blob/v5.0.1/src/commands/blueprints/deploy.ts)_
127
132
 
128
133
  ## `sanity-run blueprints destroy`
129
134
 
130
- Destroy a Blueprint deployment
135
+ Destroy a Blueprint deployment (will not delete local files)
131
136
 
132
137
  ```
133
138
  USAGE
@@ -137,13 +142,13 @@ FLAGS
137
142
  --force Force destroy (skip confirmation)
138
143
 
139
144
  DESCRIPTION
140
- Destroy a Blueprint deployment
145
+ Destroy a Blueprint deployment (will not delete local files)
141
146
 
142
147
  EXAMPLES
143
148
  $ sanity-run blueprints destroy
144
149
  ```
145
150
 
146
- _See code: [src/commands/blueprints/destroy.ts](https://github.com/sanity-io/runtime-cli/blob/v4.5.1/src/commands/blueprints/destroy.ts)_
151
+ _See code: [src/commands/blueprints/destroy.ts](https://github.com/sanity-io/runtime-cli/blob/v5.0.1/src/commands/blueprints/destroy.ts)_
147
152
 
148
153
  ## `sanity-run blueprints info`
149
154
 
@@ -160,7 +165,7 @@ EXAMPLES
160
165
  $ sanity-run blueprints info
161
166
  ```
162
167
 
163
- _See code: [src/commands/blueprints/info.ts](https://github.com/sanity-io/runtime-cli/blob/v4.5.1/src/commands/blueprints/info.ts)_
168
+ _See code: [src/commands/blueprints/info.ts](https://github.com/sanity-io/runtime-cli/blob/v5.0.1/src/commands/blueprints/info.ts)_
164
169
 
165
170
  ## `sanity-run blueprints init [DIR]`
166
171
 
@@ -192,7 +197,7 @@ EXAMPLES
192
197
  $ sanity-run blueprints init --blueprint-type <json|js|ts> --project-id <projectId>
193
198
  ```
194
199
 
195
- _See code: [src/commands/blueprints/init.ts](https://github.com/sanity-io/runtime-cli/blob/v4.5.1/src/commands/blueprints/init.ts)_
200
+ _See code: [src/commands/blueprints/init.ts](https://github.com/sanity-io/runtime-cli/blob/v5.0.1/src/commands/blueprints/init.ts)_
196
201
 
197
202
  ## `sanity-run blueprints logs`
198
203
 
@@ -214,7 +219,7 @@ EXAMPLES
214
219
  $ sanity-run blueprints logs --watch
215
220
  ```
216
221
 
217
- _See code: [src/commands/blueprints/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v4.5.1/src/commands/blueprints/logs.ts)_
222
+ _See code: [src/commands/blueprints/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v5.0.1/src/commands/blueprints/logs.ts)_
218
223
 
219
224
  ## `sanity-run blueprints plan`
220
225
 
@@ -231,7 +236,7 @@ EXAMPLES
231
236
  $ sanity-run blueprints plan
232
237
  ```
233
238
 
234
- _See code: [src/commands/blueprints/plan.ts](https://github.com/sanity-io/runtime-cli/blob/v4.5.1/src/commands/blueprints/plan.ts)_
239
+ _See code: [src/commands/blueprints/plan.ts](https://github.com/sanity-io/runtime-cli/blob/v5.0.1/src/commands/blueprints/plan.ts)_
235
240
 
236
241
  ## `sanity-run functions dev`
237
242
 
@@ -251,7 +256,7 @@ EXAMPLES
251
256
  $ sanity-run functions dev --port 8974
252
257
  ```
253
258
 
254
- _See code: [src/commands/functions/dev.ts](https://github.com/sanity-io/runtime-cli/blob/v4.5.1/src/commands/functions/dev.ts)_
259
+ _See code: [src/commands/functions/dev.ts](https://github.com/sanity-io/runtime-cli/blob/v5.0.1/src/commands/functions/dev.ts)_
255
260
 
256
261
  ## `sanity-run functions env add NAME KEY VALUE`
257
262
 
@@ -273,7 +278,7 @@ EXAMPLES
273
278
  $ sanity-run functions env add MyFunction API_URL https://api.example.com/
274
279
  ```
275
280
 
276
- _See code: [src/commands/functions/env/add.ts](https://github.com/sanity-io/runtime-cli/blob/v4.5.1/src/commands/functions/env/add.ts)_
281
+ _See code: [src/commands/functions/env/add.ts](https://github.com/sanity-io/runtime-cli/blob/v5.0.1/src/commands/functions/env/add.ts)_
277
282
 
278
283
  ## `sanity-run functions env list NAME`
279
284
 
@@ -293,7 +298,7 @@ EXAMPLES
293
298
  $ sanity-run functions env list MyFunction
294
299
  ```
295
300
 
296
- _See code: [src/commands/functions/env/list.ts](https://github.com/sanity-io/runtime-cli/blob/v4.5.1/src/commands/functions/env/list.ts)_
301
+ _See code: [src/commands/functions/env/list.ts](https://github.com/sanity-io/runtime-cli/blob/v5.0.1/src/commands/functions/env/list.ts)_
297
302
 
298
303
  ## `sanity-run functions env remove NAME KEY`
299
304
 
@@ -314,7 +319,7 @@ EXAMPLES
314
319
  $ sanity-run functions env remove MyFunction API_URL
315
320
  ```
316
321
 
317
- _See code: [src/commands/functions/env/remove.ts](https://github.com/sanity-io/runtime-cli/blob/v4.5.1/src/commands/functions/env/remove.ts)_
322
+ _See code: [src/commands/functions/env/remove.ts](https://github.com/sanity-io/runtime-cli/blob/v5.0.1/src/commands/functions/env/remove.ts)_
318
323
 
319
324
  ## `sanity-run functions invoke NAME`
320
325
 
@@ -340,7 +345,7 @@ EXAMPLES
340
345
  $ sanity-run functions invoke <name> --file 'payload.json'
341
346
  ```
342
347
 
343
- _See code: [src/commands/functions/invoke.ts](https://github.com/sanity-io/runtime-cli/blob/v4.5.1/src/commands/functions/invoke.ts)_
348
+ _See code: [src/commands/functions/invoke.ts](https://github.com/sanity-io/runtime-cli/blob/v5.0.1/src/commands/functions/invoke.ts)_
344
349
 
345
350
  ## `sanity-run functions logs NAME`
346
351
 
@@ -372,7 +377,7 @@ EXAMPLES
372
377
  $ sanity-run functions logs <name> --delete
373
378
  ```
374
379
 
375
- _See code: [src/commands/functions/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v4.5.1/src/commands/functions/logs.ts)_
380
+ _See code: [src/commands/functions/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v5.0.1/src/commands/functions/logs.ts)_
376
381
 
377
382
  ## `sanity-run functions test NAME`
378
383
 
@@ -405,7 +410,7 @@ EXAMPLES
405
410
  $ sanity-run functions test <name> --data '{ "id": 1 }' --timeout 60
406
411
  ```
407
412
 
408
- _See code: [src/commands/functions/test.ts](https://github.com/sanity-io/runtime-cli/blob/v4.5.1/src/commands/functions/test.ts)_
413
+ _See code: [src/commands/functions/test.ts](https://github.com/sanity-io/runtime-cli/blob/v5.0.1/src/commands/functions/test.ts)_
409
414
 
410
415
  ## `sanity-run help [COMMAND]`
411
416
 
@@ -3,6 +3,8 @@ import { createRequire } from 'node:module';
3
3
  import { basename, dirname, extname, join } from 'node:path';
4
4
  import { cwd } from 'node:process';
5
5
  import { findUpSync } from 'find-up';
6
+ import { isLocalFunctionResource } from '../../utils/types.js';
7
+ import { validateFunctionResource } from '../../utils/validate/resource.js';
6
8
  import { blueprintParserValidator } from '../../utils/vendor/parser-validator.js';
7
9
  const SUPPORTED_FILE_EXTENSIONS = ['.json', '.js', '.mjs', '.cjs', '.ts'];
8
10
  const SUPPORTED_FILE_NAMES_IN_PRIORITY_ORDER = SUPPORTED_FILE_EXTENSIONS.map((ext) => `blueprint${ext}`);
@@ -108,37 +110,23 @@ export async function readLocalBlueprint(blueprintPath) {
108
110
  }
109
111
  }
110
112
  const parserResult = blueprintParserValidator(rawBlueprint);
111
- const { blueprint: parsedBlueprint } = parserResult;
113
+ const parsedBlueprint = parserResult.blueprint;
112
114
  const errors = parserResult.errors || [];
115
+ // further validation - remove once validator is updated
116
+ if (parsedBlueprint.resources) {
117
+ // validate function resources
118
+ const functionResources = parsedBlueprint.resources.filter(isLocalFunctionResource);
119
+ const fnErrors = functionResources.map((r) => validateFunctionResource(r));
120
+ errors.push(...fnErrors.flat());
121
+ }
113
122
  const configIds = readConfigFile(foundPath);
114
123
  const configPath = configIds?.configPath;
115
- const blueprintMetadata = parsedBlueprint.metadata;
116
- // find projectId
117
124
  let projectId;
118
- if (configIds?.projectId) {
125
+ if (configIds?.projectId)
119
126
  projectId = configIds.projectId;
120
- }
121
- else if (blueprintMetadata?.projectId) {
122
- projectId = blueprintMetadata.projectId;
123
- }
124
- else {
125
- const projectResource = parsedBlueprint.resources.find((r) => r.type === 'sanity.project');
126
- if (projectResource)
127
- projectId = projectResource.id;
128
- }
129
- // find stackId
130
127
  let stackId;
131
- if (configIds?.stackId) {
128
+ if (configIds?.stackId)
132
129
  stackId = configIds.stackId;
133
- }
134
- else if (blueprintMetadata?.stackId) {
135
- stackId = blueprintMetadata.stackId;
136
- }
137
- else {
138
- const stackResource = parsedBlueprint.resources.find((r) => r.type === 'sanity.blueprints.stack');
139
- if (stackResource)
140
- stackId = stackResource.id;
141
- }
142
130
  // LAUNCH LIMIT: 1 Stack per Project - infer stackId from projectId
143
131
  if (!stackId && projectId)
144
132
  stackId = `ST-${projectId}`;
@@ -2,6 +2,7 @@ import type { LocalFunctionResource } from '../../utils/types.js';
2
2
  interface FunctionResourceOptions {
3
3
  name: string;
4
4
  type: string;
5
+ lang: string;
5
6
  displayName?: string;
6
7
  blueprintFilePath?: string;
7
8
  }
@@ -7,16 +7,16 @@ const DEFAULT_FUNCTION_TEMPLATE = /*js*/ `export async function handler({context
7
7
  const time = new Date().toLocaleTimeString()
8
8
  console.log(\`👋 Your Sanity Function was called at \${time}\`)
9
9
  }`;
10
- const DEFAULT_PACKAGE_JSON = `{
11
- "name": "<<NAME>>",
12
- "type": "module",
13
- "main": "index.js"
14
- }`;
10
+ const DEFAULT_PACKAGE_JSON = {
11
+ name: '',
12
+ type: 'module',
13
+ main: '',
14
+ };
15
15
  /**
16
16
  * Creates a new function resource file and adds it to the blueprint
17
17
  */
18
18
  export function createFunctionResource(options) {
19
- const { name, type, displayName = name, blueprintFilePath } = options;
19
+ const { name, type, lang, displayName = name, blueprintFilePath } = options;
20
20
  let workingDir = cwd();
21
21
  if (blueprintFilePath) {
22
22
  if (!existsSync(blueprintFilePath)) {
@@ -34,19 +34,32 @@ export function createFunctionResource(options) {
34
34
  if (!existsSync(functionDir)) {
35
35
  mkdirSync(functionDir, { recursive: true });
36
36
  }
37
- // Create index.js with default template
38
- const indexPath = join(functionDir, 'index.js');
37
+ if (!['ts', 'js'].includes(lang))
38
+ throw Error(`Unsupported language: ${lang}`);
39
+ // Create index.<lang> with default template
40
+ const indexPath = join(functionDir, `index.${lang}`);
39
41
  writeFileSync(indexPath, DEFAULT_FUNCTION_TEMPLATE);
40
42
  // Create package.json
41
43
  const packagePath = join(functionDir, 'package.json');
42
- const packageContent = DEFAULT_PACKAGE_JSON.replace('<<NAME>>', name);
43
- writeFileSync(packagePath, packageContent);
44
+ const packageContent = {
45
+ ...DEFAULT_PACKAGE_JSON,
46
+ name,
47
+ main: `index.${lang}`,
48
+ };
49
+ writeFileSync(packagePath, JSON.stringify(packageContent, null, 2));
50
+ // type looks like 'document-publish'
51
+ const typeParts = type.split('-');
52
+ const typeName = typeParts[0];
53
+ const eventOn = typeParts[1];
44
54
  // Create resource definition
45
55
  const resourceJson = {
46
56
  displayName,
47
57
  name,
48
- type: `sanity.function.${type}`,
49
58
  src: `functions/${name}`,
59
+ type: `sanity.function.${typeName}`,
60
+ event: {
61
+ on: [eventOn],
62
+ },
50
63
  };
51
64
  // Add to blueprint or return for manual addition
52
65
  const resource = addResourceToBlueprint({ blueprintFilePath, resource: resourceJson });
@@ -27,8 +27,6 @@ export async function getStack({ stackId, auth, }) {
27
27
  };
28
28
  }
29
29
  export async function createStack({ stackPayload, auth, }) {
30
- // LAUNCH LIMIT: 1 Stack per Project
31
- stackPayload.useProjectBasedId = true;
32
30
  const response = await fetch(stacksUrl, {
33
31
  method: 'POST',
34
32
  headers: getHeaders(auth),
@@ -7,13 +7,17 @@ export default class AddCommand extends Command {
7
7
  };
8
8
  static flags: {
9
9
  name: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
- 'function-type': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
+ 'fn-type': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
11
+ language: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
12
+ javascript: import("@oclif/core/interfaces").BooleanFlag<boolean>;
11
13
  };
12
14
  run(): Promise<void>;
13
15
  promptForFunctionName(): Promise<string>;
14
16
  promptForFunctionType(): Promise<string>;
15
- addFunction({ name, type }: {
17
+ promptForFunctionLang(): Promise<string>;
18
+ addFunction({ name, type, lang, }: {
16
19
  name?: string;
17
20
  type?: string;
21
+ lang?: string;
18
22
  }): Promise<void>;
19
23
  }
@@ -1,16 +1,18 @@
1
1
  import { cwd } from 'node:process';
2
2
  import { Args, Command, Flags } from '@oclif/core';
3
+ import chalk from 'chalk';
3
4
  import highlight from 'color-json';
4
5
  import inquirer from 'inquirer';
5
6
  import { findBlueprintFile } from '../../actions/blueprints/blueprint.js';
6
7
  import { createFunctionResource } from '../../actions/blueprints/resources.js';
7
- import { validateFunctionName, validateFunctionType } from '../../utils/validate/resource.js';
8
+ import { validateFunctionName } from '../../utils/validate/resource.js';
8
9
  export default class AddCommand extends Command {
9
- static description = 'Add a resource to a Blueprint';
10
+ static description = 'Add a (function) resource to a Blueprint';
10
11
  static examples = [
11
12
  '<%= config.bin %> <%= command.id %> function',
12
13
  '<%= config.bin %> <%= command.id %> function --name my-function',
13
- '<%= config.bin %> <%= command.id %> function --name my-function --function-type document-publish',
14
+ '<%= config.bin %> <%= command.id %> function --name my-function --fn-type document-publish',
15
+ '<%= config.bin %> <%= command.id %> function --name my-function --fn-type document-publish --lang js',
14
16
  ];
15
17
  static args = {
16
18
  type: Args.string({
@@ -24,11 +26,23 @@ export default class AddCommand extends Command {
24
26
  description: 'Name of the resource to add',
25
27
  char: 'n',
26
28
  }),
27
- 'function-type': Flags.string({
28
- description: 'Type of function to add (e.g. document-publish)',
29
+ 'fn-type': Flags.string({
30
+ description: 'Type of new function',
29
31
  options: ['document-publish' /*, 'document-create', 'document-delete'*/],
32
+ aliases: ['function-type'],
33
+ // default: 'document-publish', // prompting informs user of default
30
34
  dependsOn: ['name'],
31
35
  }),
36
+ language: Flags.string({
37
+ description: 'Language of the new function',
38
+ aliases: ['function-language', 'lang'],
39
+ options: ['ts', 'js'],
40
+ default: 'ts',
41
+ }),
42
+ javascript: Flags.boolean({
43
+ description: 'Use JavaScript instead of TypeScript',
44
+ aliases: ['js'],
45
+ }),
32
46
  };
33
47
  async run() {
34
48
  const { args, flags } = await this.parse(AddCommand);
@@ -38,9 +52,11 @@ export default class AddCommand extends Command {
38
52
  if (!existingBlueprint) {
39
53
  this.error('No Blueprint file found. Run `sanity-run blueprints init` first.');
40
54
  }
41
- const resourceName = flags.name;
42
- const functionType = flags['function-type'];
43
- await this.addFunction({ name: resourceName, type: functionType });
55
+ const { name: resourceName, 'fn-type': functionType, javascript } = flags;
56
+ let { lang: functionLang } = flags;
57
+ if (javascript)
58
+ functionLang = 'js';
59
+ await this.addFunction({ name: resourceName, type: functionType, lang: functionLang });
44
60
  }
45
61
  async promptForFunctionName() {
46
62
  const { functionName } = await inquirer.prompt([
@@ -69,21 +85,41 @@ export default class AddCommand extends Command {
69
85
  ]);
70
86
  return functionType;
71
87
  }
72
- async addFunction({ name, type }) {
88
+ async promptForFunctionLang() {
89
+ const { functionLang } = await inquirer.prompt([
90
+ {
91
+ type: 'list',
92
+ name: 'functionLang',
93
+ message: 'Choose function language:',
94
+ choices: [
95
+ { name: 'TypeScript', value: 'ts' },
96
+ { name: 'JavaScript', value: 'js' },
97
+ ],
98
+ default: 'ts',
99
+ },
100
+ ]);
101
+ return functionLang;
102
+ }
103
+ async addFunction({ name, type, lang, }) {
73
104
  const functionName = name || (await this.promptForFunctionName());
74
105
  if (!validateFunctionName(functionName)) {
75
106
  this.error('Invalid function name. Must be 6+ characters, no special characters, no spaces');
76
107
  }
77
108
  const functionType = type || (await this.promptForFunctionType());
78
- if (!validateFunctionType(functionType)) {
109
+ const functionLang = lang || (await this.promptForFunctionLang());
110
+ if (!['document-publish', 'document-create', 'document-delete'].includes(functionType)) {
79
111
  this.error('Invalid function type. Must be one of: document-publish, document-create, document-delete');
80
112
  }
81
113
  const { filePath, resourceAdded, resource } = createFunctionResource({
82
114
  name: functionName,
83
115
  type: functionType,
116
+ lang: functionLang,
84
117
  displayName: functionName,
85
118
  });
86
119
  this.log(`\nCreated function: ${filePath.replace(cwd(), '')}`);
120
+ if (functionLang === 'ts') {
121
+ this.log(chalk.dim('To avoid committing build artifacts, it is helpful to .gitignore "functions/**/.build/**"'));
122
+ }
87
123
  if (!resourceAdded) {
88
124
  // print the resource JSON for manual addition
89
125
  this.log('\nAdd this Function resource to your blueprint:');
@@ -9,6 +9,8 @@ export default class ConfigCommand extends Command {
9
9
  'stack-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
10
  };
11
11
  sanityToken: string | undefined;
12
+ projectId: string | undefined;
13
+ stackId: string | undefined;
12
14
  run(): Promise<void>;
13
15
  promptForProjectId({ knownProjectId }: {
14
16
  knownProjectId?: string;
@@ -17,11 +19,16 @@ export default class ConfigCommand extends Command {
17
19
  projectId: string;
18
20
  knownStackId?: string;
19
21
  }): Promise<string | undefined>;
20
- testConfigAndReport({ stackId, projectId }: {
22
+ testConfigAndReport({ stackId, projectId, reinit, }: {
21
23
  stackId: string;
22
24
  projectId: string;
25
+ reinit?: boolean;
23
26
  }): Promise<{
24
27
  ok: boolean;
25
28
  error: string | null;
26
29
  }>;
30
+ startReinitializeStack({ projectId, stackId }: {
31
+ projectId: string;
32
+ stackId: string;
33
+ }): Promise<void>;
27
34
  }
@@ -1,10 +1,11 @@
1
1
  import { Command, Flags } from '@oclif/core';
2
+ import chalk from 'chalk';
2
3
  import highlight from 'color-json';
3
4
  import inquirer from 'inquirer';
4
5
  import Spinner from 'yocto-spinner';
5
6
  import { readLocalBlueprint, writeConfigFile } from '../../actions/blueprints/blueprint.js';
6
- import { listProjects } from '../../actions/blueprints/projects.js';
7
- import { getStack, listStacks } from '../../actions/blueprints/stacks.js';
7
+ import { getProject, listProjects } from '../../actions/blueprints/projects.js';
8
+ import { createStack, getStack, listStacks } from '../../actions/blueprints/stacks.js';
8
9
  import { bold, dim, niceId } from '../../utils/display/colors.js';
9
10
  import { presentBlueprintParserErrors } from '../../utils/display/errors.js';
10
11
  import { validTokenOrErrorMessage } from '../../utils/validated-token.js';
@@ -43,6 +44,8 @@ export default class ConfigCommand extends Command {
43
44
  }),
44
45
  };
45
46
  sanityToken;
47
+ projectId;
48
+ stackId;
46
49
  async run() {
47
50
  const { flags } = await this.parse(ConfigCommand);
48
51
  const { edit: editConfig, 'project-id': editProjectId, 'stack-id': editStackId, 'test-config': testConfig, } = flags;
@@ -84,22 +87,27 @@ export default class ConfigCommand extends Command {
84
87
  // LAUNCH LIMIT: 1 Stack per Project - do not allow Stack ID to be set
85
88
  // const stackId =
86
89
  // editStackId || (await this.promptForStackId({projectId, knownStackId: configStackId}))
87
- const stackId = configStackId;
90
+ let stackId = configStackId;
88
91
  if (testConfig) {
89
92
  if (projectId && stackId) {
90
- const { ok: newConfigOk } = await this.testConfigAndReport({ stackId, projectId });
91
- if (!newConfigOk) {
93
+ const { ok: newConfigOk } = await this.testConfigAndReport({
94
+ stackId,
95
+ projectId,
96
+ reinit: editConfig,
97
+ });
98
+ if (!newConfigOk)
92
99
  this.error('Updated configuration has not been saved.');
93
- }
94
100
  }
95
101
  else {
96
102
  this.error('Unable to test the configuration. Both Project and Stack IDs must be set.');
97
103
  }
98
104
  }
105
+ // LAUNCH LIMIT: 1 Stack per Project - do not allow Stack ID to be set
106
+ if (stackId?.endsWith(projectId))
107
+ stackId = undefined;
99
108
  try {
100
109
  // update or create .blueprint/config.json
101
- // LAUNCH LIMIT: 1 Stack per Project - do not allow Stack ID to be set
102
- writeConfigFile({ projectId /*, stackId*/ });
110
+ writeConfigFile({ projectId, stackId });
103
111
  this.log('Configuration updated successfully.');
104
112
  }
105
113
  catch (error) {
@@ -159,7 +167,7 @@ export default class ConfigCommand extends Command {
159
167
  }
160
168
  return undefined;
161
169
  }
162
- async testConfigAndReport({ stackId, projectId }) {
170
+ async testConfigAndReport({ stackId, projectId, reinit = false, }) {
163
171
  if (!this.sanityToken)
164
172
  this.error('Unable to test the configuration. Missing API token.');
165
173
  const spinner = Spinner({ text: 'Testing the configuration...' }).start();
@@ -168,12 +176,41 @@ export default class ConfigCommand extends Command {
168
176
  auth: { token: this.sanityToken, projectId },
169
177
  });
170
178
  if (!ok) {
171
- spinner.error(error ?? 'Unknown error testing the configuration');
172
- this.log('Use the --edit flag to interactively update the configuration.');
179
+ spinner.error('Blueprint deployment not found');
180
+ // check if configured project and stack can be reinitialized
181
+ if (reinit && stackId === `ST-${projectId}`) {
182
+ await this.startReinitializeStack({ projectId, stackId });
183
+ return { ok: true, error: null };
184
+ }
173
185
  }
174
186
  else {
175
187
  spinner.success('Configuration is valid.');
176
188
  }
177
189
  return { ok, error };
178
190
  }
191
+ async startReinitializeStack({ projectId, stackId }) {
192
+ if (!this.sanityToken)
193
+ this.error('Unable to reinitialize the Stack. Missing API token.');
194
+ const auth = { token: this.sanityToken, projectId };
195
+ // stack id IS ST-${projectId} – it has already been checked and doesn't exist
196
+ this.log(`A new Blueprint deployment can be created with the ${chalk.bold('existing')} configuration.`);
197
+ const { confirm } = await inquirer.prompt([
198
+ {
199
+ type: 'confirm',
200
+ name: 'confirm',
201
+ message: `Do you want to create a ${chalk.blue('new')}, empty Blueprint deployment with the ${chalk.blue('existing')} configuration?`,
202
+ },
203
+ ]);
204
+ if (!confirm)
205
+ this.error('Reinitialization cancelled.');
206
+ const { ok: projectOk, project } = await getProject(auth);
207
+ if (!projectOk)
208
+ this.error('Failed to find Project while creating Stack');
209
+ const projectDisplayName = project.displayName;
210
+ const stackPayload = { name: projectDisplayName, projectId, document: { resources: [] } };
211
+ const response = await createStack({ stackPayload, auth });
212
+ if (!response.ok)
213
+ this.error(response.error || 'Failed to create new Stack');
214
+ this.log(`New Blueprint deployment created for "${projectDisplayName}"`);
215
+ }
179
216
  }
@@ -6,7 +6,7 @@ import { destroyStack, getStack } from '../../actions/blueprints/stacks.js';
6
6
  import { DeployedBlueprintCommand } from '../../baseCommands.js';
7
7
  import { bold, niceId } from '../../utils/display/colors.js';
8
8
  export default class DestroyCommand extends DeployedBlueprintCommand {
9
- static description = 'Destroy a Blueprint deployment';
9
+ static description = 'Destroy a Blueprint deployment (will not delete local files)';
10
10
  static examples = [
11
11
  '<%= config.bin %> <%= command.id %>',
12
12
  // LAUNCH LIMIT: 1 Stack per Project - do not allow Stack ID to be set
@@ -1,5 +1,5 @@
1
1
  import { Command } from '@oclif/core';
2
- import type { AuthParams, Stack, StackPayload } from '../../utils/types.js';
2
+ import type { AuthParams, Stack } from '../../utils/types.js';
3
3
  export default class InitCommand extends Command {
4
4
  static description: string;
5
5
  static examples: string[];
@@ -23,9 +23,10 @@ export default class InitCommand extends Command {
23
23
  promptForStackId({ projectId }: {
24
24
  projectId: string;
25
25
  }): Promise<string>;
26
- createEmptyStack({ stackPayload, auth, }: {
27
- stackPayload: StackPayload;
28
- auth: AuthParams;
26
+ createEmptyStack({ projectId, name, projectBased, }: {
27
+ projectId: string;
28
+ name: string;
29
+ projectBased?: boolean;
29
30
  }): Promise<Stack>;
30
31
  createProjectBasedStack(auth: AuthParams): Promise<Stack>;
31
32
  }
@@ -1,11 +1,12 @@
1
1
  import { join } from 'node:path';
2
2
  import { cwd } from 'node:process';
3
3
  import { Args, Command, Flags } from '@oclif/core';
4
+ import chalk from 'chalk';
4
5
  import inquirer from 'inquirer';
5
6
  import { findBlueprintFile, writeBlueprintToDisk, writeConfigFile, } from '../../actions/blueprints/blueprint.js';
6
7
  import { getProject, listProjects } from '../../actions/blueprints/projects.js';
7
8
  import { createStack, getStack, listStacks } from '../../actions/blueprints/stacks.js';
8
- import { bold, dim, niceId, underline } from '../../utils/display/colors.js';
9
+ import { niceId } from '../../utils/display/colors.js';
9
10
  import { validTokenOrErrorMessage } from '../../utils/validated-token.js';
10
11
  const LAUNCH_LIMIT_STACK_PER_PROJECT = true;
11
12
  export default class InitCommand extends Command {
@@ -47,7 +48,6 @@ export default class InitCommand extends Command {
47
48
  'stack-name': Flags.string({
48
49
  description: 'Name to use for a NEW Stack',
49
50
  aliases: ['name'],
50
- dependsOn: ['project-id'],
51
51
  exclusive: ['stack-id'],
52
52
  hidden: true, // LAUNCH LIMIT: 1 Stack per Project
53
53
  }),
@@ -55,21 +55,18 @@ export default class InitCommand extends Command {
55
55
  sanityToken;
56
56
  async run() {
57
57
  const { args, flags } = await this.parse(InitCommand);
58
+ const { token, error: tokenErr } = await validTokenOrErrorMessage();
59
+ if (tokenErr)
60
+ this.error(tokenErr.message);
61
+ this.sanityToken = token;
58
62
  const { 'blueprint-type': flagBlueprintType, 'project-id': flagProjectId, 'stack-id': flagStackId, 'stack-name': flagStackName, dir: flagDir, } = flags;
59
63
  const { dir: argDir } = args;
60
64
  const dirProvided = argDir || flagDir;
61
65
  const here = cwd();
62
66
  const dir = argDir || flagDir || here;
63
67
  const existingBlueprint = findBlueprintFile(dir);
64
- if (existingBlueprint) {
65
- this.log(`A Blueprint file already exists: ${existingBlueprint.blueprintFilePath.replace(here, '')}`);
66
- this.log('Use `sanity-run blueprints config --edit` to edit the configuration.');
68
+ if (existingBlueprint)
67
69
  this.error('Existing Blueprint found.');
68
- }
69
- const { token, error: tokenErr } = await validTokenOrErrorMessage();
70
- if (tokenErr)
71
- this.error(tokenErr.message);
72
- this.sanityToken = token;
73
70
  const blueprintExtension = flagBlueprintType || (await this.promptForBlueprintType());
74
71
  if (!blueprintExtension)
75
72
  this.error('Blueprint type is required.');
@@ -80,23 +77,19 @@ export default class InitCommand extends Command {
80
77
  projectId = pickedProject.projectId;
81
78
  }
82
79
  const auth = { token: this.sanityToken, projectId };
83
- // LAUNCH LIMIT: 1 Stack per Project - do not prompt for Stack, just create one
84
- if (LAUNCH_LIMIT_STACK_PER_PROJECT) {
85
- const stack = await this.createProjectBasedStack(auth);
80
+ if (flagStackName) {
81
+ // using --stack-name gets around "LAUNCH LIMIT: 1 Stack per Project"
82
+ const stack = await this.createEmptyStack({
83
+ projectId,
84
+ name: flagStackName,
85
+ projectBased: false,
86
+ });
86
87
  stackId = stack.id;
87
88
  }
88
- // while LAUNCH_LIMIT_STACK_PER_PROJECT is true, the stackId is already set
89
- if (!stackId) {
90
- if (flagStackName) {
91
- const stack = await this.createEmptyStack({
92
- stackPayload: { name: flagStackName, projectId, document: { resources: [] } },
93
- auth,
94
- });
95
- stackId = stack.id;
96
- }
97
- else {
98
- stackId = await this.promptForStackId({ projectId });
99
- }
89
+ // LAUNCH LIMIT: 1 Stack per Project - do not prompt for Stack, just create one
90
+ if (!stackId && LAUNCH_LIMIT_STACK_PER_PROJECT) {
91
+ const stack = await this.createProjectBasedStack(auth);
92
+ // stackId = stack.id
100
93
  }
101
94
  const fileName = `blueprint.${blueprintExtension}`;
102
95
  const filePath = join(dir, fileName);
@@ -104,8 +97,7 @@ export default class InitCommand extends Command {
104
97
  this.log(`New Blueprint created: ${dirProvided}/`);
105
98
  writeBlueprintToDisk({ blueprintFilePath: filePath });
106
99
  this.log(`Created new blueprint: ${dirProvided ?? '.'}/${fileName}`);
107
- // LAUNCH LIMIT: 1 Stack per Project - do not persist stackId
108
- writeConfigFile({ blueprintFilePath: filePath, projectId /*, stackId*/ });
100
+ writeConfigFile({ blueprintFilePath: filePath, projectId, stackId });
109
101
  this.log(`Created new config file: ${dirProvided ?? '.'}/.blueprint/config.json`);
110
102
  if (blueprintExtension === 'ts') {
111
103
  this.log('\nNote: TypeScript support requires "tsx" to be installed. Run: npm install -D tsx');
@@ -156,11 +148,13 @@ export default class InitCommand extends Command {
156
148
  const { ok: stacksOk, error: stacksErr, stacks, } = await listStacks({ token: this.sanityToken, projectId });
157
149
  if (!stacksOk)
158
150
  this.error(stacksErr || 'Failed to list Stacks');
159
- const stackChoices = [{ name: bold('✨ Create a new Stack'), value: 'new' }];
151
+ const stackChoices = [
152
+ { name: chalk.bold('✨ Create a new Stack'), value: 'new' },
153
+ ];
160
154
  if (stacks.length > 0) {
161
- stackChoices.push(new inquirer.Separator(underline('Use an existing Stack:')));
155
+ stackChoices.push(new inquirer.Separator(chalk.underline('Use an existing Stack:')));
162
156
  stackChoices.push(...stacks.map((s) => ({
163
- name: `"${s.name}" ${niceId(s.id)} ${dim(`(${s.resources.length} res)`)}`,
157
+ name: `"${s.name}" ${niceId(s.id)} ${chalk.dim(`(${s.resources.length} res)`)}`,
164
158
  value: s.id,
165
159
  })));
166
160
  }
@@ -181,15 +175,21 @@ export default class InitCommand extends Command {
181
175
  validate: (input) => input.length > 0 || 'Stack name is required',
182
176
  },
183
177
  ]);
184
- const stack = await this.createEmptyStack({
185
- stackPayload: { name: stackName, projectId, document: { resources: [] } },
186
- auth: { token: this.sanityToken, projectId },
187
- });
178
+ const stack = await this.createEmptyStack({ projectId, name: stackName });
188
179
  return stack.id;
189
180
  }
190
181
  return pickedStackId;
191
182
  }
192
- async createEmptyStack({ stackPayload, auth, }) {
183
+ async createEmptyStack({ projectId, name, projectBased = true, }) {
184
+ if (!this.sanityToken)
185
+ this.error('Unable to create Stack. Missing API token.');
186
+ const stackPayload = {
187
+ name,
188
+ projectId,
189
+ useProjectBasedId: projectBased,
190
+ document: { resources: [] },
191
+ };
192
+ const auth = { token: this.sanityToken, projectId };
193
193
  const response = await createStack({ stackPayload, auth });
194
194
  if (!response.ok)
195
195
  this.error(response.error || 'Failed to create new Stack');
@@ -208,19 +208,12 @@ export default class InitCommand extends Command {
208
208
  const { stack: existingStack, ok: stackOk } = await getStack({ stackId: inferredStackId, auth });
209
209
  // if existing stack, return stack
210
210
  if (stackOk && existingStack) {
211
- this.warn(`Found existing deployment for "${projectDisplayName}" Blueprint`);
212
- this.warn('Deploying an empty Blueprint will override the existing deployment.');
211
+ this.log(chalk.red(`Found existing deployment for "${projectDisplayName}" Blueprint`));
212
+ this.log(chalk.red('Deploying an empty Blueprint will override the existing deployment.'));
213
213
  return existingStack;
214
214
  }
215
215
  // if not, create a stack
216
- const stack = await this.createEmptyStack({
217
- stackPayload: {
218
- projectId,
219
- name: projectDisplayName,
220
- document: { resources: [] },
221
- },
222
- auth,
223
- });
216
+ const stack = await this.createEmptyStack({ projectId, name: projectDisplayName });
224
217
  return stack;
225
218
  }
226
219
  }
@@ -877,7 +877,7 @@ declare class SelectionRange {
877
877
  the character before its position, 1 the character after, and 0
878
878
  means no association.
879
879
  */
880
- get assoc(): 1 | 0 | -1;
880
+ get assoc(): 0 | 1 | -1;
881
881
  /**
882
882
  The bidirectional text level associated with this cursor, if
883
883
  any.
@@ -1274,8 +1274,8 @@ declare class FacetProvider {
1274
1274
  id: number;
1275
1275
  dynamicSlot(addresses: any): {
1276
1276
  create(state: any): number;
1277
- update(state: any, tr: any): 1 | 0;
1278
- reconfigure: (state: any, oldState: any) => 1 | 0;
1277
+ update(state: any, tr: any): 0 | 1;
1278
+ reconfigure: (state: any, oldState: any) => 0 | 1;
1279
1279
  };
1280
1280
  }
1281
1281
  declare class PrecExtension {
@@ -1,4 +1,6 @@
1
1
  import chalk from 'chalk';
2
+ // TODO: remove simple exports and use chalk directly
3
+ // move compound styling like niceId to formatters
2
4
  export function bold(str) {
3
5
  return chalk.bold(str);
4
6
  }
@@ -55,6 +55,11 @@ export interface LocalFunctionResource extends LocalResource {
55
55
  memory?: number;
56
56
  timeout?: number;
57
57
  env?: Record<string, string>;
58
+ event?: {
59
+ on: Array<string>;
60
+ filter?: string;
61
+ projection?: string;
62
+ };
58
63
  }
59
64
  export interface Stack {
60
65
  id: string;
@@ -1,2 +1,4 @@
1
+ import type { LocalFunctionResource } from '../types.js';
2
+ import { type BlueprintParserError } from '../types.js';
1
3
  export declare function validateFunctionName(name: string): boolean;
2
- export declare function validateFunctionType(type: string): boolean;
4
+ export declare function validateFunctionResource(resource: LocalFunctionResource): BlueprintParserError[];
@@ -1,8 +1,97 @@
1
+ import { BlueprintParserErrorType } from '../types.js';
1
2
  export function validateFunctionName(name) {
2
3
  // must be 6+ characters, no special characters, no spaces, allow _ and -
3
4
  return /^[a-zA-Z0-9][a-zA-Z0-9_-]{5,}$/.test(name);
4
5
  }
5
- export function validateFunctionType(type) {
6
- const functionType = type.replace('sanity.function.', '');
7
- return ['document-publish', 'document-create', 'document-delete'].includes(functionType);
6
+ export function validateFunctionResource(resource) {
7
+ const { name: fnName } = resource;
8
+ const msgPrefix = `Function "${fnName}":`;
9
+ const errors = [];
10
+ if (!validateFunctionName(resource.name)) {
11
+ errors.push({
12
+ message: `${msgPrefix} Function name must be at least 6 characters, start with a letter or number, and only contain letters, numbers, _ or -`,
13
+ type: BlueprintParserErrorType.InvalidProperty,
14
+ });
15
+ }
16
+ if (!resource.type.startsWith('sanity.function.')) {
17
+ errors.push({
18
+ message: `${msgPrefix} Resource type must start with "sanity.function."`,
19
+ type: BlueprintParserErrorType.InvalidType,
20
+ });
21
+ }
22
+ if (!resource.event || !Array.isArray(resource.event.on) || resource.event.on.length === 0) {
23
+ errors.push({
24
+ message: `${msgPrefix} event.on must be a non-empty array`,
25
+ type: BlueprintParserErrorType.MissingRequiredProperty,
26
+ });
27
+ }
28
+ else if (resource.event.on[0] !== 'publish') {
29
+ errors.push({
30
+ message: `${msgPrefix} First event.on value must be "publish"`,
31
+ type: BlueprintParserErrorType.InvalidValue,
32
+ });
33
+ }
34
+ if (resource.event?.filter && typeof resource.event.filter !== 'string') {
35
+ errors.push({
36
+ message: `${msgPrefix} event.filter must be a string`,
37
+ type: BlueprintParserErrorType.InvalidType,
38
+ });
39
+ }
40
+ if (resource.event?.projection && typeof resource.event.projection !== 'string') {
41
+ errors.push({
42
+ message: `${msgPrefix} event.projection must be a string`,
43
+ type: BlueprintParserErrorType.InvalidType,
44
+ });
45
+ }
46
+ if (resource.memory !== undefined) {
47
+ if (!Number.isInteger(resource.memory)) {
48
+ errors.push({
49
+ message: `${msgPrefix} memory must be an integer`,
50
+ type: BlueprintParserErrorType.InvalidType,
51
+ });
52
+ }
53
+ else if (resource.memory < 1 || resource.memory > 10) {
54
+ errors.push({
55
+ message: `${msgPrefix} memory must be between 1 and 10 (GB)`,
56
+ type: BlueprintParserErrorType.InvalidValue,
57
+ });
58
+ }
59
+ }
60
+ if (resource.timeout !== undefined) {
61
+ if (!Number.isInteger(resource.timeout)) {
62
+ errors.push({
63
+ message: `${msgPrefix} timeout must be an integer`,
64
+ type: BlueprintParserErrorType.InvalidType,
65
+ });
66
+ }
67
+ else if (resource.timeout < 5 || resource.timeout > 900) {
68
+ errors.push({
69
+ message: `${msgPrefix} timeout must be between 5 and 900 (seconds)`,
70
+ type: BlueprintParserErrorType.InvalidValue,
71
+ });
72
+ }
73
+ }
74
+ if (resource.env !== undefined) {
75
+ if (typeof resource.env !== 'object') {
76
+ errors.push({
77
+ message: `${msgPrefix} env must be an object`,
78
+ type: BlueprintParserErrorType.InvalidType,
79
+ });
80
+ }
81
+ else {
82
+ if (!Object.keys(resource.env).every((key) => typeof key === 'string')) {
83
+ errors.push({
84
+ message: `${msgPrefix} All env keys must be strings`,
85
+ type: BlueprintParserErrorType.InvalidFormat,
86
+ });
87
+ }
88
+ if (!Object.values(resource.env).every((value) => typeof value === 'string')) {
89
+ errors.push({
90
+ message: `${msgPrefix} All env values must be strings`,
91
+ type: BlueprintParserErrorType.InvalidFormat,
92
+ });
93
+ }
94
+ }
95
+ }
96
+ return errors;
8
97
  }
@@ -12,11 +12,12 @@
12
12
  "required": true
13
13
  }
14
14
  },
15
- "description": "Add a resource to a Blueprint",
15
+ "description": "Add a (function) resource to a Blueprint",
16
16
  "examples": [
17
17
  "<%= config.bin %> <%= command.id %> function",
18
18
  "<%= config.bin %> <%= command.id %> function --name my-function",
19
- "<%= config.bin %> <%= command.id %> function --name my-function --function-type document-publish"
19
+ "<%= config.bin %> <%= command.id %> function --name my-function --fn-type document-publish",
20
+ "<%= config.bin %> <%= command.id %> function --name my-function --fn-type document-publish --lang js"
20
21
  ],
21
22
  "flags": {
22
23
  "name": {
@@ -27,18 +28,46 @@
27
28
  "multiple": false,
28
29
  "type": "option"
29
30
  },
30
- "function-type": {
31
+ "fn-type": {
32
+ "aliases": [
33
+ "function-type"
34
+ ],
31
35
  "dependsOn": [
32
36
  "name"
33
37
  ],
34
- "description": "Type of function to add (e.g. document-publish)",
35
- "name": "function-type",
38
+ "description": "Type of new function",
39
+ "name": "fn-type",
36
40
  "hasDynamicHelp": false,
37
41
  "multiple": false,
38
42
  "options": [
39
43
  "document-publish"
40
44
  ],
41
45
  "type": "option"
46
+ },
47
+ "language": {
48
+ "aliases": [
49
+ "function-language",
50
+ "lang"
51
+ ],
52
+ "description": "Language of the new function",
53
+ "name": "language",
54
+ "default": "ts",
55
+ "hasDynamicHelp": false,
56
+ "multiple": false,
57
+ "options": [
58
+ "ts",
59
+ "js"
60
+ ],
61
+ "type": "option"
62
+ },
63
+ "javascript": {
64
+ "aliases": [
65
+ "js"
66
+ ],
67
+ "description": "Use JavaScript instead of TypeScript",
68
+ "name": "javascript",
69
+ "allowNo": false,
70
+ "type": "boolean"
42
71
  }
43
72
  },
44
73
  "hasDynamicHelp": false,
@@ -166,7 +195,7 @@
166
195
  "blueprints:destroy": {
167
196
  "aliases": [],
168
197
  "args": {},
169
- "description": "Destroy a Blueprint deployment",
198
+ "description": "Destroy a Blueprint deployment (will not delete local files)",
170
199
  "examples": [
171
200
  "<%= config.bin %> <%= command.id %>"
172
201
  ],
@@ -320,9 +349,6 @@
320
349
  "aliases": [
321
350
  "name"
322
351
  ],
323
- "dependsOn": [
324
- "project-id"
325
- ],
326
352
  "description": "Name to use for a NEW Stack",
327
353
  "exclusive": [
328
354
  "stack-id"
@@ -791,5 +817,5 @@
791
817
  ]
792
818
  }
793
819
  },
794
- "version": "4.5.1"
820
+ "version": "5.0.1"
795
821
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sanity/runtime-cli",
3
3
  "description": "Sanity's Runtime CLI for Blueprints and Functions",
4
- "version": "4.5.1",
4
+ "version": "5.0.1",
5
5
  "author": "Sanity Runtime Team",
6
6
  "type": "module",
7
7
  "license": "MIT",