@sanity/cli 3.65.2-corel.472 → 3.66.0
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 +445 -1082
- package/lib/_chunks-cjs/cli.js.map +1 -1
- package/lib/index.d.mts +0 -1
- package/lib/index.d.ts +0 -1
- package/package.json +7 -7
- package/src/CommandRunner.ts +1 -2
- package/src/actions/init-project/bootstrapRemoteTemplate.ts +10 -7
- package/src/actions/init-project/initProject.ts +1 -17
- package/src/commands/index.ts +0 -2
- package/src/commands/init/initCommand.ts +0 -9
- package/src/types.ts +0 -1
- package/src/util/remoteTemplate.ts +16 -0
- package/src/actions/init-plugin/initPlugin.ts +0 -119
- package/src/actions/init-plugin/pluginTemplates.ts +0 -38
- package/src/actions/init-project/reconfigureV2Project.ts +0 -446
- package/src/commands/upgrade/upgradeCommand.ts +0 -38
- package/src/commands/upgrade/upgradeDependencies.ts +0 -289
@@ -1,289 +0,0 @@
|
|
1
|
-
import {promises as fs} from 'node:fs'
|
2
|
-
import path from 'node:path'
|
3
|
-
import util from 'node:util'
|
4
|
-
|
5
|
-
import boxen from 'boxen'
|
6
|
-
import {noop, padStart} from 'lodash'
|
7
|
-
import resolveFrom from 'resolve-from'
|
8
|
-
import rimrafCb from 'rimraf'
|
9
|
-
import semver from 'semver'
|
10
|
-
|
11
|
-
import {type CliCommandContext} from '../..'
|
12
|
-
import {
|
13
|
-
findSanityModuleVersions,
|
14
|
-
type ModuleVersionResult,
|
15
|
-
} from '../../actions/versions/findSanityModuleVersions'
|
16
|
-
import {debug} from '../../debug'
|
17
|
-
import {type CliCommandAction, type PackageJson} from '../../types'
|
18
|
-
import {getFormatters} from '../versions/printVersionResult'
|
19
|
-
|
20
|
-
const rimraf = util.promisify(rimrafCb)
|
21
|
-
|
22
|
-
const unsupportedMessage = `
|
23
|
-
\`sanity upgrade\` is not supported as of sanity v3.
|
24
|
-
Use npm-check-updates or similar (https://www.npmjs.com/package/npm-check-updates)
|
25
|
-
`.trim()
|
26
|
-
|
27
|
-
export interface UpgradeCommandFlags {
|
28
|
-
'range'?: string
|
29
|
-
'tag'?: string
|
30
|
-
'offline'?: boolean
|
31
|
-
'save-exact'?: boolean
|
32
|
-
}
|
33
|
-
|
34
|
-
const upgradeDependencies: CliCommandAction<UpgradeCommandFlags> =
|
35
|
-
async function upgradeDependencies(args, context) {
|
36
|
-
const {output, workDir, yarn, chalk, sanityMajorVersion} = context
|
37
|
-
if (sanityMajorVersion >= 3) {
|
38
|
-
throw new Error(unsupportedMessage)
|
39
|
-
}
|
40
|
-
|
41
|
-
const {extOptions, argsWithoutOptions} = args
|
42
|
-
const modules = argsWithoutOptions.slice()
|
43
|
-
const {range, tag} = extOptions
|
44
|
-
const saveExact = extOptions['save-exact']
|
45
|
-
const targetRange = tag || range
|
46
|
-
|
47
|
-
if (range && tag) {
|
48
|
-
throw new Error('Both --tag and --range specified, can only use one')
|
49
|
-
}
|
50
|
-
|
51
|
-
if (range && !semver.validRange(range)) {
|
52
|
-
throw new Error(`Invalid semver range "${range}"`)
|
53
|
-
}
|
54
|
-
|
55
|
-
// Find which modules needs update according to the target range
|
56
|
-
const versions = await findSanityModuleVersions(context, {
|
57
|
-
target: targetRange,
|
58
|
-
includeCli: false,
|
59
|
-
})
|
60
|
-
const allNeedsUpdate = versions.filter((mod) => mod.needsUpdate)
|
61
|
-
|
62
|
-
debug('In need of update: %s', allNeedsUpdate.map((mod) => mod.name).join(', '))
|
63
|
-
|
64
|
-
const needsUpdate =
|
65
|
-
modules.length === 0
|
66
|
-
? allNeedsUpdate
|
67
|
-
: allNeedsUpdate.filter((outOfDate) => modules.indexOf(outOfDate.name) !== -1)
|
68
|
-
|
69
|
-
const semverBreakingUpgrades = versions.filter(hasSemverBreakingUpgrade)
|
70
|
-
const baseMajorUpgrade = semverBreakingUpgrades.find((mod) => mod.name === '@sanity/base')
|
71
|
-
const majorUpgrades = semverBreakingUpgrades.filter((mod) => mod.name !== '@sanity/base')
|
72
|
-
schedulePrintMajorUpgrades({baseMajorUpgrade, majorUpgrades}, context)
|
73
|
-
|
74
|
-
// If all modules are up-to-date, say so and exit
|
75
|
-
if (needsUpdate.length === 0) {
|
76
|
-
const specified = modules.length === 0 ? 'All' : 'All *specified*'
|
77
|
-
context.output.print(
|
78
|
-
`${chalk.green('✔')} ${specified} Sanity modules are at latest compatible versions`,
|
79
|
-
)
|
80
|
-
return
|
81
|
-
}
|
82
|
-
|
83
|
-
// Ignore modules that are pinned, but give some indication that this has happened
|
84
|
-
const pinned = needsUpdate.filter((mod) => mod.isPinned)
|
85
|
-
const nonPinned = needsUpdate.filter((mod) => !mod.isPinned)
|
86
|
-
const pinnedNames = pinned.map((mod) => mod.name).join(`\n - `)
|
87
|
-
if (nonPinned.length === 0) {
|
88
|
-
context.output.warn(
|
89
|
-
`${chalk.yellow(
|
90
|
-
'⚠',
|
91
|
-
)} All modules are pinned to specific versions, not upgrading:\n - ${pinnedNames}`,
|
92
|
-
)
|
93
|
-
return
|
94
|
-
}
|
95
|
-
|
96
|
-
if (pinned.length > 0) {
|
97
|
-
context.output.warn(
|
98
|
-
`${chalk.yellow(
|
99
|
-
'⚠',
|
100
|
-
)} The follow modules are pinned to specific versions, not upgrading:\n - ${pinnedNames}`,
|
101
|
-
)
|
102
|
-
}
|
103
|
-
|
104
|
-
// Yarn fails to upgrade `react-ace` in some versions, see function for details
|
105
|
-
await maybeDeleteReactAce(nonPinned, workDir)
|
106
|
-
|
107
|
-
// Forcefully remove non-symlinked module paths to force upgrade
|
108
|
-
await Promise.all(
|
109
|
-
nonPinned.map((mod) =>
|
110
|
-
deleteIfNotSymlink(
|
111
|
-
path.join(context.workDir, 'node_modules', mod.name.replace(/\//g, path.sep)),
|
112
|
-
),
|
113
|
-
),
|
114
|
-
)
|
115
|
-
|
116
|
-
// Replace versions in `package.json`
|
117
|
-
const versionPrefix = saveExact ? '' : '^'
|
118
|
-
const oldManifest = await readLocalManifest(workDir)
|
119
|
-
const newManifest = nonPinned.reduce((target, mod) => {
|
120
|
-
if (oldManifest.dependencies && oldManifest.dependencies[mod.name]) {
|
121
|
-
target.dependencies[mod.name] =
|
122
|
-
mod.latestInRange === 'unknown'
|
123
|
-
? oldManifest.dependencies[mod.name]
|
124
|
-
: versionPrefix + mod.latestInRange
|
125
|
-
}
|
126
|
-
|
127
|
-
if (oldManifest.devDependencies && oldManifest.devDependencies[mod.name]) {
|
128
|
-
target.devDependencies[mod.name] =
|
129
|
-
mod.latestInRange === 'unknown'
|
130
|
-
? oldManifest.devDependencies[mod.name]
|
131
|
-
: versionPrefix + mod.latestInRange
|
132
|
-
}
|
133
|
-
|
134
|
-
return target
|
135
|
-
}, oldManifest)
|
136
|
-
|
137
|
-
// Write new `package.json`
|
138
|
-
const manifestPath = path.join(context.workDir, 'package.json')
|
139
|
-
await writeJson(manifestPath, newManifest)
|
140
|
-
|
141
|
-
// Run `yarn install`
|
142
|
-
const flags = extOptions.offline ? ['--offline'] : []
|
143
|
-
const cmd = ['install'].concat(flags)
|
144
|
-
|
145
|
-
debug('Running yarn %s', cmd.join(' '))
|
146
|
-
await yarn(cmd, {...output, rootDir: workDir})
|
147
|
-
|
148
|
-
context.output.print('')
|
149
|
-
context.output.print(`${chalk.green('✔')} Modules upgraded:`)
|
150
|
-
|
151
|
-
const {versionLength, formatName} = getFormatters(nonPinned)
|
152
|
-
nonPinned.forEach((mod) => {
|
153
|
-
const current = chalk.yellow(padStart(mod.installed || '<missing>', versionLength))
|
154
|
-
const latest = chalk.green(mod.latestInRange)
|
155
|
-
context.output.print(`${formatName(mod.name)} ${current} → ${latest}`)
|
156
|
-
})
|
157
|
-
}
|
158
|
-
|
159
|
-
export default upgradeDependencies
|
160
|
-
|
161
|
-
function writeJson(filePath: string, data: PackageJson) {
|
162
|
-
return fs.writeFile(filePath, `${JSON.stringify(data, null, 2)}\n`)
|
163
|
-
}
|
164
|
-
|
165
|
-
async function deleteIfNotSymlink(modPath: string): Promise<void | null> {
|
166
|
-
const stats = await fs.lstat(modPath).catch(noop)
|
167
|
-
if (!stats || stats.isSymbolicLink()) {
|
168
|
-
return null
|
169
|
-
}
|
170
|
-
|
171
|
-
return rimraf(modPath)
|
172
|
-
}
|
173
|
-
|
174
|
-
function hasSemverBreakingUpgrade(mod: ModuleVersionResult): boolean {
|
175
|
-
const current = mod.installed || semver.minVersion(mod.declared)?.toString() || ''
|
176
|
-
return !semver.satisfies(mod.latest, `^${current}`) && semver.gt(mod.latest, current)
|
177
|
-
}
|
178
|
-
|
179
|
-
function getMajorUpgradeText(
|
180
|
-
mods: ModuleVersionResult[],
|
181
|
-
chalk: CliCommandContext['chalk'],
|
182
|
-
): string {
|
183
|
-
const modNames = mods.map((mod) => `${mod.name} (v${semver.major(mod.latest)})`).join('\n - ')
|
184
|
-
|
185
|
-
return [
|
186
|
-
`The following modules has new major versions\n`,
|
187
|
-
`released and will have to be manually upgraded:\n\n`,
|
188
|
-
` - ${modNames}\n\n`,
|
189
|
-
chalk.yellow('⚠'),
|
190
|
-
` Note that major versions can contain backwards\n`,
|
191
|
-
` incompatible changes and should be handled with care.`,
|
192
|
-
].join('')
|
193
|
-
}
|
194
|
-
|
195
|
-
function getMajorStudioUpgradeText(
|
196
|
-
mod: ModuleVersionResult,
|
197
|
-
chalk: CliCommandContext['chalk'],
|
198
|
-
): string {
|
199
|
-
const prev = semver.major(mod.installed || semver.minVersion(mod.declared)?.toString() || '')
|
200
|
-
const next = semver.major(mod.latest)
|
201
|
-
return [
|
202
|
-
'There is now a new major version of Sanity Studio!',
|
203
|
-
'',
|
204
|
-
'Read more about the new version and how to upgrade:',
|
205
|
-
chalk.blueBright(`https://www.sanity.io/changelog/studio?from=v${prev}&to=v${next}`),
|
206
|
-
].join('\n')
|
207
|
-
}
|
208
|
-
|
209
|
-
function schedulePrintMajorUpgrades(
|
210
|
-
{
|
211
|
-
baseMajorUpgrade,
|
212
|
-
majorUpgrades,
|
213
|
-
}: {baseMajorUpgrade?: ModuleVersionResult; majorUpgrades: ModuleVersionResult[]},
|
214
|
-
{chalk, output}: CliCommandContext,
|
215
|
-
): void {
|
216
|
-
if (majorUpgrades.length === 0 && !baseMajorUpgrade) {
|
217
|
-
return
|
218
|
-
}
|
219
|
-
|
220
|
-
process.on('beforeExit', () => {
|
221
|
-
output.print('') // Separate previous output with a newline
|
222
|
-
|
223
|
-
if (baseMajorUpgrade) {
|
224
|
-
output.warn(
|
225
|
-
boxen(getMajorStudioUpgradeText(baseMajorUpgrade, chalk), {
|
226
|
-
borderColor: 'green',
|
227
|
-
padding: 1,
|
228
|
-
}),
|
229
|
-
)
|
230
|
-
return
|
231
|
-
}
|
232
|
-
|
233
|
-
output.warn(
|
234
|
-
boxen(getMajorUpgradeText(majorUpgrades, chalk), {
|
235
|
-
borderColor: 'yellow',
|
236
|
-
padding: 1,
|
237
|
-
}),
|
238
|
-
)
|
239
|
-
})
|
240
|
-
}
|
241
|
-
|
242
|
-
// Workaround for https://github.com/securingsincity/react-ace/issues/1048
|
243
|
-
// Yarn fails to upgrade `react-ace` because `react-ace.min.js` is a _file_ in one version
|
244
|
-
// but a _folder_ in the next. If we're upgrading the `@sanity/code-input`, remove the
|
245
|
-
// `react-ace` dependency before installing
|
246
|
-
async function maybeDeleteReactAce(toUpgrade: ModuleVersionResult[], workDir: string) {
|
247
|
-
const codeInputUpdate = toUpgrade.find((mod) => mod.name === '@sanity/code-input')
|
248
|
-
if (!codeInputUpdate) {
|
249
|
-
return
|
250
|
-
}
|
251
|
-
|
252
|
-
// Assume it is an old version if we can't figure out which one is installed
|
253
|
-
const installed = codeInputUpdate.installed ? codeInputUpdate.installed : '2.4.0'
|
254
|
-
const upgradeTo = codeInputUpdate.latestInRange
|
255
|
-
|
256
|
-
// react-ace was upgraded in 2.24.1, so if we're going from <= 2.24.0 to => 2.24.1,
|
257
|
-
// we should remove it.
|
258
|
-
const shouldDelete = semver.lte(installed, '2.24.0') && semver.gte(upgradeTo, '2.24.1')
|
259
|
-
if (!shouldDelete) {
|
260
|
-
return
|
261
|
-
}
|
262
|
-
|
263
|
-
// Try to find the path to it from `@sanity/code-input`, otherwise try the studio root `node_modules`
|
264
|
-
const depRootPath = path.join(workDir, 'node_modules')
|
265
|
-
const closestReactAcePath =
|
266
|
-
getModulePath('react-ace', path.join(depRootPath, '@sanity', 'code-input')) ||
|
267
|
-
path.join(depRootPath, 'react-ace')
|
268
|
-
|
269
|
-
await rimraf(closestReactAcePath)
|
270
|
-
}
|
271
|
-
|
272
|
-
function getModulePath(modName: string, fromPath: string): string | undefined {
|
273
|
-
const manifestFile = `${modName.replace(/\//g, path.sep)}/package.json`
|
274
|
-
const manifestPath = resolveFrom.silent(fromPath, manifestFile)
|
275
|
-
return manifestPath ? path.dirname(manifestPath) : undefined
|
276
|
-
}
|
277
|
-
|
278
|
-
async function readLocalManifest(dirName: string, fileName = 'package.json') {
|
279
|
-
try {
|
280
|
-
const content = await fs.readFile(path.join(dirName, fileName), 'utf8')
|
281
|
-
return JSON.parse(content)
|
282
|
-
} catch (err) {
|
283
|
-
if (err.code === 'ENOENT') {
|
284
|
-
return {}
|
285
|
-
}
|
286
|
-
|
287
|
-
throw new Error(`Error while attempting to read projects "${fileName}":\n${err.message}`)
|
288
|
-
}
|
289
|
-
}
|