@sanity/runtime-cli 17.6.2 → 17.7.0-blueprinit.g71744ef
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 +20 -20
- package/dist/actions/blueprinit/manifest.d.ts +15 -0
- package/dist/actions/blueprinit/manifest.js +82 -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 +34 -0
- package/dist/actions/blueprinit/templates.js +83 -0
- package/dist/actions/blueprinit/workspace.d.ts +16 -0
- package/dist/actions/blueprinit/workspace.js +143 -0
- package/dist/actions/sanity/datasets.d.ts +15 -0
- package/dist/actions/sanity/datasets.js +26 -0
- package/dist/commands/init.d.ts +17 -0
- package/dist/commands/init.js +59 -0
- package/dist/cores/blueprinit/adopt.d.ts +6 -0
- package/dist/cores/blueprinit/adopt.js +119 -0
- package/dist/cores/blueprinit/finish.d.ts +14 -0
- package/dist/cores/blueprinit/finish.js +64 -0
- package/dist/cores/blueprinit/fresh.d.ts +3 -0
- package/dist/cores/blueprinit/fresh.js +120 -0
- package/dist/cores/blueprinit/preview.d.ts +15 -0
- package/dist/cores/blueprinit/preview.js +14 -0
- package/dist/cores/blueprinit/prompts.d.ts +5 -0
- package/dist/cores/blueprinit/prompts.js +22 -0
- package/dist/cores/blueprinit/selection.d.ts +15 -0
- package/dist/cores/blueprinit/selection.js +90 -0
- package/dist/cores/blueprinit/types.d.ts +16 -0
- package/dist/cores/blueprinit/types.js +1 -0
- package/dist/cores/blueprinit.d.ts +7 -0
- package/dist/cores/blueprinit.js +48 -0
- package/dist/utils/display/blueprints-formatting.js +10 -3
- package/dist/utils/display/resources-formatting.d.ts +3 -2
- package/dist/utils/display/resources-formatting.js +23 -12
- package/oclif.manifest.json +130 -1
- package/package.json +13 -13
- package/skills/init.md +155 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { treeify } from 'array-treeify';
|
|
2
|
-
import { SANITY_ACCESS_ROBOT, SANITY_ACCESS_ROLE, SANITY_FUNCTION_DOCUMENT, SANITY_FUNCTION_DURABLE, SANITY_FUNCTION_MEDIA_LIBRARY_ASSET, SANITY_FUNCTION_PUBSUB, SANITY_FUNCTION_SCHEDULED, SANITY_FUNCTION_SYNC_TAG_INVALIDATE, SANITY_PROJECT, SANITY_PROJECT_CORS, SANITY_PROJECT_DATASET, SANITY_PROJECT_WEBHOOK, } from '../../constants.js';
|
|
2
|
+
import { SANITY_ACCESS_ROBOT, SANITY_ACCESS_ROLE, SANITY_FUNCTION_DOCUMENT, SANITY_FUNCTION_DURABLE, SANITY_FUNCTION_MEDIA_LIBRARY_ASSET, SANITY_FUNCTION_PUBSUB, SANITY_FUNCTION_SCHEDULED, SANITY_FUNCTION_SYNC_TAG_INVALIDATE, SANITY_PROJECT, SANITY_PROJECT_CORS, SANITY_PROJECT_DATASET, SANITY_PROJECT_WEBHOOK, SANITY_STUDIO, } from '../../constants.js';
|
|
3
3
|
import { styleText } from '../style-text.js';
|
|
4
|
-
import { isCorsOriginResource, isDatasetResource, isRobotResource, isRoleResource, isWebhookResource, } from '../types.js';
|
|
4
|
+
import { isCorsOriginResource, isDatasetResource, isRobotResource, isRoleResource, isStudioResource, isWebhookResource, } from '../types.js';
|
|
5
5
|
import { formatDateTime, formatDuration } from './dates.js';
|
|
6
6
|
import { capitalize, niceId, renderSection } from './presenters.js';
|
|
7
|
-
import { arrayifyCors, arrayifyDataset, arrayifyFunction, arrayifyRobot, arrayifyRole, arrayifyWebhook, } from './resources-formatting.js';
|
|
7
|
+
import { arrayifyCors, arrayifyDataset, arrayifyFunction, arrayifyRobot, arrayifyRole, arrayifyStudio, arrayifyWebhook, } from './resources-formatting.js';
|
|
8
8
|
const functionCategory = {
|
|
9
9
|
label: 'Functions',
|
|
10
10
|
displayNameAttribute: 'displayName',
|
|
@@ -58,6 +58,13 @@ const RESOURCE_CATEGORIES = {
|
|
|
58
58
|
return isWebhookResource(res) ? arrayifyWebhook(res) : [];
|
|
59
59
|
},
|
|
60
60
|
},
|
|
61
|
+
[SANITY_STUDIO]: {
|
|
62
|
+
label: 'Studios',
|
|
63
|
+
displayNameAttribute: 'title',
|
|
64
|
+
formatDetails(res) {
|
|
65
|
+
return isStudioResource(res) ? arrayifyStudio(res) : [];
|
|
66
|
+
},
|
|
67
|
+
},
|
|
61
68
|
};
|
|
62
69
|
const categoryByLabel = Object.values(RESOURCE_CATEGORIES).reduce((acc, curr) => {
|
|
63
70
|
acc[curr.label] = curr;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import type { BlueprintCorsOriginResource, BlueprintDatasetResource, BlueprintDocumentWebhookResource, BlueprintResource, BlueprintRobotResource, BlueprintRoleResource } from '@sanity/blueprints';
|
|
1
|
+
import type { BlueprintCorsOriginResource, BlueprintDatasetResource, BlueprintDocumentWebhookResource, BlueprintResource, BlueprintRobotResource, BlueprintRoleResource, BlueprintStudioResource } from '@sanity/blueprints';
|
|
2
2
|
import type { TreeInput } from 'array-treeify';
|
|
3
|
-
export declare function arrayifyFunction(fn: BlueprintResource): TreeInput;
|
|
4
3
|
export declare function arrayifyCors(resource: BlueprintCorsOriginResource): TreeInput;
|
|
5
4
|
export declare function arrayifyDataset(resource: BlueprintDatasetResource): TreeInput;
|
|
5
|
+
export declare function arrayifyFunction(fn: BlueprintResource): TreeInput;
|
|
6
6
|
export declare function arrayifyRobot(resource: BlueprintRobotResource): TreeInput;
|
|
7
7
|
export declare function arrayifyRole(resource: BlueprintRoleResource): TreeInput;
|
|
8
|
+
export declare function arrayifyStudio(resource: BlueprintStudioResource): TreeInput;
|
|
8
9
|
export declare function arrayifyWebhook(resource: BlueprintDocumentWebhookResource): TreeInput;
|
|
@@ -1,11 +1,23 @@
|
|
|
1
1
|
import { hasEventSource, isLocalFunctionResource, isScheduleEvent, } from '../../utils/types.js';
|
|
2
2
|
import { styleText } from '../style-text.js';
|
|
3
|
+
import { niceId } from './presenters.js';
|
|
3
4
|
function formatLabel(label) {
|
|
4
5
|
return styleText('dim', `${label}:`);
|
|
5
6
|
}
|
|
6
7
|
function formatLabeledValue(label, value) {
|
|
7
8
|
return `${styleText('dim', `${label}:`)} ${value}`;
|
|
8
9
|
}
|
|
10
|
+
export function arrayifyCors(resource) {
|
|
11
|
+
return [formatLabeledValue('origin', resource.origin)];
|
|
12
|
+
}
|
|
13
|
+
export function arrayifyDataset(resource) {
|
|
14
|
+
const details = [formatLabeledValue('title', resource.datasetName)];
|
|
15
|
+
if (resource.aclMode)
|
|
16
|
+
details.push(formatLabeledValue('visibility', resource.aclMode));
|
|
17
|
+
if (resource.project)
|
|
18
|
+
details.push(formatLabeledValue('project', niceId(resource.project)));
|
|
19
|
+
return details;
|
|
20
|
+
}
|
|
9
21
|
function arrayifyEvent(event) {
|
|
10
22
|
if (!event)
|
|
11
23
|
return undefined;
|
|
@@ -55,19 +67,8 @@ export function arrayifyFunction(fn) {
|
|
|
55
67
|
}
|
|
56
68
|
return details;
|
|
57
69
|
}
|
|
58
|
-
export function arrayifyCors(resource) {
|
|
59
|
-
return [formatLabeledValue('origin', resource.origin)];
|
|
60
|
-
}
|
|
61
|
-
export function arrayifyDataset(resource) {
|
|
62
|
-
const details = [formatLabeledValue('title', resource.datasetName)];
|
|
63
|
-
if (resource.aclMode)
|
|
64
|
-
details.push(formatLabeledValue('visibility', resource.aclMode));
|
|
65
|
-
if (resource.project)
|
|
66
|
-
details.push(formatLabeledValue('project', resource.project));
|
|
67
|
-
return details;
|
|
68
|
-
}
|
|
69
70
|
export function arrayifyRobot(resource) {
|
|
70
|
-
const details = [
|
|
71
|
+
const details = [];
|
|
71
72
|
if (resource.memberships.length > 0) {
|
|
72
73
|
details.push(formatLabel('memberships'));
|
|
73
74
|
const memberships = [];
|
|
@@ -115,8 +116,16 @@ export function arrayifyRole(resource) {
|
|
|
115
116
|
}
|
|
116
117
|
return details;
|
|
117
118
|
}
|
|
119
|
+
export function arrayifyStudio(resource) {
|
|
120
|
+
const details = [formatLabeledValue('appHost', resource.slug)];
|
|
121
|
+
if (resource.project)
|
|
122
|
+
details.push(formatLabeledValue('project', niceId(resource.project)));
|
|
123
|
+
return details;
|
|
124
|
+
}
|
|
118
125
|
export function arrayifyWebhook(resource) {
|
|
119
126
|
const details = [];
|
|
127
|
+
if (resource.displayName)
|
|
128
|
+
details.push(formatLabeledValue('displayName', resource.displayName));
|
|
120
129
|
if (resource.description)
|
|
121
130
|
details.push(formatLabeledValue('description', resource.description));
|
|
122
131
|
details.push(formatLabeledValue('url', resource.url));
|
|
@@ -131,6 +140,8 @@ export function arrayifyWebhook(resource) {
|
|
|
131
140
|
details.push(formatLabeledValue('httpMethod', resource.httpMethod));
|
|
132
141
|
if (resource.dataset)
|
|
133
142
|
details.push(formatLabeledValue('dataset', resource.dataset));
|
|
143
|
+
if (resource.project)
|
|
144
|
+
details.push(formatLabeledValue('project', niceId(resource.project)));
|
|
134
145
|
// not included: headers, includeDrafts, includeAllVersions, secret, apiVersion
|
|
135
146
|
return details;
|
|
136
147
|
}
|
package/oclif.manifest.json
CHANGED
|
@@ -1,5 +1,134 @@
|
|
|
1
1
|
{
|
|
2
2
|
"commands": {
|
|
3
|
+
"init": {
|
|
4
|
+
"aliases": [],
|
|
5
|
+
"args": {},
|
|
6
|
+
"description": "Scaffolds a Blueprint, Studio, and starter function around an existing Sanity project.\n\nThis hidden command is an experiment; its interface and generated files are not stable.",
|
|
7
|
+
"examples": [
|
|
8
|
+
"<%= config.bin %> <%= command.id %>",
|
|
9
|
+
"<%= config.bin %> <%= command.id %> --yes",
|
|
10
|
+
"<%= config.bin %> <%= command.id %> --project-id <id> --dataset <name> --yes"
|
|
11
|
+
],
|
|
12
|
+
"flags": {
|
|
13
|
+
"json": {
|
|
14
|
+
"description": "Format output as json",
|
|
15
|
+
"name": "json",
|
|
16
|
+
"allowNo": false,
|
|
17
|
+
"type": "boolean"
|
|
18
|
+
},
|
|
19
|
+
"path": {
|
|
20
|
+
"aliases": [
|
|
21
|
+
"blueprint-path"
|
|
22
|
+
],
|
|
23
|
+
"char": "p",
|
|
24
|
+
"description": "Path to a Blueprint file or directory containing one",
|
|
25
|
+
"env": "SANITY_BLUEPRINT_PATH",
|
|
26
|
+
"hidden": true,
|
|
27
|
+
"name": "path",
|
|
28
|
+
"hasDynamicHelp": false,
|
|
29
|
+
"multiple": false,
|
|
30
|
+
"type": "option"
|
|
31
|
+
},
|
|
32
|
+
"trace": {
|
|
33
|
+
"description": "Trace output",
|
|
34
|
+
"hidden": true,
|
|
35
|
+
"name": "trace",
|
|
36
|
+
"allowNo": false,
|
|
37
|
+
"type": "boolean"
|
|
38
|
+
},
|
|
39
|
+
"validate-resources": {
|
|
40
|
+
"description": "Validate resources",
|
|
41
|
+
"hidden": true,
|
|
42
|
+
"name": "validate-resources",
|
|
43
|
+
"allowNo": true,
|
|
44
|
+
"type": "boolean"
|
|
45
|
+
},
|
|
46
|
+
"verbose": {
|
|
47
|
+
"description": "Verbose output",
|
|
48
|
+
"hidden": true,
|
|
49
|
+
"name": "verbose",
|
|
50
|
+
"allowNo": false,
|
|
51
|
+
"type": "boolean"
|
|
52
|
+
},
|
|
53
|
+
"llms": {
|
|
54
|
+
"aliases": [
|
|
55
|
+
"skill"
|
|
56
|
+
],
|
|
57
|
+
"description": "Show agent-oriented guidance for this command",
|
|
58
|
+
"hidden": true,
|
|
59
|
+
"name": "llms",
|
|
60
|
+
"allowNo": false,
|
|
61
|
+
"type": "boolean"
|
|
62
|
+
},
|
|
63
|
+
"yes": {
|
|
64
|
+
"char": "y",
|
|
65
|
+
"description": "Skip confirmation prompts",
|
|
66
|
+
"name": "yes",
|
|
67
|
+
"allowNo": false,
|
|
68
|
+
"type": "boolean"
|
|
69
|
+
},
|
|
70
|
+
"organization-id": {
|
|
71
|
+
"aliases": [
|
|
72
|
+
"organization",
|
|
73
|
+
"organizationId",
|
|
74
|
+
"org"
|
|
75
|
+
],
|
|
76
|
+
"description": "Organization to use when the account has several",
|
|
77
|
+
"name": "organization-id",
|
|
78
|
+
"hasDynamicHelp": false,
|
|
79
|
+
"multiple": false,
|
|
80
|
+
"type": "option"
|
|
81
|
+
},
|
|
82
|
+
"project-id": {
|
|
83
|
+
"aliases": [
|
|
84
|
+
"project",
|
|
85
|
+
"projectId"
|
|
86
|
+
],
|
|
87
|
+
"description": "Project to use when the organization has several",
|
|
88
|
+
"name": "project-id",
|
|
89
|
+
"hasDynamicHelp": false,
|
|
90
|
+
"multiple": false,
|
|
91
|
+
"type": "option"
|
|
92
|
+
},
|
|
93
|
+
"dataset": {
|
|
94
|
+
"description": "Dataset to attach",
|
|
95
|
+
"name": "dataset",
|
|
96
|
+
"hasDynamicHelp": false,
|
|
97
|
+
"multiple": false,
|
|
98
|
+
"type": "option"
|
|
99
|
+
},
|
|
100
|
+
"stack-name": {
|
|
101
|
+
"description": "Name for the new organization-scoped Stack",
|
|
102
|
+
"name": "stack-name",
|
|
103
|
+
"hasDynamicHelp": false,
|
|
104
|
+
"multiple": false,
|
|
105
|
+
"type": "option"
|
|
106
|
+
},
|
|
107
|
+
"studio-name": {
|
|
108
|
+
"description": "Name and hosted slug for the Studio resource",
|
|
109
|
+
"name": "studio-name",
|
|
110
|
+
"hasDynamicHelp": false,
|
|
111
|
+
"multiple": false,
|
|
112
|
+
"type": "option"
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
"hasDynamicHelp": false,
|
|
116
|
+
"hidden": true,
|
|
117
|
+
"hiddenAliases": [],
|
|
118
|
+
"id": "init",
|
|
119
|
+
"pluginAlias": "@sanity/runtime-cli",
|
|
120
|
+
"pluginName": "@sanity/runtime-cli",
|
|
121
|
+
"pluginType": "core",
|
|
122
|
+
"strict": true,
|
|
123
|
+
"summary": "Experimental blueprints-first project init",
|
|
124
|
+
"enableJsonFlag": true,
|
|
125
|
+
"isESM": true,
|
|
126
|
+
"relativePath": [
|
|
127
|
+
"dist",
|
|
128
|
+
"commands",
|
|
129
|
+
"init.js"
|
|
130
|
+
]
|
|
131
|
+
},
|
|
3
132
|
"blueprints:add": {
|
|
4
133
|
"aliases": [],
|
|
5
134
|
"args": {
|
|
@@ -3127,5 +3256,5 @@
|
|
|
3127
3256
|
]
|
|
3128
3257
|
}
|
|
3129
3258
|
},
|
|
3130
|
-
"version": "17.
|
|
3259
|
+
"version": "17.7.0-blueprinit.g71744ef"
|
|
3131
3260
|
}
|
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.7.0-blueprinit.g71744ef",
|
|
5
5
|
"author": "Sanity Runtime Team",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"license": "MIT",
|
|
@@ -65,20 +65,20 @@
|
|
|
65
65
|
"@architect/hydrate": "~6.0.2",
|
|
66
66
|
"@architect/inventory": "~6.1.0",
|
|
67
67
|
"@inquirer/prompts": "^8.5.2",
|
|
68
|
-
"@oclif/core": "^4.13.
|
|
69
|
-
"@oclif/plugin-help": "^6.2.
|
|
68
|
+
"@oclif/core": "^4.13.4",
|
|
69
|
+
"@oclif/plugin-help": "^6.2.58",
|
|
70
70
|
"@sanity-labs/design-tokens": "^0.0.2-alpha.2",
|
|
71
71
|
"@sanity-labs/oclif-plugin-skills-flag": "^0.2.1",
|
|
72
|
-
"@sanity/blueprints": "^0.23.
|
|
73
|
-
"@sanity/blueprints-parser": "^0.
|
|
74
|
-
"@sanity/cli-build": "^5.
|
|
75
|
-
"@sanity/cli-core": "^
|
|
76
|
-
"@sanity/client": "^
|
|
72
|
+
"@sanity/blueprints": "^0.23.6",
|
|
73
|
+
"@sanity/blueprints-parser": "^0.5.0",
|
|
74
|
+
"@sanity/cli-build": "^5.2.0",
|
|
75
|
+
"@sanity/cli-core": "^3.0.0",
|
|
76
|
+
"@sanity/client": "^8.0.0",
|
|
77
77
|
"adm-zip": "^0.6.0",
|
|
78
|
-
"array-treeify": "^0.
|
|
78
|
+
"array-treeify": "^0.2.0",
|
|
79
79
|
"cardinal": "^2.1.1",
|
|
80
80
|
"empathic": "^2.0.1",
|
|
81
|
-
"eventsource": "^
|
|
81
|
+
"eventsource": "^5.1.0",
|
|
82
82
|
"groq-js": "^2.0.0",
|
|
83
83
|
"jiti": "^2.7.0",
|
|
84
84
|
"mime-types": "^3.0.2",
|
|
@@ -92,15 +92,15 @@
|
|
|
92
92
|
"xdg-basedir": "^5.1.0"
|
|
93
93
|
},
|
|
94
94
|
"devDependencies": {
|
|
95
|
-
"@biomejs/biome": "2.5.
|
|
95
|
+
"@biomejs/biome": "2.5.8",
|
|
96
96
|
"@codemirror/lang-json": "^6.0.2",
|
|
97
97
|
"@codemirror/state": "^6.7.1",
|
|
98
98
|
"@enhance/store": "^1.0.2",
|
|
99
99
|
"@lezer/highlight": "^1.2.3",
|
|
100
|
-
"@oclif/test": "^4.1.
|
|
100
|
+
"@oclif/test": "^4.1.22",
|
|
101
101
|
"@playwright/test": "^1.62.1",
|
|
102
102
|
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
103
|
-
"@sanity/functions": "^1.6.
|
|
103
|
+
"@sanity/functions": "^1.6.6",
|
|
104
104
|
"@types/adm-zip": "^0.5.8",
|
|
105
105
|
"@types/cardinal": "^2.1.1",
|
|
106
106
|
"@types/mime-types": "^3.0.1",
|
package/skills/init.md
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# init
|
|
2
|
+
|
|
3
|
+
Use `init` to scaffold a Blueprint around an existing Sanity project. The command is
|
|
4
|
+
experimental, hidden from root help, and available from the `blueprinit` npm dist-tag.
|
|
5
|
+
|
|
6
|
+
Use it for demos and evaluation, not as a stable project initializer. Its flags, generated files,
|
|
7
|
+
and resource model may change.
|
|
8
|
+
|
|
9
|
+
## Know what it does
|
|
10
|
+
|
|
11
|
+
`init` uses an existing Sanity organization, project, and dataset. It writes local Blueprint
|
|
12
|
+
files, then creates an empty organization-scoped Stack. The generated Blueprint attaches the
|
|
13
|
+
project and dataset and declares resources for a later deployment.
|
|
14
|
+
|
|
15
|
+
It does not create an organization, project, or dataset. It does not deploy the attached resources,
|
|
16
|
+
CORS origin, Studio, or Function. Those changes happen only if `blueprints deploy` is run later.
|
|
17
|
+
|
|
18
|
+
## Inspect the target directory
|
|
19
|
+
|
|
20
|
+
Run the command from the directory that should contain the Blueprint.
|
|
21
|
+
|
|
22
|
+
Before running:
|
|
23
|
+
|
|
24
|
+
1. Check the working tree and existing files. Do not discard unrelated user changes.
|
|
25
|
+
2. Look for a root `sanity.blueprint.*` file. If one exists, use the existing Blueprint instead of
|
|
26
|
+
initializing again.
|
|
27
|
+
3. Look for a root `sanity.config.*` file. Its presence selects the Studio adoption flow.
|
|
28
|
+
4. Confirm the user asked to initialize this directory. The command writes files and creates a
|
|
29
|
+
remote Stack.
|
|
30
|
+
5. Confirm the user is signed in. If needed, have them run:
|
|
31
|
+
|
|
32
|
+
```sh
|
|
33
|
+
npx sanity login
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
The account must have at least one organization, one project in the selected organization, and one
|
|
37
|
+
dataset in the selected project.
|
|
38
|
+
|
|
39
|
+
Interactive runs show the Blueprint resources, hosted Studio URL, local changes, and remote Stack
|
|
40
|
+
action before the confirmation prompt. Project and dataset attachment plus CORS, Studio, and
|
|
41
|
+
Function creation remain pending until a later deployment.
|
|
42
|
+
|
|
43
|
+
## Choose the flow
|
|
44
|
+
|
|
45
|
+
- **Existing Blueprint with a configured Stack:** Exit without changes and use
|
|
46
|
+
`blueprints config --edit` or `blueprints doctor`.
|
|
47
|
+
- **Existing Blueprint without a configured Stack:** Finish setup with `blueprints init`; it can
|
|
48
|
+
connect the existing manifest without rewriting it.
|
|
49
|
+
- **Root Studio config:** Adopt the Studio in place. Read literal `projectId` and `dataset` strings
|
|
50
|
+
from `sanity.config.*`, falling back to `sanity.cli.*`. Do not move the Studio.
|
|
51
|
+
- **Fresh workspace:** Create a Blueprint, an npm-workspace Studio, and a starter `set-slug`
|
|
52
|
+
document function.
|
|
53
|
+
|
|
54
|
+
Do not rewrite a Studio config merely to make adoption work unless the user asks. Dynamic
|
|
55
|
+
`projectId` or `dataset` values built from environment variables or imports cannot be detected.
|
|
56
|
+
|
|
57
|
+
For an existing Blueprint, inspect it with:
|
|
58
|
+
|
|
59
|
+
```sh
|
|
60
|
+
npx @sanity/runtime-cli@blueprinit blueprints doctor
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Run unattended
|
|
64
|
+
|
|
65
|
+
When the organization and project IDs are known, run this from the target directory:
|
|
66
|
+
|
|
67
|
+
```sh
|
|
68
|
+
npx @sanity/runtime-cli@blueprinit init --yes \
|
|
69
|
+
--organization-id <organization-id> \
|
|
70
|
+
--project-id <project-id> \
|
|
71
|
+
--dataset <dataset-name>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Replace all placeholders with real values. The project must belong to the organization, and the
|
|
75
|
+
dataset must belong to the project. Do not guess any value.
|
|
76
|
+
|
|
77
|
+
`--yes` skips confirmation. Without explicit values, an unattended run stops when the account has
|
|
78
|
+
several organizations, projects, or datasets. Ask the user for the missing value or have them run
|
|
79
|
+
the command interactively.
|
|
80
|
+
|
|
81
|
+
Use `--stack-name <name>` and `--studio-name <name>` when those generated names need to be stable.
|
|
82
|
+
The command normalizes both names to lowercase kebab case. The Studio name is also its hosted slug,
|
|
83
|
+
so it must be available in the target environment. Stack and Studio names must differ because they
|
|
84
|
+
also name Blueprint resources.
|
|
85
|
+
|
|
86
|
+
When `SANITY_INTERNAL_ENV=staging`, the generated Studio URL and CORS origin use
|
|
87
|
+
`https://<studio-name>.studio.sanity.work`. Other environments use
|
|
88
|
+
`https://<studio-name>.sanity.studio`.
|
|
89
|
+
|
|
90
|
+
For interactive organization, project, dataset, confirmation, and Studio-name prompts, have the
|
|
91
|
+
user run:
|
|
92
|
+
|
|
93
|
+
```sh
|
|
94
|
+
npx @sanity/runtime-cli@blueprinit init
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
When the project has several datasets, the interactive command prompts for one and lists
|
|
98
|
+
`production` first. Report the selected dataset from the command output.
|
|
99
|
+
|
|
100
|
+
## Review the result
|
|
101
|
+
|
|
102
|
+
A successful fresh run creates or updates:
|
|
103
|
+
|
|
104
|
+
```text
|
|
105
|
+
.
|
|
106
|
+
├── .sanity/blueprint.config.json
|
|
107
|
+
├── sanity.blueprint.ts
|
|
108
|
+
├── package.json
|
|
109
|
+
├── functions/
|
|
110
|
+
│ └── set-slug/
|
|
111
|
+
└── studios/
|
|
112
|
+
└── studio/
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
The command also creates or updates `.gitignore`. It preserves existing package metadata and adds
|
|
116
|
+
the required npm workspaces and `@sanity/blueprints` dependency.
|
|
117
|
+
|
|
118
|
+
An adopted Studio stays at the repository root. The command adds the Blueprint, Blueprint config,
|
|
119
|
+
dependency, and `.gitignore` entry, but does not generate the starter Function.
|
|
120
|
+
|
|
121
|
+
After the command exits:
|
|
122
|
+
|
|
123
|
+
1. Confirm the output names the expected organization, project, and dataset.
|
|
124
|
+
2. Confirm `.sanity/blueprint.config.json` exists. Its presence means Stack creation completed.
|
|
125
|
+
3. Review `sanity.blueprint.ts`, including the Studio slug and credentialed CORS origin, plus
|
|
126
|
+
`package.json`, `.gitignore`, and the working-tree diff.
|
|
127
|
+
4. Report the Stack ID and every created or modified path.
|
|
128
|
+
|
|
129
|
+
Do not deploy as part of initialization unless the user separately asks for deployment. To continue
|
|
130
|
+
after reviewing the scaffold, install dependencies and preview the deployment:
|
|
131
|
+
|
|
132
|
+
```sh
|
|
133
|
+
npm install
|
|
134
|
+
npx @sanity/runtime-cli@blueprinit blueprints plan
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Treat dependency installation and planning as separate follow-up actions when they were not part of
|
|
138
|
+
the user's request.
|
|
139
|
+
|
|
140
|
+
## Handle failures
|
|
141
|
+
|
|
142
|
+
- **`No Sanity session found.`** Stop and ask the user to run `npx sanity login`. Authentication
|
|
143
|
+
fails before files are written.
|
|
144
|
+
- **Multiple organizations or projects found.** Rerun with the matching `--organization-id` and
|
|
145
|
+
`--project-id`. Selection fails before files are written.
|
|
146
|
+
- **No datasets found.** Ask the user to create or choose a project with a dataset. The command does
|
|
147
|
+
not create datasets.
|
|
148
|
+
- **Could not read `projectId` and `dataset`.** The detected Studio config does not contain both
|
|
149
|
+
values as string literals. Pass explicit `--project-id` and `--dataset` values or report the config
|
|
150
|
+
file and let the user decide whether to change it.
|
|
151
|
+
- **Refusing to overwrite an existing path.** Inspect the reported Studio or Function directory.
|
|
152
|
+
Do not delete or replace it without the user's direction.
|
|
153
|
+
- **Stack quota or duplicate-name error.** Local scaffold files may already exist while
|
|
154
|
+
`.sanity/blueprint.config.json` does not. Resolve the Stack error, then run the recovery command
|
|
155
|
+
printed by `init`, which is `blueprints init`. It connects the existing manifest without rewriting it.
|