@sanity/runtime-cli 17.8.0-next.g5972da4 → 17.9.0-blueprinit.g14aaebd
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 +21 -20
- package/dist/actions/blueprinit/manifest.d.ts +46 -0
- package/dist/actions/blueprinit/manifest.js +121 -0
- package/dist/actions/blueprinit/quote.d.ts +6 -0
- package/dist/actions/blueprinit/quote.js +8 -0
- package/dist/actions/blueprinit/studio.d.ts +6 -0
- package/dist/actions/blueprinit/studio.js +43 -0
- package/dist/actions/blueprinit/templates.d.ts +73 -0
- package/dist/actions/blueprinit/templates.js +138 -0
- package/dist/actions/blueprinit/versions.d.ts +8 -0
- package/dist/actions/blueprinit/versions.js +11 -0
- package/dist/actions/blueprinit/workspace.d.ts +27 -0
- package/dist/actions/blueprinit/workspace.js +145 -0
- package/dist/actions/blueprints/pre-deploy.js +2 -0
- package/dist/actions/blueprints/stacks.d.ts +1 -0
- package/dist/actions/sanity/create-project.d.ts +19 -0
- package/dist/actions/sanity/create-project.js +32 -0
- package/dist/actions/sanity/datasets.d.ts +15 -0
- package/dist/actions/sanity/datasets.js +26 -0
- package/dist/commands/functions/test.d.ts +1 -0
- package/dist/commands/functions/test.js +5 -0
- package/dist/commands/init.d.ts +21 -0
- package/dist/commands/init.js +82 -0
- package/dist/cores/blueprinit/adopt.d.ts +6 -0
- package/dist/cores/blueprinit/adopt.js +137 -0
- package/dist/cores/blueprinit/columns.d.ts +26 -0
- package/dist/cores/blueprinit/columns.js +27 -0
- package/dist/cores/blueprinit/finish.d.ts +15 -0
- package/dist/cores/blueprinit/finish.js +72 -0
- package/dist/cores/blueprinit/fresh.d.ts +3 -0
- package/dist/cores/blueprinit/fresh.js +219 -0
- package/dist/cores/blueprinit/naming.d.ts +27 -0
- package/dist/cores/blueprinit/naming.js +43 -0
- package/dist/cores/blueprinit/preview.d.ts +34 -0
- package/dist/cores/blueprinit/preview.js +110 -0
- package/dist/cores/blueprinit/project-choice.d.ts +28 -0
- package/dist/cores/blueprinit/project-choice.js +82 -0
- package/dist/cores/blueprinit/prompts.d.ts +13 -0
- package/dist/cores/blueprinit/prompts.js +42 -0
- package/dist/cores/blueprinit/results.d.ts +8 -0
- package/dist/cores/blueprinit/results.js +4 -0
- package/dist/cores/blueprinit/selection.d.ts +15 -0
- package/dist/cores/blueprinit/selection.js +90 -0
- package/dist/cores/blueprinit/stack-name.d.ts +39 -0
- package/dist/cores/blueprinit/stack-name.js +56 -0
- package/dist/cores/blueprinit/target.d.ts +33 -0
- package/dist/cores/blueprinit/target.js +80 -0
- package/dist/cores/blueprinit/types.d.ts +20 -0
- package/dist/cores/blueprinit/types.js +1 -0
- package/dist/cores/blueprinit.d.ts +7 -0
- package/dist/cores/blueprinit.js +64 -0
- package/dist/cores/functions/test.js +41 -26
- package/dist/utils/display/intro.d.ts +6 -0
- package/dist/utils/display/intro.js +63 -0
- package/dist/utils/functions/child-process-wrapper.js +3 -2
- package/dist/utils/functions/child-runtime/durable.d.ts +2 -2
- package/dist/utils/functions/child-runtime/durable.js +52 -2
- package/dist/utils/functions/durable-logs.d.ts +16 -0
- package/dist/utils/functions/durable-logs.js +52 -0
- package/dist/utils/functions/invoke/local.js +2 -1
- package/dist/utils/types.d.ts +18 -4
- package/oclif.manifest.json +159 -1
- package/package.json +1 -1
- package/skills/init.md +199 -0
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.9.0-blueprinit.g14aaebd/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.9.0-blueprinit.g14aaebd/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.9.0-blueprinit.g14aaebd/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.9.0-blueprinit.g14aaebd/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.9.0-blueprinit.g14aaebd/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.9.0-blueprinit.g14aaebd/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.9.0-blueprinit.g14aaebd/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.9.0-blueprinit.g14aaebd/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.9.0-blueprinit.g14aaebd/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.9.0-blueprinit.g14aaebd/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.9.0-blueprinit.g14aaebd/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.9.0-blueprinit.g14aaebd/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.9.0-blueprinit.g14aaebd/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.9.0-blueprinit.g14aaebd/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.9.0-blueprinit.g14aaebd/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.9.0-blueprinit.g14aaebd/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.9.0-blueprinit.g14aaebd/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.9.0-blueprinit.g14aaebd/src/commands/functions/logs.ts)_
|
|
782
782
|
|
|
783
783
|
## `sanity-run functions test [NAME]`
|
|
784
784
|
|
|
@@ -790,7 +790,7 @@ USAGE
|
|
|
790
790
|
<value>] | | | --file-before <value> | --file-after <value> | --document-id-before <value> | --document-id-after
|
|
791
791
|
<value>] [--data-after <value> | | | | | | | ] [-e create|update|delete] [-t <value>] [-a <value>]
|
|
792
792
|
[--with-user-token] [--media-library-id <value> | [--project-id <value> | --organization-id <value>] | --dataset
|
|
793
|
-
<value>]
|
|
793
|
+
<value>] [--no-wait]
|
|
794
794
|
|
|
795
795
|
ARGUMENTS
|
|
796
796
|
[NAME] The name of the Sanity Function
|
|
@@ -812,6 +812,7 @@ FLAGS
|
|
|
812
812
|
--file-before=<value> Original document
|
|
813
813
|
--json Format output as json
|
|
814
814
|
--media-library-id=<value> Sanity Media Library ID to use
|
|
815
|
+
--no-wait Skip durable wait delays instead of sleeping
|
|
815
816
|
--organization-id=<value> Sanity organization ID used to scope Blueprint and Stack
|
|
816
817
|
--project-id=<value> Sanity project ID used to scope Blueprint and Stack
|
|
817
818
|
--with-user-token Prime access token from CLI config
|
|
@@ -835,7 +836,7 @@ EXAMPLES
|
|
|
835
836
|
$ sanity-run functions test <name> --event update --data-before '{ "title": "before" }' --data-after '{ "title": "after" }'
|
|
836
837
|
```
|
|
837
838
|
|
|
838
|
-
_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.9.0-blueprinit.g14aaebd/src/commands/functions/test.ts)_
|
|
839
840
|
|
|
840
841
|
## `sanity-run help [COMMAND]`
|
|
841
842
|
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export declare const STARTER_DOCUMENT_TYPE = "post";
|
|
2
|
+
export declare const STARTER_FUNCTION_NAME = "set-slug";
|
|
3
|
+
export declare const DEFAULT_STUDIO_NAME = "studio";
|
|
4
|
+
/**
|
|
5
|
+
* Whether the Blueprint takes ownership of an existing dataset or makes a new one.
|
|
6
|
+
*
|
|
7
|
+
* A project this command just created has no datasets, so its Blueprint creates one.
|
|
8
|
+
* A project the user already had has the dataset they picked, so its Blueprint attaches.
|
|
9
|
+
*/
|
|
10
|
+
export type DatasetAction = 'attach' | 'create';
|
|
11
|
+
export interface BlueprintManifestOptions {
|
|
12
|
+
projectName: string;
|
|
13
|
+
displayName: string;
|
|
14
|
+
projectId: string;
|
|
15
|
+
datasetName: string;
|
|
16
|
+
datasetAction: DatasetAction;
|
|
17
|
+
studioName: string;
|
|
18
|
+
studioSlug: string;
|
|
19
|
+
studioSrc: string;
|
|
20
|
+
studioOrigin: string;
|
|
21
|
+
withFunction: boolean;
|
|
22
|
+
}
|
|
23
|
+
export declare function renderBlueprint(options: BlueprintManifestOptions): string;
|
|
24
|
+
export declare function hostedStudioOrigin(studioName: string, sanityEnv?: string): string;
|
|
25
|
+
/**
|
|
26
|
+
* The Blueprint-local name for the attached project.
|
|
27
|
+
*
|
|
28
|
+
* Kept apart from the Stack name so a default Stack name can never collide with a
|
|
29
|
+
* resource name, and suffixed so a reference states which resource it reads.
|
|
30
|
+
*/
|
|
31
|
+
export declare function projectResourceName(baseName: string): string;
|
|
32
|
+
/** The Blueprint-local name for the Studio's credentialed CORS origin. */
|
|
33
|
+
export declare function corsResourceName(studioName: string): string;
|
|
34
|
+
/** Where a fresh scaffold puts the Studio, relative to the Blueprint. */
|
|
35
|
+
export declare function studioSourcePath(studioName: string): string;
|
|
36
|
+
/**
|
|
37
|
+
* The default name for the new Stack, which is also the hosted Studio slug.
|
|
38
|
+
*
|
|
39
|
+
* A Studio slug must be unique across every Sanity organization and no API can report
|
|
40
|
+
* whether one is free, so the default carries both the project and the dataset to make
|
|
41
|
+
* an accidental match unlikely.
|
|
42
|
+
*/
|
|
43
|
+
export declare function defaultStackName(baseName: string, datasetName: string): string;
|
|
44
|
+
/** The slug form of a project display name, falling back to its ID. */
|
|
45
|
+
export declare function projectBaseName(displayName: string, projectId: string): string;
|
|
46
|
+
export declare function slugify(value: string): string;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { quote } from './quote.js';
|
|
2
|
+
export const STARTER_DOCUMENT_TYPE = 'post';
|
|
3
|
+
export const STARTER_FUNCTION_NAME = 'set-slug';
|
|
4
|
+
export const DEFAULT_STUDIO_NAME = 'studio';
|
|
5
|
+
export function renderBlueprint(options) {
|
|
6
|
+
const { projectName, displayName, projectId, datasetName, datasetAction, studioName, studioSlug, studioSrc, studioOrigin, withFunction, } = options;
|
|
7
|
+
const definers = [
|
|
8
|
+
'defineBlueprint',
|
|
9
|
+
'defineCorsOrigin',
|
|
10
|
+
'defineDataset',
|
|
11
|
+
'defineProject',
|
|
12
|
+
'defineStudio',
|
|
13
|
+
];
|
|
14
|
+
if (withFunction)
|
|
15
|
+
definers.splice(3, 0, 'defineDocumentFunction');
|
|
16
|
+
const project = quote(`$.resources.${projectName}.id`);
|
|
17
|
+
// `retain` is spelled out on both paths. The coordinator defaults to `allow`, and neither
|
|
18
|
+
// the dataset nor the project provider overrides that, so a created dataset would
|
|
19
|
+
// otherwise be deleted, with its content, by `blueprints destroy`.
|
|
20
|
+
const datasetLifecycle = datasetAction === 'attach'
|
|
21
|
+
? ` lifecycle: {
|
|
22
|
+
deletionPolicy: 'retain',
|
|
23
|
+
ownershipAction: {
|
|
24
|
+
type: 'attach',
|
|
25
|
+
id: ${quote(datasetName)},
|
|
26
|
+
projectId: ${project},
|
|
27
|
+
},
|
|
28
|
+
},`
|
|
29
|
+
: ` lifecycle: {deletionPolicy: 'retain'},`;
|
|
30
|
+
const inlineImport = `import {${definers.join(', ')}} from '@sanity/blueprints'`;
|
|
31
|
+
const imports = inlineImport.length > 100
|
|
32
|
+
? `import {\n${definers.map((definer) => ` ${definer},`).join('\n')}\n} from '@sanity/blueprints'`
|
|
33
|
+
: inlineImport;
|
|
34
|
+
const functionResource = withFunction
|
|
35
|
+
? ` defineDocumentFunction({
|
|
36
|
+
name: ${quote(STARTER_FUNCTION_NAME)},
|
|
37
|
+
displayName: 'Set slug',
|
|
38
|
+
project: ${project},
|
|
39
|
+
event: {
|
|
40
|
+
on: ['create', 'update'],
|
|
41
|
+
filter: "_type == '${STARTER_DOCUMENT_TYPE}' && !defined(slug.current)",
|
|
42
|
+
projection: '{_id, title, slug}',
|
|
43
|
+
},
|
|
44
|
+
}),
|
|
45
|
+
`
|
|
46
|
+
: '';
|
|
47
|
+
return `${imports}
|
|
48
|
+
|
|
49
|
+
export default defineBlueprint({
|
|
50
|
+
resources: [
|
|
51
|
+
defineProject({
|
|
52
|
+
name: ${quote(projectName)},
|
|
53
|
+
displayName: ${quote(displayName)},
|
|
54
|
+
lifecycle: {
|
|
55
|
+
deletionPolicy: 'retain',
|
|
56
|
+
ownershipAction: {type: 'attach', id: ${quote(projectId)}},
|
|
57
|
+
},
|
|
58
|
+
}),
|
|
59
|
+
defineDataset({
|
|
60
|
+
project: ${project},
|
|
61
|
+
name: ${quote(datasetName)},
|
|
62
|
+
${datasetLifecycle}
|
|
63
|
+
}),
|
|
64
|
+
defineCorsOrigin({
|
|
65
|
+
project: ${project},
|
|
66
|
+
name: ${quote(corsResourceName(studioName))},
|
|
67
|
+
origin: ${quote(studioOrigin)},
|
|
68
|
+
allowCredentials: true,
|
|
69
|
+
}),
|
|
70
|
+
defineStudio({
|
|
71
|
+
project: ${project},
|
|
72
|
+
name: ${quote(studioName)},
|
|
73
|
+
slug: ${quote(studioSlug)},
|
|
74
|
+
title: ${quote(displayName)},
|
|
75
|
+
src: ${quote(studioSrc)},
|
|
76
|
+
}),
|
|
77
|
+
${functionResource} ],
|
|
78
|
+
})
|
|
79
|
+
`;
|
|
80
|
+
}
|
|
81
|
+
export function hostedStudioOrigin(studioName, sanityEnv) {
|
|
82
|
+
const hostname = sanityEnv?.toLowerCase() === 'staging' ? 'studio.sanity.work' : 'sanity.studio';
|
|
83
|
+
return `https://${studioName}.${hostname}`;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* The Blueprint-local name for the attached project.
|
|
87
|
+
*
|
|
88
|
+
* Kept apart from the Stack name so a default Stack name can never collide with a
|
|
89
|
+
* resource name, and suffixed so a reference states which resource it reads.
|
|
90
|
+
*/
|
|
91
|
+
export function projectResourceName(baseName) {
|
|
92
|
+
return `${baseName}-project`;
|
|
93
|
+
}
|
|
94
|
+
/** The Blueprint-local name for the Studio's credentialed CORS origin. */
|
|
95
|
+
export function corsResourceName(studioName) {
|
|
96
|
+
return `${studioName}-cors`;
|
|
97
|
+
}
|
|
98
|
+
/** Where a fresh scaffold puts the Studio, relative to the Blueprint. */
|
|
99
|
+
export function studioSourcePath(studioName) {
|
|
100
|
+
return `studios/${studioName}`;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* The default name for the new Stack, which is also the hosted Studio slug.
|
|
104
|
+
*
|
|
105
|
+
* A Studio slug must be unique across every Sanity organization and no API can report
|
|
106
|
+
* whether one is free, so the default carries both the project and the dataset to make
|
|
107
|
+
* an accidental match unlikely.
|
|
108
|
+
*/
|
|
109
|
+
export function defaultStackName(baseName, datasetName) {
|
|
110
|
+
return `${baseName}-${datasetName}`;
|
|
111
|
+
}
|
|
112
|
+
/** The slug form of a project display name, falling back to its ID. */
|
|
113
|
+
export function projectBaseName(displayName, projectId) {
|
|
114
|
+
return slugify(displayName) || projectId;
|
|
115
|
+
}
|
|
116
|
+
export function slugify(value) {
|
|
117
|
+
return value
|
|
118
|
+
.toLowerCase()
|
|
119
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
120
|
+
.replace(/^-+|-+$/g, '');
|
|
121
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A single-quoted TypeScript string literal, for the files this command generates.
|
|
3
|
+
*
|
|
4
|
+
* Both generators write source code, so both need the same escaping rules.
|
|
5
|
+
*/
|
|
6
|
+
export function quote(value) {
|
|
7
|
+
return `'${value.replaceAll('\\', '\\\\').replaceAll("'", "\\'")}'`;
|
|
8
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { readdirSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
const STUDIO_CONFIG_PATTERN = /^sanity\.config\.[cm]?[jt]sx?$/;
|
|
4
|
+
const STUDIO_CLI_PATTERN = /^sanity\.cli\.[cm]?[jt]sx?$/;
|
|
5
|
+
export function detectStudio(dir) {
|
|
6
|
+
let entries;
|
|
7
|
+
try {
|
|
8
|
+
entries = readdirSync(dir, { withFileTypes: true })
|
|
9
|
+
.filter((entry) => entry.isFile())
|
|
10
|
+
.map((entry) => entry.name);
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
15
|
+
const configFile = entries.find((name) => STUDIO_CONFIG_PATTERN.test(name));
|
|
16
|
+
if (!configFile)
|
|
17
|
+
return undefined;
|
|
18
|
+
const detected = { configFile };
|
|
19
|
+
const cliFile = entries.find((name) => STUDIO_CLI_PATTERN.test(name));
|
|
20
|
+
for (const file of [configFile, cliFile]) {
|
|
21
|
+
if (!file)
|
|
22
|
+
continue;
|
|
23
|
+
const source = readSource(join(dir, file));
|
|
24
|
+
if (!source)
|
|
25
|
+
continue;
|
|
26
|
+
detected.projectId ??= extractLiteral(source, 'projectId');
|
|
27
|
+
detected.dataset ??= extractLiteral(source, 'dataset');
|
|
28
|
+
if (detected.projectId && detected.dataset)
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
return detected;
|
|
32
|
+
}
|
|
33
|
+
function readSource(filePath) {
|
|
34
|
+
try {
|
|
35
|
+
return readFileSync(filePath, 'utf8');
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function extractLiteral(source, key) {
|
|
42
|
+
return source.match(new RegExp(`\\b${key}\\s*:\\s*(['"\`])([^'"\`\\\\]+)\\1`))?.[2];
|
|
43
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
export declare function renderStudioConfig(options: {
|
|
2
|
+
displayName: string;
|
|
3
|
+
projectId: string;
|
|
4
|
+
datasetName: string;
|
|
5
|
+
}): string;
|
|
6
|
+
/**
|
|
7
|
+
* `sanity dev` and `sanity build` read the project and dataset from here, not from
|
|
8
|
+
* `sanity.config.ts`, and fail with `No CLI config found` when the file is absent.
|
|
9
|
+
*
|
|
10
|
+
* `sanity init` also writes a `deployment.autoUpdates` block. It is left out because it only
|
|
11
|
+
* affects `sanity deploy`, and the Blueprint's `defineStudio` already declares auto-updates.
|
|
12
|
+
*/
|
|
13
|
+
export declare function renderStudioCliConfig(options: {
|
|
14
|
+
projectId: string;
|
|
15
|
+
datasetName: string;
|
|
16
|
+
}): string;
|
|
17
|
+
export declare const STUDIO_SCHEMA_TYPES = "import {post} from './post'\n\nexport const schemaTypes = [post]\n";
|
|
18
|
+
export declare const STUDIO_POST_TYPE = "import {defineField, defineType} from 'sanity'\n\nexport const post = defineType({\n name: 'post',\n title: 'Post',\n type: 'document',\n fields: [\n defineField({name: 'title', type: 'string', validation: (rule) => rule.required()}),\n // The set-slug function fills this when it is empty.\n defineField({name: 'slug', type: 'slug', options: {source: 'title'}}),\n defineField({name: 'publishedAt', title: 'Published at', type: 'datetime'}),\n defineField({name: 'body', type: 'text'}),\n ],\n})\n";
|
|
19
|
+
export declare const FUNCTION_SET_SLUG = "import {createClient} from '@sanity/client'\nimport {documentEventHandler} from '@sanity/functions'\n\nconst slugify = (title: string) =>\n title\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, 96)\n\nexport const handler = documentEventHandler(async ({context, event}) => {\n const {_id, title, slug} = event.data\n if (!title || slug?.current) return\n\n const client = createClient({apiVersion: '2025-05-01', ...context.clientOptions})\n const current = slugify(title)\n await client.patch(_id).set({slug: {_type: 'slug', current}}).commit()\n\n console.log(`Set slug for ${_id}: ${current}`)\n})\n";
|
|
20
|
+
export interface StudioVersions {
|
|
21
|
+
sanity: string;
|
|
22
|
+
vision: string;
|
|
23
|
+
}
|
|
24
|
+
export declare const studioPackageJson: (name: string, versions: StudioVersions) => {
|
|
25
|
+
name: string;
|
|
26
|
+
version: string;
|
|
27
|
+
private: boolean;
|
|
28
|
+
license: string;
|
|
29
|
+
keywords: string[];
|
|
30
|
+
scripts: {
|
|
31
|
+
dev: string;
|
|
32
|
+
build: string;
|
|
33
|
+
};
|
|
34
|
+
dependencies: {
|
|
35
|
+
'@sanity/vision': string;
|
|
36
|
+
react: string;
|
|
37
|
+
'react-dom': string;
|
|
38
|
+
sanity: string;
|
|
39
|
+
'styled-components': string;
|
|
40
|
+
};
|
|
41
|
+
devDependencies: {
|
|
42
|
+
'@types/react': string;
|
|
43
|
+
typescript: string;
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
/** Copied from `templates/shared/tsconfig.json` in `@sanity/cli`. */
|
|
47
|
+
export declare const STUDIO_TSCONFIG: {
|
|
48
|
+
compilerOptions: {
|
|
49
|
+
target: string;
|
|
50
|
+
lib: string[];
|
|
51
|
+
allowJs: boolean;
|
|
52
|
+
skipLibCheck: boolean;
|
|
53
|
+
strict: boolean;
|
|
54
|
+
forceConsistentCasingInFileNames: boolean;
|
|
55
|
+
module: string;
|
|
56
|
+
moduleDetection: string;
|
|
57
|
+
isolatedModules: boolean;
|
|
58
|
+
jsx: string;
|
|
59
|
+
incremental: boolean;
|
|
60
|
+
};
|
|
61
|
+
include: string[];
|
|
62
|
+
exclude: string[];
|
|
63
|
+
};
|
|
64
|
+
export declare const functionPackageJson: (name: string) => {
|
|
65
|
+
name: string;
|
|
66
|
+
version: string;
|
|
67
|
+
private: boolean;
|
|
68
|
+
type: string;
|
|
69
|
+
dependencies: {
|
|
70
|
+
'@sanity/client': string;
|
|
71
|
+
'@sanity/functions': string;
|
|
72
|
+
};
|
|
73
|
+
};
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { STARTER_DOCUMENT_TYPE, STARTER_FUNCTION_NAME } from './manifest.js';
|
|
2
|
+
import { quote } from './quote.js';
|
|
3
|
+
export function renderStudioConfig(options) {
|
|
4
|
+
return `import {defineConfig} from 'sanity'
|
|
5
|
+
import {structureTool} from 'sanity/structure'
|
|
6
|
+
import {visionTool} from '@sanity/vision'
|
|
7
|
+
import {schemaTypes} from './schemaTypes'
|
|
8
|
+
|
|
9
|
+
export default defineConfig({
|
|
10
|
+
name: 'default',
|
|
11
|
+
title: ${quote(options.displayName)},
|
|
12
|
+
projectId: ${quote(options.projectId)},
|
|
13
|
+
dataset: ${quote(options.datasetName)},
|
|
14
|
+
plugins: [structureTool(), visionTool()],
|
|
15
|
+
schema: {types: schemaTypes},
|
|
16
|
+
})
|
|
17
|
+
`;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* `sanity dev` and `sanity build` read the project and dataset from here, not from
|
|
21
|
+
* `sanity.config.ts`, and fail with `No CLI config found` when the file is absent.
|
|
22
|
+
*
|
|
23
|
+
* `sanity init` also writes a `deployment.autoUpdates` block. It is left out because it only
|
|
24
|
+
* affects `sanity deploy`, and the Blueprint's `defineStudio` already declares auto-updates.
|
|
25
|
+
*/
|
|
26
|
+
export function renderStudioCliConfig(options) {
|
|
27
|
+
return `import {defineCliConfig} from 'sanity/cli'
|
|
28
|
+
|
|
29
|
+
export default defineCliConfig({
|
|
30
|
+
api: {
|
|
31
|
+
projectId: ${quote(options.projectId)},
|
|
32
|
+
dataset: ${quote(options.datasetName)},
|
|
33
|
+
},
|
|
34
|
+
})
|
|
35
|
+
`;
|
|
36
|
+
}
|
|
37
|
+
export const STUDIO_SCHEMA_TYPES = `import {post} from './post'
|
|
38
|
+
|
|
39
|
+
export const schemaTypes = [post]
|
|
40
|
+
`;
|
|
41
|
+
export const STUDIO_POST_TYPE = `import {defineField, defineType} from 'sanity'
|
|
42
|
+
|
|
43
|
+
export const post = defineType({
|
|
44
|
+
name: '${STARTER_DOCUMENT_TYPE}',
|
|
45
|
+
title: 'Post',
|
|
46
|
+
type: 'document',
|
|
47
|
+
fields: [
|
|
48
|
+
defineField({name: 'title', type: 'string', validation: (rule) => rule.required()}),
|
|
49
|
+
// The ${STARTER_FUNCTION_NAME} function fills this when it is empty.
|
|
50
|
+
defineField({name: 'slug', type: 'slug', options: {source: 'title'}}),
|
|
51
|
+
defineField({name: 'publishedAt', title: 'Published at', type: 'datetime'}),
|
|
52
|
+
defineField({name: 'body', type: 'text'}),
|
|
53
|
+
],
|
|
54
|
+
})
|
|
55
|
+
`;
|
|
56
|
+
export const FUNCTION_SET_SLUG = `import {createClient} from '@sanity/client'
|
|
57
|
+
import {documentEventHandler} from '@sanity/functions'
|
|
58
|
+
|
|
59
|
+
const slugify = (title: string) =>
|
|
60
|
+
title
|
|
61
|
+
.toLowerCase()
|
|
62
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
63
|
+
.replace(/^-+|-+$/g, '')
|
|
64
|
+
.slice(0, 96)
|
|
65
|
+
|
|
66
|
+
export const handler = documentEventHandler(async ({context, event}) => {
|
|
67
|
+
const {_id, title, slug} = event.data
|
|
68
|
+
if (!title || slug?.current) return
|
|
69
|
+
|
|
70
|
+
const client = createClient({apiVersion: '2025-05-01', ...context.clientOptions})
|
|
71
|
+
const current = slugify(title)
|
|
72
|
+
await client.patch(_id).set({slug: {_type: 'slug', current}}).commit()
|
|
73
|
+
|
|
74
|
+
console.log(\`Set slug for \${_id}: \${current}\`)
|
|
75
|
+
})
|
|
76
|
+
`;
|
|
77
|
+
/**
|
|
78
|
+
* Versions `sanity init` pins itself, in `studioDependencies` in `@sanity/cli`.
|
|
79
|
+
*
|
|
80
|
+
* `sanity` and `@sanity/vision` are resolved at scaffold time instead, the way that command
|
|
81
|
+
* resolves them, so a Studio here matches the one `sanity init` would have written.
|
|
82
|
+
*/
|
|
83
|
+
const REACT_VERSION = '^19.2.4';
|
|
84
|
+
const STYLED_COMPONENTS_VERSION = '^6.1.18';
|
|
85
|
+
const TYPES_REACT_VERSION = '^19.2.14';
|
|
86
|
+
const TYPESCRIPT_VERSION = '^5.8';
|
|
87
|
+
export const studioPackageJson = (name, versions) => ({
|
|
88
|
+
name,
|
|
89
|
+
version: '1.0.0',
|
|
90
|
+
private: true,
|
|
91
|
+
license: 'UNLICENSED',
|
|
92
|
+
keywords: ['sanity'],
|
|
93
|
+
// The Blueprint deploys this Studio, so there is no `sanity deploy` script.
|
|
94
|
+
// Running one would create a second hosted Studio that the Stack does not own.
|
|
95
|
+
scripts: {
|
|
96
|
+
dev: 'sanity dev',
|
|
97
|
+
build: 'sanity build',
|
|
98
|
+
},
|
|
99
|
+
dependencies: {
|
|
100
|
+
'@sanity/vision': versions.vision,
|
|
101
|
+
react: REACT_VERSION,
|
|
102
|
+
'react-dom': REACT_VERSION,
|
|
103
|
+
sanity: versions.sanity,
|
|
104
|
+
'styled-components': STYLED_COMPONENTS_VERSION,
|
|
105
|
+
},
|
|
106
|
+
devDependencies: {
|
|
107
|
+
'@types/react': TYPES_REACT_VERSION,
|
|
108
|
+
typescript: TYPESCRIPT_VERSION,
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
/** Copied from `templates/shared/tsconfig.json` in `@sanity/cli`. */
|
|
112
|
+
export const STUDIO_TSCONFIG = {
|
|
113
|
+
compilerOptions: {
|
|
114
|
+
target: 'ES2017',
|
|
115
|
+
lib: ['dom', 'dom.iterable', 'esnext'],
|
|
116
|
+
allowJs: true,
|
|
117
|
+
skipLibCheck: true,
|
|
118
|
+
strict: true,
|
|
119
|
+
forceConsistentCasingInFileNames: true,
|
|
120
|
+
module: 'Preserve',
|
|
121
|
+
moduleDetection: 'force',
|
|
122
|
+
isolatedModules: true,
|
|
123
|
+
jsx: 'preserve',
|
|
124
|
+
incremental: true,
|
|
125
|
+
},
|
|
126
|
+
include: ['**/*.ts', '**/*.tsx'],
|
|
127
|
+
exclude: ['node_modules'],
|
|
128
|
+
};
|
|
129
|
+
export const functionPackageJson = (name) => ({
|
|
130
|
+
name,
|
|
131
|
+
version: '0.1.0',
|
|
132
|
+
private: true,
|
|
133
|
+
type: 'module',
|
|
134
|
+
dependencies: {
|
|
135
|
+
'@sanity/client': '^8',
|
|
136
|
+
'@sanity/functions': '^1',
|
|
137
|
+
},
|
|
138
|
+
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Logger } from '../../utils/logger.js';
|
|
2
|
+
/**
|
|
3
|
+
* The latest version as a caret range, the form `sanity init` writes.
|
|
4
|
+
*
|
|
5
|
+
* `getLatestNpmVersion` answers `latest` when the registry cannot be read, and `^latest`
|
|
6
|
+
* is not a range, so that answer passes through unchanged.
|
|
7
|
+
*/
|
|
8
|
+
export declare function getLatestNpmRange(pkg: string, logger: Logger): Promise<string>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { getLatestNpmVersion } from '../../utils/external/npmjs.js';
|
|
2
|
+
/**
|
|
3
|
+
* The latest version as a caret range, the form `sanity init` writes.
|
|
4
|
+
*
|
|
5
|
+
* `getLatestNpmVersion` answers `latest` when the registry cannot be read, and `^latest`
|
|
6
|
+
* is not a range, so that answer passes through unchanged.
|
|
7
|
+
*/
|
|
8
|
+
export async function getLatestNpmRange(pkg, logger) {
|
|
9
|
+
const version = await getLatestNpmVersion(pkg, logger);
|
|
10
|
+
return version === 'latest' ? version : `^${version}`;
|
|
11
|
+
}
|