@sanity/runtime-cli 17.15.0 → 17.16.0-next.g26925c0
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 +19 -19
- package/dist/actions/blueprints/blueprint.d.ts +20 -9
- package/dist/actions/blueprints/blueprint.js +25 -79
- package/dist/actions/blueprints/config.d.ts +1 -0
- package/dist/actions/blueprints/config.js +7 -1
- package/dist/baseCommands.js +3 -3
- package/dist/config.d.ts +1 -2
- package/dist/config.js +1 -2
- package/dist/cores/blueprints/doctor.js +2 -2
- package/dist/cores/blueprints/init.js +11 -2
- package/dist/cores/functions/test.js +28 -5
- package/dist/server/app.js +2 -2
- package/dist/server/static/components/app.css +8 -1
- package/dist/utils/functions/child-process-wrapper.js +1 -1
- package/dist/utils/functions/child-runtime/invoke.d.ts +1 -0
- package/dist/utils/functions/child-runtime/invoke.js +26 -9
- package/dist/utils/functions/extract-durable-config.js +1 -4
- package/dist/utils/functions/invoke/local.js +8 -3
- package/dist/utils/functions/invoke/nested.js +2 -1
- package/dist/utils/types.d.ts +5 -1
- package/oclif.manifest.json +1 -1
- package/package.json +2 -2
- package/dist/actions/blueprints/resolve.d.ts +0 -51
- package/dist/actions/blueprints/resolve.js +0 -52
package/README.md
CHANGED
|
@@ -90,7 +90,7 @@ EXAMPLES
|
|
|
90
90
|
$ sanity-run blueprints add function --name my-function --fn-type document-create --fn-type document-update --lang js
|
|
91
91
|
```
|
|
92
92
|
|
|
93
|
-
_See code: [src/commands/blueprints/add.ts](https://github.com/sanity-io/runtime-cli/blob/v17.
|
|
93
|
+
_See code: [src/commands/blueprints/add.ts](https://github.com/sanity-io/runtime-cli/blob/v17.16.0-next.g26925c0/src/commands/blueprints/add.ts)_
|
|
94
94
|
|
|
95
95
|
## `sanity-run blueprints config`
|
|
96
96
|
|
|
@@ -127,7 +127,7 @@ EXAMPLES
|
|
|
127
127
|
$ sanity-run blueprints config --edit --project-id <projectId> --stack <name-or-id>
|
|
128
128
|
```
|
|
129
129
|
|
|
130
|
-
_See code: [src/commands/blueprints/config.ts](https://github.com/sanity-io/runtime-cli/blob/v17.
|
|
130
|
+
_See code: [src/commands/blueprints/config.ts](https://github.com/sanity-io/runtime-cli/blob/v17.16.0-next.g26925c0/src/commands/blueprints/config.ts)_
|
|
131
131
|
|
|
132
132
|
## `sanity-run blueprints deploy`
|
|
133
133
|
|
|
@@ -183,7 +183,7 @@ EXAMPLES
|
|
|
183
183
|
$ sanity-run blueprints deploy --new-stack-name <new-name>
|
|
184
184
|
```
|
|
185
185
|
|
|
186
|
-
_See code: [src/commands/blueprints/deploy.ts](https://github.com/sanity-io/runtime-cli/blob/v17.
|
|
186
|
+
_See code: [src/commands/blueprints/deploy.ts](https://github.com/sanity-io/runtime-cli/blob/v17.16.0-next.g26925c0/src/commands/blueprints/deploy.ts)_
|
|
187
187
|
|
|
188
188
|
## `sanity-run blueprints destroy`
|
|
189
189
|
|
|
@@ -221,7 +221,7 @@ EXAMPLES
|
|
|
221
221
|
$ sanity-run blueprints destroy --stack <name-or-id> --project-id <projectId> --force --no-wait
|
|
222
222
|
```
|
|
223
223
|
|
|
224
|
-
_See code: [src/commands/blueprints/destroy.ts](https://github.com/sanity-io/runtime-cli/blob/v17.
|
|
224
|
+
_See code: [src/commands/blueprints/destroy.ts](https://github.com/sanity-io/runtime-cli/blob/v17.16.0-next.g26925c0/src/commands/blueprints/destroy.ts)_
|
|
225
225
|
|
|
226
226
|
## `sanity-run blueprints doctor`
|
|
227
227
|
|
|
@@ -253,7 +253,7 @@ EXAMPLES
|
|
|
253
253
|
$ sanity-run blueprints doctor --fix
|
|
254
254
|
```
|
|
255
255
|
|
|
256
|
-
_See code: [src/commands/blueprints/doctor.ts](https://github.com/sanity-io/runtime-cli/blob/v17.
|
|
256
|
+
_See code: [src/commands/blueprints/doctor.ts](https://github.com/sanity-io/runtime-cli/blob/v17.16.0-next.g26925c0/src/commands/blueprints/doctor.ts)_
|
|
257
257
|
|
|
258
258
|
## `sanity-run blueprints info`
|
|
259
259
|
|
|
@@ -291,7 +291,7 @@ EXAMPLES
|
|
|
291
291
|
$ sanity-run blueprints info --organization-id <orgId> --stack <name-or-id>
|
|
292
292
|
```
|
|
293
293
|
|
|
294
|
-
_See code: [src/commands/blueprints/info.ts](https://github.com/sanity-io/runtime-cli/blob/v17.
|
|
294
|
+
_See code: [src/commands/blueprints/info.ts](https://github.com/sanity-io/runtime-cli/blob/v17.16.0-next.g26925c0/src/commands/blueprints/info.ts)_
|
|
295
295
|
|
|
296
296
|
## `sanity-run blueprints init [DIR]`
|
|
297
297
|
|
|
@@ -355,7 +355,7 @@ EXAMPLES
|
|
|
355
355
|
$ sanity-run blueprints init old-stack --type <json|js|ts> --project-id <projectId> --stack-id <existingStackId>
|
|
356
356
|
```
|
|
357
357
|
|
|
358
|
-
_See code: [src/commands/blueprints/init.ts](https://github.com/sanity-io/runtime-cli/blob/v17.
|
|
358
|
+
_See code: [src/commands/blueprints/init.ts](https://github.com/sanity-io/runtime-cli/blob/v17.16.0-next.g26925c0/src/commands/blueprints/init.ts)_
|
|
359
359
|
|
|
360
360
|
## `sanity-run blueprints logs`
|
|
361
361
|
|
|
@@ -401,7 +401,7 @@ EXAMPLES
|
|
|
401
401
|
$ sanity-run blueprints logs --before 2026-05-01T00:00:00Z
|
|
402
402
|
```
|
|
403
403
|
|
|
404
|
-
_See code: [src/commands/blueprints/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v17.
|
|
404
|
+
_See code: [src/commands/blueprints/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v17.16.0-next.g26925c0/src/commands/blueprints/logs.ts)_
|
|
405
405
|
|
|
406
406
|
## `sanity-run blueprints mint-deploy-token`
|
|
407
407
|
|
|
@@ -446,7 +446,7 @@ EXAMPLES
|
|
|
446
446
|
$ sanity-run blueprints mint-deploy-token --organization-id <orgId>
|
|
447
447
|
```
|
|
448
448
|
|
|
449
|
-
_See code: [src/commands/blueprints/mint-deploy-token.ts](https://github.com/sanity-io/runtime-cli/blob/v17.
|
|
449
|
+
_See code: [src/commands/blueprints/mint-deploy-token.ts](https://github.com/sanity-io/runtime-cli/blob/v17.16.0-next.g26925c0/src/commands/blueprints/mint-deploy-token.ts)_
|
|
450
450
|
|
|
451
451
|
## `sanity-run blueprints plan`
|
|
452
452
|
|
|
@@ -479,7 +479,7 @@ EXAMPLES
|
|
|
479
479
|
$ sanity-run blueprints plan --organization-id <orgId> --stack <name-or-id>
|
|
480
480
|
```
|
|
481
481
|
|
|
482
|
-
_See code: [src/commands/blueprints/plan.ts](https://github.com/sanity-io/runtime-cli/blob/v17.
|
|
482
|
+
_See code: [src/commands/blueprints/plan.ts](https://github.com/sanity-io/runtime-cli/blob/v17.16.0-next.g26925c0/src/commands/blueprints/plan.ts)_
|
|
483
483
|
|
|
484
484
|
## `sanity-run blueprints promote`
|
|
485
485
|
|
|
@@ -515,7 +515,7 @@ EXAMPLES
|
|
|
515
515
|
$ sanity-run blueprints promote --new-stack-name <new-name>
|
|
516
516
|
```
|
|
517
517
|
|
|
518
|
-
_See code: [src/commands/blueprints/promote.ts](https://github.com/sanity-io/runtime-cli/blob/v17.
|
|
518
|
+
_See code: [src/commands/blueprints/promote.ts](https://github.com/sanity-io/runtime-cli/blob/v17.16.0-next.g26925c0/src/commands/blueprints/promote.ts)_
|
|
519
519
|
|
|
520
520
|
## `sanity-run blueprints stacks`
|
|
521
521
|
|
|
@@ -556,7 +556,7 @@ EXAMPLES
|
|
|
556
556
|
$ sanity-run blueprints stacks --organization-id <organizationId> --include-projects
|
|
557
557
|
```
|
|
558
558
|
|
|
559
|
-
_See code: [src/commands/blueprints/stacks.ts](https://github.com/sanity-io/runtime-cli/blob/v17.
|
|
559
|
+
_See code: [src/commands/blueprints/stacks.ts](https://github.com/sanity-io/runtime-cli/blob/v17.16.0-next.g26925c0/src/commands/blueprints/stacks.ts)_
|
|
560
560
|
|
|
561
561
|
## `sanity-run functions add`
|
|
562
562
|
|
|
@@ -608,7 +608,7 @@ EXAMPLES
|
|
|
608
608
|
$ sanity-run functions add --name my-function --type document-create --type document-update --lang js
|
|
609
609
|
```
|
|
610
610
|
|
|
611
|
-
_See code: [src/commands/functions/add.ts](https://github.com/sanity-io/runtime-cli/blob/v17.
|
|
611
|
+
_See code: [src/commands/functions/add.ts](https://github.com/sanity-io/runtime-cli/blob/v17.16.0-next.g26925c0/src/commands/functions/add.ts)_
|
|
612
612
|
|
|
613
613
|
## `sanity-run functions dev`
|
|
614
614
|
|
|
@@ -643,7 +643,7 @@ EXAMPLES
|
|
|
643
643
|
$ sanity-run functions dev --timeout 60
|
|
644
644
|
```
|
|
645
645
|
|
|
646
|
-
_See code: [src/commands/functions/dev.ts](https://github.com/sanity-io/runtime-cli/blob/v17.
|
|
646
|
+
_See code: [src/commands/functions/dev.ts](https://github.com/sanity-io/runtime-cli/blob/v17.16.0-next.g26925c0/src/commands/functions/dev.ts)_
|
|
647
647
|
|
|
648
648
|
## `sanity-run functions env add NAME KEY VALUE`
|
|
649
649
|
|
|
@@ -676,7 +676,7 @@ EXAMPLES
|
|
|
676
676
|
$ sanity-run functions env add --stack <name-or-id> MyFunction API_URL https://api.example.com/
|
|
677
677
|
```
|
|
678
678
|
|
|
679
|
-
_See code: [src/commands/functions/env/add.ts](https://github.com/sanity-io/runtime-cli/blob/v17.
|
|
679
|
+
_See code: [src/commands/functions/env/add.ts](https://github.com/sanity-io/runtime-cli/blob/v17.16.0-next.g26925c0/src/commands/functions/env/add.ts)_
|
|
680
680
|
|
|
681
681
|
## `sanity-run functions env list NAME`
|
|
682
682
|
|
|
@@ -706,7 +706,7 @@ EXAMPLES
|
|
|
706
706
|
$ sanity-run functions env list --stack <name-or-id> MyFunction
|
|
707
707
|
```
|
|
708
708
|
|
|
709
|
-
_See code: [src/commands/functions/env/list.ts](https://github.com/sanity-io/runtime-cli/blob/v17.
|
|
709
|
+
_See code: [src/commands/functions/env/list.ts](https://github.com/sanity-io/runtime-cli/blob/v17.16.0-next.g26925c0/src/commands/functions/env/list.ts)_
|
|
710
710
|
|
|
711
711
|
## `sanity-run functions env remove NAME KEY`
|
|
712
712
|
|
|
@@ -738,7 +738,7 @@ EXAMPLES
|
|
|
738
738
|
$ sanity-run functions env remove --stack <name-or-id> MyFunction API_URL
|
|
739
739
|
```
|
|
740
740
|
|
|
741
|
-
_See code: [src/commands/functions/env/remove.ts](https://github.com/sanity-io/runtime-cli/blob/v17.
|
|
741
|
+
_See code: [src/commands/functions/env/remove.ts](https://github.com/sanity-io/runtime-cli/blob/v17.16.0-next.g26925c0/src/commands/functions/env/remove.ts)_
|
|
742
742
|
|
|
743
743
|
## `sanity-run functions logs [NAME]`
|
|
744
744
|
|
|
@@ -778,7 +778,7 @@ EXAMPLES
|
|
|
778
778
|
$ sanity-run functions logs <name> --delete
|
|
779
779
|
```
|
|
780
780
|
|
|
781
|
-
_See code: [src/commands/functions/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v17.
|
|
781
|
+
_See code: [src/commands/functions/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v17.16.0-next.g26925c0/src/commands/functions/logs.ts)_
|
|
782
782
|
|
|
783
783
|
## `sanity-run functions test [NAME]`
|
|
784
784
|
|
|
@@ -836,7 +836,7 @@ EXAMPLES
|
|
|
836
836
|
$ sanity-run functions test <name> --event update --data-before '{ "title": "before" }' --data-after '{ "title": "after" }'
|
|
837
837
|
```
|
|
838
838
|
|
|
839
|
-
_See code: [src/commands/functions/test.ts](https://github.com/sanity-io/runtime-cli/blob/v17.
|
|
839
|
+
_See code: [src/commands/functions/test.ts](https://github.com/sanity-io/runtime-cli/blob/v17.16.0-next.g26925c0/src/commands/functions/test.ts)_
|
|
840
840
|
|
|
841
841
|
## `sanity-run help [COMMAND]`
|
|
842
842
|
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
import type { BlueprintResource } from '@sanity/blueprints';
|
|
2
|
+
import { type StackConfig, type ConfigSource as StackConfigSource, type StackIds } from '@sanity/blueprints/resolve';
|
|
2
3
|
import { type Blueprint } from '@sanity/blueprints-parser';
|
|
3
4
|
import type { Logger } from '../../utils/logger.js';
|
|
4
5
|
import type { BlueprintParserError, ScopeType } from '../../utils/types.js';
|
|
5
6
|
import { type LocatedBlueprintsConfig } from './config.js';
|
|
6
|
-
|
|
7
|
-
declare const SUPPORTED_FILE_EXTENSIONS: readonly ['.json', '.js', '.mjs', '.ts'];
|
|
8
|
-
type BlueprintFileExtension = (typeof SUPPORTED_FILE_EXTENSIONS)[number];
|
|
7
|
+
type BlueprintFileExtension = '.json' | '.js' | '.mjs' | '.ts';
|
|
9
8
|
export declare const JSON_BLUEPRINT_CONTENT: {
|
|
10
9
|
blueprintVersion: string;
|
|
11
10
|
resources: never[];
|
|
12
11
|
};
|
|
13
12
|
export declare const TS_BLUEPRINT_CONTENT: string;
|
|
14
13
|
/** Function type with attached attributes */
|
|
15
|
-
export type BlueprintModule = ((args?: unknown) =>
|
|
14
|
+
export type BlueprintModule = ((args?: unknown) => unknown) & {
|
|
16
15
|
organizationId?: string;
|
|
17
16
|
projectId?: string;
|
|
18
17
|
stackId?: string;
|
|
@@ -23,12 +22,22 @@ type FileInfo = {
|
|
|
23
22
|
extension: BlueprintFileExtension;
|
|
24
23
|
};
|
|
25
24
|
/**
|
|
26
|
-
* Finds the blueprint file in the given path or current working directory
|
|
25
|
+
* Finds the blueprint file in the given path or current working directory, searching parent directories
|
|
26
|
+
* @see {@link findBlueprintFilePath} in `@sanity/blueprints/resolve`
|
|
27
27
|
* @returns The path, file name, and extension of the blueprint file
|
|
28
28
|
*/
|
|
29
29
|
export declare function findBlueprintFile(blueprintPath?: string): FileInfo | null;
|
|
30
|
-
/**
|
|
31
|
-
|
|
30
|
+
/**
|
|
31
|
+
* Where a resolved id came from: a `@sanity/blueprints/resolve` source,
|
|
32
|
+
* or `inferred` for the legacy `ST-<projectId>` Stack id backfill
|
|
33
|
+
*/
|
|
34
|
+
export type ConfigSource = StackConfigSource | 'inferred';
|
|
35
|
+
/** Resolved Stack ids and scope, with the CLI's sources */
|
|
36
|
+
export interface ResolvedIds extends Omit<StackConfig, 'sources'> {
|
|
37
|
+
sources: {
|
|
38
|
+
[K in keyof StackIds]?: ConfigSource;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
32
41
|
/** Result of loading a blueprint file from disk. */
|
|
33
42
|
export interface LoadedBlueprintFile {
|
|
34
43
|
rawBlueprint: Record<string, unknown>;
|
|
@@ -69,6 +78,7 @@ export interface ReadBlueprintResult {
|
|
|
69
78
|
/**
|
|
70
79
|
* Load a blueprint file from disk: read JSON or import+execute a JS/TS module.
|
|
71
80
|
* Returns the raw blueprint data and the module reference (if dynamic).
|
|
81
|
+
* @see {@link loadBlueprintFileFromDisk} in `@sanity/blueprints/resolve`
|
|
72
82
|
*/
|
|
73
83
|
export declare function loadBlueprintFile(fileInfo: FileInfo): Promise<LoadedBlueprintFile>;
|
|
74
84
|
/**
|
|
@@ -87,7 +97,7 @@ export interface LocalBlueprint extends ParsedBlueprintContent {
|
|
|
87
97
|
/**
|
|
88
98
|
* Find, load, and parse a local blueprint file in one step.
|
|
89
99
|
* Does not read the config file or resolve IDs -- callers that need
|
|
90
|
-
* scope/stack information should use `readConfigFile` + `
|
|
100
|
+
* scope/stack information should use `readConfigFile` + `resolveStackConfig` separately.
|
|
91
101
|
*
|
|
92
102
|
* @param blueprintPath Path to a blueprint file or directory containing one
|
|
93
103
|
* @param options.validateResources Whether to validate function resources
|
|
@@ -99,7 +109,7 @@ export declare function loadAndParseBlueprint(blueprintPath?: string, options?:
|
|
|
99
109
|
* Reads the blueprint file from disk and parses it.
|
|
100
110
|
* Resolves IDs from environment > blueprint module > config file.
|
|
101
111
|
* Can infer stackId from projectId for legacy ST-<projectId> stacks.
|
|
102
|
-
* @see {@link loadBlueprintFile} {@link readConfigFile} {@link
|
|
112
|
+
* @see {@link loadBlueprintFile} {@link readConfigFile} {@link resolveStackConfig} {@link parseBlueprintContent}
|
|
103
113
|
* @todo deprecate in favor of decomposed functions
|
|
104
114
|
* @returns Known information about the Blueprint, config, and Stack
|
|
105
115
|
*/
|
|
@@ -114,3 +124,4 @@ export declare function addResourceToBlueprint<T extends BlueprintResource>({ bl
|
|
|
114
124
|
blueprintFilePath?: string;
|
|
115
125
|
resource: T;
|
|
116
126
|
}): T | undefined;
|
|
127
|
+
export {};
|
|
@@ -1,20 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
2
|
import { basename, dirname, extname } from 'node:path';
|
|
3
|
-
import { cwd } from 'node:process';
|
|
4
3
|
import { pathToFileURL } from 'node:url';
|
|
4
|
+
import { findBlueprintFile as findBlueprintFilePath, loadBlueprintFile as loadBlueprintFileFromDisk, resolveStackConfig, } from '@sanity/blueprints/resolve';
|
|
5
5
|
import blueprintParserValidator from '@sanity/blueprints-parser';
|
|
6
|
-
import * as find from 'empathic/find';
|
|
7
6
|
import { createJiti } from 'jiti';
|
|
8
7
|
import { SANITY_FUNCTION_DOCUMENT, SANITY_FUNCTION_DURABLE, SANITY_FUNCTION_MEDIA_LIBRARY_ASSET, SANITY_FUNCTION_SCHEDULED, } from '../../constants.js';
|
|
9
8
|
import { validateResources } from '../../utils/blueprints/validate-resources.js';
|
|
10
9
|
import { backfillProjectBasedStackId, readConfigFile, } from './config.js';
|
|
11
|
-
import { resolveIds } from './resolve.js';
|
|
12
|
-
const SUPPORTED_FILE_EXTENSIONS = ['.json', '.js', '.mjs', '.ts'];
|
|
13
|
-
let SUPPORTED_FILE_NAMES = SUPPORTED_FILE_EXTENSIONS.map((ext) => `blueprint${ext}`);
|
|
14
|
-
SUPPORTED_FILE_NAMES = [
|
|
15
|
-
...SUPPORTED_FILE_NAMES,
|
|
16
|
-
...SUPPORTED_FILE_NAMES.map((name) => `sanity.${name}`),
|
|
17
|
-
];
|
|
18
10
|
export const JSON_BLUEPRINT_CONTENT = {
|
|
19
11
|
blueprintVersion: '2024-10-01',
|
|
20
12
|
resources: [],
|
|
@@ -29,88 +21,42 @@ export default defineBlueprint({
|
|
|
29
21
|
})
|
|
30
22
|
`.trim();
|
|
31
23
|
/**
|
|
32
|
-
* Finds the blueprint file in the given path or current working directory
|
|
24
|
+
* Finds the blueprint file in the given path or current working directory, searching parent directories
|
|
25
|
+
* @see {@link findBlueprintFilePath} in `@sanity/blueprints/resolve`
|
|
33
26
|
* @returns The path, file name, and extension of the blueprint file
|
|
34
27
|
*/
|
|
35
28
|
export function findBlueprintFile(blueprintPath) {
|
|
36
|
-
|
|
37
|
-
if (
|
|
38
|
-
const pathExists = existsSync(blueprintPath);
|
|
39
|
-
if (!pathExists)
|
|
40
|
-
return null;
|
|
41
|
-
const stat = statSync(blueprintPath);
|
|
42
|
-
if (stat.isFile()) {
|
|
43
|
-
return {
|
|
44
|
-
blueprintFilePath: blueprintPath,
|
|
45
|
-
fileName: basename(blueprintPath),
|
|
46
|
-
extension: extname(blueprintPath),
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
if (stat.isDirectory()) {
|
|
50
|
-
dirToSearch = blueprintPath;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
const blueprintFile = find.any(SUPPORTED_FILE_NAMES, { cwd: dirToSearch });
|
|
54
|
-
if (!blueprintFile)
|
|
29
|
+
const blueprintFilePath = findBlueprintFilePath(blueprintPath);
|
|
30
|
+
if (!blueprintFilePath)
|
|
55
31
|
return null;
|
|
56
32
|
return {
|
|
57
|
-
blueprintFilePath
|
|
58
|
-
fileName: basename(
|
|
59
|
-
extension: extname(
|
|
33
|
+
blueprintFilePath,
|
|
34
|
+
fileName: basename(blueprintFilePath),
|
|
35
|
+
extension: extname(blueprintFilePath),
|
|
60
36
|
};
|
|
61
37
|
}
|
|
62
38
|
/**
|
|
63
39
|
* Load a blueprint file from disk: read JSON or import+execute a JS/TS module.
|
|
64
40
|
* Returns the raw blueprint data and the module reference (if dynamic).
|
|
41
|
+
* @see {@link loadBlueprintFileFromDisk} in `@sanity/blueprints/resolve`
|
|
65
42
|
*/
|
|
66
43
|
export async function loadBlueprintFile(fileInfo) {
|
|
67
|
-
const { blueprintFilePath, fileName
|
|
68
|
-
let rawBlueprint;
|
|
69
|
-
let blueprintModule;
|
|
44
|
+
const { blueprintFilePath, fileName } = fileInfo;
|
|
70
45
|
try {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
blueprintModule = mod.default;
|
|
81
|
-
break;
|
|
82
|
-
}
|
|
83
|
-
case '.ts': {
|
|
84
|
-
const jiti = createJiti(dirname(blueprintFilePath));
|
|
85
|
-
const modDefault = await jiti.import(pathToFileURL(blueprintFilePath).href, { default: true });
|
|
86
|
-
blueprintModule = modDefault;
|
|
87
|
-
break;
|
|
88
|
-
}
|
|
89
|
-
default:
|
|
90
|
-
throw Error(`Unsupported Blueprint manifest extension: ${extension}`);
|
|
91
|
-
}
|
|
46
|
+
const { blueprint, module } = await loadBlueprintFileFromDisk(blueprintFilePath, {
|
|
47
|
+
// Use jiti without module cache to avoid stale loads
|
|
48
|
+
loader: (path) => {
|
|
49
|
+
return createJiti(path, { moduleCache: false }).import(pathToFileURL(path).href, {
|
|
50
|
+
default: true,
|
|
51
|
+
});
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
return { rawBlueprint: { ...blueprint }, module };
|
|
92
55
|
}
|
|
93
56
|
catch (err) {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
// Dynamic modules: extract attached properties, then execute to get raw blueprint
|
|
97
|
-
if (blueprintModule) {
|
|
98
|
-
if (typeof blueprintModule === 'function') {
|
|
99
|
-
try {
|
|
100
|
-
rawBlueprint = blueprintModule();
|
|
101
|
-
}
|
|
102
|
-
catch {
|
|
103
|
-
throw Error(`Error executing Blueprint manifest: ${fileName}`);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
else {
|
|
107
|
-
throw Error(`Blueprint manifest ${fileName} must export a default function.`);
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
if (typeof rawBlueprint === 'undefined') {
|
|
111
|
-
throw Error('Could not read Blueprint manifest.');
|
|
57
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
58
|
+
throw Error(`Could not parse Blueprint manifest: ${fileName}\n${message}`);
|
|
112
59
|
}
|
|
113
|
-
return { rawBlueprint, module: blueprintModule };
|
|
114
60
|
}
|
|
115
61
|
/**
|
|
116
62
|
* Run the blueprint parser/validator on raw blueprint data.
|
|
@@ -142,7 +88,7 @@ export function parseBlueprintContent(rawBlueprint, options) {
|
|
|
142
88
|
/**
|
|
143
89
|
* Find, load, and parse a local blueprint file in one step.
|
|
144
90
|
* Does not read the config file or resolve IDs -- callers that need
|
|
145
|
-
* scope/stack information should use `readConfigFile` + `
|
|
91
|
+
* scope/stack information should use `readConfigFile` + `resolveStackConfig` separately.
|
|
146
92
|
*
|
|
147
93
|
* @param blueprintPath Path to a blueprint file or directory containing one
|
|
148
94
|
* @param options.validateResources Whether to validate function resources
|
|
@@ -165,7 +111,7 @@ export async function loadAndParseBlueprint(blueprintPath, options = { validateR
|
|
|
165
111
|
* Reads the blueprint file from disk and parses it.
|
|
166
112
|
* Resolves IDs from environment > blueprint module > config file.
|
|
167
113
|
* Can infer stackId from projectId for legacy ST-<projectId> stacks.
|
|
168
|
-
* @see {@link loadBlueprintFile} {@link readConfigFile} {@link
|
|
114
|
+
* @see {@link loadBlueprintFile} {@link readConfigFile} {@link resolveStackConfig} {@link parseBlueprintContent}
|
|
169
115
|
* @todo deprecate in favor of decomposed functions
|
|
170
116
|
* @returns Known information about the Blueprint, config, and Stack
|
|
171
117
|
*/
|
|
@@ -180,7 +126,7 @@ export async function readLocalBlueprint(logger, validate, blueprintPath) {
|
|
|
180
126
|
// 2. Read the config file
|
|
181
127
|
const blueprintConfig = readConfigFile(fileInfo.blueprintFilePath);
|
|
182
128
|
// 3. Resolve IDs: env > module > config
|
|
183
|
-
const resolved =
|
|
129
|
+
const resolved = resolveStackConfig({
|
|
184
130
|
module: loaded.module,
|
|
185
131
|
config: blueprintConfig,
|
|
186
132
|
});
|
|
@@ -9,6 +9,7 @@ export interface BlueprintsConfig extends ConfigUpdate {
|
|
|
9
9
|
blueprintConfigVersion?: typeof BLUEPRINT_CONFIG_VERSION;
|
|
10
10
|
runtimeCliVersion?: typeof RUNTIME_CLI_VERSION;
|
|
11
11
|
updatedAt?: number;
|
|
12
|
+
internalEnv?: string;
|
|
12
13
|
}
|
|
13
14
|
export interface LocatedBlueprintsConfig extends BlueprintsConfig {
|
|
14
15
|
configPath: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
2
|
import { dirname, join } from 'node:path';
|
|
3
|
-
import { cwd } from 'node:process';
|
|
3
|
+
import { cwd, env } from 'node:process';
|
|
4
4
|
import config, { BLUEPRINT_CONFIG_DIR, BLUEPRINT_CONFIG_FILE, BLUEPRINT_CONFIG_VERSION, RUNTIME_CLI_VERSION, } from '../../config.js';
|
|
5
5
|
import { getProject } from '../sanity/projects.js';
|
|
6
6
|
import { listStacks } from './stacks.js';
|
|
@@ -48,6 +48,12 @@ export function writeConfigFile(blueprintFilePath, options) {
|
|
|
48
48
|
config.blueprintConfigVersion = BLUEPRINT_CONFIG_VERSION;
|
|
49
49
|
config.runtimeCliVersion = RUNTIME_CLI_VERSION;
|
|
50
50
|
config.updatedAt = Date.now();
|
|
51
|
+
if (env.SANITY_INTERNAL_ENV) {
|
|
52
|
+
config.internalEnv = env.SANITY_INTERNAL_ENV;
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
delete config.internalEnv;
|
|
56
|
+
}
|
|
51
57
|
writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
52
58
|
return config;
|
|
53
59
|
}
|
package/dist/baseCommands.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// * https://oclif.io/docs/base_class
|
|
2
2
|
import { Command, CommandHelp, Errors, Flags as OclifFlags } from '@oclif/core';
|
|
3
|
+
import { resolveStackConfig } from '@sanity/blueprints/resolve';
|
|
3
4
|
import { findBlueprintFile, loadBlueprintFile, parseBlueprintContent, } from './actions/blueprints/blueprint.js';
|
|
4
5
|
import { backfillProjectBasedStackId, readConfigFile, } from './actions/blueprints/config.js';
|
|
5
|
-
import { resolveIds } from './actions/blueprints/resolve.js';
|
|
6
6
|
import { getStack, resolveStackIdByNameOrId } from './actions/blueprints/stacks.js';
|
|
7
7
|
import config from './config.js';
|
|
8
8
|
import { CI_SETUP_DOCS_URL } from './constants.js';
|
|
@@ -295,8 +295,8 @@ export class ResolvedCommand extends RuntimeCommand {
|
|
|
295
295
|
};
|
|
296
296
|
}
|
|
297
297
|
// 4. Resolve IDs
|
|
298
|
-
const resolved =
|
|
299
|
-
|
|
298
|
+
const resolved = resolveStackConfig({
|
|
299
|
+
overrides: {
|
|
300
300
|
projectId: this.flags['project-id'],
|
|
301
301
|
organizationId: this.flags['organization-id'],
|
|
302
302
|
},
|
package/dist/config.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export declare const BLUEPRINT_CONFIG_VERSION = "v2025-05-08";
|
|
2
2
|
export declare const BLUEPRINTS_API_VERSION: string;
|
|
3
|
-
export
|
|
4
|
-
export declare const BLUEPRINT_CONFIG_FILE = "blueprint.config.json";
|
|
3
|
+
export { STACK_CONFIG_DIR as BLUEPRINT_CONFIG_DIR, STACK_CONFIG_FILE as BLUEPRINT_CONFIG_FILE, } from '@sanity/blueprints/resolve';
|
|
5
4
|
export declare const RUNTIME_CLI_NAME = "@sanity/runtime-cli";
|
|
6
5
|
export declare let RUNTIME_CLI_VERSION: string | undefined;
|
|
7
6
|
export declare const RUNTIME_CLI_USER_AGENT: string;
|
package/dist/config.js
CHANGED
|
@@ -8,8 +8,7 @@ export const BLUEPRINT_CONFIG_VERSION = 'v2025-05-08';
|
|
|
8
8
|
// Default API version for Blueprints service calls.
|
|
9
9
|
// Overridable globally via env, or per-endpoint via the `version` arg to `blueprintsUrl`.
|
|
10
10
|
export const BLUEPRINTS_API_VERSION = env.SANITY_BLUEPRINTS_API_VERSION ?? 'v2026-06-15';
|
|
11
|
-
export
|
|
12
|
-
export const BLUEPRINT_CONFIG_FILE = 'blueprint.config.json';
|
|
11
|
+
export { STACK_CONFIG_DIR as BLUEPRINT_CONFIG_DIR, STACK_CONFIG_FILE as BLUEPRINT_CONFIG_FILE, } from '@sanity/blueprints/resolve';
|
|
13
12
|
export const RUNTIME_CLI_NAME = '@sanity/runtime-cli';
|
|
14
13
|
export let RUNTIME_CLI_VERSION;
|
|
15
14
|
try {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { readFileSync } from 'node:fs';
|
|
2
2
|
import { dirname } from 'node:path';
|
|
3
3
|
import { arch, cwd, env, version as nodeVersion, platform } from 'node:process';
|
|
4
|
+
import { resolveStackConfig } from '@sanity/blueprints/resolve';
|
|
4
5
|
import { formatDateTime } from '@sanity/cli-core/dates';
|
|
5
6
|
import * as resolve from 'empathic/resolve';
|
|
6
7
|
import { loadAndParseBlueprint, } from '../../actions/blueprints/blueprint.js';
|
|
7
8
|
import { readConfigFile } from '../../actions/blueprints/config.js';
|
|
8
|
-
import { resolveIds } from '../../actions/blueprints/resolve.js';
|
|
9
9
|
import { getStack } from '../../actions/blueprints/stacks.js';
|
|
10
10
|
import config, { RUNTIME_CLI_VERSION } from '../../config.js';
|
|
11
11
|
import { presentBlueprintParserErrors } from '../../utils/display/errors.js';
|
|
@@ -92,7 +92,7 @@ export async function blueprintDoctorCore(options) {
|
|
|
92
92
|
validateResources: options.validateResources || false,
|
|
93
93
|
});
|
|
94
94
|
const blueprintConfig = readConfigFile(blueprint.fileInfo.blueprintFilePath);
|
|
95
|
-
const resolved =
|
|
95
|
+
const resolved = resolveStackConfig({
|
|
96
96
|
module: blueprint.module,
|
|
97
97
|
config: blueprintConfig,
|
|
98
98
|
});
|
|
@@ -125,6 +125,16 @@ async function handleExistingBlueprint(options) {
|
|
|
125
125
|
error: 'Flag --example cannot be used with an existing Blueprint.',
|
|
126
126
|
};
|
|
127
127
|
}
|
|
128
|
+
const existingBlueprint = await readLocalBlueprint(log, { resources: validateResources || false }, existingBlueprintFile.blueprintFilePath);
|
|
129
|
+
const hasStack = Boolean(existingBlueprint.blueprintConfig?.stackId);
|
|
130
|
+
if (hasStack) {
|
|
131
|
+
const overwrite = await confirm({
|
|
132
|
+
message: 'This Blueprint has an existing Stack. Are you sure you want to re-initialize?',
|
|
133
|
+
default: true,
|
|
134
|
+
});
|
|
135
|
+
if (!overwrite)
|
|
136
|
+
return { success: false, error: 'Initialization cancelled.' };
|
|
137
|
+
}
|
|
128
138
|
// --stack-name with a scope flag means create a new stack before configuring
|
|
129
139
|
let resolvedStackId = flagStackId;
|
|
130
140
|
if (!resolvedStackId && flagStackName) {
|
|
@@ -142,7 +152,7 @@ async function handleExistingBlueprint(options) {
|
|
|
142
152
|
}
|
|
143
153
|
// unknown intent, prompt for confirmation
|
|
144
154
|
const flagProvidedConfig = [flagProjectId, flagOrganizationId, flagStackId].some(Boolean);
|
|
145
|
-
if (!flagProvidedConfig && !flagStackName) {
|
|
155
|
+
if (!flagProvidedConfig && !hasStack && !flagStackName) {
|
|
146
156
|
const overwrite = await confirm({
|
|
147
157
|
message: "This Blueprint doesn't have a deployment Stack yet. Configure one now?",
|
|
148
158
|
default: true,
|
|
@@ -150,7 +160,6 @@ async function handleExistingBlueprint(options) {
|
|
|
150
160
|
if (!overwrite)
|
|
151
161
|
return { success: false, error: 'Initialization cancelled.' };
|
|
152
162
|
}
|
|
153
|
-
const existingBlueprint = await readLocalBlueprint(log, { resources: validateResources || false }, existingBlueprintFile.blueprintFilePath);
|
|
154
163
|
return blueprintConfigCore({
|
|
155
164
|
blueprint: existingBlueprint,
|
|
156
165
|
bin,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { dirname } from 'node:path';
|
|
2
2
|
import { testAction } from '../../actions/functions/test.js';
|
|
3
3
|
import config from '../../config.js';
|
|
4
|
-
import { STEP_PHASE_GLYPH } from '../../constants.js';
|
|
4
|
+
import { SANITY_FUNCTION_DURABLE, STEP_PHASE_GLYPH } from '../../constants.js';
|
|
5
5
|
import { resolveDeployedResources } from '../../utils/blueprints/resolve-deployed-resources.js';
|
|
6
6
|
import { createDurableJsonCollector } from '../../utils/functions/durable-logs.js';
|
|
7
7
|
import { findFunctionInResources, getFunctionNames } from '../../utils/functions/find.js';
|
|
@@ -88,15 +88,38 @@ export async function functionTestCore(options) {
|
|
|
88
88
|
* surfaced after the spinner resolves, including failed ones — a downstream
|
|
89
89
|
* error is fire-and-forget (it doesn't reject the caller) but is still shown.
|
|
90
90
|
*/
|
|
91
|
-
const runNested = async (nestedName, nestedPayload, ctx, depth, callStack) => {
|
|
91
|
+
const runNested = async (nestedName, nestedPayload, ctx, depth, callStack, metadata) => {
|
|
92
92
|
const order = ++nestedOrder;
|
|
93
93
|
const nestedResource = findFunctionInResources(blueprint.resources, nestedName);
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
94
|
+
const isLiveDurable = metadata?.origin === 'step.delegate' && nestedResource.type === SANITY_FUNCTION_DURABLE;
|
|
95
|
+
if (isLiveDurable) {
|
|
96
|
+
log(`↳ BEGIN: invoke('${nestedName}')`);
|
|
97
|
+
}
|
|
98
|
+
try {
|
|
99
|
+
const result = await runFunction(nestedResource, { payload: nestedPayload, event: 'nested' }, { ...ctx, resources: resolvedResources }, { depth, callStack, onNestedInvoke: runNested, onStepEvent });
|
|
100
|
+
if (result.error && isLiveDurable) {
|
|
101
|
+
log(result.error.stack || result.error.message);
|
|
102
|
+
}
|
|
103
|
+
nestedRuns.push({
|
|
104
|
+
order,
|
|
105
|
+
name: nestedName,
|
|
106
|
+
logs: result.logs,
|
|
107
|
+
error: result.error,
|
|
108
|
+
isLiveDurable,
|
|
109
|
+
});
|
|
110
|
+
return result;
|
|
111
|
+
}
|
|
112
|
+
finally {
|
|
113
|
+
if (isLiveDurable) {
|
|
114
|
+
log(`↳ END: invoke('${nestedName}')`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
97
117
|
};
|
|
98
118
|
const logNestedRuns = () => {
|
|
99
119
|
for (const run of [...nestedRuns].sort((a, b) => a.order - b.order)) {
|
|
120
|
+
// Skip if is Durable so log ordering is retained
|
|
121
|
+
if (run.isLiveDurable)
|
|
122
|
+
continue;
|
|
100
123
|
log(`↳ BEGIN: invoke('${run.name}')`);
|
|
101
124
|
// Show any logs received
|
|
102
125
|
if (run.logs?.trim()) {
|
package/dist/server/app.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { existsSync, readFileSync, watchFile } from 'node:fs';
|
|
2
2
|
import * as http from 'node:http';
|
|
3
3
|
import { dirname } from 'node:path';
|
|
4
|
+
import { resolveStackConfig } from '@sanity/blueprints/resolve';
|
|
4
5
|
import { default as mime } from 'mime-types';
|
|
5
6
|
import { WebSocket, WebSocketServer } from 'ws';
|
|
6
7
|
import { findBlueprintFile, loadAndParseBlueprint } from '../actions/blueprints/blueprint.js';
|
|
7
8
|
import { readConfigFile } from '../actions/blueprints/config.js';
|
|
8
|
-
import { resolveIds } from '../actions/blueprints/resolve.js';
|
|
9
9
|
import config from '../config.js';
|
|
10
10
|
import { isRecord } from '../utils/is-record.js';
|
|
11
11
|
import { isEventType, isGroqContextOptions, } from '../utils/types.js';
|
|
@@ -47,7 +47,7 @@ const app = (host, port, validateResources, executionOptions) => {
|
|
|
47
47
|
const blueprint = await loadAndParseBlueprint(undefined, { validateResources });
|
|
48
48
|
const { parsedBlueprint, fileInfo, module: blueprintModule } = blueprint;
|
|
49
49
|
const blueprintConfig = readConfigFile(fileInfo.blueprintFilePath);
|
|
50
|
-
const { projectId, organizationId } =
|
|
50
|
+
const { projectId, organizationId } = resolveStackConfig({
|
|
51
51
|
module: blueprintModule,
|
|
52
52
|
config: blueprintConfig,
|
|
53
53
|
});
|
|
@@ -191,7 +191,7 @@ body {
|
|
|
191
191
|
.border-right {
|
|
192
192
|
border-right-width: 1px;
|
|
193
193
|
border-right-style: solid;
|
|
194
|
-
border-
|
|
194
|
+
border-right-color: var(--card-border-color);
|
|
195
195
|
}
|
|
196
196
|
|
|
197
197
|
.hr-border {
|
|
@@ -413,6 +413,13 @@ ol[type='content'] li:hover:not(.selected:not(.selected)) {
|
|
|
413
413
|
border-right: none;
|
|
414
414
|
}
|
|
415
415
|
|
|
416
|
+
fieldset {
|
|
417
|
+
& :is(input:not([role='switch']), select, textarea) {
|
|
418
|
+
border: 1px solid light-dark(var(--gray-200), var(--gray-800)) !important;
|
|
419
|
+
border-radius: var(--radius-2);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
|
|
416
423
|
& :is(input:not([is='switch']), select, textarea) {
|
|
417
424
|
border: 1px solid light-dark(var(--gray-200), var(--gray-800)) !important;
|
|
418
425
|
border-radius: var(--radius-2);
|
|
@@ -86,7 +86,7 @@ process.on('message', async (data) => {
|
|
|
86
86
|
{
|
|
87
87
|
emit: (e) => process.send(JSON.stringify({type: 'step-event', event: e})),
|
|
88
88
|
wait: (ms) => new Promise((resolve) => setTimeout(resolve, noWait ? 0 : ms)),
|
|
89
|
-
invoke: invoker.
|
|
89
|
+
invoke: invoker.delegate,
|
|
90
90
|
},
|
|
91
91
|
)
|
|
92
92
|
} else {
|
|
@@ -10,6 +10,17 @@ export function createInvoker() {
|
|
|
10
10
|
const pending = new Map()
|
|
11
11
|
let invokeSeq = 0
|
|
12
12
|
|
|
13
|
+
function sendInvokeRequest(name, payload = {}, metadata = {}) {
|
|
14
|
+
if (typeof name !== 'string' || name.length === 0) {
|
|
15
|
+
return Promise.reject(new Error('context.invoke requires a function name'))
|
|
16
|
+
}
|
|
17
|
+
const id = String(++invokeSeq)
|
|
18
|
+
return new Promise((resolve, reject) => {
|
|
19
|
+
pending.set(id, {resolve, reject})
|
|
20
|
+
process.send(JSON.stringify({type: 'invoke-request', id, name, payload, metadata}))
|
|
21
|
+
})
|
|
22
|
+
}
|
|
23
|
+
|
|
13
24
|
/**
|
|
14
25
|
* `context.invoke(name, payload)` — ask the parent to execute another blueprint
|
|
15
26
|
* function and resolve with its return value. Sent over IPC and correlated by id.
|
|
@@ -18,14 +29,20 @@ export function createInvoker() {
|
|
|
18
29
|
* @returns {Promise<unknown>}
|
|
19
30
|
*/
|
|
20
31
|
function invoke(name, payload = {}) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
32
|
+
return sendInvokeRequest(name, payload)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* durable `step.delegate(name, payload)` — ask the parent durable to execute another blueprint function
|
|
37
|
+
* and resolve with its return value. Sent over IPC and correlated by id. Adds an `origin` field to the message so the parent can
|
|
38
|
+
* distinguish between a normal invoke and a durable delegate for logging purposes.
|
|
39
|
+
* @param {string} name
|
|
40
|
+
* @param {Record<string, unknown>} [payload]
|
|
41
|
+
* @returns {Promise<unknown>}
|
|
42
|
+
*/
|
|
43
|
+
function delegate(name, payload = {}) {
|
|
44
|
+
const metadata = {origin: 'step.delegate'}
|
|
45
|
+
return sendInvokeRequest(name, payload, metadata)
|
|
29
46
|
}
|
|
30
47
|
|
|
31
48
|
function handleResponse(msg) {
|
|
@@ -43,5 +60,5 @@ export function createInvoker() {
|
|
|
43
60
|
}
|
|
44
61
|
}
|
|
45
62
|
|
|
46
|
-
return {invoke, handleResponse}
|
|
63
|
+
return {delegate, invoke, handleResponse}
|
|
47
64
|
}
|
|
@@ -5,7 +5,7 @@ import { SANITY_FUNCTION_DURABLE } from '../../constants.js';
|
|
|
5
5
|
import { isLocalFunctionResource } from '../types.js';
|
|
6
6
|
import { findFunctionEntryPoint } from './find-entry-point.js';
|
|
7
7
|
import { transpileFunction } from './transpile/function.js';
|
|
8
|
-
const DURABLE_CONFIG_KEYS = ['event', 'concurrency', 'debounce'
|
|
8
|
+
const DURABLE_CONFIG_KEYS = ['event', 'concurrency', 'debounce'];
|
|
9
9
|
/**
|
|
10
10
|
* Extracts the blueprint config from the function source code and mutates it to the resource object.
|
|
11
11
|
* This is used for durable functions that may not have a config defined in the blueprint.
|
|
@@ -47,9 +47,6 @@ export const extractDurableConfig = async (resource, blueprintFileDir) => {
|
|
|
47
47
|
if (resource.debounce === undefined && config?.debounce !== undefined) {
|
|
48
48
|
resource.debounce = config.debounce;
|
|
49
49
|
}
|
|
50
|
-
if (resource.debounceKey === undefined && config?.debounceKey !== undefined) {
|
|
51
|
-
resource.debounceKey = config.debounceKey;
|
|
52
|
-
}
|
|
53
50
|
// Validate the resource after merging the config values
|
|
54
51
|
const errors = validateDurableFunction(resource);
|
|
55
52
|
if (errors.length > 0) {
|
|
@@ -156,14 +156,14 @@ export default async function invoke(resource, payload, context, options) {
|
|
|
156
156
|
// Resolve a nested `context.invoke(name, payload)` by re-entering the invoke
|
|
157
157
|
// pipeline via the supplied callback, then hand the result back to the child.
|
|
158
158
|
async function handleNestedInvoke(msg) {
|
|
159
|
-
const { id, name, payload: nestedPayload } = msg;
|
|
159
|
+
const { id, name, payload: nestedPayload, metadata } = msg;
|
|
160
160
|
pauseTimer();
|
|
161
161
|
const nestedStart = performance.now();
|
|
162
162
|
try {
|
|
163
163
|
if (!onNestedInvoke) {
|
|
164
164
|
throw new Error('Nested context.invoke is not supported in this context');
|
|
165
165
|
}
|
|
166
|
-
const nested = await onNestedInvoke(name, nestedPayload ?? {}, context, depth + 1, callStack);
|
|
166
|
+
const nested = await onNestedInvoke(name, nestedPayload ?? {}, context, depth + 1, callStack, metadata);
|
|
167
167
|
nestedTimings[`invoke:${name}`] =
|
|
168
168
|
(nestedTimings[`invoke:${name}`] ?? 0) + (performance.now() - nestedStart);
|
|
169
169
|
// Fire-and-forget contract: in production `context.invoke` returns once the
|
|
@@ -231,7 +231,12 @@ export default async function invoke(resource, payload, context, options) {
|
|
|
231
231
|
}
|
|
232
232
|
// Nested invoke request — handle without tearing down the child.
|
|
233
233
|
if (msg?.type === 'invoke-request') {
|
|
234
|
-
handleNestedInvoke({
|
|
234
|
+
handleNestedInvoke({
|
|
235
|
+
id: msg.id,
|
|
236
|
+
name: msg.name,
|
|
237
|
+
payload: msg.payload,
|
|
238
|
+
metadata: msg.metadata,
|
|
239
|
+
});
|
|
235
240
|
return;
|
|
236
241
|
}
|
|
237
242
|
// Terminal result message.
|
|
@@ -28,7 +28,7 @@ export function assertNestedInvokeAllowed(name, depth, callStack) {
|
|
|
28
28
|
* stack extended by this function, and normalize timings.
|
|
29
29
|
*/
|
|
30
30
|
export async function runFunction(resource, payload, context, options) {
|
|
31
|
-
const { forceColor, timeout, depth = 0, callStack = [], onNestedInvoke } = options;
|
|
31
|
+
const { forceColor, timeout, depth = 0, callStack = [], onNestedInvoke, onStepEvent } = options;
|
|
32
32
|
assertNestedInvokeAllowed(resource.name, depth, callStack);
|
|
33
33
|
const response = await invoke(resource, payload, context, {
|
|
34
34
|
forceColor,
|
|
@@ -36,6 +36,7 @@ export async function runFunction(resource, payload, context, options) {
|
|
|
36
36
|
onNestedInvoke,
|
|
37
37
|
depth,
|
|
38
38
|
callStack: [...callStack, resource.name],
|
|
39
|
+
onStepEvent,
|
|
39
40
|
});
|
|
40
41
|
return { ...response, timings: response.timings ?? {} };
|
|
41
42
|
}
|
package/dist/utils/types.d.ts
CHANGED
|
@@ -187,12 +187,15 @@ export interface InvokeExecutionOptions {
|
|
|
187
187
|
/** Don't wait the full duration during a wait durable event @internal */
|
|
188
188
|
noWait?: boolean;
|
|
189
189
|
}
|
|
190
|
+
export type NestedInvokeMetadata = {
|
|
191
|
+
origin?: 'step.delegate';
|
|
192
|
+
};
|
|
190
193
|
/**
|
|
191
194
|
* Re-entrant callback that executes a named function from the blueprint on behalf
|
|
192
195
|
* of a nested `context.invoke(name, payload)` and returns its invocation result.
|
|
193
196
|
* @internal
|
|
194
197
|
*/
|
|
195
|
-
export type NestedInvoke = (name: string, payload: Record<string, unknown>, context: InvokeContextOptions, depth: number, callStack: string[]) => Promise<InvocationResponse & {
|
|
198
|
+
export type NestedInvoke = (name: string, payload: Record<string, unknown>, context: InvokeContextOptions, depth: number, callStack: string[], metadata?: NestedInvokeMetadata) => Promise<InvocationResponse & {
|
|
196
199
|
timings: Record<string, number>;
|
|
197
200
|
}>;
|
|
198
201
|
/**
|
|
@@ -233,6 +236,7 @@ export type ChildToParentMessage = {
|
|
|
233
236
|
name: string;
|
|
234
237
|
payload: Record<string, unknown>;
|
|
235
238
|
isDurable?: boolean;
|
|
239
|
+
metadata?: NestedInvokeMetadata;
|
|
236
240
|
} | {
|
|
237
241
|
type: 'result';
|
|
238
242
|
json?: JsonInvocationResponse;
|
package/oclif.manifest.json
CHANGED
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": "17.
|
|
4
|
+
"version": "17.16.0-next.g26925c0",
|
|
5
5
|
"author": "Sanity Runtime Team",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"license": "MIT",
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"@oclif/core": "^4.14.0",
|
|
69
69
|
"@oclif/plugin-help": "^6.3.0",
|
|
70
70
|
"@sanity-labs/oclif-plugin-skills-flag": "^0.2.1",
|
|
71
|
-
"@sanity/blueprints": "^0.
|
|
71
|
+
"@sanity/blueprints": "^0.28.0",
|
|
72
72
|
"@sanity/blueprints-parser": "^0.5.0",
|
|
73
73
|
"@sanity/cli-build": "^6.3.0",
|
|
74
74
|
"@sanity/cli-core": "^3.7.0",
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import type { ScopeType } from '../../utils/types.js';
|
|
2
|
-
/**
|
|
3
|
-
* Source of a resolved config value.
|
|
4
|
-
* - flags: from CLI flags like `--project-id`
|
|
5
|
-
* - env: from the environment - usually CLI var like `SANITY_ORGANIZATION_ID`
|
|
6
|
-
* - module: from the blueprint module - undocumented escape hatch
|
|
7
|
-
* - config: from the config file - .sanity/blueprint.config.json most common
|
|
8
|
-
* - inferred: legacy `ST-<projectId>` stacks from launch
|
|
9
|
-
*/
|
|
10
|
-
export type ConfigSource = 'flags' | 'env' | 'module' | 'config' | 'inferred';
|
|
11
|
-
/** A set of optional IDs from a single source. */
|
|
12
|
-
export interface IdValues {
|
|
13
|
-
organizationId?: string;
|
|
14
|
-
projectId?: string;
|
|
15
|
-
stackId?: string;
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Sources to resolve IDs from, in descending priority.
|
|
19
|
-
* Each key maps to a source; the first non-empty value wins.
|
|
20
|
-
*
|
|
21
|
-
* - `env` defaults to reading SANITY_* process.env vars
|
|
22
|
-
* - `module` and `config` accept any object with `{organizationId?, projectId?, stackId?}`
|
|
23
|
-
*/
|
|
24
|
-
export interface IdSources {
|
|
25
|
-
flags?: IdValues | null;
|
|
26
|
-
env?: IdValues | null;
|
|
27
|
-
module?: IdValues | null;
|
|
28
|
-
config?: IdValues | null;
|
|
29
|
-
}
|
|
30
|
-
export interface ResolvedIds {
|
|
31
|
-
organizationId?: string;
|
|
32
|
-
projectId?: string;
|
|
33
|
-
stackId?: string;
|
|
34
|
-
scopeType?: ScopeType;
|
|
35
|
-
scopeId?: string;
|
|
36
|
-
sources: {
|
|
37
|
-
organizationId?: ConfigSource;
|
|
38
|
-
projectId?: ConfigSource;
|
|
39
|
-
stackId?: ConfigSource;
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Resolve organization, project, and stack IDs from a prioritized set of sources.
|
|
44
|
-
* Precedence: flags > env > module > config.
|
|
45
|
-
* Derives scopeType/scopeId from the resolved IDs (project > organization).
|
|
46
|
-
*
|
|
47
|
-
* Env vars are read from process.env by default (SANITY_ORGANIZATION_ID,
|
|
48
|
-
* SANITY_PROJECT_ID, SANITY_BLUEPRINT_STACK_ID). Pass `env` explicitly to
|
|
49
|
-
* override, or `null` to skip.
|
|
50
|
-
*/
|
|
51
|
-
export declare function resolveIds(sources?: IdSources): ResolvedIds;
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { env as processEnv } from 'node:process';
|
|
2
|
-
/**
|
|
3
|
-
* Resolve organization, project, and stack IDs from a prioritized set of sources.
|
|
4
|
-
* Precedence: flags > env > module > config.
|
|
5
|
-
* Derives scopeType/scopeId from the resolved IDs (project > organization).
|
|
6
|
-
*
|
|
7
|
-
* Env vars are read from process.env by default (SANITY_ORGANIZATION_ID,
|
|
8
|
-
* SANITY_PROJECT_ID, SANITY_BLUEPRINT_STACK_ID). Pass `env` explicitly to
|
|
9
|
-
* override, or `null` to skip.
|
|
10
|
-
*/
|
|
11
|
-
export function resolveIds(sources = {}) {
|
|
12
|
-
const envValues = sources.env !== undefined
|
|
13
|
-
? sources.env
|
|
14
|
-
: {
|
|
15
|
-
organizationId: processEnv.SANITY_ORGANIZATION_ID,
|
|
16
|
-
projectId: processEnv.SANITY_PROJECT_ID,
|
|
17
|
-
stackId: processEnv.SANITY_BLUEPRINT_STACK_ID,
|
|
18
|
-
};
|
|
19
|
-
const ordered = [
|
|
20
|
-
{ source: 'flags', values: sources.flags },
|
|
21
|
-
{ source: 'env', values: envValues },
|
|
22
|
-
{ source: 'module', values: sources.module },
|
|
23
|
-
{ source: 'config', values: sources.config },
|
|
24
|
-
];
|
|
25
|
-
const result = { sources: {} };
|
|
26
|
-
for (const { source, values } of ordered) {
|
|
27
|
-
if (values === null || values === undefined)
|
|
28
|
-
continue;
|
|
29
|
-
if (!result.organizationId && values.organizationId) {
|
|
30
|
-
result.organizationId = values.organizationId;
|
|
31
|
-
result.sources.organizationId = source;
|
|
32
|
-
}
|
|
33
|
-
if (!result.projectId && values.projectId) {
|
|
34
|
-
result.projectId = values.projectId;
|
|
35
|
-
result.sources.projectId = source;
|
|
36
|
-
}
|
|
37
|
-
if (!result.stackId && values.stackId) {
|
|
38
|
-
result.stackId = values.stackId;
|
|
39
|
-
result.sources.stackId = source;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
// Scope is as specific as possible; project > organization
|
|
43
|
-
if (result.projectId) {
|
|
44
|
-
result.scopeType = 'project';
|
|
45
|
-
result.scopeId = result.projectId;
|
|
46
|
-
}
|
|
47
|
-
else if (result.organizationId) {
|
|
48
|
-
result.scopeType = 'organization';
|
|
49
|
-
result.scopeId = result.organizationId;
|
|
50
|
-
}
|
|
51
|
-
return result;
|
|
52
|
-
}
|