@sanity/runtime-cli 10.11.0 → 10.11.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/10.11.0 linux-x64 node-v22.20.0
23
+ @sanity/runtime-cli/10.11.2 linux-x64 node-v22.20.0
24
24
  $ sanity-run --help [COMMAND]
25
25
  USAGE
26
26
  $ sanity-run COMMAND
@@ -89,7 +89,7 @@ EXAMPLES
89
89
  $ sanity-run blueprints add function --name my-function --fn-type document-create --fn-type document-update --lang js
90
90
  ```
91
91
 
92
- _See code: [src/commands/blueprints/add.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.0/src/commands/blueprints/add.ts)_
92
+ _See code: [src/commands/blueprints/add.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.2/src/commands/blueprints/add.ts)_
93
93
 
94
94
  ## `sanity-run blueprints config`
95
95
 
@@ -120,7 +120,7 @@ EXAMPLES
120
120
  $ sanity-run blueprints config --edit --project-id <projectId> --stack-id <stackId>
121
121
  ```
122
122
 
123
- _See code: [src/commands/blueprints/config.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.0/src/commands/blueprints/config.ts)_
123
+ _See code: [src/commands/blueprints/config.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.2/src/commands/blueprints/config.ts)_
124
124
 
125
125
  ## `sanity-run blueprints deploy`
126
126
 
@@ -142,7 +142,7 @@ EXAMPLES
142
142
  $ sanity-run blueprints deploy --no-wait
143
143
  ```
144
144
 
145
- _See code: [src/commands/blueprints/deploy.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.0/src/commands/blueprints/deploy.ts)_
145
+ _See code: [src/commands/blueprints/deploy.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.2/src/commands/blueprints/deploy.ts)_
146
146
 
147
147
  ## `sanity-run blueprints destroy`
148
148
 
@@ -167,7 +167,7 @@ EXAMPLES
167
167
  $ sanity-run blueprints destroy --stack-id <stackId> --project-id <projectId> --force --no-wait
168
168
  ```
169
169
 
170
- _See code: [src/commands/blueprints/destroy.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.0/src/commands/blueprints/destroy.ts)_
170
+ _See code: [src/commands/blueprints/destroy.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.2/src/commands/blueprints/destroy.ts)_
171
171
 
172
172
  ## `sanity-run blueprints doctor`
173
173
 
@@ -185,7 +185,7 @@ DESCRIPTION
185
185
  Diagnose potential issues with Blueprint configuration
186
186
  ```
187
187
 
188
- _See code: [src/commands/blueprints/doctor.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.0/src/commands/blueprints/doctor.ts)_
188
+ _See code: [src/commands/blueprints/doctor.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.2/src/commands/blueprints/doctor.ts)_
189
189
 
190
190
  ## `sanity-run blueprints info`
191
191
 
@@ -207,7 +207,7 @@ EXAMPLES
207
207
  $ sanity-run blueprints info --stack-id <stackId>
208
208
  ```
209
209
 
210
- _See code: [src/commands/blueprints/info.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.0/src/commands/blueprints/info.ts)_
210
+ _See code: [src/commands/blueprints/info.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.2/src/commands/blueprints/info.ts)_
211
211
 
212
212
  ## `sanity-run blueprints init [DIR]`
213
213
 
@@ -245,7 +245,7 @@ EXAMPLES
245
245
  $ sanity-run blueprints init --blueprint-type <json|js|ts> --stack-name <stackName>
246
246
  ```
247
247
 
248
- _See code: [src/commands/blueprints/init.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.0/src/commands/blueprints/init.ts)_
248
+ _See code: [src/commands/blueprints/init.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.2/src/commands/blueprints/init.ts)_
249
249
 
250
250
  ## `sanity-run blueprints logs`
251
251
 
@@ -267,7 +267,7 @@ EXAMPLES
267
267
  $ sanity-run blueprints logs --watch
268
268
  ```
269
269
 
270
- _See code: [src/commands/blueprints/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.0/src/commands/blueprints/logs.ts)_
270
+ _See code: [src/commands/blueprints/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.2/src/commands/blueprints/logs.ts)_
271
271
 
272
272
  ## `sanity-run blueprints plan`
273
273
 
