@sanity/runtime-cli 14.8.0 → 14.8.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.
Files changed (37) hide show
  1. package/README.md +36 -28
  2. package/dist/actions/blueprints/assets.d.ts +2 -2
  3. package/dist/actions/blueprints/assets.js +1 -1
  4. package/dist/actions/blueprints/resources.d.ts +2 -2
  5. package/dist/actions/blueprints/resources.js +60 -12
  6. package/dist/baseCommands.d.ts +8 -0
  7. package/dist/baseCommands.js +8 -0
  8. package/dist/commands/blueprints/config.js +3 -12
  9. package/dist/commands/blueprints/destroy.js +3 -6
  10. package/dist/commands/blueprints/init.js +3 -11
  11. package/dist/commands/blueprints/promote.d.ts +0 -1
  12. package/dist/commands/blueprints/promote.js +0 -4
  13. package/dist/commands/blueprints/stacks.js +3 -12
  14. package/dist/commands/functions/test.js +3 -12
  15. package/dist/constants.d.ts +2 -1
  16. package/dist/cores/blueprints/config.js +6 -2
  17. package/dist/cores/blueprints/deploy.js +3 -3
  18. package/dist/cores/blueprints/promote.d.ts +0 -1
  19. package/dist/cores/blueprints/promote.js +0 -3
  20. package/dist/cores/functions/add.d.ts +1 -0
  21. package/dist/cores/functions/add.js +2 -2
  22. package/dist/utils/display/blueprints-formatting.d.ts +3 -2
  23. package/dist/utils/display/blueprints-formatting.js +3 -2
  24. package/dist/utils/display/resources-formatting.d.ts +2 -3
  25. package/dist/utils/display/resources-formatting.js +4 -4
  26. package/dist/utils/find-function.d.ts +3 -3
  27. package/dist/utils/find-function.js +3 -2
  28. package/dist/utils/functions/prepare-asset.d.ts +2 -2
  29. package/dist/utils/functions/should-auto-resolve-deps.js +1 -1
  30. package/dist/utils/functions/should-transpile.js +1 -1
  31. package/dist/utils/invoke-local.d.ts +1 -7
  32. package/dist/utils/invoke-local.js +5 -24
  33. package/dist/utils/types.d.ts +6 -79
  34. package/dist/utils/types.js +1 -10
  35. package/dist/utils/validate/index.d.ts +2 -2
  36. package/oclif.manifest.json +17 -33
  37. package/package.json +1 -1
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/14.8.0 linux-x64 node-v24.14.0
23
+ @sanity/runtime-cli/14.8.2 linux-x64 node-v24.14.1
24
24
  $ sanity-run --help [COMMAND]
25
25
  USAGE
26
26
  $ sanity-run COMMAND
@@ -101,7 +101,7 @@ EXAMPLES
101
101
  $ sanity-run blueprints add function --name my-function --fn-type document-create --fn-type document-update --lang js
102
102
  ```
103
103
 
104
- _See code: [src/commands/blueprints/add.ts](https://github.com/sanity-io/runtime-cli/blob/v14.8.0/src/commands/blueprints/add.ts)_
104
+ _See code: [src/commands/blueprints/add.ts](https://github.com/sanity-io/runtime-cli/blob/v14.8.2/src/commands/blueprints/add.ts)_
105
105
 
106
106
  ## `sanity-run blueprints config`
107
107
 
@@ -109,12 +109,14 @@ View or edit the local Blueprint configuration
109
109
 
110
110
  ```
111
111
  USAGE
112
- $ sanity-run blueprints config [--json] [--validate-resources] [--project-id <value> -e] [--stack <value> ]
112
+ $ sanity-run blueprints config [--json] [--validate-resources] [--project-id <value> -e] [--organization-id <value> ]
113
+ [--stack <value> ]
113
114
 
114
115
  FLAGS
115
116
  -e, --edit Modify the configuration interactively, or directly when combined with ID flags.
116
117
  --json Format output as json
117
- --project-id=<value> Directly set the project ID in the configuration. Requires --edit flag
118
+ --organization-id=<value> Sanity organization ID used to scope Blueprint and Stack
119
+ --project-id=<value> Sanity project ID used to scope Blueprint and Stack
118
120
  --stack=<value> Stack name or ID to set in the configuration. Requires --edit flag
119
121
  --[no-]validate-resources Validate resources
120
122
 
@@ -138,7 +140,7 @@ EXAMPLES
138
140
  $ sanity-run blueprints config --edit --project-id <projectId> --stack <name-or-id>
139
141
  ```
140
142
 
141
- _See code: [src/commands/blueprints/config.ts](https://github.com/sanity-io/runtime-cli/blob/v14.8.0/src/commands/blueprints/config.ts)_
143
+ _See code: [src/commands/blueprints/config.ts](https://github.com/sanity-io/runtime-cli/blob/v14.8.2/src/commands/blueprints/config.ts)_
142
144
 
143
145
  ## `sanity-run blueprints deploy`
144
146
 
@@ -177,7 +179,7 @@ EXAMPLES
177
179
  $ sanity-run blueprints deploy --fn-installer npm
178
180
  ```
179
181
 
