@sanity/runtime-cli 11.1.0 → 11.1.2

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/11.1.0 linux-x64 node-v24.11.0
23
+ @sanity/runtime-cli/11.1.2 linux-x64 node-v24.11.0
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/v11.1.0/src/commands/blueprints/add.ts)_
95
+ _See code: [src/commands/blueprints/add.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.2/src/commands/blueprints/add.ts)_
96
96
 
97
97
  ## `sanity-run blueprints config`
98
98
 
@@ -124,7 +124,7 @@ EXAMPLES
124
124
  $ sanity-run blueprints config --edit --project-id <projectId> --stack-id <stackId>
125
125
  ```
126
126
 
127
- _See code: [src/commands/blueprints/config.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.0/src/commands/blueprints/config.ts)_
127
+ _See code: [src/commands/blueprints/config.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.2/src/commands/blueprints/config.ts)_
128
128
 
129
129
  ## `sanity-run blueprints deploy`
130
130
 
@@ -146,7 +146,7 @@ EXAMPLES
146
146
  $ sanity-run blueprints deploy --no-wait
147
147
  ```
148
148
 
149
- _See code: [src/commands/blueprints/deploy.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.0/src/commands/blueprints/deploy.ts)_
149
+ _See code: [src/commands/blueprints/deploy.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.2/src/commands/blueprints/deploy.ts)_
150
150
 
151
151
  ## `sanity-run blueprints destroy`
152
152
 
@@ -173,7 +173,7 @@ EXAMPLES
173
173
  $ sanity-run blueprints destroy --stack-id <stackId> --project-id <projectId> --force --no-wait
174
174
  ```
175
175
 
176
- _See code: [src/commands/blueprints/destroy.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.0/src/commands/blueprints/destroy.ts)_
176
+ _See code: [src/commands/blueprints/destroy.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.2/src/commands/blueprints/destroy.ts)_
177
177
 
178
178
  ## `sanity-run blueprints doctor`
179
179
 
@@ -191,7 +191,7 @@ DESCRIPTION
191
191
  Diagnose potential issues with Blueprint configuration
192
192
  ```
193
193
 
194
- _See code: [src/commands/blueprints/doctor.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.0/src/commands/blueprints/doctor.ts)_
194
+ _See code: [src/commands/blueprints/doctor.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.2/src/commands/blueprints/doctor.ts)_
195
195
 
196
196
  ## `sanity-run blueprints info`
197
197
 
@@ -213,7 +213,7 @@ EXAMPLES
213
213
  $ sanity-run blueprints info --stack-id <stackId>
214
214
  ```
215
215
 
216
- _See code: [src/commands/blueprints/info.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.0/src/commands/blueprints/info.ts)_
216
+ _See code: [src/commands/blueprints/info.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.2/src/commands/blueprints/info.ts)_
217
217
 
218
218
  ## `sanity-run blueprints init [DIR]`
219
219
 
@@ -252,7 +252,7 @@ EXAMPLES
252
252
  $ sanity-run blueprints init --blueprint-type <json|js|ts> --stack-name <stackName>
253
253
  ```
254
254
 
255
- _See code: [src/commands/blueprints/init.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.0/src/commands/blueprints/init.ts)_
255
+ _See code: [src/commands/blueprints/init.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.2/src/commands/blueprints/init.ts)_
256
256
 
257
257
  ## `sanity-run blueprints logs`
258
258
 
@@ -274,7 +274,7 @@ EXAMPLES
274
274
  $ sanity-run blueprints logs --watch
275
275
  ```
276
276
 
277
- _See code: [src/commands/blueprints/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.0/src/commands/blueprints/logs.ts)_
277
+ _See code: [src/commands/blueprints/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.2/src/commands/blueprints/logs.ts)_
278
278
 
279
279
  ## `sanity-run blueprints plan`
280
280
 
@@ -291,7 +291,7 @@ EXAMPLES
291
291
  $ sanity-run blueprints plan
292
292
  ```
293
293
 
294
- _See code: [src/commands/blueprints/plan.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.0/src/commands/blueprints/plan.ts)_
294
+ _See code: [src/commands/blueprints/plan.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.2/src/commands/blueprints/plan.ts)_
295
295
 
296
296
  ## `sanity-run blueprints stacks`
297
297
 