@@ -284,7 +284,7 @@ EXAMPLES
284
284
  $ sanity-run blueprints plan
285
285
  ```
286
286
 
287
- _See code: [src/commands/blueprints/plan.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.0/src/commands/blueprints/plan.ts)_
287
+ _See code: [src/commands/blueprints/plan.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.2/src/commands/blueprints/plan.ts)_
288
288
 
289
289
  ## `sanity-run blueprints stacks`
290
290
 
@@ -306,7 +306,7 @@ EXAMPLES
306
306
  $ sanity-run blueprints stacks --project-id <projectId>
307
307
  ```
308
308
 
309
- _See code: [src/commands/blueprints/stacks.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.0/src/commands/blueprints/stacks.ts)_
309
+ _See code: [src/commands/blueprints/stacks.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.2/src/commands/blueprints/stacks.ts)_
310
310
 
311
311
  ## `sanity-run functions dev`
312
312
 
@@ -328,7 +328,7 @@ EXAMPLES
328
328
  $ sanity-run functions dev --port 8974
329
329
  ```
330
330
 
331
- _See code: [src/commands/functions/dev.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.0/src/commands/functions/dev.ts)_
331
+ _See code: [src/commands/functions/dev.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.2/src/commands/functions/dev.ts)_
332
332
 
333
333
  ## `sanity-run functions env add NAME KEY VALUE`
334
334
 
@@ -350,7 +350,7 @@ EXAMPLES
350
350
  $ sanity-run functions env add MyFunction API_URL https://api.example.com/
351
351
  ```
352
352
 
353
- _See code: [src/commands/functions/env/add.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.0/src/commands/functions/env/add.ts)_
353
+ _See code: [src/commands/functions/env/add.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.2/src/commands/functions/env/add.ts)_
354
354
 
355
355
  ## `sanity-run functions env list NAME`
356
356
 
@@ -370,7 +370,7 @@ EXAMPLES
370
370
  $ sanity-run functions env list MyFunction
371
371
  ```
372
372
 
373
- _See code: [src/commands/functions/env/list.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.0/src/commands/functions/env/list.ts)_
373
+ _See code: [src/commands/functions/env/list.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.2/src/commands/functions/env/list.ts)_
374
374
 
375
375
  ## `sanity-run functions env remove NAME KEY`
376
376
 
@@ -391,7 +391,7 @@ EXAMPLES
391
391
  $ sanity-run functions env remove MyFunction API_URL
392
392
  ```
393
393
 
394
- _See code: [src/commands/functions/env/remove.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.0/src/commands/functions/env/remove.ts)_
394
+ _See code: [src/commands/functions/env/remove.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.2/src/commands/functions/env/remove.ts)_
395
395
 
396
396
  ## `sanity-run functions logs NAME`
397
397
 
@@ -425,7 +425,7 @@ EXAMPLES
425
425
  $ sanity-run functions logs <name> --delete
426
426
  ```
427
427
 
428
- _See code: [src/commands/functions/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.0/src/commands/functions/logs.ts)_
428
+ _See code: [src/commands/functions/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.2/src/commands/functions/logs.ts)_
429
429
 
430
430
  ## `sanity-run functions test NAME`
431
431
 
@@ -472,7 +472,7 @@ EXAMPLES
472
472
  $ sanity-run functions test <name> --event update --data-before '{ "title": "before" }' --data-after '{ "title": "after" }'
473
473
  ```
474
474
 
