From 35420781c832fee912ff18a10c235d51f3588156 Mon Sep 17 00:00:00 2001 From: Raine Revere Date: Sun, 19 Nov 2023 18:41:08 +0000 Subject: [PATCH 01/12] viewMany: Exclude options.packageFile from memoization comparison (#1351). This was preventing memoization of duplicate packages in workspaces. --- src/package-managers/npm.ts | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/src/package-managers/npm.ts b/src/package-managers/npm.ts index 0e66b508..d7288ec3 100644 --- a/src/package-managers/npm.ts +++ b/src/package-managers/npm.ts @@ -39,6 +39,10 @@ const isExplicitRange = (spec: VersionSpec) => { return range.some(parsed => EXPLICIT_RANGE_OPS.has(parsed.operator || '')) } +/** Returns true if the version is sa valid, exact version. */ +const isExactVersion = (version: Version) => + version && (!nodeSemver.validRange(version) || versionUtil.isWildCard(version)) + /** Normalizes the keys of an npm config for pacote. */ export const normalizeNpmConfig = ( npmConfig: NpmConfig, @@ -428,7 +432,7 @@ async function viewMany( return mockViewMany(mockReturnedVersions)(packageName, fields, currentVersion, options) } - if (currentVersion && (!nodeSemver.validRange(currentVersion) || versionUtil.isWildCard(currentVersion))) { + if (isExactVersion(currentVersion)) { return Promise.resolve({} as Index) } @@ -473,8 +477,31 @@ async function viewMany( return resultNormalized } -/** Memoize viewMany for --deep performance. */ -export const viewManyMemoized = memoize(viewMany) +/** Memoize viewMany for --deep and --workspaces performance. */ +export const viewManyMemoized = memoize(viewMany, { + // serializer args are incorrectly typed as any[] instead of being generic, so we need to cast it + serializer: (([ + packageName, + fields, + currentVersion, + options, + retried, + npmConfigLocal, + npmConfigWorkspaceProject, + ]: Parameters) => + JSON.stringify([ + packageName, + fields, + // currentVersion does not change the behavior of viewMany unless it is an invalid/inexact version which causes it to short circuit + isExactVersion(currentVersion), + // packageFile varies by cwd in workspaces/deep mode, so we do not want to memoize on that + omit(options, 'packageFile'), + // make sure retries do not get memoized + retried, + npmConfigLocal, + npmConfigWorkspaceProject, + ])) as (args: any[]) => string, +}) /** * Returns the value of one of the properties retrieved by npm view. From ea36075fff06bd09d840c5bb3403a556f63f4c1b Mon Sep 17 00:00:00 2001 From: Raine Revere Date: Sun, 19 Nov 2023 18:43:56 +0000 Subject: [PATCH 02/12] 16.14.7 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 472a8648..1bbe5111 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "npm-check-updates", - "version": "16.14.6", + "version": "16.14.7", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "npm-check-updates", - "version": "16.14.6", + "version": "16.14.7", "license": "Apache-2.0", "dependencies": { "chalk": "^5.3.0", diff --git a/package.json b/package.json index 373c3f19..519b7856 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "npm-check-updates", - "version": "16.14.6", + "version": "16.14.7", "author": "Tomas Junnonen ", "license": "Apache-2.0", "contributors": [ From 3e46cc8b8d7d241b09217ee914dea4ac66756e57 Mon Sep 17 00:00:00 2001 From: Raine Revere Date: Sun, 19 Nov 2023 19:22:42 +0000 Subject: [PATCH 03/12] Use pacote.manifest when fetching only dist-tags. --- src/package-managers/npm.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/package-managers/npm.ts b/src/package-managers/npm.ts index d7288ec3..8c63f9e5 100644 --- a/src/package-managers/npm.ts +++ b/src/package-managers/npm.ts @@ -449,7 +449,18 @@ async function viewMany( let result: any try { - result = (await pacote.packument(packageName, npmConfigMerged)) as any + // when just fetching the dist-tag, use pacote.manifest instead of pacote.packument for a much smaller payload + if (fieldsExtended.length === 1 && fieldsExtended[0] === 'dist-tags.') { + const [, tag] = fieldsExtended[0].split('dist-tags') + result = { + [`dist-tags.${tag}`]: { + name: packageName, + version: (await pacote.manifest(packageName, npmConfigMerged))?.version, + }, + } + } else { + result = await pacote.packument(packageName, npmConfigMerged) + } } catch (err: any) { if (options.retry && ++retried <= options.retry) { return viewMany(packageName, fieldsExtended, currentVersion, options, retried, npmConfigLocal) From c4a8786599df8c8d45d8b0898a8f077f6b8d7509 Mon Sep 17 00:00:00 2001 From: Raine Revere Date: Sun, 19 Nov 2023 19:24:43 +0000 Subject: [PATCH 04/12] 16.14.8 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1bbe5111..f2e0f4fe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "npm-check-updates", - "version": "16.14.7", + "version": "16.14.8", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "npm-check-updates", - "version": "16.14.7", + "version": "16.14.8", "license": "Apache-2.0", "dependencies": { "chalk": "^5.3.0", diff --git a/package.json b/package.json index 519b7856..1b5ed154 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "npm-check-updates", - "version": "16.14.7", + "version": "16.14.8", "author": "Tomas Junnonen ", "license": "Apache-2.0", "contributors": [ From 1805e9e07ee4fe237df99733a4c12147ddb6326c Mon Sep 17 00:00:00 2001 From: Raine Revere Date: Sun, 19 Nov 2023 19:59:03 +0000 Subject: [PATCH 05/12] Fix pacote.manifest condition (#1351). --- src/package-managers/npm.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/package-managers/npm.ts b/src/package-managers/npm.ts index 8c63f9e5..31b2100b 100644 --- a/src/package-managers/npm.ts +++ b/src/package-managers/npm.ts @@ -450,12 +450,13 @@ async function viewMany( let result: any try { // when just fetching the dist-tag, use pacote.manifest instead of pacote.packument for a much smaller payload - if (fieldsExtended.length === 1 && fieldsExtended[0] === 'dist-tags.') { + if (fieldsExtended.length === 1 && fieldsExtended[0].startsWith('dist-tags.')) { const [, tag] = fieldsExtended[0].split('dist-tags') + const manifest = await pacote.manifest(packageName, npmConfigMerged) result = { [`dist-tags.${tag}`]: { name: packageName, - version: (await pacote.manifest(packageName, npmConfigMerged))?.version, + version: manifest?.version, }, } } else { From ba6889441e667da3f70267cdfb2cf06caf5aa543 Mon Sep 17 00:00:00 2001 From: Raine Revere Date: Sun, 19 Nov 2023 19:59:43 +0000 Subject: [PATCH 06/12] 16.14.9 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index f2e0f4fe..823d237a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "npm-check-updates", - "version": "16.14.8", + "version": "16.14.9", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "npm-check-updates", - "version": "16.14.8", + "version": "16.14.9", "license": "Apache-2.0", "dependencies": { "chalk": "^5.3.0", diff --git a/package.json b/package.json index 1b5ed154..fe9339d3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "npm-check-updates", - "version": "16.14.8", + "version": "16.14.9", "author": "Tomas Junnonen ", "license": "Apache-2.0", "contributors": [ From c513a84806f81db3161df67d44a93c0bfeddaa2f Mon Sep 17 00:00:00 2001 From: Raine Revere Date: Sun, 19 Nov 2023 20:42:13 +0000 Subject: [PATCH 07/12] Fix pacote.manifest for real. --- src/package-managers/npm.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/package-managers/npm.ts b/src/package-managers/npm.ts index 31b2100b..f291d727 100644 --- a/src/package-managers/npm.ts +++ b/src/package-managers/npm.ts @@ -451,7 +451,7 @@ async function viewMany( try { // when just fetching the dist-tag, use pacote.manifest instead of pacote.packument for a much smaller payload if (fieldsExtended.length === 1 && fieldsExtended[0].startsWith('dist-tags.')) { - const [, tag] = fieldsExtended[0].split('dist-tags') + const [, tag] = fieldsExtended[0].split('dist-tags.') const manifest = await pacote.manifest(packageName, npmConfigMerged) result = { [`dist-tags.${tag}`]: { From 1249013d0eeaa55b5b781de2c35c88c39a01b8c7 Mon Sep 17 00:00:00 2001 From: Raine Revere Date: Sun, 19 Nov 2023 20:42:30 +0000 Subject: [PATCH 08/12] npm: minor refactor --- src/package-managers/npm.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/package-managers/npm.ts b/src/package-managers/npm.ts index f291d727..1507e658 100644 --- a/src/package-managers/npm.ts +++ b/src/package-managers/npm.ts @@ -436,11 +436,12 @@ async function viewMany( return Promise.resolve({} as Index) } - const fieldsExtended = options.format?.includes('time') ? [...fields, 'time'] : fields + const fullMetadata = !!options.format?.includes('time') + const fieldsExtended = fullMetadata ? [...fields, 'time'] : fields const npmConfigMerged = mergeNpmConfigs( { - npmConfigUser: { ...npmConfig, fullMetadata: fieldsExtended.includes('time') }, + npmConfigUser: { ...npmConfig, fullMetadata }, npmConfigLocal, npmConfigWorkspaceProject, }, @@ -450,8 +451,8 @@ async function viewMany( let result: any try { // when just fetching the dist-tag, use pacote.manifest instead of pacote.packument for a much smaller payload - if (fieldsExtended.length === 1 && fieldsExtended[0].startsWith('dist-tags.')) { - const [, tag] = fieldsExtended[0].split('dist-tags.') + if (!fullMetadata && fields.length === 1 && fields[0].startsWith('dist-tags.')) { + const [, tag] = fields[0].split('dist-tags.') const manifest = await pacote.manifest(packageName, npmConfigMerged) result = { [`dist-tags.${tag}`]: { @@ -478,7 +479,7 @@ async function viewMany( if (field.startsWith('dist-tags.') && result.versions) { const packument: Packument = result.versions[get(result, field) as unknown as string] // since viewOne only keeps a single field, we need to add time onto the dist-tag field - value = options.format?.includes('time') ? { ...packument, time: result.time } : packument + value = fullMetadata ? { ...packument, time: result.time } : packument } return { @@ -729,7 +730,7 @@ export const distTag: GetVersion = async ( options, npmConfig, npmConfigProject, - )) as unknown as Packument // known type based on dist-tags.latest + )) as Packument // known type based on dist-tags.latest // latest should not be deprecated // if latest exists and latest is not a prerelease version, return it From 2fe9bf89cfa3591d98429d2a83585ea920efd448 Mon Sep 17 00:00:00 2001 From: Raine Revere Date: Sun, 19 Nov 2023 21:18:38 +0000 Subject: [PATCH 09/12] 16.14.10 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 823d237a..00f8625a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "npm-check-updates", - "version": "16.14.9", + "version": "16.14.10", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "npm-check-updates", - "version": "16.14.9", + "version": "16.14.10", "license": "Apache-2.0", "dependencies": { "chalk": "^5.3.0", diff --git a/package.json b/package.json index fe9339d3..440cf869 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "npm-check-updates", - "version": "16.14.9", + "version": "16.14.10", "author": "Tomas Junnonen ", "license": "Apache-2.0", "contributors": [ From 5a1e8927967d135976425513377d36bc2f70be59 Mon Sep 17 00:00:00 2001 From: Raine Revere Date: Sun, 19 Nov 2023 21:41:35 +0000 Subject: [PATCH 10/12] Revert pacote.manifest since it is the same fetch as pacote.packument. --- src/package-managers/npm.ts | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/package-managers/npm.ts b/src/package-managers/npm.ts index 1507e658..1fea42f0 100644 --- a/src/package-managers/npm.ts +++ b/src/package-managers/npm.ts @@ -450,19 +450,7 @@ async function viewMany( let result: any try { - // when just fetching the dist-tag, use pacote.manifest instead of pacote.packument for a much smaller payload - if (!fullMetadata && fields.length === 1 && fields[0].startsWith('dist-tags.')) { - const [, tag] = fields[0].split('dist-tags.') - const manifest = await pacote.manifest(packageName, npmConfigMerged) - result = { - [`dist-tags.${tag}`]: { - name: packageName, - version: manifest?.version, - }, - } - } else { - result = await pacote.packument(packageName, npmConfigMerged) - } + result = await pacote.packument(packageName, npmConfigMerged) } catch (err: any) { if (options.retry && ++retried <= options.retry) { return viewMany(packageName, fieldsExtended, currentVersion, options, retried, npmConfigLocal) From 82fc6212bccc28eb6eb193d97fa153f132cd47a1 Mon Sep 17 00:00:00 2001 From: Raine Revere Date: Sun, 19 Nov 2023 21:51:55 +0000 Subject: [PATCH 11/12] Fix fullMetadata extended regression. --- src/package-managers/npm.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/package-managers/npm.ts b/src/package-managers/npm.ts index 1fea42f0..64ee279c 100644 --- a/src/package-managers/npm.ts +++ b/src/package-managers/npm.ts @@ -436,8 +436,9 @@ async function viewMany( return Promise.resolve({} as Index) } - const fullMetadata = !!options.format?.includes('time') - const fieldsExtended = fullMetadata ? [...fields, 'time'] : fields + // fields may already include time + const fieldsExtended = options.format?.includes('time') ? [...fields, 'time'] : fields + const fullMetadata = fieldsExtended.includes('time') const npmConfigMerged = mergeNpmConfigs( { From be4b557d3da1f118ca3e7286fc34ab106fdb10ed Mon Sep 17 00:00:00 2001 From: Raine Revere Date: Sun, 19 Nov 2023 21:52:16 +0000 Subject: [PATCH 12/12] 16.14.11 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 00f8625a..59dbef58 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "npm-check-updates", - "version": "16.14.10", + "version": "16.14.11", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "npm-check-updates", - "version": "16.14.10", + "version": "16.14.11", "license": "Apache-2.0", "dependencies": { "chalk": "^5.3.0", diff --git a/package.json b/package.json index 440cf869..44f01b9f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "npm-check-updates", - "version": "16.14.10", + "version": "16.14.11", "author": "Tomas Junnonen ", "license": "Apache-2.0", "contributors": [