@@ -316,7 +316,7 @@ EXAMPLES
316
316
  $ sanity-run blueprints stacks --organization-id <organizationId>
317
317
  ```
318
318
 
319
- _See code: [src/commands/blueprints/stacks.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.0/src/commands/blueprints/stacks.ts)_
319
+ _See code: [src/commands/blueprints/stacks.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.2/src/commands/blueprints/stacks.ts)_
320
320
 
321
321
  ## `sanity-run functions add`
322
322
 
@@ -358,7 +358,7 @@ EXAMPLES
358
358
  $ sanity-run functions add --name my-function --type document-create --type document-update --lang js
359
359
  ```
360
360
 
361
- _See code: [src/commands/functions/add.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.0/src/commands/functions/add.ts)_
361
+ _See code: [src/commands/functions/add.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.2/src/commands/functions/add.ts)_
362
362
 
363
363
  ## `sanity-run functions dev`
364
364
 
@@ -380,7 +380,7 @@ EXAMPLES
380
380
  $ sanity-run functions dev --port 8974
381
381
  ```
382
382
 
383
- _See code: [src/commands/functions/dev.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.0/src/commands/functions/dev.ts)_
383
+ _See code: [src/commands/functions/dev.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.2/src/commands/functions/dev.ts)_
384
384
 
385
385
  ## `sanity-run functions env add NAME KEY VALUE`
386
386
 
@@ -402,7 +402,7 @@ EXAMPLES
402
402
  $ sanity-run functions env add MyFunction API_URL https://api.example.com/
403
403
  ```
404
404
 
405
- _See code: [src/commands/functions/env/add.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.0/src/commands/functions/env/add.ts)_
405
+ _See code: [src/commands/functions/env/add.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.2/src/commands/functions/env/add.ts)_
406
406
 
407
407
  ## `sanity-run functions env list NAME`
408
408
 
@@ -422,7 +422,7 @@ EXAMPLES
422
422
  $ sanity-run functions env list MyFunction
423
423
  ```
424
424
 
425
- _See code: [src/commands/functions/env/list.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.0/src/commands/functions/env/list.ts)_
425
+ _See code: [src/commands/functions/env/list.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.2/src/commands/functions/env/list.ts)_
426
426
 
427
427
  ## `sanity-run functions env remove NAME KEY`
428
428
 
@@ -443,7 +443,7 @@ EXAMPLES
443
443
  $ sanity-run functions env remove MyFunction API_URL
444
444
  ```
445
445
 
446
- _See code: [src/commands/functions/env/remove.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.0/src/commands/functions/env/remove.ts)_
446
+ _See code: [src/commands/functions/env/remove.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.2/src/commands/functions/env/remove.ts)_
447
447
 
448
448
  ## `sanity-run functions logs NAME`
449
449
 
@@ -477,7 +477,7 @@ EXAMPLES
477
477
  $ sanity-run functions logs <name> --delete
478
478
  ```
479
479
 
480
- _See code: [src/commands/functions/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.0/src/commands/functions/logs.ts)_
480
+ _See code: [src/commands/functions/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.2/src/commands/functions/logs.ts)_
481
481
 
482
482
  ## `sanity-run functions test NAME`
483
483
 
@@ -526,7 +526,7 @@ EXAMPLES
526
526
  $ sanity-run functions test <name> --event update --data-before '{ "title": "before" }' --data-after '{ "title": "after" }'
527
527
  ```
528
528
 
529
- _See code: [src/commands/functions/test.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.0/src/commands/functions/test.ts)_
529
+ _See code: [src/commands/functions/test.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.2/src/commands/functions/test.ts)_
530
530
 
531
531
  ## `sanity-run help [COMMAND]`
532
532
 
@@ -57,7 +57,7 @@ export async function createFunctionResource(options) {
57
57
  }
58
58
  }
59
59
  // type looks like 'document-publish' or 'media-library-asset-delete'
60
- const typeName = type[0].substring(type[0].lastIndexOf('-') + 1);
60
+ const typeName = type[0].substring(0, type[0].lastIndexOf('-'));
61
61
  const eventsOn = type.map((t) => t.substring(t.lastIndexOf('-') + 1));
62
62
  // Create resource definition