475
- _See code: [src/commands/functions/test.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.0/src/commands/functions/test.ts)_
475
+ _See code: [src/commands/functions/test.ts](https://github.com/sanity-io/runtime-cli/blob/v10.11.2/src/commands/functions/test.ts)_
476
476
 
477
477
  ## `sanity-run help [COMMAND]`
478
478
 
@@ -6,7 +6,7 @@ import { findUpSync } from 'find-up';
6
6
  import { createJiti } from 'jiti';
7
7
  import { isLocalFunctionResource } from '../../utils/types.js';
8
8
  import { validateFunctionResource } from '../../utils/validate/resource.js';
9
- import { readConfigFile } from './config.js';
9
+ import { backfillOrganizationId, readConfigFile } from './config.js';
10
10
  const SUPPORTED_FILE_EXTENSIONS = ['.json', '.js', '.mjs', '.ts'];
11
11
  let SUPPORTED_FILE_NAMES = SUPPORTED_FILE_EXTENSIONS.map((ext) => `blueprint${ext}`);
12
12
  SUPPORTED_FILE_NAMES = [
@@ -132,6 +132,16 @@ export async function readLocalBlueprint(blueprintPath) {
132
132
  const { SANITY_ORGANIZATION_ID: envOrganizationId, SANITY_PROJECT_ID: envProjectId, SANITY_BLUEPRINT_STACK_ID: envStackId, } = env;
133
133
  const configIds = readConfigFile(foundFilePath);
134
134
  const configPath = configIds?.configPath;
135
+ // passively heal config on disk by getting organizationId from projectId
136
+ if (configIds && !configIds.organizationId && configIds.projectId) {
137
+ try {
138
+ await backfillOrganizationId({
139
+ projectId: configIds.projectId,
140
+ blueprintFilePath: foundFilePath,
141
+ });
142
+ }
143
+ catch { }
144
+ }
135
145
  let organizationId;
136
146
  if (envOrganizationId)
137
147
  organizationId = envOrganizationId;
@@ -10,8 +10,17 @@ export declare function writeConfigFile({ blueprintFilePath, organizationId, pro
10
10
  stackId?: string;
11
11
  } & ({
12
12
  organizationId: string;
13
- projectId?: never;
13
+ projectId?: string;
14
14
  } | {
15
15
  projectId: string;
16
- organizationId?: never;
16
+ organizationId?: string;
17
17
  })): void;
18
+ /**
19
+ * Find and write an organizationId to the config file by getting it from the projectId
20
+ * @throws {Error} if unable to fetch project
21
+ * @returns {Promise<string>} the discovered organizationId
22
+ */
23
+ export declare function backfillOrganizationId({ blueprintFilePath, projectId, }: {
24
+ blueprintFilePath: string;
25
+ projectId: string;
26
+ }): Promise<string>;
@@ -1,7 +1,8 @@
1
1
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
2
2
  import { dirname, join } from 'node:path';
3
3
  import { cwd } from 'node:process';
4
- import { BLUEPRINT_CONFIG_FILE, BLUEPRINT_CONFIG_VERSION, BLUEPRINT_DIR } from '../../config.js';
4
+ import config, { BLUEPRINT_CONFIG_FILE, BLUEPRINT_CONFIG_VERSION, BLUEPRINT_DIR, } from '../../config.js';
5
+ import { getProject } from '../sanity/projects.js';
5
6
  export function readConfigFile(blueprintFilePath) {
6
7
  const blueprintDir = blueprintFilePath ? dirname(blueprintFilePath) : cwd();
7
8
  const configPath = join(blueprintDir, BLUEPRINT_DIR, BLUEPRINT_CONFIG_FILE);
@@ -32,10 +33,39 @@ export function writeConfigFile({ blueprintFilePath, organizationId, projectId,
32
33
  // config broken, start fresh
33
34
  }
34
35
  }
35
- config.organizationId = organizationId;
36
- config.projectId = projectId;
37
- config.stackId = stackId;
36
+ if (organizationId)
37
+ config.organizationId = organizationId;
38
+ if (projectId)
39
+ config.projectId = projectId;
40
+ if (stackId)
41
+ config.stackId = stackId;
38
42
  config.blueprintConfigVersion = BLUEPRINT_CONFIG_VERSION;
39
43
  config.updatedAt = Date.now();
40
44
  writeFileSync(configPath, JSON.stringify(config, null, 2));
41
45
  }
46
+ /**
47
+ * Find and write an organizationId to the config file by getting it from the projectId
48
+ * @throws {Error} if unable to fetch project
49
+ * @returns {Promise<string>} the discovered organizationId
50
+ */
51
+ export async function backfillOrganizationId({ blueprintFilePath, projectId, }) {
52
+ const token = config.token;
53
+ if (!token)
54
+ throw new Error('No token found');
55
+ let organizationId;
56
+ try {
57
+ const response = await getProject({ token, scopeType: 'project', scopeId: projectId });
58
+ if (!response.ok)
59
+ throw new Error('Failed to get project');
60
+ if (!response.project)
61
+ throw new Error('No project found');
62
+ organizationId = response.project.organizationId;
63
+ }
64
+ catch (error) {
65
+ throw new Error('Failed to backfill organizationId', { cause: error });
66
+ }
67
+ if (!organizationId)
68
+ throw new Error('No organizationId found');
69
+ writeConfigFile({ blueprintFilePath, organizationId });
70
+ return organizationId;
71
+ }
@@ -33,11 +33,20 @@ export async function getBlueprintAndStack({ token, blueprintPath, }) {
33
33
  issues.push({ code: 'NO_STACK_ID', message: 'Stack ID not found' });
34
34
  return { localBlueprint, issues };
35
35
  }
36
- const auth = { token, projectId };
37
- const { error, ok, stack: deployedStack } = await getStack({ stackId, auth });
38
- if (!ok) {
39
- issues.push({ code: 'NO_STACK', message: error || 'Unknown error' });
36
+ const stackResponse = await getStack({
37
+ stackId,
38
+ auth: {
39
+ scopeType: 'project',
40
+ scopeId: projectId,
41
+ token,
42
+ },
43
+ });
44
+ if (!stackResponse.ok) {
45
+ issues.push({ code: 'NO_STACK', message: stackResponse.error || 'Unknown error' });
40
46
  return { localBlueprint, issues };
41
47
  }
42
- return { localBlueprint: localBlueprint, deployedStack };
48
+ return {
49
+ localBlueprint: localBlueprint,
50
+ deployedStack: stackResponse.stack,
51
+ };
43
52
  }
@@ -1,4 +1,4 @@
1
- import type { AuthParams, Stack, StackMutation } from '../../utils/types.js';
1
+ import type { AuthParams, ScopeType, Stack, StackMutation } from '../../utils/types.js';
2
2
  export declare const stacksUrl: string;
3
3
  interface ListStacksResponse {
4
4
  ok: boolean;
@@ -10,7 +10,7 @@ interface GetStackResponse {
10
10
  ok: boolean;
11
11
  error: string | null;
12
12
  stack: Stack;
13
- response: Response;
13
+ response?: Response;
14
14
  }
15
15
  export declare function getStack({ stackId, auth, }: {
16
16
  stackId: string;
@@ -25,9 +25,10 @@ export declare function createStack({ stackMutation, auth, }: {
25
25
  stackMutation: StackMutation;
26
26
  auth: AuthParams;
27
27
  }): Promise<CreateStackResponse>;
28
- export declare function createEmptyStack({ token, projectId, name, projectBased, }: {
28
+ export declare function createEmptyStack({ token, scopeType, scopeId, name, projectBased, }: {
29
29
  token: string;
30
- projectId: string;
30
+ scopeType: ScopeType;
31
+ scopeId: string;
31
32
  name: string;
32
33
  projectBased?: boolean;
33
34
  }): Promise<Stack>;
@@ -2,6 +2,7 @@ import config from '../../config.js';
2
2
  import getHeaders from '../../utils/get-headers.js';
3
3
  const { apiUrl } = config;
4
4
  export const stacksUrl = `${apiUrl}vX/blueprints/stacks`;
5
+ /** Discriminate between Resource and Resource with parameters */
5
6
  function hasParameters(obj) {
6
7
  return (typeof obj === 'object' &&
7
8
  obj !== null &&
@@ -9,6 +10,7 @@ function hasParameters(obj) {
9
10
  typeof obj.parameters === 'object' &&
10
11
  obj.parameters !== null);
11
12
  }
13
+ /** Flatten Resource with parameters */
12
14
  function flattenResource(resource) {
13
15
  if (hasParameters(resource)) {
14
16
  const { parameters, ...rest } = resource;
@@ -16,6 +18,7 @@ function flattenResource(resource) {
16
18
  }
17
19
  return resource;
18
20
  }
21
+ /** Flatten a Stack's resources */
19
22
  function flattenStackResources(stack) {
20
23
  if (stack && Array.isArray(stack.resources)) {
21
24
  return {
@@ -63,15 +66,18 @@ export async function createStack({ stackMutation, auth, }) {
63
66
  stack: response.ok ? flattenStackResources(data) : data,
64
67
  };
65
68
  }
66
- export async function createEmptyStack({ token, projectId, name, projectBased = true, }) {
69
+ export async function createEmptyStack({ token, scopeType, scopeId, name, projectBased = true, }) {
67
70
  const stackMutation = {
68
71
  name,
69
- projectId,
72
+ scopeType,
73
+ scopeId,
70
74
  useProjectBasedId: projectBased,
71
75
  document: { resources: [] },
72
76
  };
73
- const auth = { token, projectId };
74
- const response = await createStack({ stackMutation, auth });
77
+ const response = await createStack({
78
+ stackMutation,
79
+ auth: { token, scopeType, scopeId },
80
+ });
75
81
  if (!response.ok) {
76
82
  throw new Error(response.error || 'Failed to create new Stack');
77
83
  }
@@ -1,3 +1,4 @@
1
+ import type { ScopeType } from '../../utils/types.js';
1
2
  export declare const projectsApiPath: string;
2
3
  export declare const orgsApiPath: string;
3
4
  export interface Project {
@@ -40,8 +41,9 @@ interface GetProjectResponse {
40
41
  error: string | null;
41
42
  project: Project;
42
43
  }
43
- export declare function getProject({ token, projectId, }: {
44
+ export declare function getProject({ token, scopeId, scopeType, }: {
44
45
  token: string;
45
- projectId: string;
46
+ scopeId: string;
47
+ scopeType: ScopeType;
46
48
  }): Promise<GetProjectResponse>;
47
49
  export {};
@@ -48,8 +48,11 @@ export async function groupProjectsByOrganization({ token, }) {
48
48
  organizations: orgsWithProjects,
49
49
  };
50
50
  }
51
- export async function getProject({ token, projectId, }) {
52
- const response = await fetch(`${projectsApiPath}/${projectId}`, {
51
+ export async function getProject({ token, scopeId, scopeType, }) {
52
+ if (scopeType !== 'project') {
53
+ throw new Error('Scope type must be project');
54
+ }
55
+ const response = await fetch(`${projectsApiPath}/${scopeId}`, {
53
56
  method: 'GET',
54
57
  headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
55
58
  });
@@ -140,7 +140,7 @@ async function testConfigAndReport({ token, stackId, projectId, }) {
140
140
  const spinner = ora('Testing the configuration...').start();
141
141
  const { ok, error } = await getStack({
142
142
  stackId,
143
- auth: { token, projectId },
143
+ auth: { token, scopeType: 'project', scopeId: projectId },
144
144
  });
145
145
  if (!ok) {
146
146
  spinner.fail('Configuration test failed.');
@@ -151,7 +151,7 @@ async function testConfigAndReport({ token, stackId, projectId, }) {
151
151
  return { ok, error };
152
152
  }
153
153
  async function startReinitializeStack({ token, projectId, }) {
154
- const auth = { token, projectId };
154
+ const auth = { token, scopeType: 'project', scopeId: projectId };
155
155
  // stack id IS ST-${projectId} – it has already been checked and doesn't exist
156
156
  const { confirm } = await inquirer.prompt([
157
157
  {
@@ -170,8 +170,15 @@ async function startReinitializeStack({ token, projectId, }) {
170
170
  };
171
171
  }
172
172
  const projectDisplayName = project.displayName;
173
- const stackMutation = { name: projectDisplayName, projectId, document: { resources: [] } };
174
- const response = await createStack({ stackMutation, auth });
173
+ const response = await createStack({
174
+ stackMutation: {
175
+ name: projectDisplayName,
176
+ scopeType: 'project',
177
+ scopeId: projectId,
178
+ document: { resources: [] },
179
+ },
180
+ auth,
181
+ });
175
182
  if (!response.ok)
176
183
  return { ok: false, error: response.error || 'Failed to create new Stack' };
177
184
  return {
@@ -46,14 +46,18 @@ export async function blueprintDeployCore(options) {
46
46
  }
47
47
  }
48
48
  }
49
- const stackMutation = {
50
- projectId,
51
- name: deployedStack.name,
52
- document: { resources: validResources },
53
- };
54
49
  const spinner = ora('Deploying...').start();
55
50
  const isoNow = new Date().toISOString();
56
- const { ok: deployOk, stack, error: deployError, } = await updateStack({ stackId, stackMutation, auth });
51
+ const { ok: deployOk, stack, error: deployError, } = await updateStack({
52
+ stackId,
53
+ stackMutation: {
54
+ scopeType: 'project',
55
+ scopeId: projectId,
56
+ name: deployedStack.name,
57
+ document: { resources: validResources },
58
+ },
59
+ auth,
60
+ });
57
61
  if (!deployOk) {
58
62
  spinner.fail(`${chalk.red('Failed')} to update deployment`);
59
63
  return { success: false, error: deployError || 'Failed to update deployment' };
@@ -12,7 +12,7 @@ export async function blueprintDestroyCore(options) {
12
12
  if (flagProjectId && flagStackId && force) {
13
13
  const { ok, error, stack } = await destroyStack({
14
14
  stackId: flagStackId,
15
- auth: { token, projectId: flagProjectId },
15
+ auth: { token, scopeType: 'project', scopeId: flagProjectId },
16
16
  });
17
17
  if (!ok)
18
18
  return { success: false, error: error || 'Failed to destroy deployment' };
@@ -22,7 +22,7 @@ export async function blueprintDestroyCore(options) {
22
22
  const { projectId, stackId } = blueprint;
23
23
  if (!projectId)
24
24
  return { success: false, error: 'Project ID is required' };
25
- const auth = { token, projectId };
25
+ const auth = { token, scopeType: 'project', scopeId: projectId };
26
26
  let stack;
27
27
  try {
28
28
  if (flagStackId) {
@@ -125,7 +125,7 @@ export async function blueprintDoctorCore(options) {
125
125
  // STACK + ACCESS
126
126
  if (diagnostics.online && diagnostics.tokenValid && token && stackId && projectId) {
127
127
  const stackResponse = await getStack({
128
- auth: { token, projectId },
128
+ auth: { token, scopeType: 'project', scopeId: projectId },
129
129
  stackId,
130
130
  });
131
131
  if (stackResponse.ok) {
@@ -134,12 +134,12 @@ export async function blueprintDoctorCore(options) {
134
134
  diagnostics.stackReady = true;
135
135
  diagnostics.userHasAccess = true;
136
136
  }
137
- else if (stackResponse.response.status === 404) {
137
+ else if (stackResponse.response?.status === 404) {
138
138
  if (v)
139
139
  yikes(`Deployment "Stack" <${stackId}> not found`);
140
140
  diagnostics.stackReady = false;
141
141
  }
142
- else if (stackResponse.response.status === 403 || stackResponse.response.status === 401) {
142
+ else if (stackResponse.response?.status === 403 || stackResponse.response?.status === 401) {
143
143
  if (v)
144
144
  yikes(`User does not have access to "Stack" <${stackId}>`);
145
145
  diagnostics.userHasAccess = false;
@@ -38,7 +38,8 @@ export async function blueprintInitCore(options) {
38
38
  // * 3. create empty stack with name from example name
39
39
  const stack = await createEmptyStack({
40
40
  token,
41
- projectId,
41
+ scopeType: 'project',
42
+ scopeId: projectId,
42
43
  name: `example-${flagExample}`,
43
44
  projectBased: false,
44
45
  });
@@ -106,17 +107,17 @@ export async function blueprintInitCore(options) {
106
107
  // using --stack-name gets around "LAUNCH LIMIT: 1 Stack per Project"
107
108
  const stack = await createEmptyStack({
108
109
  token,
109
- projectId,
110
+ scopeType: 'project',
111
+ scopeId: projectId,
110
112
  name: flagStackName,
111
113
  projectBased: false,
112
114
  });
113
115
  stackId = stack.id;
114
116
  }
115
- const auth = { token: token, projectId };
116
117
  if (!stackId) {
117
118
  // LAUNCH LIMIT: 1 Stack per Project - do not prompt for Stack, just create one
118
119
  if (LAUNCH_LIMIT_STACK_PER_PROJECT) {
119
- await createProjectBasedStack(auth, token, log);
120
+ await createProjectBasedStack({ token, scopeType: 'project', scopeId: projectId }, log);
120
121
  // do not set stackId, to avoid saving it to the config file
121
122
  }
122
123
  else {
@@ -175,10 +176,17 @@ async function promptForBlueprintType() {
175
176
  return pickedBlueprintsType;
176
177
  }
177
178
  // LAUNCH LIMIT: 1 Stack per Project - create exclusive stack for project
178
- async function createProjectBasedStack(auth, token, log) {
179
- const { projectId } = auth;
179
+ async function createProjectBasedStack(auth, log) {
180
+ if (auth.scopeType !== 'project') {
181
+ throw new Error('Auth must be for a project');
182
+ }
183
+ const { scopeId: projectId, token } = auth;
180
184
  // get project
181
- const { ok: projectOk, project } = await getProject(auth);
185
+ const { ok: projectOk, project } = await getProject({
186
+ token: auth.token,
187
+ scopeType: 'project',
188
+ scopeId: projectId,
189
+ });
182
190
  if (!projectOk) {
183
191
  throw new Error('Failed to find Project while creating Stack');
184
192
  }
@@ -196,7 +204,8 @@ async function createProjectBasedStack(auth, token, log) {
196
204
  // if not, create a stack
197
205
  const stack = await createEmptyStack({
198
206
  token,
199
- projectId,
207
+ scopeType: 'project',
208
+ scopeId: projectId,
200
209
  name: projectDisplayName,
201
210
  });
202
211
  return stack;
@@ -7,7 +7,10 @@ export async function blueprintPlanCore(options) {
7
7
  log(`${chalk.bold.blueBright('Blueprint Deployment Plan')} ${chalk.dim(`(${fileInfo.fileName})`)}`);
8
8
  log(formatResourceTree(parsedBlueprint.resources));
9
9
  if (token && projectId && stackId) {
10
- const stackResponse = await getStack({ stackId, auth: { token, projectId } });
10
+ const stackResponse = await getStack({
11
+ auth: { token, scopeType: 'project', scopeId: projectId },
12
+ stackId,
13
+ });
11
14
  if (!stackResponse.ok) {
12
15
  log(chalk.dim('Unable to retrieve live deployment for comparison'));
13
16
  }
@@ -11,7 +11,7 @@ export async function blueprintStacksCore(options) {
11
11
  return { success: false, error: 'No Project ID provided' };
12
12
  }
13
13
  try {
14
- const { ok, stacks, error } = await listStacks({ token, projectId });
14
+ const { ok, stacks, error } = await listStacks({ token, scopeType: 'project', scopeId: projectId });
15
15
  if (!ok)
16
16
  return { success: false, error: error || 'Failed to list stacks' };
17
17
  if (!stacks || stacks.length === 0) {
@@ -48,7 +48,7 @@ export async function initDeployedBlueprintConfig(config) {
48
48
  if (!stackId)
49
49
  return { ok: false, error: 'Missing deployment configuration for Blueprint' };
50
50
  }
51
- const auth = { token: config.token, projectId };
51
+ const auth = { token: config.token, scopeType: 'project', scopeId: projectId };
52
52
  const stackResponse = await getStack({ stackId, auth });
53
53
  if (!stackResponse.ok) {
54
54
  config.log(`Could not retrieve deployment info for ${niceId(stackId)}. Was it destroyed?`);
@@ -54,7 +54,7 @@ export async function promptForProject({ token, knownOrganizationId, knownProjec
54
54
  return pickedProject;
55
55
  }
56
56
  export async function promptForStackId({ projectId, token, }) {
57
- const { ok: stacksOk, error: stacksErr, stacks } = await listStacks({ token, projectId });
57
+ const { ok: stacksOk, error: stacksErr, stacks, } = await listStacks({ token, scopeType: 'project', scopeId: projectId });
58
58
  if (!stacksOk) {
59
59
  throw new Error(stacksErr || 'Failed to list Stacks');
60
60
  }
@@ -87,7 +87,8 @@ export async function promptForStackId({ projectId, token, }) {
87
87
  ]);
88
88
  const stack = await createEmptyStack({
89
89
  token,
90
- projectId,
90
+ scopeType: 'project',
91
+ scopeId: projectId,
91
92
  name: stackName,
92
93
  });
93
94
  return stack.id;
@@ -1,9 +1,9 @@
1
1
  import type { AuthParams } from './types.js';
2
- export default function getHeaders({ token, projectId }: AuthParams): {
2
+ export default function getHeaders({ token, scopeId, scopeType }: AuthParams): {
3
3
  Accept: string;
4
4
  'Content-Type': string;
5
5
  Authorization: string;
6
- 'X-Sanity-Scope-Type': string;
6
+ 'X-Sanity-Scope-Type': import("./types.js").ScopeType;
7
7
  'X-Sanity-Scope-Id': string;
8
8
  'User-Agent': string;
9
9
  };
@@ -1,21 +1,12 @@
1
- const userAgent = await getUserAgent();
2
- async function getUserAgent() {
3
- try {
4
- const pkg = await (await import('../../package.json', { with: { type: 'json' } })).default;
5
- return `${pkg.name}@${pkg.version}`;
6
- }
7
- catch {
8
- return 'unknown@0.0.0';
9
- }
10
- }
11
- export default function getHeaders({ token, projectId }) {
12
- // TODO: support organization scope type
1
+ import pkg from '../../package.json' with { type: 'json' };
2
+ const userAgent = `${pkg.name}@${pkg.version}`;
3
+ export default function getHeaders({ token, scopeId, scopeType }) {
13
4
  return {
14
5
  Accept: 'application/json',
15
6
  'Content-Type': 'application/json',
16
7
  Authorization: `Bearer ${token}`,
17
- 'X-Sanity-Scope-Type': 'project',
18
- 'X-Sanity-Scope-Id': projectId,
8
+ 'X-Sanity-Scope-Type': scopeType,
9
+ 'X-Sanity-Scope-Id': scopeId,
19
10
  'User-Agent': userAgent,
20
11
  };
21
12
  }
@@ -11,7 +11,8 @@ export type Result<T, E = string> = {
11
11
  /** @internal */
12
12
  export interface AuthParams {
13
13
  token: string;
14
- projectId: string;
14
+ scopeType: ScopeType;
15
+ scopeId: string;
15
16
  }
16
17
  /** @internal */
17
18
  export interface GroqRule {
@@ -55,7 +56,8 @@ export interface Stack {
55
56
  id: string;
56
57
  name: string;
57
58
  displayName: string;
58
- projectId: string;
59
+ scopeType: ScopeType;
60
+ scopeId: string;
59
61
  resources: Array<DeployedResource>;
60
62
  createdAt?: string;
61
63
  updatedAt?: string;
@@ -71,7 +73,8 @@ export interface StackOperation {
71
73
  /** @internal */
72
74
  export interface StackMutation {
73
75
  name: string;
74
- projectId: string;
76
+ scopeType: ScopeType;
77
+ scopeId: string;
75
78
  document: Blueprint;
76
79
  useProjectBasedId?: boolean;
77
80
  }
@@ -1,7 +1,7 @@
1
1
  import { BlueprintParserErrorType } from '../types.js';
2
2
  export function validateFunctionName(name) {
3
- // must be 6+ characters, no special characters, no spaces, allow _ and -
4
- return /^[a-zA-Z0-9][a-zA-Z0-9_-]{5,}$/.test(name);
3
+ // must be 3+ characters, no special characters, no spaces, allow _ and -
4
+ return /^[a-zA-Z0-9][a-zA-Z0-9_-]{2,}$/.test(name);
5
5
  }
6
6
  const validFunctionEventNames = ['publish', 'create', 'update', 'delete'];
7
7
  export function validateFunctionResource(resource) {
@@ -10,7 +10,7 @@ export function validateFunctionResource(resource) {
10
10
  const errors = [];
11
11
  if (!validateFunctionName(resource.name)) {
12
12
  errors.push({
13
- message: `${msgPrefix} Function name must be at least 6 characters, start with a letter or number, and only contain letters, numbers, _ or -`,
13
+ message: `${msgPrefix} Function name must be at least 3 characters, start with a letter or number, and only contain letters, numbers, _ or -`,
14
14
  type: BlueprintParserErrorType.InvalidProperty,
15
15
  });
16
16
  }
@@ -1177,5 +1177,5 @@
1177
1177
  ]
1178
1178
  }
1179
1179
  },
1180
- "version": "10.11.0"
1180
+ "version": "10.11.2"
1181
1181
  }
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": "10.11.0",
4
+ "version": "10.11.2",
5
5
  "author": "Sanity Runtime Team",
6
6
  "type": "module",
7
7
  "license": "MIT",