180
- _See code: [src/commands/blueprints/deploy.ts](https://github.com/sanity-io/runtime-cli/blob/v14.8.0/src/commands/blueprints/deploy.ts)_
182
+ _See code: [src/commands/blueprints/deploy.ts](https://github.com/sanity-io/runtime-cli/blob/v14.8.2/src/commands/blueprints/deploy.ts)_
181
183
 
182
184
  ## `sanity-run blueprints destroy`
183
185
 
@@ -186,13 +188,14 @@ Destroy the remote Stack deployment and its resources (will not delete local fil
186
188
  ```
187
189
  USAGE
188
190
  $ sanity-run blueprints destroy [--json] [--validate-resources] [--project-id <value> --stack <value> --force]
189
- [--no-wait]
191
+ [--organization-id <value> ] [--no-wait]
190
192
 
191
193
  FLAGS
192
194
  --force Force Stack destruction (skip confirmation)
193
195
  --json Format output as json
194
196
  --no-wait Do not wait for Stack destruction to complete
195
- --project-id=<value> Project associated with the Stack
197
+ --organization-id=<value> Sanity organization ID used to scope Blueprint and Stack
198
+ --project-id=<value> Sanity project ID used to scope Blueprint and Stack
196
199
  --stack=<value> Stack name or ID to destroy (defaults to the locally configured Stack)
197
200
  --[no-]validate-resources Validate resources
198
201
 
@@ -212,7 +215,7 @@ EXAMPLES
212
215
  $ sanity-run blueprints destroy --stack <name-or-id> --project-id <projectId> --force --no-wait
213
216
  ```
214
217
 
215
- _See code: [src/commands/blueprints/destroy.ts](https://github.com/sanity-io/runtime-cli/blob/v14.8.0/src/commands/blueprints/destroy.ts)_
218
+ _See code: [src/commands/blueprints/destroy.ts](https://github.com/sanity-io/runtime-cli/blob/v14.8.2/src/commands/blueprints/destroy.ts)_
216
219
 
217
220
  ## `sanity-run blueprints doctor`
218
221
 
@@ -239,7 +242,7 @@ DESCRIPTION
239
242
  issues.
240
243
  ```
241
244
 
242
- _See code: [src/commands/blueprints/doctor.ts](https://github.com/sanity-io/runtime-cli/blob/v14.8.0/src/commands/blueprints/doctor.ts)_
245
+ _See code: [src/commands/blueprints/doctor.ts](https://github.com/sanity-io/runtime-cli/blob/v14.8.2/src/commands/blueprints/doctor.ts)_
243
246
 
244
247
  ## `sanity-run blueprints info`
245
248
 
@@ -271,7 +274,7 @@ EXAMPLES
271
274
  $ sanity-run blueprints info --stack <name-or-id>
272
275
  ```
273
276
 
274
- _See code: [src/commands/blueprints/info.ts](https://github.com/sanity-io/runtime-cli/blob/v14.8.0/src/commands/blueprints/info.ts)_
277
+ _See code: [src/commands/blueprints/info.ts](https://github.com/sanity-io/runtime-cli/blob/v14.8.2/src/commands/blueprints/info.ts)_
275
278
 
276
279
  ## `sanity-run blueprints init [DIR]`
277
280
 
@@ -280,7 +283,8 @@ Initialize a local Blueprint and optionally provision a remote Stack deployment
280
283
  ```
281
284
  USAGE
282
285
  $ sanity-run blueprints init [DIR] [--json] [--validate-resources] [--verbose] [--dir <value>] [--example <value> |
283
- --blueprint-type json|js|ts | --stack-id <value> | --stack-name <value>] [--project-id <value>]
286
+ --blueprint-type json|js|ts | --stack-id <value> | --stack-name <value>] [--project-id <value>] [--organization-id
287
+ <value>]
284
288
 
285
289
  ARGUMENTS
286
290
  [DIR] Directory to create the local Blueprint in
@@ -291,7 +295,8 @@ FLAGS
291
295
  --dir=<value> Directory to create the local Blueprint in
292
296
  --example=<value> Example to use for the local Blueprint
293
297
  --json Format output as json
294
- --project-id=<value> Sanity project ID used to scope local Blueprint and remote Stack
298
+ --organization-id=<value> Sanity organization ID used to scope Blueprint and Stack
299
+ --project-id=<value> Sanity project ID used to scope Blueprint and Stack
295
300
  --stack-id=<value> Existing Stack ID used to scope local Blueprint
296
301
  --stack-name=<value> Name to use for a new Stack provisioned during initialization
297
302
  --[no-]validate-resources Validate resources
@@ -323,7 +328,7 @@ EXAMPLES
323
328
  $ sanity-run blueprints init --blueprint-type <json|js|ts> --stack-name <stackName>
324
329
  ```
325
330
 
326
- _See code: [src/commands/blueprints/init.ts](https://github.com/sanity-io/runtime-cli/blob/v14.8.0/src/commands/blueprints/init.ts)_
331
+ _See code: [src/commands/blueprints/init.ts](https://github.com/sanity-io/runtime-cli/blob/v14.8.2/src/commands/blueprints/init.ts)_
327
332
 
328
333
  ## `sanity-run blueprints logs`
329
334
 
@@ -354,7 +359,7 @@ EXAMPLES
354
359
  $ sanity-run blueprints logs --watch
355
360
  ```
356
361
 
357
- _See code: [src/commands/blueprints/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v14.8.0/src/commands/blueprints/logs.ts)_
362
+ _See code: [src/commands/blueprints/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v14.8.2/src/commands/blueprints/logs.ts)_
358
363
 
359
364
  ## `sanity-run blueprints plan`
360
365
 
@@ -382,7 +387,7 @@ EXAMPLES
382
387
  $ sanity-run blueprints plan
383
388
  ```
384
389
 
385
- _See code: [src/commands/blueprints/plan.ts](https://github.com/sanity-io/runtime-cli/blob/v14.8.0/src/commands/blueprints/plan.ts)_
390
+ _See code: [src/commands/blueprints/plan.ts](https://github.com/sanity-io/runtime-cli/blob/v14.8.2/src/commands/blueprints/plan.ts)_
386
391
 
387
392
  ## `sanity-run blueprints stacks`
388
393
 
@@ -390,11 +395,12 @@ List all remote Stack deployments (defaults to the current Blueprint's project s
390
395
 
391
396
  ```
392
397
  USAGE
393
- $ sanity-run blueprints stacks [--json] [--validate-resources] [--project-id <value> | ]
398
+ $ sanity-run blueprints stacks [--json] [--validate-resources] [--project-id <value> | --organization-id <value>]
394
399
 
395
400
  FLAGS
396
401
  --json Format output as json
397
- --project-id=<value> Project ID to show Stack deployments for
402
+ --organization-id=<value> Sanity organization ID used to scope Blueprint and Stack
403
+ --project-id=<value> Sanity project ID used to scope Blueprint and Stack
398
404
  --[no-]validate-resources Validate resources
399
405
 
400
406
  DESCRIPTION
@@ -413,7 +419,7 @@ EXAMPLES
413
419
  $ sanity-run blueprints stacks --organization-id <organizationId>
414
420
  ```
415
421
 
416
- _See code: [src/commands/blueprints/stacks.ts](https://github.com/sanity-io/runtime-cli/blob/v14.8.0/src/commands/blueprints/stacks.ts)_
422
+ _See code: [src/commands/blueprints/stacks.ts](https://github.com/sanity-io/runtime-cli/blob/v14.8.2/src/commands/blueprints/stacks.ts)_
417
423
 
418
424
  ## `sanity-run functions add`
419
425
 
@@ -466,7 +472,7 @@ EXAMPLES
466
472
  $ sanity-run functions add --name my-function --type document-create --type document-update --lang js
467
473
  ```
468
474
 
469
- _See code: [src/commands/functions/add.ts](https://github.com/sanity-io/runtime-cli/blob/v14.8.0/src/commands/functions/add.ts)_
475
+ _See code: [src/commands/functions/add.ts](https://github.com/sanity-io/runtime-cli/blob/v14.8.2/src/commands/functions/add.ts)_
470
476
 
471
477
  ## `sanity-run functions dev`
472
478
 
@@ -502,7 +508,7 @@ EXAMPLES
502
508
  $ sanity-run functions dev --timeout 60
503
509
  ```
504
510
 
505
- _See code: [src/commands/functions/dev.ts](https://github.com/sanity-io/runtime-cli/blob/v14.8.0/src/commands/functions/dev.ts)_
511
+ _See code: [src/commands/functions/dev.ts](https://github.com/sanity-io/runtime-cli/blob/v14.8.2/src/commands/functions/dev.ts)_
506
512
 
507
513
  ## `sanity-run functions env add NAME KEY VALUE`
508
514
 
@@ -533,7 +539,7 @@ EXAMPLES
533
539
  $ sanity-run functions env add MyFunction API_URL https://api.example.com/
534
540
  ```
535
541
 
536
- _See code: [src/commands/functions/env/add.ts](https://github.com/sanity-io/runtime-cli/blob/v14.8.0/src/commands/functions/env/add.ts)_
542
+ _See code: [src/commands/functions/env/add.ts](https://github.com/sanity-io/runtime-cli/blob/v14.8.2/src/commands/functions/env/add.ts)_
537
543
 
538
544
  ## `sanity-run functions env list NAME`
539
545
 
@@ -561,7 +567,7 @@ EXAMPLES
561
567
  $ sanity-run functions env list MyFunction
562
568
  ```
563
569
 
564
- _See code: [src/commands/functions/env/list.ts](https://github.com/sanity-io/runtime-cli/blob/v14.8.0/src/commands/functions/env/list.ts)_
570
+ _See code: [src/commands/functions/env/list.ts](https://github.com/sanity-io/runtime-cli/blob/v14.8.2/src/commands/functions/env/list.ts)_
565
571
 
566
572
  ## `sanity-run functions env remove NAME KEY`
567
573
 
@@ -591,7 +597,7 @@ EXAMPLES
591
597
  $ sanity-run functions env remove MyFunction API_URL
592
598
  ```
593
599
 
594
- _See code: [src/commands/functions/env/remove.ts](https://github.com/sanity-io/runtime-cli/blob/v14.8.0/src/commands/functions/env/remove.ts)_
600
+ _See code: [src/commands/functions/env/remove.ts](https://github.com/sanity-io/runtime-cli/blob/v14.8.2/src/commands/functions/env/remove.ts)_
595
601
 
596
602
  ## `sanity-run functions logs [NAME]`
597
603
 
@@ -633,7 +639,7 @@ EXAMPLES
633
639
  $ sanity-run functions logs <name> --delete
634
640
  ```
635
641
 
636
- _See code: [src/commands/functions/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v14.8.0/src/commands/functions/logs.ts)_
642
+ _See code: [src/commands/functions/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v14.8.2/src/commands/functions/logs.ts)_
637
643
 
638
644
  ## `sanity-run functions test [NAME]`
639
645
 
@@ -644,7 +650,8 @@ USAGE
644
650
  $ sanity-run functions test [NAME] [--json] [--validate-resources] [--data-before <value> | [-d <value> | -f
645
651
  <value> | --document-id <value>] | | | --file-before <value> | --file-after <value> | --document-id-before <value>
646
652
  | --document-id-after <value>] [--data-after <value> | | | | | | | ] [-e create|update|delete] [-t <value>]
647
- [-a <value>] [--with-user-token] [--media-library-id <value> | --project-id <value> | --dataset <value>]
653
+ [-a <value>] [--organization-id <value>] [--with-user-token] [--media-library-id <value> | --project-id <value> |
654
+ --dataset <value>]
648
655
 
649
656
  ARGUMENTS
650
657
  [NAME] The name of the Sanity Function
@@ -666,7 +673,8 @@ FLAGS
666
673
  --file-before=<value> Original document
667
674
  --json Format output as json
668
675
  --media-library-id=<value> Sanity Media Library ID to use
669
- --project-id=<value> Sanity Project ID to use
676
+ --organization-id=<value> Sanity organization ID used to scope Blueprint and Stack
677
+ --project-id=<value> Sanity project ID used to scope Blueprint and Stack
670
678
  --[no-]validate-resources Validate resources
671
679
  --with-user-token Prime access token from CLI config
672
680
 
@@ -689,7 +697,7 @@ EXAMPLES
689
697
  $ sanity-run functions test <name> --event update --data-before '{ "title": "before" }' --data-after '{ "title": "after" }'
690
698
  ```
691
699
 
692
- _See code: [src/commands/functions/test.ts](https://github.com/sanity-io/runtime-cli/blob/v14.8.0/src/commands/functions/test.ts)_
700
+ _See code: [src/commands/functions/test.ts](https://github.com/sanity-io/runtime-cli/blob/v14.8.2/src/commands/functions/test.ts)_
693
701
 
694
702
  ## `sanity-run help [COMMAND]`
695
703
 
@@ -1,11 +1,11 @@
1
- import type { Resource } from '@sanity/blueprints-parser';
1
+ import type { BlueprintResource } from '@sanity/blueprints';
2
2
  import AdmZip from 'adm-zip';
3
3
  import type { Logger } from '../../utils/logger.js';
4
4
  import type { AuthParams, InstallerType } from '../../utils/types.js';
5
5
  export declare const ASSET_CHECK_URL: string;
6
6
  export declare const ASSET_STASH_URL: string;
7
7
  export declare function stashAsset({ resource, auth, logger, installer, }: {
8
- resource: Resource;
8
+ resource: BlueprintResource;
9
9
  auth: AuthParams;
10
10
  logger: Logger;
11
11
  installer?: InstallerType;
@@ -66,7 +66,7 @@ export async function stashAsset({ resource, auth, logger, installer, }) {
66
66
  return { success: false, error: err instanceof Error ? err.message : `${err}` };
67
67
  }
68
68
  }
69
- async function prepareStudioAsset({ resource }) {
69
+ async function prepareStudioAsset({ resource, }) {
70
70
  if (!('src' in resource) || typeof resource.src !== 'string') {
71
71
  return {
72
72
  success: false,
@@ -1,5 +1,5 @@
1
1
  import type { Logger } from '../../utils/logger.js';
2
- import type { FunctionResourceBase } from '../../utils/types.js';
2
+ import type { FunctionResource } from '../../utils/types.js';
3
3
  interface FunctionResourceOptions {
4
4
  name: string;
5
5
  type: string[];
@@ -14,6 +14,6 @@ interface FunctionResourceOptions {
14
14
  export declare function createFunctionResource(options: FunctionResourceOptions, logger: Logger): Promise<{
15
15
  filePath: string;
16
16
  resourceAdded: boolean;
17
- resource: FunctionResourceBase;
17
+ resource: FunctionResource;
18
18
  }>;
19
19
  export {};
@@ -2,7 +2,6 @@ import { spawn } from 'node:child_process';
2
2
  import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
3
3
  import { dirname, join } from 'node:path';
4
4
  import { cwd } from 'node:process';
5
- import { SANITY_FUNCTION_PREFIX } from '../../constants.js';
6
5
  import { styleText } from '../../utils/style-text.js';
7
6
  import { writeOrUpdateNodeDependency } from '../node.js';
8
7
  import { addResourceToBlueprint } from './blueprint.js';
@@ -16,6 +15,12 @@ export const handler = documentEventHandler(async ({ context, event }) => {
16
15
  const time = new Date().toLocaleTimeString()
17
16
  console.log(\`👋 Your Sanity Function was called at \${time}\`)
18
17
  })`;
18
+ const DEFAULT_SCHEDULED_HELPER_FUNCTION_TEMPLATE = /*ts*/ `import { scheduledEventHandler } from '@sanity/functions'
19
+
20
+ export const handler = scheduledEventHandler(async ({ context }) => {
21
+ const time = new Date().toLocaleTimeString()
22
+ console.log(\`Your scheduled Sanity Function was called at \${time}\`)
23
+ })`;
19
24
  /**
20
25
  * Creates a new function resource file and adds it to the blueprint
21
26
  */
@@ -40,9 +45,24 @@ export async function createFunctionResource(options, logger) {
40
45
  mkdirSync(functionDir, { recursive: true });
41
46
  if (!['ts', 'js'].includes(lang))
42
47
  throw Error(`Unsupported language: ${lang}`);
48
+ // type looks like 'document-publish', 'media-library-asset-delete' or 'scheduled-function'
49
+ // and we are guaranteed to have the same leading words (typeName below) for all provided type strings (via guards in the call site for this method).
50
+ // TODO: this substring convention is brittle - consider mapping EVENT_* constants to typeName values explicitly instead of relying on string splitting.
51
+ const typeName = type[0].substring(0, type[0].lastIndexOf('-'));
43
52
  // Create index.<lang> with default template
44
53
  const indexPath = join(functionDir, `index.${lang}`);
45
- writeFileSync(indexPath, addHelpers ? DEFAULT_HELPER_FUNCTION_TEMPLATE : DEFAULT_FUNCTION_TEMPLATE);
54
+ let template = DEFAULT_FUNCTION_TEMPLATE;
55
+ if (addHelpers) {
56
+ switch (typeName) {
57
+ case 'scheduled':
58
+ template = DEFAULT_SCHEDULED_HELPER_FUNCTION_TEMPLATE;
59
+ break;
60
+ default:
61
+ template = DEFAULT_HELPER_FUNCTION_TEMPLATE;
62
+ break;
63
+ }
64
+ }
65
+ writeFileSync(indexPath, template);
46
66
  if (addHelpers && blueprintFilePath) {
47
67
  try {
48
68
  await writeOrUpdateNodeDependency(blueprintFilePath, '@sanity/functions', logger);
@@ -57,18 +77,46 @@ export async function createFunctionResource(options, logger) {
57
77
  throw new Error(`Failed to install dependencies using \`${installCommand}\``);
58
78
  }
59
79
  }
60
- // type looks like 'document-publish' or 'media-library-asset-delete'
61
- const typeName = type[0].substring(0, type[0].lastIndexOf('-'));
62
80
  const eventsOn = type.map((t) => t.substring(t.lastIndexOf('-') + 1));
63
81
  // Create resource definition
64
- const resourceJson = {
65
- name,
66
- src: `functions/${name}`,
67
- type: `${SANITY_FUNCTION_PREFIX}${typeName}`,
68
- event: {
69
- on: eventsOn,
70
- },
71
- };
82
+ let resourceJson;
83
+ switch (typeName) {
84
+ case 'document':
85
+ resourceJson = {
86
+ name,
87
+ src: `functions/${name}`,
88
+ type: 'sanity.function.document',
89
+ event: {
90
+ on: eventsOn,
91
+ },
92
+ };
93
+ break;
94
+ case 'media-library-asset':
95
+ resourceJson = {
96
+ name,
97
+ src: `functions/${name}`,
98
+ type: 'sanity.function.media-library.asset',
99
+ event: {
100
+ on: eventsOn,
101
+ resource: { type: 'media-library', id: 'my-media-library-id' },
102
+ },
103
+ };
104
+ break;
105
+ case 'scheduled':
106
+ resourceJson = {
107
+ name,
108
+ src: `functions/${name}`,
109
+ type: 'sanity.function.cron',
110
+ event: {
111
+ expression: '0 0 * * *',
112
+ },
113
+ };
114
+ break;
115
+ // TODO: add sync tag invalidate funx
116
+ }
117
+ if (!resourceJson) {
118
+ throw new Error('Could not create function resource based on selections');
119
+ }
72
120
  // Add to blueprint or return for manual addition
73
121
  const resource = addResourceToBlueprint({ blueprintFilePath, resource: resourceJson });
74
122
  return {
@@ -12,6 +12,14 @@ export declare const baseFlags: {
12
12
  verbose: Interfaces.BooleanFlag<boolean>;
13
13
  };
14
14
  export declare const stackFlag: Interfaces.OptionFlag<string | undefined, Interfaces.CustomOptions>;
15
+ export declare const projectIdFlagConfig: {
16
+ description: string;
17
+ aliases: string[];
18
+ };
19
+ export declare const organizationIdFlagConfig: {
20
+ description: string;
21
+ aliases: string[];
22
+ };
15
23
  /**
16
24
  * @description Unhides a flag by setting its hidden property to false
17
25
  * Also makes oclif's types happy when destructuring the flag
@@ -35,6 +35,14 @@ export const stackFlag = OclifFlags.string({
35
35
  description: 'Stack name or ID to use instead of the locally configured Stack',
36
36
  hidden: true,
37
37
  });
38
+ export const projectIdFlagConfig = {
39
+ description: 'Sanity project ID used to scope Blueprint and Stack',
40
+ aliases: ['project', 'projectId'],
41
+ };
42
+ export const organizationIdFlagConfig = {
43
+ description: 'Sanity organization ID used to scope Blueprint and Stack',
44
+ aliases: ['organization', 'organizationId', 'org'],
45
+ };
38
46
  /**
39
47
  * @description Unhides a flag by setting its hidden property to false
40
48
  * Also makes oclif's types happy when destructuring the flag
@@ -1,5 +1,5 @@
1
1
  import { Flags } from '@oclif/core';
2
- import { LocalBlueprintCommand } from '../../baseCommands.js';
2
+ import { LocalBlueprintCommand, organizationIdFlagConfig, projectIdFlagConfig, } from '../../baseCommands.js';
3
3
  import { blueprintConfigCore } from '../../cores/blueprints/config.js';
4
4
  import { Logger } from '../../utils/logger.js';
5
5
  export default class ConfigCommand extends LocalBlueprintCommand {
@@ -21,17 +21,8 @@ If you need to switch your Blueprint to a different Stack, use --edit --stack.`;
21
21
  description: 'Modify the configuration interactively, or directly when combined with ID flags.',
22
22
  default: false,
23
23
  }),
24
- 'project-id': Flags.string({
25
- description: 'Directly set the project ID in the configuration. Requires --edit flag',
26
- aliases: ['project', 'projectId'],
27
- dependsOn: ['edit'],
28
- }),
29
- 'organization-id': Flags.string({
30
- description: 'Directly set the organization ID in the configuration. Requires --edit flag',
31
- aliases: ['organization', 'organizationId', 'org'],
32
- dependsOn: ['edit'],
33
- hidden: true,
34
- }),
24
+ 'project-id': Flags.string({ ...projectIdFlagConfig, dependsOn: ['edit'] }),
25
+ 'organization-id': Flags.string({ ...organizationIdFlagConfig, dependsOn: ['edit'] }),
35
26
  stack: Flags.string({
36
27
  description: 'Stack name or ID to set in the configuration. Requires --edit flag',
37
28
  aliases: ['stack-id', 'stackId'],
@@ -1,5 +1,5 @@
1
1
  import { Flags } from '@oclif/core';
2
- import { LocalBlueprintCommand } from '../../baseCommands.js';
2
+ import { LocalBlueprintCommand, organizationIdFlagConfig, projectIdFlagConfig, } from '../../baseCommands.js';
3
3
  import { blueprintDestroyCore } from '../../cores/blueprints/destroy.js';
4
4
  import { Logger } from '../../utils/logger.js';
5
5
  export default class DestroyCommand extends LocalBlueprintCommand {
@@ -20,17 +20,14 @@ Use this to clean up test environments or decommission a Stack you no longer nee
20
20
  default: false,
21
21
  }),
22
22
  'project-id': Flags.string({
23
- description: 'Project associated with the Stack',
24
- aliases: ['projectId', 'project'],
23
+ ...projectIdFlagConfig,
25
24
  dependsOn: ['stack', 'force'],
26
25
  exclusive: ['organization-id'],
27
26
  }),
28
27
  'organization-id': Flags.string({
29
- description: 'Organization associated with the Stack',
30
- aliases: ['organizationId', 'organization', 'org'],
28
+ ...organizationIdFlagConfig,
31
29
  dependsOn: ['stack', 'force'],
32
30
  exclusive: ['project-id'],
33
- hidden: true,
34
31
  }),
35
32
  stack: Flags.string({
36
33
  description: 'Stack name or ID to destroy (defaults to the locally configured Stack)',
@@ -1,5 +1,5 @@
1
1
  import { Args, Flags } from '@oclif/core';
2
- import { baseFlags, RuntimeCommand, unhide } from '../../baseCommands.js';
2
+ import { baseFlags, organizationIdFlagConfig, projectIdFlagConfig, RuntimeCommand, unhide, } from '../../baseCommands.js';
3
3
  import { blueprintInitCore } from '../../cores/blueprints/init.js';
4
4
  import { Logger } from '../../utils/logger.js';
5
5
  import { validTokenOrErrorMessage } from '../../utils/validated-token.js';
@@ -38,19 +38,11 @@ After initialization, use 'blueprints plan' to preview changes, then 'blueprints
38
38
  options: ['json', 'js', 'ts'],
39
39
  aliases: ['type'],
40
40
  }),
41
- 'project-id': Flags.string({
42
- description: 'Sanity project ID used to scope local Blueprint and remote Stack',
43
- aliases: ['project', 'projectId'],
44
- }),
45
- 'organization-id': Flags.string({
46
- description: 'Sanity organization ID used to scope local Blueprint and remote Stack',
47
- aliases: ['organization', 'organizationId', 'org'],
48
- hidden: true,
49
- }),
41
+ 'project-id': Flags.string({ ...projectIdFlagConfig }),
42
+ 'organization-id': Flags.string({ ...organizationIdFlagConfig }),
50
43
  'stack-id': Flags.string({
51
44
  description: 'Existing Stack ID used to scope local Blueprint',
52
45
  aliases: ['stackId'],
53
- dependsOn: ['project-id'],
54
46
  exclusive: ['stack-name'],
55
47
  }),
56
48
  'stack-name': Flags.string({
@@ -6,7 +6,6 @@ export default class PromoteCommand extends DeployedStackCommand<typeof PromoteC
6
6
  static examples: string[];
7
7
  static flags: {
8
8
  stack: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
9
- 'i-know-what-im-doing': import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
9
  force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
11
10
  };
12
11
  run(): Promise<Record<string, unknown> | undefined>;
@@ -15,10 +15,6 @@ export default class PromoteCommand extends DeployedStackCommand {
15
15
  description: 'Stack name or ID to promote',
16
16
  aliases: ['id'],
17
17
  }),
18
- 'i-know-what-im-doing': Flags.boolean({
19
- description: 'Must be set',
20
- default: false,
21
- }),
22
18
  force: Flags.boolean({
23
19
  description: 'Skip confirmation prompt',
24
20
  default: false,
@@ -1,5 +1,5 @@
1
1
  import { Flags } from '@oclif/core';
2
- import { LocalBlueprintCommand } from '../../baseCommands.js';
2
+ import { LocalBlueprintCommand, organizationIdFlagConfig, projectIdFlagConfig, } from '../../baseCommands.js';
3
3
  import { blueprintStacksCore } from '../../cores/blueprints/stacks.js';
4
4
  import { Logger } from '../../utils/logger.js';
5
5
  export default class StacksCommand extends LocalBlueprintCommand {
@@ -13,17 +13,8 @@ Use this to discover existing Stacks you can scope a local Blueprint to (using '
13
13
  '<%= config.bin %> <%= command.id %> --organization-id <organizationId>',
14
14
  ];
15
15
  static flags = {
16
- 'project-id': Flags.string({
17
- description: 'Project ID to show Stack deployments for',
18
- aliases: ['projectId', 'project'],
19
- exclusive: ['organization-id'],
20
- }),
21
- 'organization-id': Flags.string({
22
- description: 'Organization ID to show Stack deployments for',
23
- aliases: ['organizationId', 'organization', 'org'],
24
- exclusive: ['project-id'],
25
- hidden: true,
26
- }),
16
+ 'project-id': Flags.string({ ...projectIdFlagConfig, exclusive: ['organization-id'] }),
17
+ 'organization-id': Flags.string({ ...organizationIdFlagConfig, exclusive: ['project-id'] }),
27
18
  };
28
19
  async run() {
29
20
  const { success, error, json } = await blueprintStacksCore({
@@ -1,5 +1,5 @@
1
1
  import { Args, Flags } from '@oclif/core';
2
- import { LocalBlueprintCommand } from '../../baseCommands.js';
2
+ import { LocalBlueprintCommand, organizationIdFlagConfig, projectIdFlagConfig, } from '../../baseCommands.js';
3
3
  import { functionTestCore } from '../../cores/functions/test.js';
4
4
  import { Logger } from '../../utils/logger.js';
5
5
  export default class TestCommand extends LocalBlueprintCommand {
@@ -101,17 +101,8 @@ Provide test data via --data (inline JSON), --file (JSON file), or --document-id
101
101
  description: 'The Sanity dataset to use',
102
102
  required: false,
103
103
  }),
104
- 'project-id': Flags.string({
105
- description: 'Sanity Project ID to use',
106
- aliases: ['project', 'projectId'],
107
- required: false,
108
- }),
109
- 'organization-id': Flags.string({
110
- description: 'Sanity Organization ID to use',
111
- aliases: ['organization', 'organizationId', 'org'],
112
- required: false,
113
- hidden: true,
114
- }),
104
+ 'project-id': Flags.string({ ...projectIdFlagConfig }),
105
+ 'organization-id': Flags.string({ ...organizationIdFlagConfig }),
115
106
  'document-id': Flags.string({
116
107
  description: 'Document to fetch and send to function',
117
108
  aliases: ['doc', 'documentId'],
@@ -16,7 +16,8 @@ export declare const EVENT_MEDIA_LIBRARY_ASSET_CREATE = "media-library-asset-cre
16
16
  export declare const EVENT_MEDIA_LIBRARY_ASSET_UPDATE = "media-library-asset-update";
17
17
  export declare const EVENT_MEDIA_LIBRARY_ASSET_DELETE = "media-library-asset-delete";
18
18
  export declare const EVENT_SCHEDULED = "scheduled-function";
19
- export declare const FUNCTION_TYPES: string[];
19
+ export declare const FUNCTION_TYPES: readonly ["document-publish", "document-create", "document-update", "document-delete", "media-library-asset-create", "media-library-asset-update", "media-library-asset-delete", "scheduled-function"];
20
+ export type ARRAY_OF_FUNCTION_TYPES = (typeof FUNCTION_TYPES)[number][];
20
21
  export declare const PROJECT_SCOPED_FUNCTION_TYPES: ReadonlySet<string>;
21
22
  export declare const ORGANIZATION_SCOPED_FUNCTION_TYPES: ReadonlySet<string>;
22
23
  export declare const MAX_ASSET_SIZE = 209715200;
@@ -36,8 +36,12 @@ export async function blueprintConfigCore(options) {
36
36
  if (flagProjectId)
37
37
  configUpdate.projectId = flagProjectId;
38
38
  if (flagStack) {
39
- const scopeType = flagProjectId ? 'project' : configScopeType;
40
- const scopeId = flagProjectId || configScopeId;
39
+ const scopeType = flagProjectId
40
+ ? 'project'
41
+ : flagOrganizationId
42
+ ? 'organization'
43
+ : configScopeType;
44
+ const scopeId = flagProjectId || flagOrganizationId || configScopeId;
41
45
  if (scopeType && scopeId) {
42
46
  configUpdate.stackId = await resolveStackIdByNameOrId(flagStack, { token, scopeType, scopeId }, log);
43
47
  }
@@ -152,9 +152,9 @@ async function preDeploy(resource, options) {
152
152
  clearTimeout(assetTimeoutTimer);
153
153
  }
154
154
  if (result.success && result.assetId) {
155
- resource.src = result.assetId;
156
- fnSpinner.succeed(`${resource.name} ${niceId(result.assetId)}`);
157
- log(` Source: ${resource.src}`);
155
+ const resourceWithAsset = { ...resource, src: result.assetId };
156
+ fnSpinner.succeed(`${resourceWithAsset.name} ${niceId(result.assetId)}`);
157
+ log(` Source: ${resourceWithAsset.src}`);
158
158
  if (result.hash) {
159
159
  if (result.hash.length > 24) {
160
160
  log.verbose(` Hash: ${result.hash.slice(0, 8)}...${result.hash.slice(-12)}`);
@@ -1,7 +1,6 @@
1
1
  import type { CoreResult, DeployedBlueprintConfig } from '../index.js';
2
2
  export interface BlueprintPromoteOptions extends DeployedBlueprintConfig {
3
3
  flags: {
4
- 'i-know-what-im-doing': boolean;
5
4
  force?: boolean;
6
5
  verbose?: boolean;
7
6
  };
@@ -4,9 +4,6 @@ import { promoteStack } from '../../actions/blueprints/stacks.js';
4
4
  import { niceId } from '../../utils/display/presenters.js';
5
5
  export async function blueprintPromoteCore(options) {
6
6
  const { log, stackId, auth, flags, deployedStack, blueprint } = options;
7
- if (!flags['i-know-what-im-doing']) {
8
- return { success: false, error: 'Seems you do not know what you are doing.' };
9
- }
10
7
  let message = `"${deployedStack.name}" ${niceId(deployedStack.id)}`;
11
8
  if (deployedStack.scopeType === 'organization') {
12
9
  message = `Stack ${message} is already org-scoped. Promote again?`;
@@ -13,4 +13,5 @@ export interface FunctionAddOptions extends CoreConfig {
13
13
  install?: boolean;
14
14
  };
15
15
  }
16
+ export declare const generateFunctionBlueprintResourceTemplate: (fnName: string, eventNames: string[]) => string;
16
17
  export declare function functionAddCore(options: FunctionAddOptions): Promise<CoreResult>;
@@ -11,7 +11,7 @@ FUNCTION_TYPES, LABEL_DOCUMENT_CREATE, LABEL_DOCUMENT_DELETE, LABEL_DOCUMENT_UPD
11
11
  import { check, indent, warn } from '../../utils/display/presenters.js';
12
12
  import { styleText } from '../../utils/style-text.js';
13
13
  import { validateFunctionName } from '../../utils/validate/resource.js';
14
- const generateFunctionBlueprintResourceTemplate = (fnName, eventNames) => {
14
+ export const generateFunctionBlueprintResourceTemplate = (fnName, eventNames) => {
15
15
  const functionType = eventNames[0].substring(0, eventNames[0].lastIndexOf('-'));
16
16
  let definer = '';
17
17
  const eventOns = eventNames.map((e) => `'${e.substring(e.lastIndexOf('-') + 1)}'`);
@@ -19,7 +19,7 @@ const generateFunctionBlueprintResourceTemplate = (fnName, eventNames) => {
19
19
  case 'document':
20
20
  definer = `defineDocumentFunction({name: '${fnName}', event: {on: [${eventOns.join(', ')}]}}), // ← add this line`;
21
21
  break;
22
- case 'media':
22
+ case 'media-library-asset':
23
23
  definer = `defineMediaLibraryAssetFunction({name: '${fnName}', event: {on: [${eventOns.join(', ')}], resource: {type: 'media-library', id: 'my-media-library-id'}}}), // ← add this line`;
24
24
  break;
25
25
  case 'scheduled':
@@ -1,9 +1,10 @@
1
- import type { Blueprint, Resource } from '@sanity/blueprints-parser';
1
+ import type { BlueprintResource } from '@sanity/blueprints';
2
+ import type { Blueprint } from '@sanity/blueprints-parser';
2
3
  import type { DeploymentPlan } from '../../actions/blueprints/stacks.js';
3
4
  import { type BlueprintResourceRecord, type Stack, type StackSummary } from '../types.js';
4
5
  export declare function formatTitle(title: string, name: string): string;
5
6
  export declare function formatDeployedResourceTree(resources: BlueprintResourceRecord[] | undefined, verbose?: boolean): string;
6
- export declare function formatResourceTree(resources: Resource[] | undefined, verbose?: boolean): string;
7
+ export declare function formatResourceTree(resources: BlueprintResource[] | undefined, verbose?: boolean): string;
7
8
  export declare function formatStackInfo(stack: Stack | StackSummary | Blueprint, isCurrentStack?: boolean): string;
8
9
  export declare function formatStacksListing(stacks: StackSummary[], currentStackId?: string): string;
9
10
  export declare function hasActionableChanges(deploymentPlan: DeploymentPlan): boolean;
@@ -62,10 +62,11 @@ const categoryByLabel = Object.values(RESOURCE_CATEGORIES).reduce((acc, curr) =>
62
62
  }, {});
63
63
  function resourceName(res, displayNameAttribute) {
64
64
  const nameParts = [styleText(['bold', 'green'], res.name)];
65
+ const resAsAny = res;
65
66
  const displayName = displayNameAttribute &&
66
67
  displayNameAttribute in res &&
67
- typeof res[displayNameAttribute] === 'string' &&
68
- res[displayNameAttribute];
68
+ typeof resAsAny[displayNameAttribute] === 'string' &&
69
+ resAsAny[displayNameAttribute];
69
70
  if (displayName && displayName !== res.name)
70
71
  nameParts.push(styleText('green', `"${displayName}"`));
71
72
  return nameParts.join(' ');
@@ -1,7 +1,6 @@
1
- import type { BlueprintCorsOriginResource, BlueprintDatasetResource, BlueprintDocumentWebhookResource, BlueprintRobotResource, BlueprintRoleResource } from '@sanity/blueprints';
1
+ import type { BlueprintCorsOriginResource, BlueprintDatasetResource, BlueprintDocumentWebhookResource, BlueprintResource, BlueprintRobotResource, BlueprintRoleResource } from '@sanity/blueprints';
2
2
  import type { TreeInput } from 'array-treeify';
3
- import { type FunctionResourceBase } from '../../utils/types.js';
4
- export declare function arrayifyFunction(fn: FunctionResourceBase): TreeInput;
3
+ export declare function arrayifyFunction(fn: BlueprintResource): TreeInput;
5
4
  export declare function arrayifyCors(resource: BlueprintCorsOriginResource): TreeInput;
6
5
  export declare function arrayifyRobot(resource: BlueprintRobotResource): TreeInput;
7
6
  export declare function arrayifyRole(resource: BlueprintRoleResource): TreeInput;
@@ -1,4 +1,4 @@
1
- import { isScheduleEvent, } from '../../utils/types.js';
1
+ import { isScheduleEvent } from '../../utils/types.js';
2
2
  import { styleText } from '../style-text.js';
3
3
  function formatLabel(label) {
4
4
  return styleText('dim', `${label}:`);
@@ -33,11 +33,11 @@ function arrayifyEvent(event) {
33
33
  }
34
34
  export function arrayifyFunction(fn) {
35
35
  const details = [formatLabeledValue('type', fn.type)];
36
- if (fn.memory)
36
+ if ('memory' in fn && fn.memory)
37
37
  details.push(formatLabeledValue('memory', fn.memory));
38
- if (fn.timeout)
38
+ if ('timeout' in fn && fn.timeout)
39
39
  details.push(formatLabeledValue('timeout', fn.timeout));
40
- if (fn.event) {
40
+ if ('event' in fn && fn.event) {
41
41
  const eventDetails = arrayifyEvent(fn.event);
42
42
  if (eventDetails) {
43
43
  details.push(formatLabel('event'));
@@ -1,8 +1,8 @@
1
- import type { Blueprint } from '@sanity/blueprints-parser';
2
- import type { DeployedResource, FunctionResource, Stack } from './types.js';
1
+ import type { Blueprint } from '@sanity/blueprints';
2
+ import { type DeployedResource, type FunctionResource, type Stack } from './types.js';
3
3
  export declare function getFunctionNames(resources: Array<{
4
4
  type?: string;
5
5
  name?: string;
6
6
  }> | undefined): string[];
7
- export declare function findFunctionInBlueprint(blueprint: Blueprint, name: string): FunctionResource;
7
+ export declare function findFunctionInBlueprint(blueprint: Pick<Blueprint, 'resources'>, name: string): FunctionResource;
8
8
  export declare function findFunctionInStack(stack: Stack, name: string): DeployedResource;
@@ -1,4 +1,5 @@
1
1
  import { SANITY_FUNCTION_PREFIX } from '../constants.js';
2
+ import { isLocalFunctionResource, } from './types.js';
2
3
  export function getFunctionNames(resources) {
3
4
  return (resources
4
5
  ?.filter((r) => r?.type?.startsWith(SANITY_FUNCTION_PREFIX))
@@ -6,13 +7,13 @@ export function getFunctionNames(resources) {
6
7
  .filter((name) => typeof name === 'string') ?? []);
7
8
  }
8
9
  export function findFunctionInBlueprint(blueprint, name) {
9
- const func = blueprint?.resources?.find((r) => r?.type?.startsWith(SANITY_FUNCTION_PREFIX) && r.name === name);
10
+ const func = blueprint?.resources?.filter(isLocalFunctionResource).find((r) => r.name === name);
10
11
  if (!func)
11
12
  throw Error(`Unable to find function ${name}`);
12
13
  return func;
13
14
  }
14
15
  export function findFunctionInStack(stack, name) {
15
- const func = stack?.resources?.find((r) => r?.type?.startsWith(SANITY_FUNCTION_PREFIX) && r.name === name);
16
+ const func = stack?.resources?.filter(isLocalFunctionResource).find((r) => r.name === name);
16
17
  if (!func)
17
18
  throw Error(`Unable to find function: "${name}"`);
18
19
  if (!isDeployedResource(func))
@@ -1,6 +1,6 @@
1
- import type { AssetPrepResult, CollectionFunction, FunctionResource, InstallerType } from '../types.js';
1
+ import type { AssetPrepResult, FunctionResource, InstallerType } from '../types.js';
2
2
  export declare function prepareAsset({ resource, }: {
3
- resource: FunctionResource | CollectionFunction;
3
+ resource: FunctionResource;
4
4
  }, { installer }?: {
5
5
  installer?: InstallerType;
6
6
  }): Promise<AssetPrepResult>;
@@ -1,5 +1,5 @@
1
1
  export async function shouldAutoResolveDependencies(resource) {
2
- if (typeof resource.autoResolveDeps === 'boolean') {
2
+ if ('autoResolveDeps' in resource && typeof resource.autoResolveDeps === 'boolean') {
3
3
  return resource.autoResolveDeps;
4
4
  }
5
5
  // otherwise hydrate is the default
@@ -1,6 +1,6 @@
1
1
  import { findFunctionEntryPoint } from './find-entry-point.js';
2
2
  export async function shouldTranspileFunction(resource) {
3
- if (typeof resource.transpile === 'boolean') {
3
+ if ('transpile' in resource && typeof resource.transpile === 'boolean') {
4
4
  return resource.transpile;
5
5
  }
6
6
  if (!resource.src) {
@@ -1,10 +1,4 @@
1
- import { type FunctionGroqResource, type FunctionResource, type GroqRuleBase, type InvocationResponse, type InvokeContextOptions, type InvokeExecutionOptions, type InvokeGroqPayloadOptions, type InvokePayloadOptions } from './types.js';
1
+ import { type FunctionGroqResource, type FunctionResource, type InvocationResponse, type InvokeContextOptions, type InvokeExecutionOptions, type InvokeGroqPayloadOptions, type InvokePayloadOptions } from './types.js';
2
2
  export declare function sanitizeLogs(logs: string): string;
3
- export declare const DEFAULT_GROQ_RULE: {
4
- on: string[];
5
- filter: string;
6
- projection: string;
7
- };
8
- export declare function isDefaultGROQRule(rule: GroqRuleBase | undefined): boolean;
9
3
  export declare function applyGroqRule(resource: FunctionGroqResource, payload: InvokeGroqPayloadOptions, projectId: string | undefined, dataset: string | undefined): Promise<any>;
10
4
  export default function invoke(resource: FunctionResource, payload: InvokePayloadOptions, context: InvokeContextOptions, options: InvokeExecutionOptions): Promise<InvocationResponse>;
@@ -11,30 +11,13 @@ import { resolveResourceDependencies } from './functions/resolve-dependencies.js
11
11
  import { shouldAutoResolveDependencies } from './functions/should-auto-resolve-deps.js';
12
12
  import { shouldTranspileFunction } from './functions/should-transpile.js';
13
13
  import { transpileFunction } from './transpile/transpile-function.js';
14
- import { isDocumentFunctionResource, isGroqContextOptions, isMediaLibraryAssetFunctionResource, } from './types.js';
14
+ import { isGroqContextOptions, } from './types.js';
15
15
  function getChildProcessWrapperPath() {
16
16
  return fileURLToPath(new URL('./child-process-wrapper.js', import.meta.url));
17
17
  }
18
18
  export function sanitizeLogs(logs) {
19
19
  return logs.replace(/([a-zA-Z0-9]{10})[a-zA-Z0-9]{65,}/g, '$1**********');
20
20
  }
21
- export const DEFAULT_GROQ_RULE = { on: ['publish'], filter: '', projection: '' };
22
- export function isDefaultGROQRule(rule) {
23
- if (!rule)
24
- return true;
25
- return (Array.isArray(rule.on) &&
26
- rule.on.length === DEFAULT_GROQ_RULE.on.length &&
27
- rule.on.every((v) => DEFAULT_GROQ_RULE.on.includes(v)) &&
28
- rule.filter === DEFAULT_GROQ_RULE.filter &&
29
- rule.projection === DEFAULT_GROQ_RULE.projection);
30
- }
31
- function getEvent(rule) {
32
- return {
33
- on: rule.on || DEFAULT_GROQ_RULE.on,
34
- filter: rule.filter || DEFAULT_GROQ_RULE.filter,
35
- projection: rule.projection || DEFAULT_GROQ_RULE.projection,
36
- };
37
- }
38
21
  export async function applyGroqRule(resource, payload, projectId, dataset) {
39
22
  const { before, after, payload: data = null } = payload;
40
23
  // If there is no rule set return everything
@@ -42,11 +25,8 @@ export async function applyGroqRule(resource, payload, projectId, dataset) {
42
25
  return data;
43
26
  // default groq rule is: gimme full doc content. otherwise, parse + eval custom rule
44
27
  // applying the GROQ filter may result in a slimmer set of documents
45
- const event = getEvent(resource.event);
46
- if (!isDefaultGROQRule(event)) {
47
- const hasProjection = event.projection?.length;
48
- const projection = hasProjection ? `${event?.projection}` : '';
49
- const query = `*[${event?.filter}]${projection}`;
28
+ if (resource.event.filter || resource.event.projection) {
29
+ const query = `*[${resource.event.filter || ''}]${resource.event.projection || ''}`;
50
30
  try {
51
31
  const rule = groq.parse(query, { mode: 'delta' });
52
32
  const sanity = projectId && dataset ? { projectId, dataset } : undefined;
@@ -91,7 +71,8 @@ export default async function invoke(resource, payload, context, options) {
91
71
  }
92
72
  const { forceColor = true, timeout = 10 } = options;
93
73
  let filteredData = {};
94
- if (isDocumentFunctionResource(resource) || isMediaLibraryAssetFunctionResource(resource)) {
74
+ if (resource.type === 'sanity.function.document' ||
75
+ resource.type === 'sanity.function.media-library.asset') {
95
76
  if (!isGroqContextOptions(context)) {
96
77
  throw new Error('GROQ-based functions require a context with clientOptions');
97
78
  }
@@ -1,6 +1,5 @@
1
- import { type BlueprintCorsOriginResource, type BlueprintDatasetResource, type BlueprintDocumentWebhookResource, type BlueprintProjectResource, type BlueprintResource, type BlueprintRobotResource, type BlueprintRoleResource } from '@sanity/blueprints';
1
+ import { type BlueprintCorsOriginResource, type BlueprintDatasetResource, type BlueprintDocumentFunctionResource, type BlueprintDocumentWebhookResource, type BlueprintMediaLibraryAssetFunctionResource, type BlueprintProjectResource, type BlueprintResource, type BlueprintRobotResource, type BlueprintRoleResource, type BlueprintScheduledFunctionResource } from '@sanity/blueprints';
2
2
  import type { Blueprint } from '@sanity/blueprints-parser';
3
- import { SANITY_FUNCTION_DOCUMENT, SANITY_FUNCTION_MEDIA_LIBRARY_ASSET, SANITY_FUNCTION_SCHEDULED } from '../constants.js';
4
3
  export type ScopeType = 'organization' | 'project';
5
4
  /** Result utility type */
6
5
  export type Result<T, E = string> = {
@@ -16,43 +15,15 @@ export interface ActionResponse {
16
15
  error: string | null;
17
16
  }
18
17
  /** @internal */
18
+ export type FunctionGroqResource = BlueprintDocumentFunctionResource | BlueprintMediaLibraryAssetFunctionResource;
19
+ export type FunctionResource = FunctionGroqResource | BlueprintScheduledFunctionResource;
20
+ /** @internal */
19
21
  export interface AuthParams {
20
22
  token: string;
21
23
  scopeType: ScopeType;
22
24
  scopeId: string;
23
25
  }
24
26
  /** @internal */
25
- export type GroqRule = GroqRuleDocumentFunction | GroqRuleMediaLibraryFunction;
26
- export interface GroqRuleBase {
27
- on: Array<string>;
28
- filter?: string;
29
- projection?: string;
30
- }
31
- interface GroqRuleDocumentFunction extends GroqRuleBase {
32
- includeDrafts?: boolean;
33
- includeAllVersions?: boolean;
34
- resource?: {
35
- type: 'dataset';
36
- id: string;
37
- };
38
- }
39
- interface GroqRuleMediaLibraryFunction extends GroqRuleBase {
40
- resource: {
41
- type: 'media-library';
42
- id: string;
43
- };
44
- }
45
- export interface FunctionResourceScheduleExplicitEvent {
46
- minute: string;
47
- hour: string;
48
- dayOfMonth: string;
49
- month: string;
50
- dayOfWeek: string;
51
- }
52
- interface FunctionResourceScheduleExpressionEvent {
53
- expression: string;
54
- }
55
- type FunctionResourceScheduleEvent = FunctionResourceScheduleExplicitEvent | FunctionResourceScheduleExpressionEvent;
56
27
  /** The Blueprint resource as represented in the Blueprints API database */
57
28
  export interface BlueprintResourceRecord extends BlueprintResource {
58
29
  id: string;
@@ -63,11 +34,8 @@ export interface BlueprintResourceRecord extends BlueprintResource {
63
34
  export interface DeployedResource extends BlueprintResourceRecord {
64
35
  externalId: string;
65
36
  }
66
- export declare function isLocalFunctionResource(r: BlueprintResource): boolean;
67
- export declare function isDocumentFunctionResource<T extends BlueprintResource>(r: T): r is T & FunctionResourceDocument;
68
- export declare function isMediaLibraryAssetFunctionResource<T extends BlueprintResource>(r: T): r is T & FunctionResourceMediaLibraryAsset;
69
- export declare function isScheduleFunctionResource<T extends BlueprintResource>(r: T): r is T & FunctionResourceSchedule;
70
- export declare function isScheduleEvent(e: unknown): e is FunctionResourceScheduleEvent;
37
+ export declare function isLocalFunctionResource(r: BlueprintResource): r is FunctionResource;
38
+ export declare function isScheduleEvent(e: unknown): e is BlueprintScheduledFunctionResource['event'];
71
39
  export declare function isCorsOriginResource(r: unknown): r is BlueprintCorsOriginResource;
72
40
  export declare function isProjectResource(r: unknown): r is BlueprintProjectResource;
73
41
  export declare function isRobotResource(r: unknown): r is BlueprintRobotResource;
@@ -76,47 +44,6 @@ export declare function isDatasetResource(r: unknown): r is BlueprintDatasetReso
76
44
  export declare function isStudioResource(r: unknown): boolean;
77
45
  export declare function isWebhookResource(r: unknown): r is BlueprintDocumentWebhookResource;
78
46
  /** @internal */
79
- export type FunctionResource = FunctionResourceDocument | FunctionResourceMediaLibraryAsset | FunctionResourceSchedule | FunctionResourceBase;
80
- export type FunctionGroqResource = FunctionResourceDocument | FunctionResourceMediaLibraryAsset;
81
- export interface FunctionResourceBase extends BlueprintResource {
82
- displayName?: string;
83
- src?: string;
84
- autoResolveDeps?: boolean;
85
- transpile?: boolean;
86
- memory?: number;
87
- timeout?: number;
88
- env?: Record<string, string>;
89
- event?: GroqRuleBase | FunctionResourceScheduleEvent;
90
- }
91
- interface FunctionResourceDocument extends FunctionResourceBase {
92
- type: typeof SANITY_FUNCTION_DOCUMENT;
93
- event?: GroqRuleDocumentFunction;
94
- }
95
- interface FunctionResourceMediaLibraryAsset extends FunctionResourceBase {
96
- type: typeof SANITY_FUNCTION_MEDIA_LIBRARY_ASSET;
97
- event: GroqRuleMediaLibraryFunction;
98
- }
99
- interface FunctionResourceSchedule extends FunctionResourceBase {
100
- type: typeof SANITY_FUNCTION_SCHEDULED;
101
- event: FunctionResourceScheduleEvent;
102
- }
103
- export interface CollectionFunction {
104
- type: typeof SANITY_FUNCTION_DOCUMENT | typeof SANITY_FUNCTION_SCHEDULED | typeof SANITY_FUNCTION_MEDIA_LIBRARY_ASSET;
105
- src: string;
106
- name: string;
107
- displayName?: string;
108
- event?: GroqRuleBase | FunctionResourceScheduleEvent;
109
- memory?: number;
110
- timeout?: number;
111
- env?: Record<string, string>;
112
- }
113
- /** @internal */
114
- export interface FunctionsCollection extends BlueprintResource {
115
- type: 'sanity.experimental.functions-collection';
116
- name: string;
117
- src?: string;
118
- functions: Array<FunctionResourceBase>;
119
- }
120
47
  export interface CorsResource extends BlueprintResource {
121
48
  origin?: string;
122
49
  }
@@ -1,18 +1,9 @@
1
1
  import { validateCorsOrigin, validateDataset, validateDocumentWebhook, validateProject, validateRobot, validateRole, } from '@sanity/blueprints';
2
- import { SANITY_FUNCTION_DOCUMENT, SANITY_FUNCTION_MEDIA_LIBRARY_ASSET, SANITY_FUNCTION_PREFIX, SANITY_FUNCTION_SCHEDULED, } from '../constants.js';
2
+ import { SANITY_FUNCTION_PREFIX } from '../constants.js';
3
3
  export function isLocalFunctionResource(r) {
4
4
  return r.type.startsWith(SANITY_FUNCTION_PREFIX);
5
5
  }
6
6
  // type narrowing with predicate functions
7
- export function isDocumentFunctionResource(r) {
8
- return r.type === SANITY_FUNCTION_DOCUMENT;
9
- }
10
- export function isMediaLibraryAssetFunctionResource(r) {
11
- return r.type === SANITY_FUNCTION_MEDIA_LIBRARY_ASSET;
12
- }
13
- export function isScheduleFunctionResource(r) {
14
- return r.type === SANITY_FUNCTION_SCHEDULED;
15
- }
16
7
  export function isScheduleEvent(e) {
17
8
  return e !== null && typeof e === 'object' && ('hour' in e || 'expression' in e);
18
9
  }
@@ -1,4 +1,4 @@
1
- import type { Resource } from '@sanity/blueprints-parser';
1
+ import { type BlueprintResource } from '@sanity/blueprints';
2
2
  import type { BlueprintParserError } from '../types.js';
3
3
  export * as validate from './resource.js';
4
- export declare function validateResources(resources: Resource[]): BlueprintParserError[];
4
+ export declare function validateResources(resources: BlueprintResource[]): BlueprintParserError[];
@@ -258,7 +258,7 @@
258
258
  "dependsOn": [
259
259
  "edit"
260
260
  ],
261
- "description": "Directly set the project ID in the configuration. Requires --edit flag",
261
+ "description": "Sanity project ID used to scope Blueprint and Stack",
262
262
  "name": "project-id",
263
263
  "hasDynamicHelp": false,
264
264
  "multiple": false,
@@ -273,8 +273,7 @@
273
273
  "dependsOn": [
274
274
  "edit"
275
275
  ],
276
- "description": "Directly set the organization ID in the configuration. Requires --edit flag",
277
- "hidden": true,
276
+ "description": "Sanity organization ID used to scope Blueprint and Stack",
278
277
  "name": "organization-id",
279
278
  "hasDynamicHelp": false,
280
279
  "multiple": false,
@@ -477,14 +476,14 @@
477
476
  },
478
477
  "project-id": {
479
478
  "aliases": [
480
- "projectId",
481
- "project"
479
+ "project",
480
+ "projectId"
482
481
  ],
483
482
  "dependsOn": [
484
483
  "stack",
485
484
  "force"
486
485
  ],
487
- "description": "Project associated with the Stack",
486
+ "description": "Sanity project ID used to scope Blueprint and Stack",
488
487
  "exclusive": [
489
488
  "organization-id"
490
489
  ],
@@ -495,19 +494,18 @@
495
494
  },
496
495
  "organization-id": {
497
496
  "aliases": [
498
- "organizationId",
499
497
  "organization",
498
+ "organizationId",
500
499
  "org"
501
500
  ],
502
501
  "dependsOn": [
503
502
  "stack",
504
503
  "force"
505
504
  ],
506
- "description": "Organization associated with the Stack",
505
+ "description": "Sanity organization ID used to scope Blueprint and Stack",
507
506
  "exclusive": [
508
507
  "project-id"
509
508
  ],
510
- "hidden": true,
511
509
  "name": "organization-id",
512
510
  "hasDynamicHelp": false,
513
511
  "multiple": false,
@@ -791,7 +789,7 @@
791
789
  "project",
792
790
  "projectId"
793
791
  ],
794
- "description": "Sanity project ID used to scope local Blueprint and remote Stack",
792
+ "description": "Sanity project ID used to scope Blueprint and Stack",
795
793
  "name": "project-id",
796
794
  "hasDynamicHelp": false,
797
795
  "multiple": false,
@@ -803,8 +801,7 @@
803
801
  "organizationId",
804
802
  "org"
805
803
  ],
806
- "description": "Sanity organization ID used to scope local Blueprint and remote Stack",
807
- "hidden": true,
804
+ "description": "Sanity organization ID used to scope Blueprint and Stack",
808
805
  "name": "organization-id",
809
806
  "hasDynamicHelp": false,
810
807
  "multiple": false,
@@ -814,9 +811,6 @@
814
811
  "aliases": [
815
812
  "stackId"
816
813
  ],
817
- "dependsOn": [
818
- "project-id"
819
- ],
820
814
  "description": "Existing Stack ID used to scope local Blueprint",
821
815
  "exclusive": [
822
816
  "stack-name"
@@ -1072,12 +1066,6 @@
1072
1066
  "multiple": false,
1073
1067
  "type": "option"
1074
1068
  },
1075
- "i-know-what-im-doing": {
1076
- "description": "Must be set",
1077
- "name": "i-know-what-im-doing",
1078
- "allowNo": false,
1079
- "type": "boolean"
1080
- },
1081
1069
  "force": {
1082
1070
  "description": "Skip confirmation prompt",
1083
1071
  "name": "force",
@@ -1154,10 +1142,10 @@
1154
1142
  },
1155
1143
  "project-id": {
1156
1144
  "aliases": [
1157
- "projectId",
1158
- "project"
1145
+ "project",
1146
+ "projectId"
1159
1147
  ],
1160
- "description": "Project ID to show Stack deployments for",
1148
+ "description": "Sanity project ID used to scope Blueprint and Stack",
1161
1149
  "exclusive": [
1162
1150
  "organization-id"
1163
1151
  ],
@@ -1168,15 +1156,14 @@
1168
1156
  },
1169
1157
  "organization-id": {
1170
1158
  "aliases": [
1171
- "organizationId",
1172
1159
  "organization",
1160
+ "organizationId",
1173
1161
  "org"
1174
1162
  ],
1175
- "description": "Organization ID to show Stack deployments for",
1163
+ "description": "Sanity organization ID used to scope Blueprint and Stack",
1176
1164
  "exclusive": [
1177
1165
  "project-id"
1178
1166
  ],
1179
- "hidden": true,
1180
1167
  "name": "organization-id",
1181
1168
  "hasDynamicHelp": false,
1182
1169
  "multiple": false,
@@ -1885,9 +1872,8 @@
1885
1872
  "project",
1886
1873
  "projectId"
1887
1874
  ],
1888
- "description": "Sanity Project ID to use",
1875
+ "description": "Sanity project ID used to scope Blueprint and Stack",
1889
1876
  "name": "project-id",
1890
- "required": false,
1891
1877
  "hasDynamicHelp": false,
1892
1878
  "multiple": false,
1893
1879
  "type": "option"
@@ -1898,10 +1884,8 @@
1898
1884
  "organizationId",
1899
1885
  "org"
1900
1886
  ],
1901
- "description": "Sanity Organization ID to use",
1902
- "hidden": true,
1887
+ "description": "Sanity organization ID used to scope Blueprint and Stack",
1903
1888
  "name": "organization-id",
1904
- "required": false,
1905
1889
  "hasDynamicHelp": false,
1906
1890
  "multiple": false,
1907
1891
  "type": "option"
@@ -2251,5 +2235,5 @@
2251
2235
  ]
2252
2236
  }
2253
2237
  },
2254
- "version": "14.8.0"
2238
+ "version": "14.8.2"
2255
2239
  }
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": "14.8.0",
4
+ "version": "14.8.2",
5
5
  "author": "Sanity Runtime Team",
6
6
  "type": "module",
7
7
  "license": "MIT",