@sanity/runtime-cli 11.0.4 → 11.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -26
- package/dist/actions/blueprints/blueprint.d.ts +3 -3
- package/dist/actions/blueprints/resources.d.ts +2 -2
- package/dist/actions/blueprints/resources.js +3 -4
- package/dist/commands/blueprints/add.js +9 -1
- package/dist/commands/functions/add.js +9 -1
- package/dist/commands/functions/test.d.ts +1 -0
- package/dist/commands/functions/test.js +6 -0
- package/dist/cores/functions/add.js +31 -9
- package/dist/cores/functions/test.d.ts +1 -0
- package/dist/cores/functions/test.js +37 -7
- package/dist/server/app.js +99 -3
- package/dist/server/static/api.js +48 -2
- package/dist/server/static/components/app.css +16 -1
- package/dist/server/static/components/fetch-button.js +14 -5
- package/dist/server/static/components/filter-api-version.js +14 -0
- package/dist/server/static/components/filter-document-id.js +26 -0
- package/dist/server/static/components/filter-with-token.js +21 -0
- package/dist/server/static/components/filters.js +47 -42
- package/dist/server/static/components/function-list.js +15 -5
- package/dist/server/static/components/run-panel.js +11 -2
- package/dist/server/static/index.html +3 -0
- package/dist/utils/display/blueprints-formatting.d.ts +1 -1
- package/dist/utils/display/blueprints-formatting.js +4 -3
- package/dist/utils/display/resources-formatting.d.ts +2 -2
- package/dist/utils/functions/fetch-document.d.ts +2 -0
- package/dist/utils/functions/fetch-document.js +15 -0
- package/dist/utils/invoke-local.d.ts +2 -2
- package/dist/utils/invoke-local.js +11 -5
- package/dist/utils/types.d.ts +41 -5
- package/dist/utils/types.js +8 -0
- package/dist/utils/validate/resource.js +55 -30
- package/oclif.manifest.json +24 -3
- package/package.json +2 -2
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.0
|
|
23
|
+
@sanity/runtime-cli/11.1.0 linux-x64 node-v24.11.0
|
|
24
24
|
$ sanity-run --help [COMMAND]
|
|
25
25
|
USAGE
|
|
26
26
|
$ sanity-run COMMAND
|
|
@@ -55,8 +55,9 @@ Add a Resource to a Blueprint
|
|
|
55
55
|
```
|
|
56
56
|
USAGE
|
|
57
57
|
$ sanity-run blueprints add TYPE [--example <value> | -n <value> | --fn-type
|
|
58
|
-
document-create|document-delete|document-update|document-publish
|
|
59
|
-
| --
|
|
58
|
+
document-create|document-delete|document-update|document-publish|media-library-asset-create|media-library-asset-upda
|
|
59
|
+
te|media-library-asset-delete... | --language ts|js | --javascript | --fn-helpers | --fn-installer
|
|
60
|
+
skip|npm|pnpm|yarn] [-i | ]
|
|
60
61
|
|
|
61
62
|
ARGUMENTS
|
|
62
63
|
TYPE (function) Type of Resource to add (e.g. function)
|
|
@@ -70,7 +71,8 @@ FLAGS
|
|
|
70
71
|
<options: skip|npm|pnpm|yarn>
|
|
71
72
|
--fn-type=<option>... Document change event(s) that should trigger the function; you can specify multiple
|
|
72
73
|
events by specifying this flag multiple times
|
|
73
|
-
<options: document-create|document-delete|document-update|document-publish
|
|
74
|
+
<options: document-create|document-delete|document-update|document-publish|media-library-
|
|
75
|
+
asset-create|media-library-asset-update|media-library-asset-delete>
|
|
74
76
|
--javascript Use JavaScript instead of TypeScript
|
|
75
77
|
--language=<option> [default: ts] Language of the new Function
|
|
76
78
|
<options: ts|js>
|
|
@@ -90,7 +92,7 @@ EXAMPLES
|
|
|
90
92
|
$ sanity-run blueprints add function --name my-function --fn-type document-create --fn-type document-update --lang js
|
|
91
93
|
```
|
|
92
94
|
|
|
93
|
-
_See code: [src/commands/blueprints/add.ts](https://github.com/sanity-io/runtime-cli/blob/v11.0
|
|
95
|
+
_See code: [src/commands/blueprints/add.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.0/src/commands/blueprints/add.ts)_
|
|
94
96
|
|
|
95
97
|
## `sanity-run blueprints config`
|
|
96
98
|
|
|
@@ -122,7 +124,7 @@ EXAMPLES
|
|
|
122
124
|
$ sanity-run blueprints config --edit --project-id <projectId> --stack-id <stackId>
|
|
123
125
|
```
|
|
124
126
|
|
|
125
|
-
_See code: [src/commands/blueprints/config.ts](https://github.com/sanity-io/runtime-cli/blob/v11.0
|
|
127
|
+
_See code: [src/commands/blueprints/config.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.0/src/commands/blueprints/config.ts)_
|
|
126
128
|
|
|
127
129
|
## `sanity-run blueprints deploy`
|
|
128
130
|
|
|
@@ -144,7 +146,7 @@ EXAMPLES
|
|
|
144
146
|
$ sanity-run blueprints deploy --no-wait
|
|
145
147
|
```
|
|
146
148
|
|
|
147
|
-
_See code: [src/commands/blueprints/deploy.ts](https://github.com/sanity-io/runtime-cli/blob/v11.0
|
|
149
|
+
_See code: [src/commands/blueprints/deploy.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.0/src/commands/blueprints/deploy.ts)_
|
|
148
150
|
|
|
149
151
|
## `sanity-run blueprints destroy`
|
|
150
152
|
|
|
@@ -171,7 +173,7 @@ EXAMPLES
|
|
|
171
173
|
$ sanity-run blueprints destroy --stack-id <stackId> --project-id <projectId> --force --no-wait
|
|
172
174
|
```
|
|
173
175
|
|
|
174
|
-
_See code: [src/commands/blueprints/destroy.ts](https://github.com/sanity-io/runtime-cli/blob/v11.0
|
|
176
|
+
_See code: [src/commands/blueprints/destroy.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.0/src/commands/blueprints/destroy.ts)_
|
|
175
177
|
|
|
176
178
|
## `sanity-run blueprints doctor`
|
|
177
179
|
|
|
@@ -189,7 +191,7 @@ DESCRIPTION
|
|
|
189
191
|
Diagnose potential issues with Blueprint configuration
|
|
190
192
|
```
|
|
191
193
|
|
|
192
|
-
_See code: [src/commands/blueprints/doctor.ts](https://github.com/sanity-io/runtime-cli/blob/v11.0
|
|
194
|
+
_See code: [src/commands/blueprints/doctor.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.0/src/commands/blueprints/doctor.ts)_
|
|
193
195
|
|
|
194
196
|
## `sanity-run blueprints info`
|
|
195
197
|
|
|
@@ -211,7 +213,7 @@ EXAMPLES
|
|
|
211
213
|
$ sanity-run blueprints info --stack-id <stackId>
|
|
212
214
|
```
|
|
213
215
|
|
|
214
|
-
_See code: [src/commands/blueprints/info.ts](https://github.com/sanity-io/runtime-cli/blob/v11.0
|
|
216
|
+
_See code: [src/commands/blueprints/info.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.0/src/commands/blueprints/info.ts)_
|
|
215
217
|
|
|
216
218
|
## `sanity-run blueprints init [DIR]`
|
|
217
219
|
|
|
@@ -250,7 +252,7 @@ EXAMPLES
|
|
|
250
252
|
$ sanity-run blueprints init --blueprint-type <json|js|ts> --stack-name <stackName>
|
|
251
253
|
```
|
|
252
254
|
|
|
253
|
-
_See code: [src/commands/blueprints/init.ts](https://github.com/sanity-io/runtime-cli/blob/v11.0
|
|
255
|
+
_See code: [src/commands/blueprints/init.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.0/src/commands/blueprints/init.ts)_
|
|
254
256
|
|
|
255
257
|
## `sanity-run blueprints logs`
|
|
256
258
|
|
|
@@ -272,7 +274,7 @@ EXAMPLES
|
|
|
272
274
|
$ sanity-run blueprints logs --watch
|
|
273
275
|
```
|
|
274
276
|
|
|
275
|
-
_See code: [src/commands/blueprints/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v11.0
|
|
277
|
+
_See code: [src/commands/blueprints/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.0/src/commands/blueprints/logs.ts)_
|
|
276
278
|
|
|
277
279
|
## `sanity-run blueprints plan`
|
|
278
280
|
|
|
@@ -289,7 +291,7 @@ EXAMPLES
|
|
|
289
291
|
$ sanity-run blueprints plan
|
|
290
292
|
```
|
|
291
293
|
|
|
292
|
-
_See code: [src/commands/blueprints/plan.ts](https://github.com/sanity-io/runtime-cli/blob/v11.0
|
|
294
|
+
_See code: [src/commands/blueprints/plan.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.0/src/commands/blueprints/plan.ts)_
|
|
293
295
|
|
|
294
296
|
## `sanity-run blueprints stacks`
|
|
295
297
|
|
|
@@ -314,7 +316,7 @@ EXAMPLES
|
|
|
314
316
|
$ sanity-run blueprints stacks --organization-id <organizationId>
|
|
315
317
|
```
|
|
316
318
|
|
|
317
|
-
_See code: [src/commands/blueprints/stacks.ts](https://github.com/sanity-io/runtime-cli/blob/v11.0
|
|
319
|
+
_See code: [src/commands/blueprints/stacks.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.0/src/commands/blueprints/stacks.ts)_
|
|
318
320
|
|
|
319
321
|
## `sanity-run functions add`
|
|
320
322
|
|
|
@@ -323,8 +325,8 @@ Add a Function to your Blueprint
|
|
|
323
325
|
```
|
|
324
326
|
USAGE
|
|
325
327
|
$ sanity-run functions add [--example <value> | -n <value> | | --language ts|js | --javascript | | ] [--type
|
|
326
|
-
document-create|document-delete|document-update|document-publish
|
|
327
|
-
[-i | ]
|
|
328
|
+
document-create|document-delete|document-update|document-publish|media-library-asset-create|media-library-asset-upda
|
|
329
|
+
te|media-library-asset-delete... ] [--helpers] [--installer skip|npm|pnpm|yarn] [-i | ]
|
|
328
330
|
|
|
329
331
|
FLAGS
|
|
330
332
|
-i, --install Shortcut for --fn-installer npm
|
|
@@ -338,7 +340,8 @@ FLAGS
|
|
|
338
340
|
<options: ts|js>
|
|
339
341
|
--type=<option>... Document change event(s) that should trigger the function; you can specify multiple events
|
|
340
342
|
by specifying this flag multiple times
|
|
341
|
-
<options: document-create|document-delete|document-update|document-publish
|
|
343
|
+
<options: document-create|document-delete|document-update|document-publish|media-library-ass
|
|
344
|
+
et-create|media-library-asset-update|media-library-asset-delete>
|
|
342
345
|
|
|
343
346
|
DESCRIPTION
|
|
344
347
|
Add a Function to your Blueprint
|
|
@@ -355,7 +358,7 @@ EXAMPLES
|
|
|
355
358
|
$ sanity-run functions add --name my-function --type document-create --type document-update --lang js
|
|
356
359
|
```
|
|
357
360
|
|
|
358
|
-
_See code: [src/commands/functions/add.ts](https://github.com/sanity-io/runtime-cli/blob/v11.0
|
|
361
|
+
_See code: [src/commands/functions/add.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.0/src/commands/functions/add.ts)_
|
|
359
362
|
|
|
360
363
|
## `sanity-run functions dev`
|
|
361
364
|
|
|
@@ -377,7 +380,7 @@ EXAMPLES
|
|
|
377
380
|
$ sanity-run functions dev --port 8974
|
|
378
381
|
```
|
|
379
382
|
|
|
380
|
-
_See code: [src/commands/functions/dev.ts](https://github.com/sanity-io/runtime-cli/blob/v11.0
|
|
383
|
+
_See code: [src/commands/functions/dev.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.0/src/commands/functions/dev.ts)_
|
|
381
384
|
|
|
382
385
|
## `sanity-run functions env add NAME KEY VALUE`
|
|
383
386
|
|
|
@@ -399,7 +402,7 @@ EXAMPLES
|
|
|
399
402
|
$ sanity-run functions env add MyFunction API_URL https://api.example.com/
|
|
400
403
|
```
|
|
401
404
|
|
|
402
|
-
_See code: [src/commands/functions/env/add.ts](https://github.com/sanity-io/runtime-cli/blob/v11.0
|
|
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)_
|
|
403
406
|
|
|
404
407
|
## `sanity-run functions env list NAME`
|
|
405
408
|
|
|
@@ -419,7 +422,7 @@ EXAMPLES
|
|
|
419
422
|
$ sanity-run functions env list MyFunction
|
|
420
423
|
```
|
|
421
424
|
|
|
422
|
-
_See code: [src/commands/functions/env/list.ts](https://github.com/sanity-io/runtime-cli/blob/v11.0
|
|
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)_
|
|
423
426
|
|
|
424
427
|
## `sanity-run functions env remove NAME KEY`
|
|
425
428
|
|
|
@@ -440,7 +443,7 @@ EXAMPLES
|
|
|
440
443
|
$ sanity-run functions env remove MyFunction API_URL
|
|
441
444
|
```
|
|
442
445
|
|
|
443
|
-
_See code: [src/commands/functions/env/remove.ts](https://github.com/sanity-io/runtime-cli/blob/v11.0
|
|
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)_
|
|
444
447
|
|
|
445
448
|
## `sanity-run functions logs NAME`
|
|
446
449
|
|
|
@@ -474,7 +477,7 @@ EXAMPLES
|
|
|
474
477
|
$ sanity-run functions logs <name> --delete
|
|
475
478
|
```
|
|
476
479
|
|
|
477
|
-
_See code: [src/commands/functions/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v11.0
|
|
480
|
+
_See code: [src/commands/functions/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.0/src/commands/functions/logs.ts)_
|
|
478
481
|
|
|
479
482
|
## `sanity-run functions test NAME`
|
|
480
483
|
|
|
@@ -484,8 +487,8 @@ Invoke a local Sanity Function
|
|
|
484
487
|
USAGE
|
|
485
488
|
$ sanity-run functions test NAME [--data-before <value> | [-d <value> | -f <value> | --document-id <value>] | |
|
|
486
489
|
| --file-before <value> | --file-after <value> | --document-id-before <value> | --document-id-after <value>]
|
|
487
|
-
[--data-after <value> | | | | | | | ] [-e create|update|delete] [-t <value>] [-a <value>] [--
|
|
488
|
-
[--
|
|
490
|
+
[--data-after <value> | | | | | | | ] [-e create|update|delete] [-t <value>] [-a <value>] [--organization-id
|
|
491
|
+
<value>] [--with-user-token] [--media-library-id <value> | --project-id <value> | --dataset <value>]
|
|
489
492
|
|
|
490
493
|
ARGUMENTS
|
|
491
494
|
NAME The name of the Sanity Function
|
|
@@ -505,6 +508,7 @@ FLAGS
|
|
|
505
508
|
--document-id-before=<value> Original document
|
|
506
509
|
--file-after=<value> Current document
|
|
507
510
|
--file-before=<value> Original document
|
|
511
|
+
--media-library-id=<value> Sanity Media Library ID to use
|
|
508
512
|
--organization-id=<value> Sanity Organization ID to use
|
|
509
513
|
--project-id=<value> Sanity Project ID to use
|
|
510
514
|
--with-user-token Prime access token from CLI config
|
|
@@ -522,7 +526,7 @@ EXAMPLES
|
|
|
522
526
|
$ sanity-run functions test <name> --event update --data-before '{ "title": "before" }' --data-after '{ "title": "after" }'
|
|
523
527
|
```
|
|
524
528
|
|
|
525
|
-
_See code: [src/commands/functions/test.ts](https://github.com/sanity-io/runtime-cli/blob/v11.0
|
|
529
|
+
_See code: [src/commands/functions/test.ts](https://github.com/sanity-io/runtime-cli/blob/v11.1.0/src/commands/functions/test.ts)_
|
|
526
530
|
|
|
527
531
|
## `sanity-run help [COMMAND]`
|
|
528
532
|
|
|
@@ -48,8 +48,8 @@ export declare function writeBlueprintToDisk({ blueprintFilePath, jsonContent, }
|
|
|
48
48
|
blueprintFilePath: string;
|
|
49
49
|
jsonContent?: Blueprint;
|
|
50
50
|
}): string;
|
|
51
|
-
export declare function addResourceToBlueprint({ blueprintFilePath, resource, }: {
|
|
51
|
+
export declare function addResourceToBlueprint<T extends Resource>({ blueprintFilePath, resource, }: {
|
|
52
52
|
blueprintFilePath?: string;
|
|
53
|
-
resource:
|
|
54
|
-
}):
|
|
53
|
+
resource: T;
|
|
54
|
+
}): T | undefined;
|
|
55
55
|
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { FunctionResourceBase } from '../../utils/types.js';
|
|
2
2
|
interface FunctionResourceOptions {
|
|
3
3
|
name: string;
|
|
4
4
|
type: string[];
|
|
@@ -13,6 +13,6 @@ interface FunctionResourceOptions {
|
|
|
13
13
|
export declare function createFunctionResource(options: FunctionResourceOptions): Promise<{
|
|
14
14
|
filePath: string;
|
|
15
15
|
resourceAdded: boolean;
|
|
16
|
-
resource:
|
|
16
|
+
resource: FunctionResourceBase;
|
|
17
17
|
}>;
|
|
18
18
|
export {};
|
|
@@ -56,10 +56,9 @@ export async function createFunctionResource(options) {
|
|
|
56
56
|
throw new Error(`Failed to install dependencies using \`${installCommand}\``);
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
|
-
// type looks like 'document-publish'
|
|
60
|
-
const
|
|
61
|
-
const
|
|
62
|
-
const eventsOn = type.map((t) => t.split('-')[1]);
|
|
59
|
+
// type looks like 'document-publish' or 'media-library-asset-delete'
|
|
60
|
+
const typeName = type[0].substring(type[0].lastIndexOf('-') + 1);
|
|
61
|
+
const eventsOn = type.map((t) => t.substring(t.lastIndexOf('-') + 1));
|
|
63
62
|
// Create resource definition
|
|
64
63
|
const resourceJson = {
|
|
65
64
|
name,
|
|
@@ -39,7 +39,15 @@ export default class AddCommand extends BlueprintCommand {
|
|
|
39
39
|
}),
|
|
40
40
|
'fn-type': Flags.string({
|
|
41
41
|
description: 'Document change event(s) that should trigger the function; you can specify multiple events by specifying this flag multiple times',
|
|
42
|
-
options: [
|
|
42
|
+
options: [
|
|
43
|
+
'document-create',
|
|
44
|
+
'document-delete',
|
|
45
|
+
'document-update',
|
|
46
|
+
'document-publish',
|
|
47
|
+
'media-library-asset-create',
|
|
48
|
+
'media-library-asset-update',
|
|
49
|
+
'media-library-asset-delete',
|
|
50
|
+
],
|
|
43
51
|
aliases: ['function-type'],
|
|
44
52
|
multiple: true,
|
|
45
53
|
multipleNonGreedy: true,
|
|
@@ -22,7 +22,15 @@ export default class AddCommand extends BlueprintCommand {
|
|
|
22
22
|
}),
|
|
23
23
|
type: Flags.string({
|
|
24
24
|
description: 'Document change event(s) that should trigger the function; you can specify multiple events by specifying this flag multiple times',
|
|
25
|
-
options: [
|
|
25
|
+
options: [
|
|
26
|
+
'document-create',
|
|
27
|
+
'document-delete',
|
|
28
|
+
'document-update',
|
|
29
|
+
'document-publish',
|
|
30
|
+
'media-library-asset-create',
|
|
31
|
+
'media-library-asset-update',
|
|
32
|
+
'media-library-asset-delete',
|
|
33
|
+
],
|
|
26
34
|
multiple: true,
|
|
27
35
|
multipleNonGreedy: true,
|
|
28
36
|
dependsOn: ['name'],
|
|
@@ -22,6 +22,7 @@ export default class TestCommand extends BlueprintCommand<typeof TestCommand> {
|
|
|
22
22
|
'document-id-before': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
23
23
|
'document-id-after': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
24
24
|
'with-user-token': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
25
|
+
'media-library-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
25
26
|
};
|
|
26
27
|
run(): Promise<void>;
|
|
27
28
|
}
|
|
@@ -143,6 +143,12 @@ export default class TestCommand extends BlueprintCommand {
|
|
|
143
143
|
description: 'Prime access token from CLI config',
|
|
144
144
|
default: false,
|
|
145
145
|
}),
|
|
146
|
+
'media-library-id': Flags.string({
|
|
147
|
+
description: 'Sanity Media Library ID to use',
|
|
148
|
+
aliases: ['media'],
|
|
149
|
+
exclusive: ['project-id', 'dataset'],
|
|
150
|
+
required: false,
|
|
151
|
+
}),
|
|
146
152
|
};
|
|
147
153
|
async run() {
|
|
148
154
|
if (this.flags.event === 'update') {
|
|
@@ -8,14 +8,21 @@ import { createFunctionResource } from '../../actions/blueprints/resources.js';
|
|
|
8
8
|
import { verifyExampleExists, writeExample } from '../../actions/sanity/examples.js';
|
|
9
9
|
import { check, indent, warn } from '../../utils/display/presenters.js';
|
|
10
10
|
import { validateFunctionName } from '../../utils/validate/resource.js';
|
|
11
|
-
const generateFunctionBlueprintResourceTemplate = (fnName, eventNames) =>
|
|
11
|
+
const generateFunctionBlueprintResourceTemplate = (fnName, eventNames) => {
|
|
12
|
+
const definer = eventNames[0].substring(0, eventNames[0].lastIndexOf('-')) === 'document'
|
|
13
|
+
? 'Document'
|
|
14
|
+
: 'MediaLibraryAsset';
|
|
15
|
+
const isML = definer.startsWith('Media');
|
|
16
|
+
const eventOns = eventNames.map((e) => `'${e.substring(e.lastIndexOf('-') + 1)}'`);
|
|
17
|
+
return `
|
|
12
18
|
export default defineBlueprint({
|
|
13
19
|
resources: [
|
|
14
20
|
// ...
|
|
15
|
-
|
|
21
|
+
define${definer}Function({name: '${fnName}', event: {on: [${eventOns.join(', ')}]${isML ? ", resource: {type: 'media-library', id: 'my-media-library-id'}" : ''}}}), // ← add this line
|
|
16
22
|
],
|
|
17
23
|
})
|
|
18
24
|
`;
|
|
25
|
+
};
|
|
19
26
|
export async function functionAddCore(options) {
|
|
20
27
|
const root = cwd();
|
|
21
28
|
const { log, blueprint, flags } = options;
|
|
@@ -115,8 +122,20 @@ export async function functionAddCore(options) {
|
|
|
115
122
|
if (fnTypes.length === 0) {
|
|
116
123
|
throw new Error('At least one function type must be provided.');
|
|
117
124
|
}
|
|
118
|
-
if (!fnTypes.every((evt) => [
|
|
119
|
-
|
|
125
|
+
if (!fnTypes.every((evt) => [
|
|
126
|
+
'document-publish',
|
|
127
|
+
'document-create',
|
|
128
|
+
'document-delete',
|
|
129
|
+
'document-update',
|
|
130
|
+
'media-library-asset-create',
|
|
131
|
+
'media-library-asset-update',
|
|
132
|
+
'media-library-asset-delete',
|
|
133
|
+
].includes(evt))) {
|
|
134
|
+
throw new Error('Invalid function type. Must be one of: document-publish, document-create, document-delete, document-update, media-library-asset-create, media-library-asset-update, media-library-asset-delete');
|
|
135
|
+
}
|
|
136
|
+
const eventSources = new Set(fnTypes.map((t) => t.substring(0, t.lastIndexOf('-'))));
|
|
137
|
+
if (eventSources.size > 1) {
|
|
138
|
+
throw new Error('Invalid function type. Cannot mix document-* and media-library-asset-* types.');
|
|
120
139
|
}
|
|
121
140
|
let addHelpers;
|
|
122
141
|
let installCommand;
|
|
@@ -195,21 +214,24 @@ async function promptForFunctionType() {
|
|
|
195
214
|
{
|
|
196
215
|
type: 'checkbox',
|
|
197
216
|
name: 'functionType',
|
|
198
|
-
message: 'Choose
|
|
217
|
+
message: 'Choose events to trigger your function:',
|
|
199
218
|
choices: [
|
|
200
219
|
{ name: 'Document Create', value: 'document-create' },
|
|
201
220
|
{ name: 'Document Update', value: 'document-update' },
|
|
202
221
|
{ name: 'Document Delete', value: 'document-delete' },
|
|
203
|
-
{
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
},
|
|
222
|
+
{ name: 'Media Library Asset Create', value: 'media-library-asset-create' },
|
|
223
|
+
{ name: 'Media Library Asset Update', value: 'media-library-asset-update' },
|
|
224
|
+
{ name: 'Media Library Asset Delete', value: 'media-library-asset-delete' },
|
|
207
225
|
],
|
|
208
226
|
default: ['document-create', 'document-update'],
|
|
209
227
|
validate(choices) {
|
|
210
228
|
if (choices.length === 0) {
|
|
211
229
|
return 'You must choose at least one function type / document change event';
|
|
212
230
|
}
|
|
231
|
+
if (choices.some((c) => String(c.value).startsWith('media-library')) &&
|
|
232
|
+
choices.some((c) => String(c.value).startsWith('document'))) {
|
|
233
|
+
return 'You cannot mix both Document and Media Library Asset events together in one Function';
|
|
234
|
+
}
|
|
213
235
|
return true;
|
|
214
236
|
},
|
|
215
237
|
},
|
|
@@ -22,6 +22,7 @@ export interface FunctionTestOptions extends CoreConfig {
|
|
|
22
22
|
'file-after'?: string;
|
|
23
23
|
'document-id-before'?: string;
|
|
24
24
|
'document-id-after'?: string;
|
|
25
|
+
'media-library-id'?: string;
|
|
25
26
|
};
|
|
26
27
|
}
|
|
27
28
|
export declare function functionTestCore(options: FunctionTestOptions): Promise<CoreResult>;
|
|
@@ -6,13 +6,13 @@ import { testAction } from '../../actions/functions/test.js';
|
|
|
6
6
|
import config from '../../config.js';
|
|
7
7
|
import buildPayload from '../../utils/build-payload.js';
|
|
8
8
|
import { findFunctionByName } from '../../utils/find-function.js';
|
|
9
|
-
import { fetchDocument } from '../../utils/functions/fetch-document.js';
|
|
9
|
+
import { fetchAsset, fetchDocument } from '../../utils/functions/fetch-document.js';
|
|
10
10
|
import { parseJsonObject } from '../../utils/parse-json-object.js';
|
|
11
11
|
import { isEventType, } from '../../utils/types.js';
|
|
12
12
|
export async function functionTestCore(options) {
|
|
13
13
|
const { blueprint, log, args, flags } = options;
|
|
14
14
|
const { name: fnName } = args;
|
|
15
|
-
const { data, event, file, timeout, api, dataset, 'document-id': documentId, 'with-user-token': withUserToken, 'data-before': dataBefore, 'data-after': dataAfter, 'file-before': fileBefore, 'file-after': fileAfter, 'document-id-before': documentIdBefore, 'document-id-after': documentIdAfter, } = flags;
|
|
15
|
+
const { data, event, file, timeout, api, dataset, 'document-id': documentId, 'with-user-token': withUserToken, 'data-before': dataBefore, 'data-after': dataAfter, 'file-before': fileBefore, 'file-after': fileAfter, 'document-id-before': documentIdBefore, 'document-id-after': documentIdAfter, 'media-library-id': mediaLibraryId, } = flags;
|
|
16
16
|
const { parsedBlueprint } = blueprint;
|
|
17
17
|
const { 'project-id': projectId = blueprint?.projectId, 'organization-id': organizationId = blueprint?.organizationId, } = flags;
|
|
18
18
|
let eventType;
|
|
@@ -30,6 +30,7 @@ export async function functionTestCore(options) {
|
|
|
30
30
|
}
|
|
31
31
|
try {
|
|
32
32
|
const resource = findFunctionByName(parsedBlueprint, fnName); // throws if not found
|
|
33
|
+
const docFunction = resource.type === 'sanity.function.document';
|
|
33
34
|
const contextOptions = {
|
|
34
35
|
clientOptions: {
|
|
35
36
|
apiVersion: api,
|
|
@@ -37,6 +38,10 @@ export async function functionTestCore(options) {
|
|
|
37
38
|
projectId,
|
|
38
39
|
organizationId,
|
|
39
40
|
},
|
|
41
|
+
eventResourceType: docFunction ? 'dataset' : 'media-library',
|
|
42
|
+
eventResourceId: (docFunction ? `${projectId}.${dataset}` : mediaLibraryId) || '',
|
|
43
|
+
functionResourceType: 'project',
|
|
44
|
+
functionResourceId: (docFunction ? projectId : organizationId) || '',
|
|
40
45
|
};
|
|
41
46
|
// If the user sets the flag to use the real token set it in our options
|
|
42
47
|
if (withUserToken) {
|
|
@@ -54,7 +59,7 @@ export async function functionTestCore(options) {
|
|
|
54
59
|
fileContents = readFileSync(join(cwd(), fileAfter), 'utf8');
|
|
55
60
|
after = parseJsonObject(fileContents);
|
|
56
61
|
}
|
|
57
|
-
else if (documentIdBefore && documentIdAfter) {
|
|
62
|
+
else if (documentIdBefore && documentIdAfter && docFunction) {
|
|
58
63
|
before = await fetchDocument(documentIdBefore, {
|
|
59
64
|
projectId,
|
|
60
65
|
dataset,
|
|
@@ -70,20 +75,45 @@ export async function functionTestCore(options) {
|
|
|
70
75
|
token: config.token || undefined,
|
|
71
76
|
});
|
|
72
77
|
}
|
|
78
|
+
else if (documentIdBefore && documentIdAfter) {
|
|
79
|
+
before = await fetchAsset(documentIdBefore, {
|
|
80
|
+
mediaLibraryId,
|
|
81
|
+
apiVersion: api,
|
|
82
|
+
apiHost: config.apiUrl,
|
|
83
|
+
token: config.token || undefined,
|
|
84
|
+
});
|
|
85
|
+
after = await fetchAsset(documentIdAfter, {
|
|
86
|
+
mediaLibraryId,
|
|
87
|
+
apiVersion: api,
|
|
88
|
+
apiHost: config.apiUrl,
|
|
89
|
+
token: config.token || undefined,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
73
92
|
let payload;
|
|
74
93
|
if (after) {
|
|
75
94
|
payload = after;
|
|
76
95
|
}
|
|
77
96
|
else {
|
|
78
|
-
|
|
79
|
-
|
|
97
|
+
if (documentId && docFunction) {
|
|
98
|
+
payload = await fetchDocument(documentId, {
|
|
80
99
|
projectId,
|
|
81
100
|
dataset,
|
|
82
101
|
apiVersion: api,
|
|
83
102
|
apiHost: config.apiUrl,
|
|
84
103
|
token: config.token || undefined,
|
|
85
|
-
})
|
|
86
|
-
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
else if (documentId) {
|
|
107
|
+
payload = await fetchAsset(documentId, {
|
|
108
|
+
mediaLibraryId,
|
|
109
|
+
apiVersion: api,
|
|
110
|
+
apiHost: config.apiUrl,
|
|
111
|
+
token: config.token || undefined,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
payload = buildPayload({ data, file });
|
|
116
|
+
}
|
|
87
117
|
}
|
|
88
118
|
const invokeOptions = {
|
|
89
119
|
event: eventType,
|
package/dist/server/app.js
CHANGED
|
@@ -14,10 +14,10 @@ const app = (port, executionOptions) => {
|
|
|
14
14
|
switch (true) {
|
|
15
15
|
case req.url === '/blueprint': {
|
|
16
16
|
try {
|
|
17
|
-
const { parsedBlueprint, projectId } = await readLocalBlueprint();
|
|
17
|
+
const { parsedBlueprint, projectId, organizationId } = await readLocalBlueprint();
|
|
18
18
|
res.setHeader('Content-Type', 'application/json');
|
|
19
19
|
res.writeHead(200);
|
|
20
|
-
res.end(JSON.stringify({ parsedBlueprint, projectId })); // Use blueprint directly
|
|
20
|
+
res.end(JSON.stringify({ parsedBlueprint, projectId, organizationId })); // Use blueprint directly
|
|
21
21
|
}
|
|
22
22
|
catch (error) {
|
|
23
23
|
res.writeHead(404);
|
|
@@ -137,6 +137,75 @@ const app = (port, executionOptions) => {
|
|
|
137
137
|
}
|
|
138
138
|
break;
|
|
139
139
|
}
|
|
140
|
+
case req.url === '/organizations': {
|
|
141
|
+
res.setHeader('Content-Type', 'application/json');
|
|
142
|
+
try {
|
|
143
|
+
const response = await fetch(`${config.apiUrl}/v2021-06-07/organizations?includeImplicitMemberships=true&includeMembers=false&includeFeatures=false`, {
|
|
144
|
+
headers: {
|
|
145
|
+
Authorization: `Bearer ${config.token}`,
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
const json = await response.json();
|
|
149
|
+
res.writeHead(200);
|
|
150
|
+
res.end(JSON.stringify(json));
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
res.writeHead(200);
|
|
154
|
+
res.end(JSON.stringify([]));
|
|
155
|
+
}
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
158
|
+
case req.url?.startsWith('/media-libraries'): {
|
|
159
|
+
const url = req.url || '';
|
|
160
|
+
const matches = url.match(/[?&]organization=([^&]+)/) || [];
|
|
161
|
+
const organizationId = matches ? matches[1] : null;
|
|
162
|
+
res.setHeader('Content-Type', 'application/json');
|
|
163
|
+
try {
|
|
164
|
+
const response = await fetch(`${config.apiUrl}/vX/media-libraries?organizationId=${organizationId}`, {
|
|
165
|
+
headers: {
|
|
166
|
+
Authorization: `Bearer ${config.token}`,
|
|
167
|
+
},
|
|
168
|
+
});
|
|
169
|
+
const json = await response.json();
|
|
170
|
+
res.writeHead(200);
|
|
171
|
+
res.end(JSON.stringify(json.data));
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
res.writeHead(200);
|
|
175
|
+
res.end(JSON.stringify([]));
|
|
176
|
+
}
|
|
177
|
+
break;
|
|
178
|
+
}
|
|
179
|
+
case req.url?.startsWith('/asset'): {
|
|
180
|
+
const url = req.url || '';
|
|
181
|
+
const parsed = parseAssetUrl(url);
|
|
182
|
+
if (parsed) {
|
|
183
|
+
const { mediaLibraryId, docId } = parsed;
|
|
184
|
+
res.setHeader('Content-Type', 'application/json');
|
|
185
|
+
try {
|
|
186
|
+
let json = {};
|
|
187
|
+
const url = buildAssetUrl(mediaLibraryId, docId, config.apiUrl);
|
|
188
|
+
if (docId) {
|
|
189
|
+
const response = await fetch(url, {
|
|
190
|
+
headers: {
|
|
191
|
+
Authorization: `Bearer ${config.token}`,
|
|
192
|
+
},
|
|
193
|
+
});
|
|
194
|
+
const queryResponse = await response.json();
|
|
195
|
+
if (queryResponse?.documents[0]) {
|
|
196
|
+
json = queryResponse?.documents[0];
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
res.writeHead(200);
|
|
200
|
+
res.end(JSON.stringify(json));
|
|
201
|
+
}
|
|
202
|
+
catch {
|
|
203
|
+
res.writeHead(200);
|
|
204
|
+
res.end(JSON.stringify([]));
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
break;
|
|
208
|
+
}
|
|
140
209
|
default: {
|
|
141
210
|
const requestPath = req.url?.endsWith('/') ? `${req.url}index.html` : req.url;
|
|
142
211
|
const filePath = new URL(`./static${requestPath}`, import.meta.url).pathname;
|
|
@@ -178,6 +247,18 @@ function parseDocumentUrl(url) {
|
|
|
178
247
|
}
|
|
179
248
|
return null;
|
|
180
249
|
}
|
|
250
|
+
// Helper function to test URL parsing and document fetching logic
|
|
251
|
+
function parseAssetUrl(url) {
|
|
252
|
+
const matches = url.match(/[?&]organization=([^&]+).*?[&]medialibrary=([^&]+).*?[&]doc=([^&]+)/) || [];
|
|
253
|
+
if (matches && matches.length === 4) {
|
|
254
|
+
const [, organizationId, mediaLibraryId, docId] = matches;
|
|
255
|
+
// Ensure all parameters are present and non-empty
|
|
256
|
+
if (organizationId && mediaLibraryId && docId) {
|
|
257
|
+
return { organizationId, mediaLibraryId, docId };
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
return null;
|
|
261
|
+
}
|
|
181
262
|
// Helper function to build expected API URL
|
|
182
263
|
function buildApiUrl(projectId, dataset, docId, apiUrl) {
|
|
183
264
|
const encodedQuery = encodeURIComponent(`*[_id == "${docId}"]`);
|
|
@@ -186,6 +267,10 @@ function buildApiUrl(projectId, dataset, docId, apiUrl) {
|
|
|
186
267
|
: `https://${projectId}.api.sanity.work/`;
|
|
187
268
|
return `${baseUrl}v1/data/query/${dataset}?query=${encodedQuery}`;
|
|
188
269
|
}
|
|
270
|
+
// Helper function to build expected API URL
|
|
271
|
+
function buildAssetUrl(mediaLibraryId, docId, apiUrl) {
|
|
272
|
+
return `${apiUrl}/v2025-03-24/media-libraries/${mediaLibraryId}/doc/${docId}`;
|
|
273
|
+
}
|
|
189
274
|
function parseInvokeRequest(body) {
|
|
190
275
|
let json;
|
|
191
276
|
try {
|
|
@@ -265,7 +350,18 @@ function parseInvokeRequest(body) {
|
|
|
265
350
|
};
|
|
266
351
|
return {
|
|
267
352
|
func,
|
|
268
|
-
data: {
|
|
353
|
+
data: {
|
|
354
|
+
context: {
|
|
355
|
+
...context,
|
|
356
|
+
clientOptions,
|
|
357
|
+
// Provide default values for required properties if not present
|
|
358
|
+
eventResourceType: typeof context.eventResourceType === 'string' ? context.eventResourceType : '',
|
|
359
|
+
eventResourceId: typeof context.eventResourceId === 'string' ? context.eventResourceId : '',
|
|
360
|
+
functionResourceType: typeof context.functionResourceType === 'string' ? context.functionResourceType : '',
|
|
361
|
+
functionResourceId: typeof context.functionResourceId === 'string' ? context.functionResourceId : '',
|
|
362
|
+
},
|
|
363
|
+
event,
|
|
364
|
+
},
|
|
269
365
|
metadata: { event: metadataEvent, before, after },
|
|
270
366
|
};
|
|
271
367
|
}
|