@sanity/runtime-cli 17.9.0-blueprinit.g14aaebd → 17.10.0-next.g5e0bba6
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.js +1 -1
- package/dist/actions/blueprints/pre-deploy.js +7 -6
- package/dist/actions/blueprints/wait-for-operation.js +2 -1
- package/dist/cores/blueprints/config.js +18 -8
- package/dist/cores/blueprints/deploy.js +9 -8
- package/dist/cores/blueprints/destroy.js +7 -6
- package/dist/cores/blueprints/doctor.js +15 -2
- package/dist/cores/blueprints/init.d.ts +2 -0
- package/dist/cores/blueprints/init.js +56 -20
- package/dist/cores/blueprints/plan.js +11 -6
- package/dist/cores/blueprints/promote.js +3 -2
- package/dist/cores/functions/add.js +11 -7
- package/dist/cores/functions/logs.js +50 -6
- package/dist/cores/index.d.ts +5 -0
- package/dist/utils/blueprints/hints.js +8 -3
- package/dist/utils/display/prompt.d.ts +15 -2
- package/dist/utils/display/prompt.js +70 -8
- package/dist/utils/functions/child-runtime/durable.js +19 -2
- package/dist/utils/package-manager.d.ts +20 -0
- package/dist/utils/package-manager.js +63 -0
- package/dist/utils/types.d.ts +10 -1
- package/oclif.manifest.json +1 -152
- package/package.json +2 -2
- package/dist/actions/blueprinit/manifest.d.ts +0 -46
- package/dist/actions/blueprinit/manifest.js +0 -121
- package/dist/actions/blueprinit/quote.d.ts +0 -6
- package/dist/actions/blueprinit/quote.js +0 -8
- package/dist/actions/blueprinit/studio.d.ts +0 -6
- package/dist/actions/blueprinit/studio.js +0 -43
- package/dist/actions/blueprinit/templates.d.ts +0 -73
- package/dist/actions/blueprinit/templates.js +0 -138
- package/dist/actions/blueprinit/versions.d.ts +0 -8
- package/dist/actions/blueprinit/versions.js +0 -11
- package/dist/actions/blueprinit/workspace.d.ts +0 -27
- package/dist/actions/blueprinit/workspace.js +0 -145
- package/dist/actions/sanity/create-project.d.ts +0 -19
- package/dist/actions/sanity/create-project.js +0 -32
- package/dist/actions/sanity/datasets.d.ts +0 -15
- package/dist/actions/sanity/datasets.js +0 -26
- package/dist/commands/init.d.ts +0 -21
- package/dist/commands/init.js +0 -82
- package/dist/cores/blueprinit/adopt.d.ts +0 -6
- package/dist/cores/blueprinit/adopt.js +0 -137
- package/dist/cores/blueprinit/columns.d.ts +0 -26
- package/dist/cores/blueprinit/columns.js +0 -27
- package/dist/cores/blueprinit/finish.d.ts +0 -15
- package/dist/cores/blueprinit/finish.js +0 -72
- package/dist/cores/blueprinit/fresh.d.ts +0 -3
- package/dist/cores/blueprinit/fresh.js +0 -219
- package/dist/cores/blueprinit/naming.d.ts +0 -27
- package/dist/cores/blueprinit/naming.js +0 -43
- package/dist/cores/blueprinit/preview.d.ts +0 -34
- package/dist/cores/blueprinit/preview.js +0 -110
- package/dist/cores/blueprinit/project-choice.d.ts +0 -28
- package/dist/cores/blueprinit/project-choice.js +0 -82
- package/dist/cores/blueprinit/prompts.d.ts +0 -13
- package/dist/cores/blueprinit/prompts.js +0 -42
- package/dist/cores/blueprinit/results.d.ts +0 -8
- package/dist/cores/blueprinit/results.js +0 -4
- package/dist/cores/blueprinit/selection.d.ts +0 -15
- package/dist/cores/blueprinit/selection.js +0 -90
- package/dist/cores/blueprinit/stack-name.d.ts +0 -39
- package/dist/cores/blueprinit/stack-name.js +0 -56
- package/dist/cores/blueprinit/target.d.ts +0 -33
- package/dist/cores/blueprinit/target.js +0 -80
- package/dist/cores/blueprinit/types.d.ts +0 -20
- package/dist/cores/blueprinit/types.js +0 -1
- package/dist/cores/blueprinit.d.ts +0 -7
- package/dist/cores/blueprinit.js +0 -64
- package/dist/utils/display/intro.d.ts +0 -6
- package/dist/utils/display/intro.js +0 -63
- package/skills/init.md +0 -199
package/oclif.manifest.json
CHANGED
|
@@ -1,156 +1,5 @@
|
|
|
1
1
|
{
|
|
2
2
|
"commands": {
|
|
3
|
-
"init": {
|
|
4
|
-
"aliases": [],
|
|
5
|
-
"args": {
|
|
6
|
-
"directory": {
|
|
7
|
-
"description": "Directory to initialize. Interactive runs are asked for one instead.",
|
|
8
|
-
"name": "directory",
|
|
9
|
-
"required": false
|
|
10
|
-
}
|
|
11
|
-
},
|
|
12
|
-
"description": "Scaffolds a Blueprint, Studio, and starter function around a Sanity project.\n\nUse a project you already have, or create one with --create-project. A new project has no\ndatasets, so the Blueprint creates the dataset rather than attaching it.\n\nPass a directory to scaffold into it. Without one, an interactive run asks where the files go.\n\nThis hidden command is an experiment; its interface and generated files are not stable.",
|
|
13
|
-
"examples": [
|
|
14
|
-
"<%= config.bin %> <%= command.id %>",
|
|
15
|
-
"<%= config.bin %> <%= command.id %> ./my-workspace",
|
|
16
|
-
"<%= config.bin %> <%= command.id %> --yes",
|
|
17
|
-
"<%= config.bin %> <%= command.id %> --project-id <id> --dataset <name> --yes",
|
|
18
|
-
"<%= config.bin %> <%= command.id %> --create-project \"My Shop\" --yes"
|
|
19
|
-
],
|
|
20
|
-
"flags": {
|
|
21
|
-
"json": {
|
|
22
|
-
"description": "Format output as json",
|
|
23
|
-
"name": "json",
|
|
24
|
-
"allowNo": false,
|
|
25
|
-
"type": "boolean"
|
|
26
|
-
},
|
|
27
|
-
"path": {
|
|
28
|
-
"aliases": [
|
|
29
|
-
"blueprint-path"
|
|
30
|
-
],
|
|
31
|
-
"char": "p",
|
|
32
|
-
"description": "Path to a Blueprint file or directory containing one",
|
|
33
|
-
"env": "SANITY_BLUEPRINT_PATH",
|
|
34
|
-
"hidden": true,
|
|
35
|
-
"name": "path",
|
|
36
|
-
"hasDynamicHelp": false,
|
|
37
|
-
"multiple": false,
|
|
38
|
-
"type": "option"
|
|
39
|
-
},
|
|
40
|
-
"trace": {
|
|
41
|
-
"description": "Trace output",
|
|
42
|
-
"hidden": true,
|
|
43
|
-
"name": "trace",
|
|
44
|
-
"allowNo": false,
|
|
45
|
-
"type": "boolean"
|
|
46
|
-
},
|
|
47
|
-
"validate-resources": {
|
|
48
|
-
"description": "Validate resources",
|
|
49
|
-
"hidden": true,
|
|
50
|
-
"name": "validate-resources",
|
|
51
|
-
"allowNo": true,
|
|
52
|
-
"type": "boolean"
|
|
53
|
-
},
|
|
54
|
-
"verbose": {
|
|
55
|
-
"description": "Verbose output",
|
|
56
|
-
"hidden": true,
|
|
57
|
-
"name": "verbose",
|
|
58
|
-
"allowNo": false,
|
|
59
|
-
"type": "boolean"
|
|
60
|
-
},
|
|
61
|
-
"llms": {
|
|
62
|
-
"aliases": [
|
|
63
|
-
"skill"
|
|
64
|
-
],
|
|
65
|
-
"description": "Show agent-oriented guidance for this command",
|
|
66
|
-
"hidden": true,
|
|
67
|
-
"name": "llms",
|
|
68
|
-
"allowNo": false,
|
|
69
|
-
"type": "boolean"
|
|
70
|
-
},
|
|
71
|
-
"yes": {
|
|
72
|
-
"char": "y",
|
|
73
|
-
"description": "Skip confirmation prompts",
|
|
74
|
-
"name": "yes",
|
|
75
|
-
"allowNo": false,
|
|
76
|
-
"type": "boolean"
|
|
77
|
-
},
|
|
78
|
-
"organization-id": {
|
|
79
|
-
"aliases": [
|
|
80
|
-
"organization",
|
|
81
|
-
"organizationId",
|
|
82
|
-
"org"
|
|
83
|
-
],
|
|
84
|
-
"description": "Organization to use when the account has several",
|
|
85
|
-
"name": "organization-id",
|
|
86
|
-
"hasDynamicHelp": false,
|
|
87
|
-
"multiple": false,
|
|
88
|
-
"type": "option"
|
|
89
|
-
},
|
|
90
|
-
"project-id": {
|
|
91
|
-
"aliases": [
|
|
92
|
-
"project",
|
|
93
|
-
"projectId"
|
|
94
|
-
],
|
|
95
|
-
"description": "Project to use when the organization has several",
|
|
96
|
-
"name": "project-id",
|
|
97
|
-
"hasDynamicHelp": false,
|
|
98
|
-
"multiple": false,
|
|
99
|
-
"type": "option"
|
|
100
|
-
},
|
|
101
|
-
"create-project": {
|
|
102
|
-
"aliases": [
|
|
103
|
-
"createProject",
|
|
104
|
-
"new-project"
|
|
105
|
-
],
|
|
106
|
-
"description": "Create a project with this display name instead of using an existing one",
|
|
107
|
-
"exclusive": [
|
|
108
|
-
"project-id"
|
|
109
|
-
],
|
|
110
|
-
"name": "create-project",
|
|
111
|
-
"hasDynamicHelp": false,
|
|
112
|
-
"multiple": false,
|
|
113
|
-
"type": "option"
|
|
114
|
-
},
|
|
115
|
-
"dataset": {
|
|
116
|
-
"description": "Dataset to attach, or to create alongside a new project",
|
|
117
|
-
"name": "dataset",
|
|
118
|
-
"hasDynamicHelp": false,
|
|
119
|
-
"multiple": false,
|
|
120
|
-
"type": "option"
|
|
121
|
-
},
|
|
122
|
-
"stack-name": {
|
|
123
|
-
"description": "Name for the new organization-scoped Stack, and the hosted Studio slug",
|
|
124
|
-
"name": "stack-name",
|
|
125
|
-
"hasDynamicHelp": false,
|
|
126
|
-
"multiple": false,
|
|
127
|
-
"type": "option"
|
|
128
|
-
},
|
|
129
|
-
"studio-name": {
|
|
130
|
-
"description": "Blueprint-local name for the Studio resource and its directory",
|
|
131
|
-
"name": "studio-name",
|
|
132
|
-
"hasDynamicHelp": false,
|
|
133
|
-
"multiple": false,
|
|
134
|
-
"type": "option"
|
|
135
|
-
}
|
|
136
|
-
},
|
|
137
|
-
"hasDynamicHelp": false,
|
|
138
|
-
"hidden": true,
|
|
139
|
-
"hiddenAliases": [],
|
|
140
|
-
"id": "init",
|
|
141
|
-
"pluginAlias": "@sanity/runtime-cli",
|
|
142
|
-
"pluginName": "@sanity/runtime-cli",
|
|
143
|
-
"pluginType": "core",
|
|
144
|
-
"strict": true,
|
|
145
|
-
"summary": "Experimental blueprints-first project init",
|
|
146
|
-
"enableJsonFlag": true,
|
|
147
|
-
"isESM": true,
|
|
148
|
-
"relativePath": [
|
|
149
|
-
"dist",
|
|
150
|
-
"commands",
|
|
151
|
-
"init.js"
|
|
152
|
-
]
|
|
153
|
-
},
|
|
154
3
|
"blueprints:add": {
|
|
155
4
|
"aliases": [],
|
|
156
5
|
"args": {
|
|
@@ -3299,5 +3148,5 @@
|
|
|
3299
3148
|
]
|
|
3300
3149
|
}
|
|
3301
3150
|
},
|
|
3302
|
-
"version": "17.
|
|
3151
|
+
"version": "17.10.0-next.g5e0bba6"
|
|
3303
3152
|
}
|
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.10.0-next.g5e0bba6",
|
|
5
5
|
"author": "Sanity Runtime Team",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"license": "MIT",
|
|
@@ -100,7 +100,7 @@
|
|
|
100
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.
|
|
103
|
+
"@sanity/functions": "^1.7.1",
|
|
104
104
|
"@types/adm-zip": "^0.5.8",
|
|
105
105
|
"@types/cardinal": "^2.1.1",
|
|
106
106
|
"@types/mime-types": "^3.0.1",
|
|
@@ -1,46 +0,0 @@
|
|
|
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;
|
|
@@ -1,121 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,43 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,73 +0,0 @@
|
|
|
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
|
-
};
|
|
@@ -1,138 +0,0 @@
|
|
|
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
|
-
});
|
|
@@ -1,8 +0,0 @@
|
|
|
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>;
|
|
@@ -1,11 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { type DatasetAction } from './manifest.js';
|
|
2
|
-
import { type StudioVersions } from './templates.js';
|
|
3
|
-
export interface WorkspaceOptions {
|
|
4
|
-
dir: string;
|
|
5
|
-
projectId: string;
|
|
6
|
-
displayName: string;
|
|
7
|
-
datasetName: string;
|
|
8
|
-
/** Attach a dataset the project already has, or create one. Defaults to attach. */
|
|
9
|
-
datasetAction?: DatasetAction;
|
|
10
|
-
stackName: string;
|
|
11
|
-
/** Blueprint-local name for the attached project resource. */
|
|
12
|
-
projectName: string;
|
|
13
|
-
studioName: string;
|
|
14
|
-
studioSlug: string;
|
|
15
|
-
studioOrigin: string;
|
|
16
|
-
blueprintsVersion: string;
|
|
17
|
-
}
|
|
18
|
-
export interface ScaffoldOptions extends WorkspaceOptions {
|
|
19
|
-
/** Resolved at scaffold time, the way `sanity init` resolves its own Studio versions. */
|
|
20
|
-
studioVersions: StudioVersions;
|
|
21
|
-
}
|
|
22
|
-
export interface WorkspaceResult {
|
|
23
|
-
blueprintFilePath: string;
|
|
24
|
-
files: string[];
|
|
25
|
-
}
|
|
26
|
-
export declare function scaffoldWorkspace(options: ScaffoldOptions): WorkspaceResult;
|
|
27
|
-
export declare function adoptWorkspace(options: WorkspaceOptions): WorkspaceResult;
|