@sanity/cli 3.93.1-next.9.198ab74452 → 3.94.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 +1 -1
- package/lib/_chunks-cjs/cli.js.map +1 -1
- package/package.json +10 -11
- 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,56 +0,0 @@
|
|
|
1
|
-
import {type CliCommandDefinition} from '../../types'
|
|
2
|
-
|
|
3
|
-
const description = 'Generates TypeScript types from schema types and GROQ queries'
|
|
4
|
-
|
|
5
|
-
const helpText = `
|
|
6
|
-
Sanity TypeGen (Beta)
|
|
7
|
-
This command is currently in beta and may undergo significant changes. Feedback is welcome!
|
|
8
|
-
|
|
9
|
-
Usage
|
|
10
|
-
sanity typegen generate [options]
|
|
11
|
-
|
|
12
|
-
Options:
|
|
13
|
-
--config-path <path>
|
|
14
|
-
Specifies the path to the typegen configuration file. This file should be a JSON file that contains settings for the type generation process.
|
|
15
|
-
Default: "sanity-typegen.json"
|
|
16
|
-
|
|
17
|
-
--help, -h
|
|
18
|
-
Displays this help message, providing information on command usage and options.
|
|
19
|
-
|
|
20
|
-
Examples:
|
|
21
|
-
Generate TypeScript type definitions from a Sanity Studio schema extracted using the \`sanity schema extract\` command.
|
|
22
|
-
$ sanity typegen generate
|
|
23
|
-
|
|
24
|
-
Configuration:
|
|
25
|
-
This command can utilize configuration settings defined in a \`sanity-typegen.json\` file. These settings include:
|
|
26
|
-
|
|
27
|
-
- "path": Specifies a glob pattern to locate your TypeScript or JavaScript files.
|
|
28
|
-
Default: "./src/**/*.{ts,tsx,js,jsx}"
|
|
29
|
-
|
|
30
|
-
- "schema": Defines the path to your Sanity schema file. This file should be generated using the \`sanity schema extract\` command.
|
|
31
|
-
Default: "schema.json"
|
|
32
|
-
|
|
33
|
-
- "generates": Indicates the path where the generated TypeScript type definitions will be saved.
|
|
34
|
-
Default: "./sanity.types.ts"
|
|
35
|
-
|
|
36
|
-
The default configuration values listed above are used if not overridden in your \`sanity-typegen.json\` configuration file. To customize the behavior of the type generation, adjust these properties in the configuration file according to your project's needs.
|
|
37
|
-
|
|
38
|
-
Note:
|
|
39
|
-
- The \`sanity schema extract\` command is a prerequisite for extracting your Sanity Studio schema into a \`schema.json\` file, which is then used by the \`sanity typegen generate\` command to generate type definitions.
|
|
40
|
-
- While this tool is in beta, we encourage you to experiment with these configurations and provide feedback to help improve its functionality and usability.
|
|
41
|
-
`
|
|
42
|
-
|
|
43
|
-
const generateTypegenCommand: CliCommandDefinition = {
|
|
44
|
-
name: 'generate',
|
|
45
|
-
group: 'typegen',
|
|
46
|
-
signature: '',
|
|
47
|
-
description,
|
|
48
|
-
helpText,
|
|
49
|
-
action: async (args, context) => {
|
|
50
|
-
const mod = await import('../../actions/typegen/generateAction')
|
|
51
|
-
|
|
52
|
-
return mod.default(args, context)
|
|
53
|
-
},
|
|
54
|
-
} satisfies CliCommandDefinition
|
|
55
|
-
|
|
56
|
-
export default generateTypegenCommand
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import {type CliCommandGroupDefinition} from '../../types'
|
|
2
|
-
|
|
3
|
-
const typegenGroup: CliCommandGroupDefinition = {
|
|
4
|
-
name: 'typegen',
|
|
5
|
-
signature: '[COMMAND]',
|
|
6
|
-
isGroupRoot: true,
|
|
7
|
-
description: 'Beta: Generate TypeScript types for schema and GROQ',
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export default typegenGroup
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import chalk from 'chalk'
|
|
2
|
-
import {padEnd, padStart} from 'lodash'
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
findSanityModuleVersions,
|
|
6
|
-
type ModuleVersionResult,
|
|
7
|
-
} from '../../actions/versions/findSanityModuleVersions'
|
|
8
|
-
import {type CliCommandAction} from '../../types'
|
|
9
|
-
|
|
10
|
-
const printVersionResultCommand: CliCommandAction = async (args, context) => {
|
|
11
|
-
const versions = await findSanityModuleVersions(context, {target: 'latest'})
|
|
12
|
-
printResult(versions, context.output.print)
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export default printVersionResultCommand
|
|
16
|
-
|
|
17
|
-
export function printResult(versions: ModuleVersionResult[], print: (msg: string) => void): void {
|
|
18
|
-
const {versionLength, formatName} = getFormatters(versions)
|
|
19
|
-
versions.forEach((mod) => {
|
|
20
|
-
const version = padStart(mod.installed || '<missing>', versionLength)
|
|
21
|
-
const latest =
|
|
22
|
-
mod.installed === mod.latest
|
|
23
|
-
? chalk.green('(up to date)')
|
|
24
|
-
: `(latest: ${chalk.yellow(mod.latest)})`
|
|
25
|
-
|
|
26
|
-
print(`${formatName(getDisplayName(mod))} ${version} ${latest}`)
|
|
27
|
-
})
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export function getFormatters(versions: ModuleVersionResult[]): {
|
|
31
|
-
nameLength: number
|
|
32
|
-
versionLength: number
|
|
33
|
-
formatName: (name: string) => string
|
|
34
|
-
} {
|
|
35
|
-
const nameLength = versions.reduce((max, mod) => Math.max(max, getDisplayName(mod).length), 0)
|
|
36
|
-
const versionLength = versions.reduce(
|
|
37
|
-
(max, mod) => Math.max(max, (mod.installed || '<missing>').length),
|
|
38
|
-
0,
|
|
39
|
-
)
|
|
40
|
-
|
|
41
|
-
const formatName = (name: string): string =>
|
|
42
|
-
padEnd(name, nameLength + 1)
|
|
43
|
-
.replace(/^@sanity\/(.*?)(\s|$)/, `${chalk.yellow('@sanity/')}${chalk.cyan('$1')}$2`)
|
|
44
|
-
.replace(/^sanity(\s|$)/, `${chalk.yellow('sanity')}$1`)
|
|
45
|
-
|
|
46
|
-
return {nameLength, versionLength, formatName}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function getDisplayName(mod: ModuleVersionResult): string {
|
|
50
|
-
return mod.isGlobal ? `${mod.name} (global)` : mod.name
|
|
51
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import printVersionResult from './printVersionResult'
|
|
2
|
-
|
|
3
|
-
const help = `
|
|
4
|
-
Shows a list of installed Sanity modules and their respective versions, and
|
|
5
|
-
checks the npm registry for the latest available versions.`
|
|
6
|
-
|
|
7
|
-
export default {
|
|
8
|
-
name: 'versions',
|
|
9
|
-
signature: '',
|
|
10
|
-
description: 'Shows installed versions of Sanity Studio and components',
|
|
11
|
-
helpText: help,
|
|
12
|
-
action: printVersionResult,
|
|
13
|
-
}
|
package/src/config.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import {type CliConfig} from './types'
|
|
2
|
-
|
|
3
|
-
/** @beta */
|
|
4
|
-
export function defineCliConfig(config: CliConfig): CliConfig {
|
|
5
|
-
return config
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* @deprecated Use `defineCliConfig` instead
|
|
10
|
-
* @beta
|
|
11
|
-
*/
|
|
12
|
-
export function createCliConfig(config: CliConfig): CliConfig {
|
|
13
|
-
return config
|
|
14
|
-
}
|
package/src/debug.ts
DELETED
package/src/index.ts
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
/* eslint-disable no-console */
|
|
2
|
-
import chalk from 'chalk'
|
|
3
|
-
import ora, {type Options, type Ora} from 'ora'
|
|
4
|
-
|
|
5
|
-
const SYMBOL_CHECK = chalk.green('✓')
|
|
6
|
-
const SYMBOL_WARN = chalk.yellow('⚠')
|
|
7
|
-
const SYMBOL_FAIL = chalk.red('✗')
|
|
8
|
-
|
|
9
|
-
let isFirstClear = true
|
|
10
|
-
|
|
11
|
-
export default {
|
|
12
|
-
print(...args: unknown[]): void {
|
|
13
|
-
console.log(...args)
|
|
14
|
-
},
|
|
15
|
-
|
|
16
|
-
success(firstPartOfMessage: unknown, ...args: unknown[]): void {
|
|
17
|
-
console.log(`${SYMBOL_CHECK} ${firstPartOfMessage}`, ...args)
|
|
18
|
-
},
|
|
19
|
-
|
|
20
|
-
warn(firstPartOfMessage: unknown, ...args: unknown[]): void {
|
|
21
|
-
console.warn(`${SYMBOL_WARN} ${firstPartOfMessage}`, ...args)
|
|
22
|
-
},
|
|
23
|
-
|
|
24
|
-
error(firstPartOfMessage: unknown, ...args: unknown[]): void {
|
|
25
|
-
if (firstPartOfMessage instanceof Error) {
|
|
26
|
-
console.error(`${SYMBOL_FAIL} ${chalk.red(firstPartOfMessage.stack)}`)
|
|
27
|
-
} else {
|
|
28
|
-
console.error(`${SYMBOL_FAIL} ${firstPartOfMessage}`, ...args)
|
|
29
|
-
}
|
|
30
|
-
},
|
|
31
|
-
|
|
32
|
-
clear: (): void => {
|
|
33
|
-
// On first run, clear completely so it doesn't show half screen on Windows.
|
|
34
|
-
// On next runs, use a different sequence that properly scrolls back.
|
|
35
|
-
process.stdout.write(isFirstClear ? '\x1bc' : '\x1b[2J\x1b[0f')
|
|
36
|
-
isFirstClear = false
|
|
37
|
-
},
|
|
38
|
-
|
|
39
|
-
spinner(options: Options): Ora {
|
|
40
|
-
const spinner = ora(options)
|
|
41
|
-
// Override the default status methods to use custom symbols instead of emojis
|
|
42
|
-
spinner.succeed = (text?: string) => spinner.stopAndPersist({text, symbol: SYMBOL_CHECK})
|
|
43
|
-
spinner.warn = (text?: string) => spinner.stopAndPersist({text, symbol: SYMBOL_WARN})
|
|
44
|
-
spinner.fail = (text?: string) => spinner.stopAndPersist({text, symbol: SYMBOL_FAIL})
|
|
45
|
-
return spinner
|
|
46
|
-
},
|
|
47
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import {getPackageManagerChoice} from './packageManagerChoice'
|
|
2
|
-
|
|
3
|
-
export async function getInstallCommand(options: {
|
|
4
|
-
workDir: string
|
|
5
|
-
pkgNames?: string[]
|
|
6
|
-
depType?: 'dev' | 'prod' | 'peer'
|
|
7
|
-
}): Promise<string> {
|
|
8
|
-
const {workDir, depType = 'prod', pkgNames} = options
|
|
9
|
-
const {chosen} = await getPackageManagerChoice(workDir, {interactive: false})
|
|
10
|
-
|
|
11
|
-
// eg `npm install`, `yarn install`, `pnpm install`
|
|
12
|
-
if (!pkgNames || pkgNames.length === 0) {
|
|
13
|
-
return `${chosen} install`
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const pkgNameString = pkgNames.join(' ')
|
|
17
|
-
|
|
18
|
-
if (chosen === 'yarn') {
|
|
19
|
-
const flag = depType === 'dev' || depType === 'peer' ? ` --${depType}` : ''
|
|
20
|
-
return `yarn add ${pkgNameString}${flag}`
|
|
21
|
-
} else if (chosen === 'pnpm') {
|
|
22
|
-
return `pnpm add ${pkgNameString} --save-${depType}`
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
return `npm install ${pkgNameString} --save-${depType}`
|
|
26
|
-
}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import path from 'node:path'
|
|
2
|
-
|
|
3
|
-
import isInstalledGlobally from 'is-installed-globally'
|
|
4
|
-
|
|
5
|
-
import {debug} from '../debug'
|
|
6
|
-
import {getPackageManagerChoice} from './packageManagerChoice'
|
|
7
|
-
|
|
8
|
-
const cliPkgName = '@sanity/cli'
|
|
9
|
-
|
|
10
|
-
interface Options {
|
|
11
|
-
cwd?: string
|
|
12
|
-
workDir?: string
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export async function getCliUpgradeCommand(options: Options = {}): Promise<string> {
|
|
16
|
-
let {cwd, workDir} = options
|
|
17
|
-
cwd = path.resolve(cwd || process.cwd())
|
|
18
|
-
workDir = path.resolve(workDir || cwd)
|
|
19
|
-
|
|
20
|
-
if (isInstalledGlobally && isInstalledUsingYarn()) {
|
|
21
|
-
debug('CLI is installed globally with yarn')
|
|
22
|
-
return `yarn global add ${cliPkgName}`
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
if (isInstalledGlobally) {
|
|
26
|
-
debug('CLI is installed globally with npm')
|
|
27
|
-
return `npm install -g ${cliPkgName}`
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const cmds = cwd === workDir ? [] : [`cd ${path.relative(cwd, workDir)}`]
|
|
31
|
-
|
|
32
|
-
const {chosen} = await getPackageManagerChoice(workDir, {interactive: false})
|
|
33
|
-
|
|
34
|
-
if (chosen === 'yarn') {
|
|
35
|
-
cmds.push(`yarn upgrade ${cliPkgName}`)
|
|
36
|
-
} else if (chosen === 'pnpm') {
|
|
37
|
-
cmds.push(`pnpm update ${cliPkgName}`)
|
|
38
|
-
} else {
|
|
39
|
-
cmds.push(`npm update ${cliPkgName}`)
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
return cmds.join(' && ')
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function isInstalledUsingYarn() {
|
|
46
|
-
const isWindows = process.platform === 'win32'
|
|
47
|
-
const yarnPath = isWindows
|
|
48
|
-
? path.join('Yarn', 'config', 'global')
|
|
49
|
-
: path.join('.config', 'yarn', 'global')
|
|
50
|
-
|
|
51
|
-
return __dirname.includes(yarnPath)
|
|
52
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import {getInstallCommand} from './getInstallCommand'
|
|
2
|
-
import {getCliUpgradeCommand} from './getUpgradeCommand'
|
|
3
|
-
import {installDeclaredPackages, installNewPackages} from './installPackages'
|
|
4
|
-
import {getPackageManagerChoice} from './packageManagerChoice'
|
|
5
|
-
import {uninstallPackages} from './uninstallPackages'
|
|
6
|
-
import {getYarnStub} from './yarnStub'
|
|
7
|
-
|
|
8
|
-
// Exported for internal CLI usage
|
|
9
|
-
export {
|
|
10
|
-
getCliUpgradeCommand,
|
|
11
|
-
getInstallCommand,
|
|
12
|
-
getPackageManagerChoice,
|
|
13
|
-
getYarnStub,
|
|
14
|
-
installDeclaredPackages,
|
|
15
|
-
installNewPackages,
|
|
16
|
-
uninstallPackages,
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// Exported for use in `sanity` (formerly `@sanity/core`)
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* @internal
|
|
23
|
-
*/
|
|
24
|
-
export const cliPackageManager = {
|
|
25
|
-
getInstallCommand,
|
|
26
|
-
getPackageManagerChoice,
|
|
27
|
-
installNewPackages,
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* @internal
|
|
32
|
-
*/
|
|
33
|
-
export type CliPackageManager = typeof cliPackageManager
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
import execa, {type CommonOptions, type ExecaReturnValue} from 'execa'
|
|
2
|
-
|
|
3
|
-
import {type CliCommandContext} from '../types'
|
|
4
|
-
import {getPartialEnvWithNpmPath, type PackageManager} from './packageManagerChoice'
|
|
5
|
-
|
|
6
|
-
export interface InstallOptions {
|
|
7
|
-
packageManager: PackageManager
|
|
8
|
-
packages: string[]
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export async function installDeclaredPackages(
|
|
12
|
-
cwd: string,
|
|
13
|
-
packageManager: PackageManager,
|
|
14
|
-
context: Pick<CliCommandContext, 'output'>,
|
|
15
|
-
): Promise<void> {
|
|
16
|
-
const {output} = context
|
|
17
|
-
const execOptions: CommonOptions<'utf8'> = {
|
|
18
|
-
encoding: 'utf8',
|
|
19
|
-
env: getPartialEnvWithNpmPath(cwd),
|
|
20
|
-
cwd,
|
|
21
|
-
stdio: 'pipe',
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// results of running execa with the selected package manager
|
|
25
|
-
let result: ExecaReturnValue<string> | undefined
|
|
26
|
-
|
|
27
|
-
type PackageManagerLibs = Exclude<PackageManager, 'manual'>
|
|
28
|
-
type InstallerArgs = {[key in PackageManagerLibs]: string[]}
|
|
29
|
-
|
|
30
|
-
const installerArgs: InstallerArgs = {
|
|
31
|
-
npm: ['install', '--legacy-peer-deps'],
|
|
32
|
-
yarn: ['install'],
|
|
33
|
-
pnpm: ['install'],
|
|
34
|
-
bun: ['install'],
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
async function handleInstall(cmd: PackageManager, args: InstallerArgs[PackageManagerLibs]) {
|
|
38
|
-
// Start a spinner for the install process
|
|
39
|
-
const progress = output.spinner(`Running ${cmd} ${args.join(' ')}\n`).start()
|
|
40
|
-
|
|
41
|
-
// Perform the install command with execa
|
|
42
|
-
result = await execa(cmd, args, execOptions)
|
|
43
|
-
|
|
44
|
-
// If the install fails, log execa's stdout and throw…
|
|
45
|
-
if (result?.exitCode || result?.failed) {
|
|
46
|
-
progress.fail()
|
|
47
|
-
output.print(result.stdout)
|
|
48
|
-
throw new Error('Dependency installation failed')
|
|
49
|
-
} else {
|
|
50
|
-
// …otherwise, just mark the install as successful
|
|
51
|
-
progress.succeed()
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
if (packageManager === 'manual') {
|
|
56
|
-
output.print(`Manual installation selected — run 'npm ${installerArgs.npm} or equivalent'`)
|
|
57
|
-
} else {
|
|
58
|
-
await handleInstall(packageManager, installerArgs[packageManager])
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export async function installNewPackages(
|
|
63
|
-
options: InstallOptions,
|
|
64
|
-
context: Pick<CliCommandContext, 'output' | 'workDir'>,
|
|
65
|
-
): Promise<void> {
|
|
66
|
-
const {packageManager, packages} = options
|
|
67
|
-
const {output, workDir} = context
|
|
68
|
-
const execOptions: CommonOptions<'utf8'> = {
|
|
69
|
-
encoding: 'utf8',
|
|
70
|
-
env: getPartialEnvWithNpmPath(workDir),
|
|
71
|
-
cwd: workDir,
|
|
72
|
-
stdio: 'inherit',
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const npmArgs = ['install', '--legacy-peer-deps', '--save', ...packages]
|
|
76
|
-
let result: ExecaReturnValue<string> | undefined
|
|
77
|
-
if (packageManager === 'npm') {
|
|
78
|
-
output.print(`Running 'npm ${npmArgs.join(' ')}'`)
|
|
79
|
-
result = await execa('npm', npmArgs, execOptions)
|
|
80
|
-
} else if (packageManager === 'yarn') {
|
|
81
|
-
const yarnArgs = ['add', ...packages]
|
|
82
|
-
output.print(`Running 'yarn ${yarnArgs.join(' ')}'`)
|
|
83
|
-
result = await execa('yarn', yarnArgs, execOptions)
|
|
84
|
-
} else if (packageManager === 'pnpm') {
|
|
85
|
-
const pnpmArgs = ['add', '--save-prod', ...packages]
|
|
86
|
-
output.print(`Running 'pnpm ${pnpmArgs.join(' ')}'`)
|
|
87
|
-
result = await execa('pnpm', pnpmArgs, execOptions)
|
|
88
|
-
} else if (packageManager === 'bun') {
|
|
89
|
-
const bunArgs = ['add', ...packages]
|
|
90
|
-
output.print(`Running 'bun ${bunArgs.join(' ')}'`)
|
|
91
|
-
result = await execa('bun', bunArgs, execOptions)
|
|
92
|
-
} else if (packageManager === 'manual') {
|
|
93
|
-
output.print(`Manual installation selected - run 'npm ${npmArgs.join(' ')}' or equivalent`)
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
if (result?.exitCode || result?.failed) {
|
|
97
|
-
throw new Error('Package installation failed')
|
|
98
|
-
}
|
|
99
|
-
}
|
|
@@ -1,204 +0,0 @@
|
|
|
1
|
-
/* eslint-disable no-process-env */
|
|
2
|
-
import path from 'node:path'
|
|
3
|
-
|
|
4
|
-
import preferredPM from 'preferred-pm'
|
|
5
|
-
import which from 'which'
|
|
6
|
-
|
|
7
|
-
import {type CliPrompter} from '../types'
|
|
8
|
-
import {isInteractive} from '../util/isInteractive'
|
|
9
|
-
|
|
10
|
-
export type PackageManager = 'npm' | 'yarn' | 'pnpm' | 'bun' | 'manual'
|
|
11
|
-
|
|
12
|
-
export const ALLOWED_PACKAGE_MANAGERS: PackageManager[] = ['npm', 'yarn', 'pnpm', 'bun', 'manual']
|
|
13
|
-
export const allowedPackageManagersString = ALLOWED_PACKAGE_MANAGERS.map((pm) => `"${pm}"`).join(
|
|
14
|
-
' | ',
|
|
15
|
-
)
|
|
16
|
-
|
|
17
|
-
const EXPERIMENTAL = ['bun']
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Attempts to resolve the most optimal package manager to use to install/upgrade
|
|
21
|
-
* packages/dependencies at a given path. It does so by looking for package manager
|
|
22
|
-
* specific lockfiles. If it finds a lockfile belonging to a certain package manager,
|
|
23
|
-
* it prioritizes this one. However, if that package manager is not installed, it will
|
|
24
|
-
* prompt the user for which one they want to use and hint at the most optimal one
|
|
25
|
-
* not being installed.
|
|
26
|
-
*
|
|
27
|
-
* Note that this function also takes local npm binary paths into account - for instance,
|
|
28
|
-
* `yarn` can be installed as a dependency of the project instead of globally, and it
|
|
29
|
-
* will use that is available.
|
|
30
|
-
*
|
|
31
|
-
* The user can also select 'manual' to skip the process and run their preferred package
|
|
32
|
-
* manager manually. Commands using this function must take this `manual` choice into
|
|
33
|
-
* account and act accordingly if chosen.
|
|
34
|
-
*
|
|
35
|
-
* @param workDir - The working directory where a lockfile is most likely to be present
|
|
36
|
-
* @param options - Pass `interactive: false` to fall back to npm if most optimal is
|
|
37
|
-
* not available, instead of prompting
|
|
38
|
-
* @returns Object of `chosen` and, if a lockfile is found, the `mostOptimal` choice
|
|
39
|
-
*/
|
|
40
|
-
export async function getPackageManagerChoice(
|
|
41
|
-
workDir: string,
|
|
42
|
-
options: {interactive: false} | {interactive?: true; prompt: CliPrompter},
|
|
43
|
-
): Promise<{chosen: PackageManager; mostOptimal?: PackageManager}> {
|
|
44
|
-
const rootDir = workDir || process.cwd()
|
|
45
|
-
const preferred = (await preferredPM(rootDir))?.name
|
|
46
|
-
|
|
47
|
-
if (preferred && (await hasCommand(preferred, rootDir))) {
|
|
48
|
-
// There is an optimal/preferred package manager, and the user has it installed!
|
|
49
|
-
return {chosen: preferred, mostOptimal: preferred}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const mostLikelyPM = await getMostLikelyInstalledPackageManager(rootDir)
|
|
53
|
-
const interactive = typeof options.interactive === 'boolean' ? options.interactive : isInteractive
|
|
54
|
-
if (!interactive) {
|
|
55
|
-
// We can't ask the user for their preference, so fall back to either the one that is being run
|
|
56
|
-
// or whatever is installed on the system (npm being the preferred choice).
|
|
57
|
-
// Note that the most optimal choice is already picked above if available.
|
|
58
|
-
return {chosen: mostLikelyPM || (await getFallback(rootDir)), mostOptimal: preferred}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
if (!('prompt' in options)) {
|
|
62
|
-
throw new Error('Must pass `prompt` when in interactive mode')
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// We can ask the user for their preference, hurray!
|
|
66
|
-
const messageSuffix = preferred ? ` (preferred is ${preferred}, but is not installed)` : ''
|
|
67
|
-
const installed = await getAvailablePackageManagers(rootDir)
|
|
68
|
-
const chosen = await options.prompt.single<PackageManager>({
|
|
69
|
-
type: 'list',
|
|
70
|
-
choices: installed.map((pm) => ({
|
|
71
|
-
value: pm,
|
|
72
|
-
name: EXPERIMENTAL.includes(pm) ? `${pm} (experimental)` : pm,
|
|
73
|
-
})),
|
|
74
|
-
default: preferred || mostLikelyPM,
|
|
75
|
-
message: `Package manager to use for installing dependencies?${messageSuffix}`,
|
|
76
|
-
})
|
|
77
|
-
|
|
78
|
-
return {chosen, mostOptimal: preferred}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
async function getFallback(cwd: string): Promise<PackageManager> {
|
|
82
|
-
if (await hasNpmInstalled(cwd)) {
|
|
83
|
-
return 'npm'
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
if (await hasYarnInstalled(cwd)) {
|
|
87
|
-
return 'yarn'
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
if (await hasPnpmInstalled(cwd)) {
|
|
91
|
-
return 'pnpm'
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
if (await hasBunInstalled(cwd)) {
|
|
95
|
-
return 'bun'
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
return 'manual'
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
async function getAvailablePackageManagers(cwd: string): Promise<PackageManager[]> {
|
|
102
|
-
const [npm, yarn, pnpm, bun] = await Promise.all([
|
|
103
|
-
hasNpmInstalled(cwd),
|
|
104
|
-
hasYarnInstalled(cwd),
|
|
105
|
-
hasPnpmInstalled(cwd),
|
|
106
|
-
hasBunInstalled(cwd),
|
|
107
|
-
])
|
|
108
|
-
|
|
109
|
-
const choices = [npm && 'npm', yarn && 'yarn', pnpm && 'pnpm', bun && 'bun', 'manual']
|
|
110
|
-
return choices.filter((pm): pm is PackageManager => pm !== false)
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
export function hasNpmInstalled(cwd?: string): Promise<boolean> {
|
|
114
|
-
return hasCommand('npm', cwd)
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
export function hasYarnInstalled(cwd?: string): Promise<boolean> {
|
|
118
|
-
return hasCommand('yarn', cwd)
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
export function hasPnpmInstalled(cwd?: string): Promise<boolean> {
|
|
122
|
-
return hasCommand('pnpm', cwd)
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
export function hasBunInstalled(cwd?: string): Promise<boolean> {
|
|
126
|
-
return hasCommand('bun', cwd)
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
export function getNpmRunPath(cwd: string): string {
|
|
130
|
-
let previous
|
|
131
|
-
let cwdPath = path.resolve(cwd)
|
|
132
|
-
const result: string[] = []
|
|
133
|
-
|
|
134
|
-
while (previous !== cwdPath) {
|
|
135
|
-
result.push(path.join(cwdPath, 'node_modules', '.bin'))
|
|
136
|
-
previous = cwdPath
|
|
137
|
-
cwdPath = path.resolve(cwdPath, '..')
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
result.push(path.resolve(cwd, process.execPath, '..'))
|
|
141
|
-
|
|
142
|
-
const pathEnv = process.env[getPathEnvVarKey()]
|
|
143
|
-
return [...result, pathEnv].join(path.delimiter)
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
export function getPartialEnvWithNpmPath(cwd: string): NodeJS.ProcessEnv {
|
|
147
|
-
const key = getPathEnvVarKey()
|
|
148
|
-
return {[key]: getNpmRunPath(cwd)}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
function getPathEnvVarKey(): string {
|
|
152
|
-
if (process.platform !== 'win32') {
|
|
153
|
-
return 'PATH'
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
return (
|
|
157
|
-
Object.keys(process.env)
|
|
158
|
-
.reverse()
|
|
159
|
-
.find((key) => key.toUpperCase() === 'PATH') || 'Path'
|
|
160
|
-
)
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
function getCommandPath(cmd: string, cwd?: string): Promise<string | null> {
|
|
164
|
-
const options = cwd ? {path: getNpmRunPath(cwd)} : {}
|
|
165
|
-
return which(cmd, options).catch(() => null)
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
function hasCommand(cmd: string, cwd?: string): Promise<boolean> {
|
|
169
|
-
return getCommandPath(cmd, cwd).then((cmdPath) => cmdPath !== null)
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
async function getMostLikelyInstalledPackageManager(
|
|
173
|
-
rootDir: string,
|
|
174
|
-
): Promise<PackageManager | undefined> {
|
|
175
|
-
const installed = await getAvailablePackageManagers(rootDir)
|
|
176
|
-
const running = getRunningPackageManager()
|
|
177
|
-
return running && installed.includes(running) ? running : undefined
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
function getRunningPackageManager(): PackageManager | undefined {
|
|
181
|
-
// Yes, the env var is lowercase - it is set by the package managers themselves
|
|
182
|
-
const agent = process.env.npm_config_user_agent || ''
|
|
183
|
-
|
|
184
|
-
if (agent.includes('yarn')) {
|
|
185
|
-
return 'yarn'
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
if (agent.includes('pnpm')) {
|
|
189
|
-
return 'pnpm'
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
if (agent.includes('bun')) {
|
|
193
|
-
return 'bun'
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
// Both yarn and pnpm does a `npm/?` thing, thus the slightly different match here
|
|
197
|
-
// Theoretically not needed since we check for yarn/pnpm above, but in case other
|
|
198
|
-
// package managers do the same thing, we'll (hopefully) catch them here.
|
|
199
|
-
if (/^npm\/\d/.test(agent)) {
|
|
200
|
-
return 'npm'
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
return undefined
|
|
204
|
-
}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import execa, {type CommonOptions, type ExecaReturnValue} from 'execa'
|
|
2
|
-
|
|
3
|
-
import {type CliCommandContext} from '../types'
|
|
4
|
-
import {getPartialEnvWithNpmPath, type PackageManager} from './packageManagerChoice'
|
|
5
|
-
|
|
6
|
-
export interface UninstallOptions {
|
|
7
|
-
packageManager: PackageManager
|
|
8
|
-
packages: string[]
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export async function uninstallPackages(
|
|
12
|
-
options: UninstallOptions,
|
|
13
|
-
context: Pick<CliCommandContext, 'output' | 'workDir'>,
|
|
14
|
-
): Promise<void> {
|
|
15
|
-
const {packageManager, packages} = options
|
|
16
|
-
const {output, workDir} = context
|
|
17
|
-
const execOptions: CommonOptions<'utf8'> = {
|
|
18
|
-
encoding: 'utf8',
|
|
19
|
-
env: getPartialEnvWithNpmPath(workDir),
|
|
20
|
-
cwd: workDir,
|
|
21
|
-
stdio: 'inherit',
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const npmArgs = ['uninstall', ...packages]
|
|
25
|
-
let result: ExecaReturnValue<string> | undefined
|
|
26
|
-
if (packageManager === 'npm') {
|
|
27
|
-
output.print(`Running 'npm ${npmArgs.join(' ')}'`)
|
|
28
|
-
result = await execa('npm', npmArgs, execOptions)
|
|
29
|
-
} else if (packageManager === 'yarn') {
|
|
30
|
-
const yarnArgs = ['remove', ...packages]
|
|
31
|
-
output.print(`Running 'yarn ${yarnArgs.join(' ')}'`)
|
|
32
|
-
result = await execa('yarn', yarnArgs, execOptions)
|
|
33
|
-
} else if (packageManager === 'pnpm') {
|
|
34
|
-
const pnpmArgs = ['remove', ...packages]
|
|
35
|
-
output.print(`Running 'pnpm ${pnpmArgs.join(' ')}'`)
|
|
36
|
-
result = await execa('pnpm', pnpmArgs, execOptions)
|
|
37
|
-
} else if (packageManager === 'manual') {
|
|
38
|
-
output.print(`Manual installation selected - run 'npm ${npmArgs.join(' ')}' or equivalent`)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
if (result?.exitCode || result?.failed) {
|
|
42
|
-
throw new Error('Package installation failed')
|
|
43
|
-
}
|
|
44
|
-
}
|