63
63
  const resourceJson = {
@@ -1,3 +1,4 @@
1
+ import type { ScopeType } from '../../utils/types.js';
1
2
  import type { CoreConfig, CoreResult } from '../index.js';
2
3
  export interface BlueprintInitOptions extends CoreConfig {
3
4
  token: string;
@@ -15,3 +16,37 @@ export interface BlueprintInitOptions extends CoreConfig {
15
16
  };
16
17
  }
17
18
  export declare function blueprintInitCore(options: BlueprintInitOptions): Promise<CoreResult>;
19
+ export declare function validateFlags(flags: {
20
+ stackId?: string;
21
+ stackName?: string;
22
+ organizationId?: string;
23
+ projectId?: string;
24
+ }): CoreResult | null;
25
+ interface ResolvedScope {
26
+ scopeType: ScopeType;
27
+ scopeId: string;
28
+ stackId: string | undefined;
29
+ }
30
+ export declare function resolveScopeAndStack(params: {
31
+ projectId: string | undefined;
32
+ organizationId: string | undefined;
33
+ stackId: string | undefined;
34
+ stackName: string | undefined;
35
+ token: string;
36
+ log: (message: string) => void;
37
+ }): Promise<ResolvedScope>;
38
+ export declare function determineBlueprintExtension(params: {
39
+ requestedType: string | undefined;
40
+ blueprintDir: string;
41
+ }): Promise<string>;
42
+ export declare function createBlueprintFiles(params: {
43
+ blueprintDir: string;
44
+ userProvidedDirName: string | undefined;
45
+ blueprintExtension: string;
46
+ scopeType: ScopeType;
47
+ scopeId: string;
48
+ stackId: string | undefined;
49
+ bin: string;
50
+ log: (message: string) => void;
51
+ }): Promise<CoreResult>;
52
+ export {};
@@ -11,149 +11,60 @@ import { verifyExampleExists, writeExample } from '../../actions/sanity/examples
11
11
  import { getProject } from '../../actions/sanity/projects.js';
12
12
  import { BLUEPRINT_CONFIG_FILE, BLUEPRINT_DIR } from '../../config.js';
13
13
  import { check, warn } from '../../utils/display/presenters.js';
14
- import { promptForProject, promptForStackId } from '../../utils/display/prompt.js';
15
- const LAUNCH_LIMIT_STACK_PER_PROJECT = true;
14
+ import { promptForProject } from '../../utils/display/prompt.js';
15
+ const SCOPE_PROJECT = 'project';
16
+ const SCOPE_ORGANIZATION = 'organization';
16
17
  export async function blueprintInitCore(options) {
17
18
  const { bin = 'sanity', log, token, args, flags } = options;
18
19
  try {
19
- const { dir: flagDir, example: flagExample, 'blueprint-type': flagBlueprintType, 'project-id': flagProjectId,
20
- // 'organization-id': flagOrganizationId,
21
- 'stack-id': flagStackId, 'stack-name': flagStackName, } = flags;
20
+ const { dir: flagDir, example: flagExample, 'blueprint-type': flagBlueprintType, 'project-id': flagProjectId, 'organization-id': flagOrganizationId, 'stack-id': flagStackId, 'stack-name': flagStackName, } = flags;
22
21
  const { dir: argDir } = args;
23
- const providedDir = argDir || flagDir;
24
- const blueprintDir = providedDir || '.';
22
+ const userProvidedDirName = argDir || flagDir;
23
+ const blueprintDir = userProvidedDirName || '.';
25
24
  const existingBlueprint = findBlueprintFile(blueprintDir);
26
25
  if (existingBlueprint) {
27
26
  return { success: false, error: 'Existing Blueprint found.' };
28
27
  }
28
+ const validationError = validateFlags({
29
+ stackId: flagStackId,
30
+ stackName: flagStackName,
31
+ organizationId: flagOrganizationId,
32
+ projectId: flagProjectId,
33
+ });
34
+ if (validationError)
35
+ return validationError;
29
36
  if (flagExample) {
30
- // ! short circuit for examples
31
- log(warn(`Example feature is experimental. Setting up "${flagExample}"...`));
32
- // we need to...
33
- // * 1. verify example exists in the recipes repo
34
- const exampleExists = await verifyExampleExists({ type: 'blueprint', name: flagExample });
35
- if (!exampleExists) {
36
- return { success: false, error: `Blueprint example "${flagExample}" does not exist.` };
37
- }
38
- // * 2. get a projectId from the user
39
- const projectId = flagProjectId || (await promptForProject({ token })).projectId;
40
- // * 3. create empty stack with name from example name
41
- const stack = await createEmptyStack({
42
- token,
43
- scopeType: 'project',
44
- scopeId: projectId,
45
- name: `example-${flagExample}`,
46
- projectBased: false,
47
- });
48
- // * 4. download and write example to disk
49
- // take into account optional providedDir
50
- const exampleDir = join(blueprintDir, providedDir ? '' : flagExample);
51
- if (existsSync(exampleDir)) {
52
- return { success: false, error: `Example directory "${exampleDir}" already exists.` };
53
- }
54
- const addedExample = await writeExample({
55
- exampleType: 'blueprint',
37
+ return handleExampleInitialization({
56
38
  exampleName: flagExample,
57
- dir: exampleDir,
58
- });
59
- if (!addedExample) {
60
- return { success: false, error: `Unable to download example "${flagExample}"` };
61
- }
62
- const { files, dir: newDir, instructions } = addedExample;
63
- for (const filePath of Object.keys(files)) {
64
- log(check(`${chalk.bold('Created:')} ${newDir}/${filePath}`));
65
- }
66
- const discoveredBlueprint = findBlueprintFile(exampleDir);
67
- if (!discoveredBlueprint) {
68
- return { success: false, error: 'Failed to find blueprint file.' };
69
- }
70
- const { blueprintFilePath } = discoveredBlueprint;
71
- // * 5. write config file
72
- writeConfigFile({ blueprintFilePath, projectId, stackId: stack.id });
73
- log(check(`${chalk.bold('Configured:')} ${exampleDir}/${BLUEPRINT_DIR}/${BLUEPRINT_CONFIG_FILE}`));
74
- // * 6. print next step
75
- log(`\n Run "${chalk.bold.magenta(`cd ${exampleDir} && npm i`)}" and check out the README`);
76
- if (instructions) {
77
- log('');
78
- log(instructions);
79
- }
80
- return { success: true };
81
- }
82
- let blueprintExtension = flagBlueprintType || (await promptForBlueprintType());
83
- if (!blueprintExtension) {
84
- return { success: false, error: 'Blueprint type is required.' };
85
- }
86
- if (blueprintExtension === 'js') {
87
- const packageJsonPath = join(blueprintDir, 'package.json');
88
- const packageExists = existsSync(packageJsonPath);
89
- if (packageExists) {
90
- // if package.json#type is not module, set blueprintExtension to mjs
91
- try {
92
- const packageJson = readFileSync(packageJsonPath, 'utf8');
93
- const packageJsonObject = JSON.parse(packageJson);
94
- if (packageJsonObject.type !== 'module') {
95
- blueprintExtension = 'mjs';
96
- }
97
- }
98
- catch { } // not our concern
99
- }
100
- }
101
- let projectId = flagProjectId;
102
- let stackId = flagStackId;
103
- if (!projectId) {
104
- const pickedProject = await promptForProject({ token });
105
- projectId = pickedProject.projectId;
106
- }
107
- log('');
108
- if (flagStackName) {
109
- // using --stack-name gets around "LAUNCH LIMIT: 1 Stack per Project"
110
- const stack = await createEmptyStack({
39
+ projectId: flagProjectId,
40
+ blueprintDir,
41
+ userProvidedDirName,
111
42
  token,
112
- scopeType: 'project',
113
- scopeId: projectId,
114
- name: flagStackName,
115
- projectBased: false,
43
+ log,
116
44
  });
117
- stackId = stack.id;
118
- }
119
- if (!stackId) {
120
- // LAUNCH LIMIT: 1 Stack per Project - do not prompt for Stack, just create one
121
- if (LAUNCH_LIMIT_STACK_PER_PROJECT) {
122
- await createProjectBasedStack({ token, scopeType: 'project', scopeId: projectId }, log);
123
- // do not set stackId, to avoid saving it to the config file
124
- }
125
- else {
126
- stackId = await promptForStackId({ projectId, token });
127
- }
128
- }
129
- const blueprintFileName = `sanity.blueprint.${blueprintExtension}`;
130
- const blueprintFilePath = join(blueprintDir, blueprintFileName);
131
- writeBlueprintToDisk({ blueprintFilePath });
132
- if (providedDir)
133
- log(check(`${chalk.bold('New folder created:')} ${providedDir}/`));
134
- log(check(`${chalk.bold('Created Blueprint:')} ${providedDir ?? '.'}/${blueprintFileName}`));
135
- writeConfigFile({ blueprintFilePath, projectId, stackId });
136
- log(check(`${chalk.bold('Added configuration:')} ${providedDir ?? '.'}/${BLUEPRINT_DIR}/${BLUEPRINT_CONFIG_FILE}`));
137
- writeGitignoreFile(blueprintFilePath);
138
- log(check(`${chalk.bold('Added .gitignore:')} ${providedDir ?? '.'}/.gitignore`));
139
- if (blueprintExtension !== 'json') {
140
- try {
141
- // check for || create package.json and add @sanity/blueprints to dependencies
142
- await writeOrUpdateNodeDependency(blueprintFilePath, '@sanity/blueprints');
143
- log(check(`${chalk.bold('Added dependency:')} @sanity/blueprints`));
144
- }
145
- catch {
146
- log(warn('Unable to add @sanity/blueprints to your project.'));
147
- }
148
45
  }
149
- const nextStepParts = [];
150
- if (providedDir)
151
- nextStepParts.push(`cd ${providedDir}`);
152
- if (blueprintExtension !== 'json')
153
- nextStepParts.push('npm install');
154
- nextStepParts.push(`${bin} blueprints --help`);
155
- log(`\n Run "${chalk.bold.magenta(nextStepParts.join(' && '))}" to get started`);
156
- return { success: true };
46
+ const { scopeType, scopeId, stackId } = await resolveScopeAndStack({
47
+ projectId: flagProjectId,
48
+ organizationId: flagOrganizationId,
49
+ stackId: flagStackId,
50
+ stackName: flagStackName,
51
+ token,
52
+ log,
53
+ });
54
+ const blueprintExtension = await determineBlueprintExtension({
55
+ requestedType: flagBlueprintType,
56
+ blueprintDir,
57
+ });
58
+ return createBlueprintFiles({
59
+ blueprintDir,
60
+ userProvidedDirName,
61
+ blueprintExtension,
62
+ scopeType,
63
+ scopeId,
64
+ stackId,
65
+ bin,
66
+ log,
67
+ });
157
68
  }
158
69
  catch (error) {
159
70
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -161,6 +72,158 @@ export async function blueprintInitCore(options) {
161
72
  return { success: false, error: errorMessage };
162
73
  }
163
74
  }
75
+ export function validateFlags(flags) {
76
+ const { stackId, stackName, organizationId, projectId } = flags;
77
+ if (stackId && stackName) {
78
+ return { success: false, error: 'Cannot specify both --stack-id and --stack-name' };
79
+ }
80
+ if (organizationId && projectId) {
81
+ return { success: false, error: 'Cannot specify both --organization-id and --project-id' };
82
+ }
83
+ return null;
84
+ }
85
+ async function handleExampleInitialization(options) {
86
+ const { exampleName, blueprintDir, userProvidedDirName, projectId, token, log } = options;
87
+ log(warn(`Example feature is experimental. Setting up "${exampleName}"...`));
88
+ const exampleExists = await verifyExampleExists({ type: 'blueprint', name: exampleName });
89
+ if (!exampleExists) {
90
+ return { success: false, error: `Blueprint example "${exampleName}" does not exist.` };
91
+ }
92
+ const resolvedProjectId = projectId || (await promptForProject({ token })).projectId;
93
+ const stack = await createEmptyStack({
94
+ token,
95
+ scopeType: SCOPE_PROJECT,
96
+ scopeId: resolvedProjectId,
97
+ name: `example-${exampleName}`,
98
+ projectBased: false,
99
+ });
100
+ const exampleDir = userProvidedDirName || join(blueprintDir, exampleName);
101
+ if (existsSync(exampleDir)) {
102
+ return { success: false, error: `Example directory "${exampleDir}" already exists.` };
103
+ }
104
+ const addedExample = await writeExample({
105
+ exampleType: 'blueprint',
106
+ exampleName,
107
+ dir: exampleDir,
108
+ });
109
+ if (!addedExample) {
110
+ return { success: false, error: `Unable to download example "${exampleName}"` };
111
+ }
112
+ const { files, dir: newDir, instructions } = addedExample;
113
+ for (const filePath of Object.keys(files)) {
114
+ log(check(`${chalk.bold('Created:')} ${newDir}/${filePath}`));
115
+ }
116
+ const discoveredBlueprint = findBlueprintFile(exampleDir);
117
+ if (!discoveredBlueprint) {
118
+ return { success: false, error: 'Failed to find blueprint file.' };
119
+ }
120
+ const { blueprintFilePath } = discoveredBlueprint;
121
+ writeConfigFile({ blueprintFilePath, projectId: resolvedProjectId, stackId: stack.id });
122
+ log(check(`${chalk.bold('Configured:')} ${exampleDir}/${BLUEPRINT_DIR}/${BLUEPRINT_CONFIG_FILE}`));
123
+ log(`\n Run "${chalk.bold.magenta(`cd ${exampleDir} && npm i`)}" and check out the README`);
124
+ if (instructions) {
125
+ log('');
126
+ log(instructions);
127
+ }
128
+ return { success: true };
129
+ }
130
+ export async function resolveScopeAndStack(params) {
131
+ const { projectId, organizationId, stackId, stackName, token, log } = params;
132
+ let scopeType = SCOPE_PROJECT;
133
+ let scopeId;
134
+ if (projectId) {
135
+ scopeType = SCOPE_PROJECT;
136
+ scopeId = projectId;
137
+ }
138
+ else if (organizationId) {
139
+ scopeType = SCOPE_ORGANIZATION;
140
+ scopeId = organizationId;
141
+ }
142
+ let resolvedStackId = stackId;
143
+ if (!resolvedStackId && stackName && scopeType && scopeId) {
144
+ // essentially the only way to create an org-scoped stack
145
+ const stack = await createEmptyStack({
146
+ token,
147
+ scopeType,
148
+ scopeId,
149
+ name: stackName,
150
+ projectBased: false,
151
+ });
152
+ resolvedStackId = stack.id;
153
+ }
154
+ if (!scopeId) {
155
+ const pickedProject = await promptForProject({ token });
156
+ scopeType = SCOPE_PROJECT;
157
+ scopeId = pickedProject.projectId;
158
+ }
159
+ if (!resolvedStackId) {
160
+ await getOrCreateProjectBasedStack({ token, projectId: scopeId, log });
161
+ }
162
+ return {
163
+ scopeType,
164
+ scopeId,
165
+ stackId: resolvedStackId,
166
+ };
167
+ }
168
+ export async function determineBlueprintExtension(params) {
169
+ const { requestedType, blueprintDir } = params;
170
+ const extension = requestedType || (await promptForBlueprintType());
171
+ if (extension === 'js') {
172
+ const packageJsonPath = join(blueprintDir, 'package.json');
173
+ const packageExists = existsSync(packageJsonPath);
174
+ if (packageExists) {
175
+ try {
176
+ const packageJson = readFileSync(packageJsonPath, 'utf8');
177
+ const packageJsonObject = JSON.parse(packageJson);
178
+ if (packageJsonObject.type !== 'module') {
179
+ return 'mjs';
180
+ }
181
+ }
182
+ catch { }
183
+ }
184
+ }
185
+ return extension;
186
+ }
187
+ export async function createBlueprintFiles(params) {
188
+ const { blueprintDir, userProvidedDirName, blueprintExtension, scopeType, scopeId, stackId, bin, log, } = params;
189
+ if (!blueprintExtension) {
190
+ return { success: false, error: 'Blueprint type is required.' };
191
+ }
192
+ const blueprintFileName = `sanity.blueprint.${blueprintExtension}`;
193
+ const blueprintFilePath = join(blueprintDir, blueprintFileName);
194
+ writeBlueprintToDisk({ blueprintFilePath });
195
+ if (userProvidedDirName) {
196
+ log(check(`${chalk.bold('New folder created:')} ${userProvidedDirName}/`));
197
+ }
198
+ const displayPath = userProvidedDirName || '.';
199
+ log(check(`${chalk.bold('Created Blueprint:')} ${displayPath}/${blueprintFileName}`));
200
+ writeConfigFile({
201
+ blueprintFilePath,
202
+ stackId,
203
+ ...(scopeType === SCOPE_ORGANIZATION ? { organizationId: scopeId } : { projectId: scopeId }),
204
+ });
205
+ log(check(`${chalk.bold('Added configuration:')} ${displayPath}/${BLUEPRINT_DIR}/${BLUEPRINT_CONFIG_FILE}`));
206
+ writeGitignoreFile(blueprintFilePath);
207
+ log(check(`${chalk.bold('Added .gitignore:')} ${displayPath}/.gitignore`));
208
+ if (blueprintExtension !== 'json') {
209
+ const blueprintsPackage = '@sanity/blueprints';
210
+ try {
211
+ await writeOrUpdateNodeDependency(blueprintFilePath, blueprintsPackage);
212
+ log(check(`${chalk.bold('Added dependency:')} ${blueprintsPackage}`));
213
+ }
214
+ catch {
215
+ log(warn(`Unable to add ${blueprintsPackage} to your project.`));
216
+ }
217
+ }
218
+ const nextStepParts = [];
219
+ if (userProvidedDirName)
220
+ nextStepParts.push(`cd ${userProvidedDirName}`);
221
+ if (blueprintExtension !== 'json')
222
+ nextStepParts.push('npm install');
223
+ nextStepParts.push(`${bin} blueprints --help`);
224
+ log(`\n Run "${chalk.bold.magenta(nextStepParts.join(' && '))}" to get started`);
225
+ return { success: true };
226
+ }
164
227
  async function promptForBlueprintType() {
165
228
  const { pickedBlueprintsType } = await inquirer.prompt([
166
229
  {
@@ -178,27 +241,24 @@ async function promptForBlueprintType() {
178
241
  return pickedBlueprintsType;
179
242
  }
180
243
  // LAUNCH LIMIT: 1 Stack per Project - create exclusive stack for project
181
- async function createProjectBasedStack(auth, log) {
182
- if (auth.scopeType !== 'project') {
183
- throw new Error('Auth must be for a project');
184
- }
185
- const { scopeId: projectId, token } = auth;
186
- // get project
244
+ async function getOrCreateProjectBasedStack(params) {
245
+ const { projectId, token, log } = params;
187
246
  const { ok: projectOk, project } = await getProject({
188
- token: auth.token,
189
- scopeType: 'project',
247
+ token,
248
+ scopeType: SCOPE_PROJECT,
190
249
  scopeId: projectId,
191
250
  });
192
251
  if (!projectOk) {
193
252
  throw new Error('Failed to find Project while creating Stack');
194
253
  }
195
- const projectDisplayName = project.displayName;
196
254
  // check if project has a stack
197
- const inferredStackId = `ST-${projectId}`;
198
- const { stack: existingStack, ok: stackOk } = await getStack({ stackId: inferredStackId, auth });
255
+ const { stack: existingStack, ok: stackOk } = await getStack({
256
+ auth: { token, scopeType: SCOPE_PROJECT, scopeId: projectId },
257
+ stackId: `ST-${projectId}`,
258
+ });
199
259
  // if existing stack, return stack
200
260
  if (stackOk && existingStack) {
201
- log(warn(`"${projectDisplayName}" has an existing deployment.`));
261
+ log(warn(`"${project.displayName}" has an existing deployment.`));
202
262
  log(warn(`Deploying an empty Blueprint ${chalk.bold.red('will override the existing deployment!')}`));
203
263
  log('');
204
264
  return existingStack;
@@ -206,9 +266,9 @@ async function createProjectBasedStack(auth, log) {
206
266
  // if not, create a stack
207
267
  const stack = await createEmptyStack({
208
268
  token,
209
- scopeType: 'project',
269
+ scopeType: SCOPE_PROJECT,
210
270
  scopeId: projectId,
211
- name: projectDisplayName,
271
+ name: project.displayName,
212
272
  });
213
273
  return stack;
214
274
  }
@@ -1408,5 +1408,5 @@
1408
1408
  ]
1409
1409
  }
1410
1410
  },
1411
- "version": "11.1.0"
1411
+ "version": "11.1.2"
1412
1412
  }
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": "11.1.0",
4
+ "version": "11.1.2",
5
5
  "author": "Sanity Runtime Team",
6
6
  "type": "module",
7
7
  "license": "MIT",