@@ -4,6 +4,7 @@ import path from 'node:path'
44import spawn from '@npmcli/promise-spawn'
55import EditablePackageJson from '@npmcli/package-json'
66import { getManifestData } from '@socketsecurity/registry'
7+ //import cacache from 'cacache'
78import meow from 'meow'
89import npa from 'npm-package-arg'
910import ora from 'ora'
@@ -12,6 +13,8 @@ import semver from 'semver'
1213import { glob as tinyGlob } from 'tinyglobby'
1314import { parse as yamlParse } from 'yaml'
1415
16+ //import { packumentCache, pacoteCachePath } from '../constants'
17+ import { packumentCache } from '../constants'
1518import { commonFlags } from '../flags'
1619import { printFlagList } from '../utils/formatting'
1720import { existsSync } from '../utils/fs'
@@ -24,11 +27,11 @@ import { isNonEmptyString } from '../utils/strings'
2427
2528import type { Content as PackageJsonContent } from '@npmcli/package-json'
2629import type { ManifestEntry } from '@socketsecurity/registry'
30+ import type { Ora } from 'ora'
2731import type { PacoteOptions } from 'pacote'
2832import type { CliSubcommand } from '../utils/meow-with-subcommands'
2933import type {
3034 Agent ,
31- AgentPlusBun ,
3235 StringKeyValueObject
3336} from '../utils/package-manager-detector'
3437
@@ -39,7 +42,6 @@ const RESOLUTIONS_FIELD_NAME = 'resolutions'
3942
4043const distPath = __dirname
4144const manifestNpmOverrides = getManifestData ( 'npm' ) !
42- const packumentCache = new Map ( )
4345
4446type NpmOverrides = { [ key : string ] : string | StringKeyValueObject }
4547type PnpmOrYarnOverrides = { [ key : string ] : string }
@@ -50,10 +52,10 @@ type GetOverridesResult = {
5052 overrides : Overrides
5153}
5254
53- const getOverridesDataByAgent : Record < AgentPlusBun , GetOverrides > = {
55+ const getOverridesDataByAgent : Record < Agent , GetOverrides > = {
5456 bun ( pkgJson : PackageJsonContent ) {
5557 const overrides = ( pkgJson as any ) ?. resolutions ?? { }
56- return { type : 'yarn' , overrides }
58+ return { type : 'yarn/berry ' , overrides }
5759 } ,
5860 // npm overrides documentation:
5961 // https://docs.npmjs.com/cli/v10/configuring-npm/package-json#overrides
@@ -69,15 +71,21 @@ const getOverridesDataByAgent: Record<AgentPlusBun, GetOverrides> = {
6971 } ,
7072 // Yarn resolutions documentation:
7173 // https://yarnpkg.com/configuration/manifest#resolutions
72- yarn ( pkgJson : PackageJsonContent ) {
74+ ' yarn/berry' ( pkgJson : PackageJsonContent ) {
7375 const overrides = ( pkgJson as any ) ?. resolutions ?? { }
74- return { type : 'yarn' , overrides }
76+ return { type : 'yarn/berry' , overrides }
77+ } ,
78+ // Yarn resolutions documentation:
79+ // https://classic.yarnpkg.com/en/docs/selective-version-resolutions
80+ 'yarn/classic' ( pkgJson : PackageJsonContent ) {
81+ const overrides = ( pkgJson as any ) ?. resolutions ?? { }
82+ return { type : 'yarn/classic' , overrides }
7583 }
7684}
7785
7886type AgentLockIncludesFn = ( lockSrc : string , name : string ) => boolean
7987
80- const lockIncludesByAgent : Record < AgentPlusBun , AgentLockIncludesFn > = ( ( ) => {
88+ const lockIncludesByAgent : Record < Agent , AgentLockIncludesFn > = ( ( ) => {
8189 const yarn = ( lockSrc : string , name : string ) => {
8290 const escapedName = escapeRegExp ( name )
8391 return new RegExp (
@@ -109,7 +117,8 @@ const lockIncludesByAgent: Record<AgentPlusBun, AgentLockIncludesFn> = (() => {
109117 'm'
110118 ) . test ( lockSrc )
111119 } ,
112- yarn
120+ 'yarn/berry' : yarn ,
121+ 'yarn/classic' : yarn
113122 }
114123} ) ( )
115124
@@ -118,7 +127,7 @@ type AgentModifyManifestFn = (
118127 overrides : Overrides
119128) => void
120129
121- const updateManifestByAgent : Record < AgentPlusBun , AgentModifyManifestFn > = {
130+ const updateManifestByAgent : Record < Agent , AgentModifyManifestFn > = {
122131 bun ( pkgJson : EditablePackageJson , overrides : Overrides ) {
123132 pkgJson . update ( {
124133 [ RESOLUTIONS_FIELD_NAME ] : < PnpmOrYarnOverrides > overrides
@@ -137,7 +146,12 @@ const updateManifestByAgent: Record<AgentPlusBun, AgentModifyManifestFn> = {
137146 }
138147 } )
139148 } ,
140- yarn ( pkgJson : EditablePackageJson , overrides : Overrides ) {
149+ 'yarn/berry' ( pkgJson : EditablePackageJson , overrides : Overrides ) {
150+ pkgJson . update ( {
151+ [ RESOLUTIONS_FIELD_NAME ] : < PnpmOrYarnOverrides > overrides
152+ } )
153+ } ,
154+ 'yarn/classic' ( pkgJson : EditablePackageJson , overrides : Overrides ) {
141155 pkgJson . update ( {
142156 [ RESOLUTIONS_FIELD_NAME ] : < PnpmOrYarnOverrides > overrides
143157 } )
@@ -150,7 +164,7 @@ type AgentListDepsFn = (
150164 rootPath : string
151165) => Promise < string >
152166
153- const lsByAgent : Record < AgentPlusBun , AgentListDepsFn > = {
167+ const lsByAgent : Record < Agent , AgentListDepsFn > = {
154168 async bun ( agentExecPath : string , cwd : string , _rootPath : string ) {
155169 try {
156170 // Bun does not support filtering by production packages yet.
@@ -166,8 +180,10 @@ const lsByAgent: Record<AgentPlusBun, AgentListDepsFn> = {
166180 [ 'ls' , '--parseable' , '--omit' , 'dev' , '--all' ] ,
167181 { cwd }
168182 )
183+ stdout = stdout . trim ( )
169184 stdout = stdout . replaceAll ( cwd , '' )
170- return rootPath === cwd ? stdout : stdout . replaceAll ( rootPath , '' )
185+ stdout = rootPath === cwd ? stdout : stdout . replaceAll ( rootPath , '' )
186+ return stdout . replaceAll ( '\\' , '/' )
171187 } catch { }
172188 return ''
173189 } ,
@@ -178,12 +194,14 @@ const lsByAgent: Record<AgentPlusBun, AgentListDepsFn> = {
178194 [ 'ls' , '--parseable' , '--prod' , '--depth' , 'Infinity' ] ,
179195 { cwd }
180196 )
197+ stdout = stdout . trim ( )
181198 stdout = stdout . replaceAll ( cwd , '' )
182- return rootPath === cwd ? stdout : stdout . replaceAll ( rootPath , '' )
199+ stdout = rootPath === cwd ? stdout : stdout . replaceAll ( rootPath , '' )
200+ return stdout . replaceAll ( '\\' , '/' )
183201 } catch { }
184202 return ''
185203 } ,
186- async yarn ( agentExecPath : string , cwd : string , _rootPath : string ) {
204+ async ' yarn/berry' ( agentExecPath : string , cwd : string , _rootPath : string ) {
187205 try {
188206 return (
189207 // Yarn Berry does not support filtering by production packages yet.
@@ -192,24 +210,33 @@ const lsByAgent: Record<AgentPlusBun, AgentListDepsFn> = {
192210 await spawn ( agentExecPath , [ 'info' , '--recursive' , '--name-only' ] , {
193211 cwd
194212 } )
195- ) . stdout
213+ ) . stdout . trim ( )
196214 )
197215 } catch { }
216+ return ''
217+ } ,
218+ async 'yarn/classic' ( agentExecPath : string , cwd : string , _rootPath : string ) {
198219 try {
199220 // However, Yarn Classic does support it.
200- return ( await spawn ( agentExecPath , [ 'list' , '--prod' ] , { cwd } ) ) . stdout
221+ // https://github.com/yarnpkg/yarn/releases/tag/v1.0.0
222+ // > Fix: Excludes dev dependencies from the yarn list output when the
223+ // environment is production
224+ return (
225+ await spawn ( agentExecPath , [ 'list' , '--prod' ] , { cwd } )
226+ ) . stdout . trim ( )
201227 } catch { }
202228 return ''
203229 }
204230}
205231
206232type AgentDepsIncludesFn = ( stdout : string , name : string ) => boolean
207233
208- const depsIncludesByAgent : Record < AgentPlusBun , AgentDepsIncludesFn > = {
209- bun : ( stdout : string , name : string ) => stdout . includes ( name ) ,
210- npm : ( stdout : string , name : string ) => stdout . includes ( name ) ,
211- pnpm : ( stdout : string , name : string ) => stdout . includes ( name ) ,
212- yarn : ( stdout : string , name : string ) => stdout . includes ( name )
234+ const depsIncludesByAgent : Record < Agent , AgentDepsIncludesFn > = {
235+ bun : ( stdout : string , name : string ) => stdout . includes ( ` ${ name } @` ) ,
236+ npm : ( stdout : string , name : string ) => stdout . includes ( `/${ name } \n` ) ,
237+ pnpm : ( stdout : string , name : string ) => stdout . includes ( `/${ name } \n` ) ,
238+ 'yarn/berry' : ( stdout : string , name : string ) => stdout . includes ( ` ${ name } @` ) ,
239+ 'yarn/classic' : ( stdout : string , name : string ) => stdout . includes ( ` ${ name } @` )
213240}
214241
215242function getDependencyEntries ( pkgJson : PackageJsonContent ) {
@@ -242,7 +269,7 @@ function getDependencyEntries(pkgJson: PackageJsonContent) {
242269}
243270
244271async function getWorkspaces (
245- agent : AgentPlusBun ,
272+ agent : Agent ,
246273 pkgPath : string ,
247274 pkgJson : PackageJsonContent
248275) : Promise < string [ ] | undefined > {
@@ -288,7 +315,7 @@ function workspaceToGlobPattern(workspace: string): string {
288315}
289316
290317type AddOverridesConfig = {
291- agent : AgentPlusBun
318+ agent : Agent
292319 agentExecPath : string
293320 lockSrc : string
294321 manifestEntries : ManifestEntry [ ]
@@ -301,6 +328,7 @@ type AddOverridesConfig = {
301328
302329type AddOverridesState = {
303330 added : Set < string >
331+ spinner ?: Ora | undefined
304332 updated : Set < string >
305333}
306334
@@ -318,12 +346,14 @@ async function addOverrides(
318346 } : AddOverridesConfig ,
319347 state : AddOverridesState = {
320348 added : new Set ( ) ,
349+ spinner : undefined ,
321350 updated : new Set ( )
322351 }
323352) : Promise < AddOverridesState > {
324353 if ( editablePkgJson === undefined ) {
325354 editablePkgJson = await EditablePackageJson . load ( pkgPath )
326355 }
356+ const { spinner } = state
327357 const pkgJson : Readonly < PackageJsonContent > = editablePkgJson . content
328358 const isRoot = pkgPath === rootPath
329359 const isLockScanned = isRoot && ! prod
@@ -342,12 +372,12 @@ async function addOverrides(
342372 } else {
343373 overridesDataObjects . push (
344374 getOverridesDataByAgent [ 'npm' ] ( pkgJson ) ,
345- getOverridesDataByAgent [ 'yarn' ] ( pkgJson )
375+ getOverridesDataByAgent [ 'yarn/classic ' ] ( pkgJson )
346376 )
347377 }
348- const spinner = isRoot
349- ? ora ( 'Fetching override manifests...' ) . start ( )
350- : undefined
378+ if ( spinner ) {
379+ spinner . text = `Adding overrides ${ isRoot ? '' : ` to ${ path . relative ( rootPath , pkgPath ) } ` } ...`
380+ }
351381 const depAliasMap = new Map < string , { id : string ; version : string } > ( )
352382 // Chunk package names to process them in parallel 3 at a time.
353383 await pEach ( manifestEntries , 3 , async ( { 1 : data } ) => {
@@ -428,21 +458,29 @@ async function addOverrides(
428458 workspaces . map ( workspaceToGlobPattern ) ,
429459 {
430460 absolute : true ,
431- cwd : pkgPath !
461+ cwd : pkgPath ! ,
462+ ignore : [ '**/node_modules/**' , '**/bower_components/**' ]
432463 }
433464 )
434465 // Chunk package names to process them in parallel 3 at a time.
435466 await pEach ( wsPkgJsonPaths , 3 , async wsPkgJsonPath => {
436- const { added, updated } = await addOverrides ( {
437- agent,
438- agentExecPath,
439- lockSrc,
440- manifestEntries,
441- pin,
442- pkgPath : path . dirname ( wsPkgJsonPath ) ,
443- prod,
444- rootPath
445- } )
467+ const { added, updated } = await addOverrides (
468+ {
469+ agent,
470+ agentExecPath,
471+ lockSrc,
472+ manifestEntries,
473+ pin,
474+ pkgPath : path . dirname ( wsPkgJsonPath ) ,
475+ prod,
476+ rootPath
477+ } ,
478+ {
479+ added : new Set ( ) ,
480+ spinner,
481+ updated : new Set ( )
482+ }
483+ )
446484 for ( const regPkgName of added ) {
447485 state . added . add ( regPkgName )
448486 }
@@ -451,8 +489,7 @@ async function addOverrides(
451489 }
452490 } )
453491 }
454- spinner ?. stop ( )
455- if ( state . added . size || state . updated . size ) {
492+ if ( state . added . size > 0 || state . updated . size > 0 ) {
456493 editablePkgJson . update ( < PackageJsonContent > Object . fromEntries ( depEntries ) )
457494 for ( const { overrides, type } of overridesDataObjects ) {
458495 updateManifestByAgent [ type ] ( editablePkgJson , toSortedObject ( overrides ) )
@@ -462,6 +499,34 @@ async function addOverrides(
462499 return state
463500}
464501
502+ // type ExtractOptions = pacote.Options & {
503+ // tmpPrefix?: string
504+ // [key: string]: any
505+ // }
506+
507+ // async function extractPackage(pkgNameOrId: string, options: ExtractOptions | undefined, callback: (tmpDirPath: string) => any) {
508+ // if (arguments.length === 2 && typeof options === 'function') {
509+ // callback = options
510+ // options = undefined
511+ // }
512+ // const { tmpPrefix, ...extractOptions } = { __proto__: null, ...options }
513+ // // cacache.tmp.withTmp DOES return a promise.
514+ // await cacache.tmp.withTmp(
515+ // pacoteCachePath,
516+ // { tmpPrefix },
517+ // // eslint-disable-next-line @typescript-eslint/no-misused-promises
518+ // async tmpDirPath => {
519+ // await pacote.extract(pkgNameOrId, tmpDirPath, {
520+ // __proto__: null,
521+ // packumentCache,
522+ // preferOffline: true,
523+ // ...<Omit<typeof extractOptions, '__proto__'>>extractOptions
524+ // })
525+ // await callback(tmpDirPath)
526+ // }
527+ // )
528+ // }
529+
465530type FetchPackageManifestOptions = {
466531 signal ?: AbortSignal
467532}
@@ -506,6 +571,7 @@ export const optimize: CliSubcommand = {
506571 const {
507572 agent,
508573 agentExecPath,
574+ agentVersion,
509575 lockSrc,
510576 lockPath,
511577 minimumNodeVersion,
@@ -535,15 +601,24 @@ export const optimize: CliSubcommand = {
535601 console . log ( `✘ ${ COMMAND_TITLE } : No package.json found` )
536602 return
537603 }
604+ if ( prod && ( agent === 'bun' || agent === 'yarn/berry' ) ) {
605+ console . log (
606+ `✘ ${ COMMAND_TITLE } : --prod not supported for ${ agent } ${ agentVersion ? `@${ agentVersion . toString ( ) } ` : '' } `
607+ )
608+ return
609+ }
538610 if ( lockPath && path . relative ( cwd , lockPath ) . startsWith ( '.' ) ) {
539611 console . log (
540612 `⚠️ ${ COMMAND_TITLE } : Package ${ lockName } found at ${ lockPath } `
541613 )
542614 }
615+ const spinner = ora ( 'Socket optimizing...' )
543616 const state : AddOverridesState = {
544617 added : new Set ( ) ,
618+ spinner,
545619 updated : new Set ( )
546620 }
621+ spinner . start ( )
547622 if ( lockSrc ) {
548623 const nodeRange = `>=${ minimumNodeVersion } `
549624 const manifestEntries = manifestNpmOverrides . filter ( ( { 1 : data } ) =>
@@ -580,18 +655,23 @@ export const optimize: CliSubcommand = {
580655 if ( isNpm || pkgJsonChanged ) {
581656 // Always update package-lock.json until the npm overrides PR lands:
582657 // https://github.com/npm/cli/pull/7025
583- const spinner = ora ( `Updating ${ lockName } ...` ) . start ( )
658+ spinner . text = `Updating ${ lockName } ...`
584659 try {
585660 if ( isNpm ) {
586661 const wrapperPath = path . join ( distPath , 'npm-cli.js' )
587- await spawn ( process . execPath , [ wrapperPath , 'install' ] , {
588- stdio : 'pipe' ,
589- env : {
590- ...process . env ,
591- UPDATE_SOCKET_OVERRIDES_IN_PACKAGE_LOCK_FILE : '1'
662+ await spawn (
663+ process . execPath ,
664+ [ wrapperPath , 'install' , '--no-audit' , '--no-fund' ] ,
665+ {
666+ stdio : 'pipe' ,
667+ env : {
668+ ...process . env ,
669+ UPDATE_SOCKET_OVERRIDES_IN_PACKAGE_LOCK_FILE : '1'
670+ }
592671 }
593- } )
672+ )
594673 } else {
674+ // All package managers support the "install" command.
595675 await spawn ( agentExecPath , [ 'install' ] , { stdio : 'pipe' } )
596676 }
597677 spinner . stop ( )
0 commit comments