Skip to content

Commit

Permalink
feat(update): pnpm update support update corepack config
Browse files Browse the repository at this point in the history
  • Loading branch information
fireairforce committed Oct 23, 2023
1 parent b551787 commit 091ad04
Show file tree
Hide file tree
Showing 8 changed files with 127 additions and 7 deletions.
1 change: 1 addition & 0 deletions packages/types/package.json
Expand Up @@ -12,6 +12,7 @@
"!*.map"
],
"scripts": {
"watch": "tsc --watch",
"test": "pnpm run compile",
"prepublishOnly": "pnpm run compile",
"compile": "tsc --build && pnpm run lint --fix",
Expand Down
1 change: 1 addition & 0 deletions packages/types/src/package.ts
Expand Up @@ -107,6 +107,7 @@ export interface BaseManifest {
author?: string
license?: string
exports?: Record<string, string>
packageManager?: string
}

export type DependencyManifest = BaseManifest & Required<Pick<BaseManifest, 'name' | 'version'>>
Expand Down
Expand Up @@ -8,6 +8,7 @@ import isEmpty from 'ramda/src/isEmpty'
export interface ChoiceRow {
name: string
value: string
path?: string
disabled?: boolean
}

Expand Down
30 changes: 28 additions & 2 deletions pkg-manager/plugin-commands-installation/src/update/index.ts
Expand Up @@ -210,7 +210,7 @@ async function interactiveUpdate (
}
return 'All of your dependencies are already up to date inside the specified ranges. Use the --latest option to update the ranges in package.json'
}
const { updateDependencies } = await prompt({
let { updateDependencies } = await prompt({
choices,
footer: '\nEnter to start updating. Ctrl-c to cancel.',
indicator (state: any, choice: any) { // eslint-disable-line @typescript-eslint/no-explicit-any
Expand All @@ -230,7 +230,7 @@ async function interactiveUpdate (

if (Array.isArray(this.selected)) {
return this.selected
// The custom format function is used to filter out "[dependencies]" or "[devDependencies]" from the output.
// The custom format function is used to filter out "[dependencies]" or "[devDependencies]" or "[packageManager]" from the output.
// https://github.com/enquirer/enquirer/blob/master/lib/prompts/select.js#L98
.filter((choice: ChoiceRow) => !/^\[.+\]$/.test(choice.name))
.map((choice: ChoiceRow) => this.styles.primary(choice.name)).join(', ')
Expand Down Expand Up @@ -267,6 +267,15 @@ async function interactiveUpdate (
},
} as any) as any // eslint-disable-line @typescript-eslint/no-explicit-any

updateDependencies = (updateDependencies as ChoiceRow[]).filter(dep => !(dep.path && dep.path.startsWith('[packageManager]')))
if (opts.save !== false) {
const packageManagerManifest = outdatedPkgsOfProjects[0].filter(pkg => pkg.belongsTo === 'packageManager')
await updateProjectCorepackConfig({
...opts,
updatedVersion: packageManagerManifest[0].wanted,
updatedPackage: packageManagerManifest[0].packageName,
})
}
const updatePkgNames = pluck('value', updateDependencies as ChoiceRow[])
return update(updatePkgNames, opts)
}
Expand Down Expand Up @@ -309,3 +318,20 @@ function makeIncludeDependenciesFromCLI (opts: {
optionalDependencies: opts.optional === true || (opts.production !== true && opts.dev !== true),
}
}

async function updateProjectCorepackConfig (opts: {
updatedVersion: string
updatedPackage: string
} & UpdateCommandOptions) {
const { updatedPackage, updatedVersion } = opts
if (opts.allProjects && Array.isArray(opts.allProjects)) {
for (const project of opts.allProjects) {
const updatedManifest = project.manifest
if (updatedManifest.packageManager) {
updatedManifest.packageManager = `${updatedPackage}@${updatedVersion}`
// eslint-disable-next-line no-await-in-loop
await project.writeProjectManifest(updatedManifest)
}
}
}
}
Expand Up @@ -353,3 +353,78 @@ test('interactively update should ignore dependencies from the ignoreDependencie
expect(lockfile.packages['/is-positive@2.0.0']).toBeTruthy()
}
})

test('interactively update should update corepack config', async () => {
prepare({
name: 'project-1',
packageManager: 'foo@0.0.6',
})

const storeDir = path.resolve('pnpm-store')

const headerChoice = {
name: 'Package Current Target URL ',
disabled: true,
hint: '',
value: '',
}

await add.handler(
{
...DEFAULT_OPTIONS,
cacheDir: path.resolve('cache'),
dir: process.cwd(),
linkWorkspacePackages: true,
save: false,
storeDir,
},
['foo@0.0.7']
)

prompt.mockResolvedValue({
updateDependencies: [
{
value: 'foo',
name: chalk`foo 0.0.6 ❯ 0.0.{greenBright.bold 7} https://pnpm.io/ `,
},
],
})

prompt.mockClear()
// t.comment('update to compatible versions')
await update.handler({
...DEFAULT_OPTIONS,
cacheDir: path.resolve('cache'),
dir: process.cwd(),
interactive: true,
linkWorkspacePackages: true,
storeDir,
})

expect(prompt.mock.calls[0][0].choices).toStrictEqual([
{
choices: [
headerChoice,
{
message: chalk`foo 0.0.6 ❯ 0.0.7 `,
value: 'foo',
name: 'foo',
},
],
name: '[packageManager]',
message: 'packageManager',
},
])
expect(prompt).toBeCalledWith(
expect.objectContaining({
footer: '\nEnter to start updating. Ctrl-c to cancel.',
message:
'Choose which packages to update ' +
`(Press ${chalk.cyan('<space>')} to select, ` +
`${chalk.cyan('<a>')} to toggle all, ` +
`${chalk.cyan('<i>')} to invert selection)`,
name: 'updateDependencies',
type: 'multiselect',
})
)
})
4 changes: 2 additions & 2 deletions pnpm/bin/pnpm.cjs
Expand Up @@ -20,7 +20,7 @@ try {
}

global['pnpm__startedAt'] = Date.now()
require('../dist/pnpm.cjs')
// require('../dist/pnpm.cjs')

// if you want to debug at your local env, you can use this
// require('../lib/pnpm')
require('../lib/pnpm')
1 change: 1 addition & 0 deletions reviewing/outdated/package.json
Expand Up @@ -12,6 +12,7 @@
"!*.map"
],
"scripts": {
"start": "tsc --watch",
"test": "pnpm run compile && pnpm run _test",
"lint": "eslint \"src/**/*.ts\" \"test/**/*.ts\"",
"prepublishOnly": "pnpm run compile",
Expand Down
21 changes: 18 additions & 3 deletions reviewing/outdated/src/outdated.ts
Expand Up @@ -27,7 +27,7 @@ export type GetLatestManifestFunction = (packageName: string, rangeOrTag: string

export interface OutdatedPackage {
alias: string
belongsTo: DependenciesField
belongsTo: DependenciesField | 'packageManager'
current?: string // not defined means the package is not installed
latestManifest?: PackageManifest
packageName: string
Expand All @@ -50,7 +50,7 @@ export async function outdated (
wantedLockfile: Lockfile | null
}
): Promise<OutdatedPackage[]> {
if (packageHasNoDeps(opts.manifest)) return []
if (packageHasNoDeps(opts.manifest) && !opts.manifest.packageManager) return []
if (opts.wantedLockfile == null) {
throw new PnpmError('OUTDATED_NO_LOCKFILE', `No lockfile in directory "${opts.lockfileDir}". Run \`pnpm install\` to generate one.`)
}
Expand All @@ -59,6 +59,22 @@ export async function outdated (
const currentLockfile = opts.currentLockfile ?? { importers: { [importerId]: {} } }

const outdated: OutdatedPackage[] = []
if (typeof opts.manifest?.packageManager === 'string') {
const [pkgManager, pkgManagerVersion] = opts.manifest.packageManager.split('@')
const latestPkgManifest = await opts.getLatestManifest(pkgManager, 'latest')

if (latestPkgManifest !== null && semver.lt(pkgManagerVersion, latestPkgManifest.version)) {
outdated.push({
alias: pkgManager,
belongsTo: 'packageManager',
current: pkgManagerVersion,
packageName: pkgManager,
latestManifest: latestPkgManifest,
wanted: latestPkgManifest.version,
workspace: opts.manifest.name,
})
}
}

const ignoreDependenciesMatcher = opts.ignoreDependencies?.length ? createMatcher(opts.ignoreDependencies) : undefined

Expand Down Expand Up @@ -154,7 +170,6 @@ export async function outdated (
packageName,
wanted,
workspace: opts.manifest.name,

})
}
})
Expand Down

0 comments on commit 091ad04

Please sign in to comment.