@sanity/cli 3.93.0 → 3.93.1-bump-pkg-utils.34.5d0c0b3d22
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/lib/_chunks-cjs/cli.js +5 -5
- package/lib/_chunks-cjs/cli.js.map +1 -1
- package/lib/_chunks-cjs/cliWorker.js.map +1 -1
- package/lib/_chunks-cjs/generateAction.js.map +1 -1
- package/lib/_chunks-cjs/getCliConfig.js.map +1 -1
- package/lib/_chunks-cjs/journeyConfig.js.map +1 -1
- package/lib/_chunks-cjs/loadEnv.js.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/index.mjs.map +1 -1
- package/lib/run.js.map +1 -1
- package/lib/workers/getAndWriteJourneySchema.js.map +1 -1
- package/lib/workers/getCliConfig.js.map +1 -1
- package/lib/workers/typegenGenerate.js.map +1 -1
- package/package.json +6 -7
- package/templates/blog/README.md +1 -1
- package/templates/clean/README.md +1 -1
- package/templates/ecommerce/README.md +1 -1
- package/templates/get-started/README.md +1 -1
- package/templates/moviedb/README.md +1 -1
- package/templates/quickstart/README.md +1 -1
- package/src/CommandRunner.ts +0 -219
- package/src/__telemetry__/cli.telemetry.ts +0 -29
- package/src/__telemetry__/init.telemetry.ts +0 -95
- package/src/actions/codemod/codemodAction.ts +0 -109
- package/src/actions/codemod/mods/deskRename.ts +0 -19
- package/src/actions/codemod/mods/index.ts +0 -9
- package/src/actions/codemod/mods/partsTypeDirective.ts +0 -28
- package/src/actions/codemod/mods/reactIconsV3.ts +0 -54
- package/src/actions/codemod/types.ts +0 -10
- package/src/actions/init-plugin/bootstrapFromTemplate.ts +0 -196
- package/src/actions/init-project/bootstrapLocalTemplate.ts +0 -201
- package/src/actions/init-project/bootstrapRemoteTemplate.ts +0 -118
- package/src/actions/init-project/createAppCliConfig.ts +0 -24
- package/src/actions/init-project/createCliConfig.ts +0 -31
- package/src/actions/init-project/createPackageManifest.ts +0 -102
- package/src/actions/init-project/createStudioConfig.ts +0 -53
- package/src/actions/init-project/determineAppTemplate.ts +0 -13
- package/src/actions/init-project/fsUtils.ts +0 -40
- package/src/actions/init-project/git.ts +0 -59
- package/src/actions/init-project/initProject.ts +0 -1708
- package/src/actions/init-project/processTemplate.ts +0 -55
- package/src/actions/init-project/promptForDatasetName.ts +0 -68
- package/src/actions/init-project/prompts/index.ts +0 -51
- package/src/actions/init-project/prompts/nextjs.ts +0 -59
- package/src/actions/init-project/readPackageJson.ts +0 -17
- package/src/actions/init-project/templates/appQuickstart.ts +0 -23
- package/src/actions/init-project/templates/appSanityUi.ts +0 -25
- package/src/actions/init-project/templates/blog.ts +0 -5
- package/src/actions/init-project/templates/clean.ts +0 -5
- package/src/actions/init-project/templates/getStarted.ts +0 -37
- package/src/actions/init-project/templates/index.ts +0 -24
- package/src/actions/init-project/templates/moviedb.ts +0 -35
- package/src/actions/init-project/templates/nextjs/index.ts +0 -238
- package/src/actions/init-project/templates/nextjs/schemaTypes/blog.ts +0 -252
- package/src/actions/init-project/templates/quickstart.ts +0 -5
- package/src/actions/init-project/templates/shopify.ts +0 -78
- package/src/actions/init-project/templates/shopifyOnline.ts +0 -50
- package/src/actions/init-project/updateInitialTemplateMetadata.ts +0 -24
- package/src/actions/login/login.telemetry.ts +0 -18
- package/src/actions/login/login.ts +0 -350
- package/src/actions/login/types.ts +0 -19
- package/src/actions/project/createProject.ts +0 -36
- package/src/actions/telemetry/setTelemetryConsent.ts +0 -101
- package/src/actions/typegen/generate.telemetry.ts +0 -20
- package/src/actions/typegen/generateAction.ts +0 -210
- package/src/actions/versions/findSanityModuleVersions.ts +0 -185
- package/src/actions/yarn/events.ts +0 -73
- package/src/cli.ts +0 -350
- package/src/cliClient.ts +0 -62
- package/src/commands/blueprints/addBlueprintsCommand.ts +0 -155
- package/src/commands/blueprints/blueprintsGroup.ts +0 -10
- package/src/commands/blueprints/configBlueprintsCommand.ts +0 -86
- package/src/commands/blueprints/deployBlueprintsCommand.ts +0 -63
- package/src/commands/blueprints/destroyBlueprintsCommand.ts +0 -78
- package/src/commands/blueprints/infoBlueprintsCommand.ts +0 -55
- package/src/commands/blueprints/initBlueprintsCommand.ts +0 -99
- package/src/commands/blueprints/logsBlueprintsCommand.ts +0 -66
- package/src/commands/blueprints/planBlueprintsCommand.ts +0 -51
- package/src/commands/blueprints/stacksBlueprintsCommand.ts +0 -66
- package/src/commands/codemod/codemodCommand.ts +0 -32
- package/src/commands/debug/debugCommand.ts +0 -26
- package/src/commands/debug/printDebugInfo.ts +0 -243
- package/src/commands/docs/docsCommand.ts +0 -20
- package/src/commands/functions/devFunctionsCommand.ts +0 -73
- package/src/commands/functions/envFunctionsCommand.ts +0 -105
- package/src/commands/functions/functionsGroup.ts +0 -10
- package/src/commands/functions/logsFunctionsCommand.ts +0 -94
- package/src/commands/functions/testFunctionsCommand.ts +0 -93
- package/src/commands/help/helpCommand.ts +0 -21
- package/src/commands/help/showHelp.ts +0 -58
- package/src/commands/index.ts +0 -72
- package/src/commands/init/initCommand.ts +0 -123
- package/src/commands/install/installCommand.ts +0 -38
- package/src/commands/learn/learnCommand.ts +0 -20
- package/src/commands/login/loginCommand.ts +0 -29
- package/src/commands/logout/logoutCommand.ts +0 -52
- package/src/commands/manage/manageCommand.ts +0 -24
- package/src/commands/projects/listProjectsCommand.ts +0 -62
- package/src/commands/projects/projectsGroup.ts +0 -10
- package/src/commands/telemetry/disableTelemetryCommand.ts +0 -19
- package/src/commands/telemetry/enableTelemetryCommand.ts +0 -19
- package/src/commands/telemetry/telemetryGroup.ts +0 -10
- package/src/commands/telemetry/telemetryStatusCommand.ts +0 -89
- package/src/commands/typegen/generateTypesCommand.ts +0 -56
- package/src/commands/typegen/typegenGroup.ts +0 -10
- package/src/commands/versions/printVersionResult.ts +0 -51
- package/src/commands/versions/versionsCommand.ts +0 -13
- package/src/config.ts +0 -14
- package/src/debug.ts +0 -3
- package/src/index.ts +0 -6
- package/src/outputters/cliOutputter.ts +0 -47
- package/src/packageManager/getInstallCommand.ts +0 -26
- package/src/packageManager/getUpgradeCommand.ts +0 -52
- package/src/packageManager/index.ts +0 -33
- package/src/packageManager/installPackages.ts +0 -99
- package/src/packageManager/packageManagerChoice.ts +0 -204
- package/src/packageManager/uninstallPackages.ts +0 -44
- package/src/packageManager/yarnStub.ts +0 -22
- package/src/prompters/cliPrompter.ts +0 -9
- package/src/run.ts +0 -8
- package/src/studioDependencies.ts +0 -25
- package/src/types.ts +0 -387
- package/src/util/canLaunchBrowser.ts +0 -12
- package/src/util/cliWorker.ts +0 -34
- package/src/util/clientWrapper.ts +0 -119
- package/src/util/copy.ts +0 -50
- package/src/util/createExpiringConfig.ts +0 -80
- package/src/util/createTelemetryStore.ts +0 -204
- package/src/util/detectRuntime.ts +0 -12
- package/src/util/dynamicRequire.ts +0 -17
- package/src/util/frameworkPort.ts +0 -63
- package/src/util/generateCommandsDocumentation.ts +0 -62
- package/src/util/getCliConfig.ts +0 -172
- package/src/util/getCliVersion.ts +0 -22
- package/src/util/getLocalVersion.ts +0 -35
- package/src/util/getProjectDefaults.ts +0 -103
- package/src/util/getProviderName.ts +0 -9
- package/src/util/getUserConfig.ts +0 -15
- package/src/util/isCi.ts +0 -7
- package/src/util/isCommandGroup.ts +0 -7
- package/src/util/isInteractive.ts +0 -3
- package/src/util/isTrueish.ts +0 -8
- package/src/util/journeyConfig.ts +0 -280
- package/src/util/loadEnv.ts +0 -110
- package/src/util/mergeCommands.ts +0 -78
- package/src/util/neatStack.ts +0 -30
- package/src/util/noSuchCommandText.ts +0 -91
- package/src/util/parseArguments.ts +0 -76
- package/src/util/pathExists.ts +0 -14
- package/src/util/readJson.ts +0 -6
- package/src/util/readdirRecursive.ts +0 -26
- package/src/util/remoteTemplate.ts +0 -320
- package/src/util/resolveLatestVersions.ts +0 -24
- package/src/util/resolveRootDir.ts +0 -59
- package/src/util/telemetryDisclosure.ts +0 -45
- package/src/util/updateNotifier.ts +0 -158
- package/src/util/writeJson.ts +0 -6
- package/src/workers/getAndWriteJourneySchema.ts +0 -7
- package/src/workers/getCliConfig.ts +0 -14
- package/src/workers/typegenGenerate.ts +0 -228
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import path from 'node:path'
|
|
2
|
-
|
|
3
|
-
import resolveFrom from 'resolve-from'
|
|
4
|
-
import semverCompare from 'semver-compare'
|
|
5
|
-
|
|
6
|
-
import {type PackageJson} from '../../../types'
|
|
7
|
-
import {readJson} from '../../../util/readJson'
|
|
8
|
-
import {type CodeMod} from '../types'
|
|
9
|
-
|
|
10
|
-
const purpose = 'Transform react-icons v2 imports to v3 form'
|
|
11
|
-
const description = `
|
|
12
|
-
Modifies all found react-icons import and require statements from their v2 form
|
|
13
|
-
to the path structure used in react-icons v3. For instance:
|
|
14
|
-
|
|
15
|
-
from: import {MdPerson} from 'react-icons/lib/md'
|
|
16
|
-
to: import {MdPerson} from 'react-icons/md'
|
|
17
|
-
|
|
18
|
-
from: import PersonIcon from 'react-icons/lib/md/person'
|
|
19
|
-
to: import {MdPerson as PersonIcon} from 'react-icons/md'
|
|
20
|
-
`.trim()
|
|
21
|
-
|
|
22
|
-
export const reactIconsV3: CodeMod = {
|
|
23
|
-
purpose,
|
|
24
|
-
description,
|
|
25
|
-
filename: 'reactIconsV3.js',
|
|
26
|
-
verify: async (context) => {
|
|
27
|
-
const {workDir} = context
|
|
28
|
-
|
|
29
|
-
const studioPkg = await maybeReadJson(path.join(workDir, 'package.json'))
|
|
30
|
-
const dependencies = (studioPkg && studioPkg.dependencies) || {}
|
|
31
|
-
const dependencyVersion = (dependencies['react-icons'] || '').replace(/^[\^~]/, '')
|
|
32
|
-
if (!dependencyVersion) {
|
|
33
|
-
throw new Error('Could not find react-icons declared as dependency in package.json')
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
if (semverCompare(dependencyVersion, '3.0.0') < 0) {
|
|
37
|
-
throw new Error('react-icons declared in package.json dependencies is lower than 3.0.0')
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const iconPkgPath = resolveFrom.silent(workDir, 'react-icons/package.json')
|
|
41
|
-
const iconPkg = iconPkgPath && (await maybeReadJson(iconPkgPath))
|
|
42
|
-
if (iconPkg && semverCompare(iconPkg.version, '3.0.0') < 0) {
|
|
43
|
-
throw new Error('The installed version of react-icon seems to be < 3.0.0')
|
|
44
|
-
}
|
|
45
|
-
},
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
async function maybeReadJson(jsonPath: string): Promise<PackageJson | null> {
|
|
49
|
-
try {
|
|
50
|
-
return await readJson(jsonPath)
|
|
51
|
-
} catch {
|
|
52
|
-
return null
|
|
53
|
-
}
|
|
54
|
-
}
|
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
import fs from 'node:fs/promises'
|
|
2
|
-
import path from 'node:path'
|
|
3
|
-
|
|
4
|
-
import {absolutify, pathIsEmpty} from '@sanity/util/fs'
|
|
5
|
-
import decompress from 'decompress'
|
|
6
|
-
import {getIt} from 'get-it'
|
|
7
|
-
import {promise} from 'get-it/middleware'
|
|
8
|
-
import resolveFrom from 'resolve-from'
|
|
9
|
-
import semver from 'semver'
|
|
10
|
-
import validateNpmPackageName from 'validate-npm-package-name'
|
|
11
|
-
|
|
12
|
-
import {type CliCommandContext} from '../..'
|
|
13
|
-
import {debug} from '../../debug'
|
|
14
|
-
import {type SanityJson} from '../../types'
|
|
15
|
-
import {dynamicRequire} from '../../util/dynamicRequire'
|
|
16
|
-
import {getCliVersion} from '../../util/getCliVersion'
|
|
17
|
-
import {readJson} from '../../util/readJson'
|
|
18
|
-
|
|
19
|
-
const request = getIt([promise()])
|
|
20
|
-
|
|
21
|
-
interface TemplateManifest {
|
|
22
|
-
sanityTemplate: {
|
|
23
|
-
minimumBaseVersion?: string
|
|
24
|
-
minimumCliVersion?: string
|
|
25
|
-
suggestedName?: string
|
|
26
|
-
requiresConfig?: boolean
|
|
27
|
-
dependencies?: Record<string, string>
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export async function bootstrapFromTemplate(
|
|
32
|
-
context: CliCommandContext,
|
|
33
|
-
url: string,
|
|
34
|
-
): Promise<{
|
|
35
|
-
name: string
|
|
36
|
-
outputPath: string
|
|
37
|
-
inPluginsPath: boolean
|
|
38
|
-
dependencies: any
|
|
39
|
-
}> {
|
|
40
|
-
const {prompt, workDir} = context
|
|
41
|
-
const cliVersion = await getCliVersion()
|
|
42
|
-
let inProjectContext = false
|
|
43
|
-
try {
|
|
44
|
-
const projectManifest = await readJson<SanityJson>(path.join(workDir, 'sanity.json'))
|
|
45
|
-
inProjectContext = Boolean(projectManifest.root)
|
|
46
|
-
} catch {
|
|
47
|
-
// Intentional noop
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
debug(inProjectContext ? 'Project context found' : 'Not in project context')
|
|
51
|
-
|
|
52
|
-
let zip: decompress.File[]
|
|
53
|
-
try {
|
|
54
|
-
debug('Fetching zip from %s', url)
|
|
55
|
-
zip = await getZip(url)
|
|
56
|
-
debug('Zip finished downloading')
|
|
57
|
-
} catch (err) {
|
|
58
|
-
err.message = `Failed to get template: ${err.message}`
|
|
59
|
-
throw err
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
debug('Looking up template manifest from zip')
|
|
63
|
-
const manifest = zip.find(
|
|
64
|
-
(file) => path.basename(file.path) === 'package.json' && !file.path.includes('node_modules'),
|
|
65
|
-
)
|
|
66
|
-
|
|
67
|
-
if (!manifest) {
|
|
68
|
-
throw new Error('Could not find `package.json` in template')
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// Note: Paths inside the zips are always unix-style, so do not use `path.join` here
|
|
72
|
-
const baseDir = `${path.dirname(manifest.path)}/template`
|
|
73
|
-
debug('Manifest path resolved to %s', manifest.path)
|
|
74
|
-
debug('Base directory resolved to %s', baseDir)
|
|
75
|
-
|
|
76
|
-
const templateFiles = zip.filter(
|
|
77
|
-
(file) => file.type === 'file' && file.path.indexOf(baseDir) === 0,
|
|
78
|
-
)
|
|
79
|
-
debug('%d files found in template', templateFiles.length)
|
|
80
|
-
|
|
81
|
-
const manifestContent = parseJson<TemplateManifest>(manifest.data.toString())
|
|
82
|
-
const tplVars = manifestContent?.sanityTemplate || {}
|
|
83
|
-
const {minimumBaseVersion, minimumCliVersion} = tplVars
|
|
84
|
-
|
|
85
|
-
if (minimumBaseVersion) {
|
|
86
|
-
debug('Template requires Sanity version %s', minimumBaseVersion)
|
|
87
|
-
const installed = getSanityVersion(workDir, cliVersion)
|
|
88
|
-
debug('Installed Sanity version is %s', installed)
|
|
89
|
-
|
|
90
|
-
if (semver.lt(installed, minimumBaseVersion)) {
|
|
91
|
-
throw new Error(
|
|
92
|
-
`Template requires Sanity at version ${minimumBaseVersion}, installed is ${installed}`,
|
|
93
|
-
)
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
if (minimumCliVersion) {
|
|
98
|
-
debug('Template requires Sanity CLI version %s', minimumCliVersion)
|
|
99
|
-
debug('Installed CLI version is %s', cliVersion)
|
|
100
|
-
|
|
101
|
-
if (semver.lt(cliVersion, minimumCliVersion)) {
|
|
102
|
-
throw new Error(
|
|
103
|
-
`Template requires @sanity/cli at version ${minimumCliVersion}, installed is ${cliVersion}`,
|
|
104
|
-
)
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
const name = await prompt.single({
|
|
109
|
-
type: 'input',
|
|
110
|
-
message: 'Plugin name:',
|
|
111
|
-
default: tplVars.suggestedName || '',
|
|
112
|
-
validate: async (pkgName) => {
|
|
113
|
-
const {validForNewPackages} = validateNpmPackageName(pkgName)
|
|
114
|
-
if (!validForNewPackages) {
|
|
115
|
-
return 'Name must be a valid npm package name (https://docs.npmjs.com/files/package.json#name)'
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const outputPath = path.join(workDir, 'plugins', pkgName)
|
|
119
|
-
const isEmpty = await pathIsEmpty(outputPath)
|
|
120
|
-
if (inProjectContext && !isEmpty) {
|
|
121
|
-
return 'Plugin with given name already exists in project'
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
return true
|
|
125
|
-
},
|
|
126
|
-
})
|
|
127
|
-
|
|
128
|
-
let outputPath = path.join(workDir, 'plugins', name)
|
|
129
|
-
if (!inProjectContext) {
|
|
130
|
-
const cwdIsEmpty = await pathIsEmpty(workDir)
|
|
131
|
-
outputPath = await prompt.single({
|
|
132
|
-
type: 'input',
|
|
133
|
-
message: 'Output path:',
|
|
134
|
-
default: cwdIsEmpty ? workDir : path.join(workDir, name),
|
|
135
|
-
validate: validateEmptyPath,
|
|
136
|
-
filter: absolutify,
|
|
137
|
-
})
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
debug('Output path set to %s', outputPath)
|
|
141
|
-
|
|
142
|
-
let createConfig = tplVars.requiresConfig
|
|
143
|
-
if (typeof createConfig === 'undefined') {
|
|
144
|
-
createConfig = await prompt.single({
|
|
145
|
-
type: 'confirm',
|
|
146
|
-
message: 'Does the plugin need a configuration file?',
|
|
147
|
-
default: false,
|
|
148
|
-
})
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
debug('Ensuring directory exists: %s', outputPath)
|
|
152
|
-
await fs.mkdir(outputPath, {recursive: true})
|
|
153
|
-
|
|
154
|
-
await Promise.all(
|
|
155
|
-
templateFiles.map((file: {path: string; data: string | Buffer}) => {
|
|
156
|
-
const filename = file.path.slice(baseDir.length)
|
|
157
|
-
|
|
158
|
-
debug('Writing template file "%s" to "%s"', filename, outputPath)
|
|
159
|
-
return fs.writeFile(path.join(outputPath, filename), file.data)
|
|
160
|
-
}),
|
|
161
|
-
)
|
|
162
|
-
|
|
163
|
-
return {name, outputPath, inPluginsPath: inProjectContext, dependencies: tplVars.dependencies}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
async function validateEmptyPath(dir: string) {
|
|
167
|
-
const isEmpty = await pathIsEmpty(dir)
|
|
168
|
-
return isEmpty ? true : 'Path is not empty'
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
function getZip(url: string): Promise<decompress.File[]> {
|
|
172
|
-
return request({url, rawBody: true}).then(
|
|
173
|
-
(res: {statusCode: number; statusMessage: string; body: Buffer}) => {
|
|
174
|
-
if (res.statusCode > 299) {
|
|
175
|
-
const httpErr = ['HTTP', res.statusCode, res.statusMessage].filter(Boolean).join(' ')
|
|
176
|
-
throw new Error(`${httpErr} trying to download ${url}`)
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
return decompress(res.body)
|
|
180
|
-
},
|
|
181
|
-
)
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
function parseJson<T = any>(json: string): T | undefined {
|
|
185
|
-
try {
|
|
186
|
-
return JSON.parse(json)
|
|
187
|
-
} catch {
|
|
188
|
-
return undefined
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
function getSanityVersion(workDir: string, fallback: string): string {
|
|
193
|
-
// This is only used in v2, thus `@sanity/base`
|
|
194
|
-
const basePkg = resolveFrom.silent(workDir, '@sanity/base/package.json')
|
|
195
|
-
return basePkg ? dynamicRequire(basePkg).version : fallback
|
|
196
|
-
}
|
|
@@ -1,201 +0,0 @@
|
|
|
1
|
-
import fs from 'node:fs/promises'
|
|
2
|
-
import path from 'node:path'
|
|
3
|
-
|
|
4
|
-
import chalk from 'chalk'
|
|
5
|
-
import {deburr} from 'lodash'
|
|
6
|
-
|
|
7
|
-
import {debug} from '../../debug'
|
|
8
|
-
import {studioDependencies} from '../../studioDependencies'
|
|
9
|
-
import {type CliCommandContext} from '../../types'
|
|
10
|
-
import {copy} from '../../util/copy'
|
|
11
|
-
import {getAndWriteJourneySchemaWorker} from '../../util/journeyConfig'
|
|
12
|
-
import {resolveLatestVersions} from '../../util/resolveLatestVersions'
|
|
13
|
-
import {createAppCliConfig} from './createAppCliConfig'
|
|
14
|
-
import {createCliConfig} from './createCliConfig'
|
|
15
|
-
import {createPackageManifest} from './createPackageManifest'
|
|
16
|
-
import {createStudioConfig, type GenerateConfigOptions} from './createStudioConfig'
|
|
17
|
-
import {determineAppTemplate} from './determineAppTemplate'
|
|
18
|
-
import {type ProjectTemplate} from './initProject'
|
|
19
|
-
import templates from './templates'
|
|
20
|
-
import {updateInitialTemplateMetadata} from './updateInitialTemplateMetadata'
|
|
21
|
-
|
|
22
|
-
export interface BootstrapLocalOptions {
|
|
23
|
-
packageName: string
|
|
24
|
-
templateName: string
|
|
25
|
-
/**
|
|
26
|
-
* Used for initializing a project from a server schema that is saved in the Journey API
|
|
27
|
-
* @beta
|
|
28
|
-
*/
|
|
29
|
-
schemaUrl?: string
|
|
30
|
-
outputPath: string
|
|
31
|
-
useTypeScript: boolean
|
|
32
|
-
variables: GenerateConfigOptions['variables']
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export async function bootstrapLocalTemplate(
|
|
36
|
-
opts: BootstrapLocalOptions,
|
|
37
|
-
context: CliCommandContext,
|
|
38
|
-
): Promise<ProjectTemplate> {
|
|
39
|
-
const {apiClient, cliRoot, output} = context
|
|
40
|
-
const templatesDir = path.join(cliRoot, 'templates')
|
|
41
|
-
const {outputPath, templateName, useTypeScript, packageName, variables} = opts
|
|
42
|
-
const sourceDir = path.join(templatesDir, templateName)
|
|
43
|
-
const sharedDir = path.join(templatesDir, 'shared')
|
|
44
|
-
const isAppTemplate = determineAppTemplate(templateName)
|
|
45
|
-
|
|
46
|
-
// Check that we have a template info file (dependencies, plugins etc)
|
|
47
|
-
const template = templates[templateName]
|
|
48
|
-
if (!template) {
|
|
49
|
-
throw new Error(`Template "${templateName}" not defined`)
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// Copy template files
|
|
53
|
-
debug('Copying files from template "%s" to "%s"', templateName, outputPath)
|
|
54
|
-
let spinner = output
|
|
55
|
-
.spinner(
|
|
56
|
-
opts.schemaUrl ? 'Extracting your Sanity configuration' : 'Bootstrapping files from template',
|
|
57
|
-
)
|
|
58
|
-
.start()
|
|
59
|
-
|
|
60
|
-
await copy(sourceDir, outputPath, {
|
|
61
|
-
rename: useTypeScript ? toTypeScriptPath : undefined,
|
|
62
|
-
})
|
|
63
|
-
await copy(path.join(sharedDir, 'gitignore.txt'), outputPath, {rename: () => '.gitignore'})
|
|
64
|
-
|
|
65
|
-
if (useTypeScript) {
|
|
66
|
-
await fs.copyFile(path.join(sharedDir, 'tsconfig.json'), path.join(outputPath, 'tsconfig.json'))
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// If we have a schemaUrl, get the schema and write it to disk
|
|
70
|
-
// At this point the selected template should already have been forced to "clean"
|
|
71
|
-
if (opts.schemaUrl) {
|
|
72
|
-
debug('Fetching and writing remote schema "%s"', opts.schemaUrl)
|
|
73
|
-
await getAndWriteJourneySchemaWorker({
|
|
74
|
-
schemasPath: path.join(outputPath, 'schemaTypes'),
|
|
75
|
-
useTypeScript,
|
|
76
|
-
schemaUrl: opts.schemaUrl,
|
|
77
|
-
})
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
spinner.succeed()
|
|
81
|
-
|
|
82
|
-
// Merge global and template-specific plugins and dependencies
|
|
83
|
-
|
|
84
|
-
// Resolve latest versions of Sanity-dependencies
|
|
85
|
-
spinner = output.spinner('Resolving latest module versions').start()
|
|
86
|
-
const dependencyVersions = await resolveLatestVersions({
|
|
87
|
-
...(isAppTemplate ? {} : studioDependencies.dependencies),
|
|
88
|
-
...(isAppTemplate ? {} : studioDependencies.devDependencies),
|
|
89
|
-
...template.dependencies,
|
|
90
|
-
...template.devDependencies,
|
|
91
|
-
})
|
|
92
|
-
spinner.succeed()
|
|
93
|
-
|
|
94
|
-
// Use the resolved version for the given dependency
|
|
95
|
-
const dependencies = Object.keys({
|
|
96
|
-
...(isAppTemplate ? {} : studioDependencies.dependencies),
|
|
97
|
-
...template.dependencies,
|
|
98
|
-
}).reduce(
|
|
99
|
-
(deps, dependency) => {
|
|
100
|
-
deps[dependency] = dependencyVersions[dependency]
|
|
101
|
-
return deps
|
|
102
|
-
},
|
|
103
|
-
{} as Record<string, string>,
|
|
104
|
-
)
|
|
105
|
-
|
|
106
|
-
const devDependencies = Object.keys({
|
|
107
|
-
...(isAppTemplate ? {} : studioDependencies.devDependencies),
|
|
108
|
-
...template.devDependencies,
|
|
109
|
-
}).reduce(
|
|
110
|
-
(deps, dependency) => {
|
|
111
|
-
deps[dependency] = dependencyVersions[dependency]
|
|
112
|
-
return deps
|
|
113
|
-
},
|
|
114
|
-
{} as Record<string, string>,
|
|
115
|
-
)
|
|
116
|
-
|
|
117
|
-
let packageJsonName: string = packageName
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Currently app init doesn't ask for a name, so we use the last part of the path
|
|
121
|
-
*/
|
|
122
|
-
if (isAppTemplate) {
|
|
123
|
-
packageJsonName = deburr(path.basename(outputPath).toLowerCase())
|
|
124
|
-
.replace(/\s+/g, '-')
|
|
125
|
-
.replace(/[^a-z0-9-]/g, '')
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// Now create a package manifest (`package.json`) with the merged dependencies
|
|
129
|
-
spinner = output.spinner('Creating default project files').start()
|
|
130
|
-
const packageManifest = await createPackageManifest({
|
|
131
|
-
name: packageJsonName,
|
|
132
|
-
dependencies,
|
|
133
|
-
devDependencies,
|
|
134
|
-
scripts: template.scripts,
|
|
135
|
-
isAppTemplate,
|
|
136
|
-
})
|
|
137
|
-
|
|
138
|
-
// ...and a studio config (`sanity.config.[ts|js]`)
|
|
139
|
-
const studioConfig = createStudioConfig({
|
|
140
|
-
template: template.configTemplate,
|
|
141
|
-
variables,
|
|
142
|
-
})
|
|
143
|
-
|
|
144
|
-
// ...and a CLI config (`sanity.cli.[ts|js]`)
|
|
145
|
-
const cliConfig = isAppTemplate
|
|
146
|
-
? createAppCliConfig({
|
|
147
|
-
entry: template.entry!,
|
|
148
|
-
organizationId: variables.organizationId,
|
|
149
|
-
})
|
|
150
|
-
: createCliConfig({
|
|
151
|
-
projectId: variables.projectId,
|
|
152
|
-
dataset: variables.dataset,
|
|
153
|
-
autoUpdates: variables.autoUpdates,
|
|
154
|
-
})
|
|
155
|
-
|
|
156
|
-
// Write non-template files to disc
|
|
157
|
-
const codeExt = useTypeScript ? 'ts' : 'js'
|
|
158
|
-
await Promise.all(
|
|
159
|
-
[
|
|
160
|
-
...[
|
|
161
|
-
isAppTemplate
|
|
162
|
-
? Promise.resolve(null)
|
|
163
|
-
: writeFileIfNotExists(`sanity.config.${codeExt}`, studioConfig),
|
|
164
|
-
],
|
|
165
|
-
writeFileIfNotExists(`sanity.cli.${codeExt}`, cliConfig),
|
|
166
|
-
writeFileIfNotExists('package.json', packageManifest),
|
|
167
|
-
...[
|
|
168
|
-
isAppTemplate
|
|
169
|
-
? Promise.resolve(null)
|
|
170
|
-
: writeFileIfNotExists(
|
|
171
|
-
'eslint.config.mjs',
|
|
172
|
-
`import studio from '@sanity/eslint-config-studio'\n\nexport default [...studio]\n`,
|
|
173
|
-
),
|
|
174
|
-
],
|
|
175
|
-
].filter(Boolean),
|
|
176
|
-
)
|
|
177
|
-
|
|
178
|
-
debug('Updating initial template metadata')
|
|
179
|
-
await updateInitialTemplateMetadata(apiClient, variables.projectId, `cli-${templateName}`)
|
|
180
|
-
|
|
181
|
-
// Finish up by providing init process with template-specific info
|
|
182
|
-
spinner.succeed()
|
|
183
|
-
return template
|
|
184
|
-
|
|
185
|
-
async function writeFileIfNotExists(fileName: string, content: string): Promise<void> {
|
|
186
|
-
const filePath = path.join(outputPath, fileName)
|
|
187
|
-
try {
|
|
188
|
-
await fs.writeFile(filePath, content, {flag: 'wx'})
|
|
189
|
-
} catch (err) {
|
|
190
|
-
if (err.code === 'EEXIST') {
|
|
191
|
-
output.warn(`\n${chalk.yellow('⚠')} File "${filePath}" already exists, skipping`)
|
|
192
|
-
} else {
|
|
193
|
-
throw err
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
function toTypeScriptPath(originalPath: string): string {
|
|
200
|
-
return originalPath.replace(/\.js$/, '.ts')
|
|
201
|
-
}
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
import {mkdir} from 'node:fs/promises'
|
|
2
|
-
import {join} from 'node:path'
|
|
3
|
-
|
|
4
|
-
import {getMonoRepo, GitHubFileReader, validateTemplate} from '@sanity/template-validator'
|
|
5
|
-
import {type Framework, frameworks} from '@vercel/frameworks'
|
|
6
|
-
import {detectFrameworkRecord, LocalFileSystemDetector} from '@vercel/fs-detectors'
|
|
7
|
-
|
|
8
|
-
import {debug} from '../../debug'
|
|
9
|
-
import {type CliCommandContext} from '../../types'
|
|
10
|
-
import {getDefaultPortForFramework} from '../../util/frameworkPort'
|
|
11
|
-
import {
|
|
12
|
-
applyEnvVariables,
|
|
13
|
-
checkIfNeedsApiToken,
|
|
14
|
-
downloadAndExtractRepo,
|
|
15
|
-
generateSanityApiToken,
|
|
16
|
-
getGitHubRawContentUrl,
|
|
17
|
-
type RepoInfo,
|
|
18
|
-
setCorsOrigin,
|
|
19
|
-
tryApplyPackageName,
|
|
20
|
-
} from '../../util/remoteTemplate'
|
|
21
|
-
import {type GenerateConfigOptions} from './createStudioConfig'
|
|
22
|
-
import {tryGitInit} from './git'
|
|
23
|
-
import {updateInitialTemplateMetadata} from './updateInitialTemplateMetadata'
|
|
24
|
-
|
|
25
|
-
export interface BootstrapRemoteOptions {
|
|
26
|
-
outputPath: string
|
|
27
|
-
repoInfo: RepoInfo
|
|
28
|
-
bearerToken?: string
|
|
29
|
-
packageName: string
|
|
30
|
-
variables: GenerateConfigOptions['variables']
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const SANITY_DEFAULT_PORT = 3333
|
|
34
|
-
const READ_TOKEN_LABEL = 'Live Preview API'
|
|
35
|
-
const WRITE_TOKEN_LABEL = 'App Write Token'
|
|
36
|
-
const INITIAL_COMMIT_MESSAGE = 'Initial commit from Sanity CLI'
|
|
37
|
-
|
|
38
|
-
export async function bootstrapRemoteTemplate(
|
|
39
|
-
opts: BootstrapRemoteOptions,
|
|
40
|
-
context: CliCommandContext,
|
|
41
|
-
): Promise<void> {
|
|
42
|
-
const {outputPath, repoInfo, bearerToken, variables, packageName} = opts
|
|
43
|
-
const {output, apiClient} = context
|
|
44
|
-
const name = [repoInfo.username, repoInfo.name, repoInfo.filePath].filter(Boolean).join('/')
|
|
45
|
-
const contentsUrl = getGitHubRawContentUrl(repoInfo)
|
|
46
|
-
const headers: Record<string, string> = {}
|
|
47
|
-
if (bearerToken) {
|
|
48
|
-
headers.Authorization = `Bearer ${bearerToken}`
|
|
49
|
-
}
|
|
50
|
-
const spinner = output.spinner(`Bootstrapping files from template "${name}"`).start()
|
|
51
|
-
const corsAdded: number[] = [SANITY_DEFAULT_PORT]
|
|
52
|
-
|
|
53
|
-
debug('Validating remote template')
|
|
54
|
-
const fileReader = new GitHubFileReader(contentsUrl, headers)
|
|
55
|
-
const packages = await getMonoRepo(fileReader)
|
|
56
|
-
const validation = await validateTemplate(fileReader, packages)
|
|
57
|
-
if (!validation.isValid) {
|
|
58
|
-
throw new Error(validation.errors.join('\n'))
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
debug('Create new directory "%s"', outputPath)
|
|
62
|
-
await mkdir(outputPath, {recursive: true})
|
|
63
|
-
|
|
64
|
-
debug('Downloading and extracting repo to %s', outputPath)
|
|
65
|
-
await downloadAndExtractRepo(outputPath, repoInfo, bearerToken)
|
|
66
|
-
|
|
67
|
-
debug('Checking if template needs read token')
|
|
68
|
-
const needsReadToken = await Promise.all(
|
|
69
|
-
(packages ?? ['']).map((pkg) => checkIfNeedsApiToken(join(outputPath, pkg), 'read')),
|
|
70
|
-
).then((results) => results.some(Boolean))
|
|
71
|
-
const needsWriteToken = await Promise.all(
|
|
72
|
-
(packages ?? ['']).map((pkg) => checkIfNeedsApiToken(join(outputPath, pkg), 'write')),
|
|
73
|
-
).then((results) => results.some(Boolean))
|
|
74
|
-
|
|
75
|
-
debug('Applying environment variables')
|
|
76
|
-
const readToken = needsReadToken
|
|
77
|
-
? await generateSanityApiToken(READ_TOKEN_LABEL, 'read', variables.projectId, apiClient)
|
|
78
|
-
: undefined
|
|
79
|
-
const writeToken = needsWriteToken
|
|
80
|
-
? await generateSanityApiToken(WRITE_TOKEN_LABEL, 'write', variables.projectId, apiClient)
|
|
81
|
-
: undefined
|
|
82
|
-
|
|
83
|
-
for (const pkg of packages ?? ['']) {
|
|
84
|
-
const packagePath = join(outputPath, pkg)
|
|
85
|
-
const packageFramework: Framework | null = await detectFrameworkRecord({
|
|
86
|
-
fs: new LocalFileSystemDetector(packagePath),
|
|
87
|
-
frameworkList: frameworks as readonly Framework[],
|
|
88
|
-
})
|
|
89
|
-
|
|
90
|
-
const port = getDefaultPortForFramework(packageFramework?.slug)
|
|
91
|
-
if (corsAdded.includes(port) === false) {
|
|
92
|
-
debug('Setting CORS origin to http://localhost:%d', port)
|
|
93
|
-
await setCorsOrigin(`http://localhost:${port}`, variables.projectId, apiClient)
|
|
94
|
-
corsAdded.push(port)
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
debug('Applying environment variables to %s', pkg)
|
|
98
|
-
// Next.js uses `.env.local` for local environment variables
|
|
99
|
-
const envName = packageFramework?.slug === 'nextjs' ? '.env.local' : '.env'
|
|
100
|
-
await applyEnvVariables(packagePath, {...variables, readToken, writeToken}, envName)
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
debug('Setting package name to %s', packageName)
|
|
104
|
-
await tryApplyPackageName(outputPath, packageName)
|
|
105
|
-
|
|
106
|
-
debug('Initializing git repository')
|
|
107
|
-
tryGitInit(outputPath, INITIAL_COMMIT_MESSAGE)
|
|
108
|
-
|
|
109
|
-
debug('Updating initial template metadata')
|
|
110
|
-
await updateInitialTemplateMetadata(apiClient, variables.projectId, `external-${name}`)
|
|
111
|
-
|
|
112
|
-
spinner.succeed()
|
|
113
|
-
if (corsAdded.length) {
|
|
114
|
-
output.success(`CORS origins added (${corsAdded.map((p) => `localhost:${p}`).join(', ')})`)
|
|
115
|
-
}
|
|
116
|
-
if (readToken) output.success(`API token generated (${READ_TOKEN_LABEL})`)
|
|
117
|
-
if (writeToken) output.success(`API token generated (${WRITE_TOKEN_LABEL})`)
|
|
118
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import {processTemplate} from './processTemplate'
|
|
2
|
-
|
|
3
|
-
const defaultAppTemplate = `
|
|
4
|
-
import {defineCliConfig} from 'sanity/cli'
|
|
5
|
-
|
|
6
|
-
export default defineCliConfig({
|
|
7
|
-
app: {
|
|
8
|
-
organizationId: '%organizationId%',
|
|
9
|
-
entry: '%entry%',
|
|
10
|
-
},
|
|
11
|
-
})
|
|
12
|
-
`
|
|
13
|
-
|
|
14
|
-
export interface GenerateCliConfigOptions {
|
|
15
|
-
organizationId?: string
|
|
16
|
-
entry: string
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function createAppCliConfig(options: GenerateCliConfigOptions): string {
|
|
20
|
-
return processTemplate({
|
|
21
|
-
template: defaultAppTemplate,
|
|
22
|
-
variables: options,
|
|
23
|
-
})
|
|
24
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import {processTemplate} from './processTemplate'
|
|
2
|
-
|
|
3
|
-
const defaultTemplate = `
|
|
4
|
-
import {defineCliConfig} from 'sanity/cli'
|
|
5
|
-
|
|
6
|
-
export default defineCliConfig({
|
|
7
|
-
api: {
|
|
8
|
-
projectId: '%projectId%',
|
|
9
|
-
dataset: '%dataset%'
|
|
10
|
-
},
|
|
11
|
-
/**
|
|
12
|
-
* Enable auto-updates for studios.
|
|
13
|
-
* Learn more at https://www.sanity.io/docs/cli#auto-updates
|
|
14
|
-
*/
|
|
15
|
-
autoUpdates: __BOOL__autoUpdates__,
|
|
16
|
-
})
|
|
17
|
-
`
|
|
18
|
-
|
|
19
|
-
export interface GenerateCliConfigOptions {
|
|
20
|
-
projectId: string
|
|
21
|
-
dataset: string
|
|
22
|
-
autoUpdates: boolean
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export function createCliConfig(options: GenerateCliConfigOptions): string {
|
|
26
|
-
return processTemplate({
|
|
27
|
-
template: defaultTemplate,
|
|
28
|
-
variables: options,
|
|
29
|
-
includeBooleanTransform: true,
|
|
30
|
-
})
|
|
31
|
-
}
|