@@ -30,28 +30,19 @@ import path from 'node:path'
3030import browserslist from 'browserslist'
3131import semver from 'semver'
3232
33- import { parse as parseBunLockb } from '@socketregistry/hyrious__bun.lockb/index.cjs'
3433import { whichReal } from '@socketsecurity/lib/bin'
3534import {
3635 BUN ,
37- BUN_LOCK ,
38- BUN_LOCKB ,
3936 NPM ,
40- NPM_SHRINKWRAP_JSON ,
41- PACKAGE_LOCK_JSON ,
4237 PNPM ,
43- PNPM_LOCK_YAML ,
4438 VLT ,
45- VLT_LOCK_JSON ,
4639 YARN ,
4740 YARN_BERRY ,
4841 YARN_CLASSIC ,
49- YARN_LOCK ,
5042} from '@socketsecurity/lib/constants/agents'
5143import { getMaintainedNodeVersions } from '@socketsecurity/lib/constants/node'
5244import { WIN32 } from '@socketsecurity/lib/constants/platform'
5345import { debugDirNs , debugNs } from '@socketsecurity/lib/debug'
54- import { readFileBinary , readFileUtf8 } from '@socketsecurity/lib/fs'
5546import {
5647 readPackageJson ,
5748 toEditablePackageJson ,
@@ -68,9 +59,6 @@ import {
6859import { FLAG_VERSION } from '../../constants/cli.mts'
6960import { VITEST } from '../../env/vitest.mts'
7061import {
71- EXT_LOCK ,
72- EXT_LOCKB ,
73- NODE_MODULES ,
7462 NPM_BUGGY_OVERRIDES_PATCHED_VERSION ,
7563 PACKAGE_JSON ,
7664} from '../../constants/packages.mts'
@@ -158,159 +146,23 @@ export type PartialEnvDetails = Readonly<
158146 >
159147>
160148
161- export type ReadLockFile =
162- | ( ( lockPath : string ) => Promise < string | Buffer | undefined > )
163- | ( (
164- lockPath : string ,
165- agentExecPath : string ,
166- ) => Promise < string | Buffer | undefined > )
167- | ( (
168- lockPath : string ,
169- agentExecPath : string ,
170- cwd : string ,
171- ) => Promise < string | Buffer | undefined > )
172-
173- const readLockFileByAgent : Map < Agent , ReadLockFile > = ( ( ) => {
174- function wrapReader < T extends ( ...args : any [ ] ) => Promise < any > > (
175- reader : T ,
176- ) : ( ...args : Parameters < T > ) => Promise < Awaited < ReturnType < T > > | undefined > {
177- return async ( ...args : any [ ] ) : Promise < any > => {
178- try {
179- return await reader ( ...args )
180- } catch { }
181- return undefined
182- }
183- }
184-
185- const binaryReader = wrapReader ( readFileBinary )
186-
187- const defaultReader = wrapReader (
188- async ( lockPath : string ) => await readFileUtf8 ( lockPath ) ,
189- )
190-
191- return new Map ( [
192- [
193- BUN ,
194- wrapReader (
195- async (
196- lockPath : string ,
197- agentExecPath : string ,
198- cwd = process . cwd ( ) ,
199- ) => {
200- const ext = path . extname ( lockPath )
201- if ( ext === EXT_LOCK ) {
202- return await defaultReader ( lockPath )
203- }
204- if ( ext === EXT_LOCKB ) {
205- const lockBuffer = await binaryReader ( lockPath )
206- if ( lockBuffer ) {
207- try {
208- return parseBunLockb ( lockBuffer )
209- } catch { }
210- }
211- // To print a Yarn lockfile to your console without writing it to disk
212- // use `bun bun.lockb`.
213- // https://bun.sh/guides/install/yarnlock
214- return (
215- await spawn ( agentExecPath , [ lockPath ] , {
216- cwd,
217- // On Windows, bun is often a .cmd file that requires shell execution.
218- // The spawn function from @socketsecurity /registry will handle this properly
219- // when shell is true.
220- shell : WIN32 ,
221- } )
222- ) . stdout
223- }
224- return undefined
225- } ,
226- ) ,
227- ] ,
228- [ NPM , defaultReader ] ,
229- [ PNPM , defaultReader ] ,
230- [ VLT , defaultReader ] ,
231- [ YARN_BERRY , defaultReader ] ,
232- [ YARN_CLASSIC , defaultReader ] ,
233- ] )
234- } ) ( )
235-
236- // The order of LOCKS properties IS significant as it affects iteration order.
237- const LOCKS : Record < string , Agent > = {
238- [ BUN_LOCK ] : BUN ,
239- [ BUN_LOCKB ] : BUN ,
240- // If both package-lock.json and npm-shrinkwrap.json are present in the root
241- // of a project, npm-shrinkwrap.json will take precedence and package-lock.json
242- // will be ignored.
243- // https://docs.npmjs.com/cli/v10/configuring-npm/package-lock-json#package-lockjson-vs-npm-shrinkwrapjson
244- [ NPM_SHRINKWRAP_JSON ] : NPM ,
245- [ PACKAGE_LOCK_JSON ] : NPM ,
246- [ PNPM_LOCK_YAML ] : PNPM ,
247- [ YARN_LOCK ] : YARN_CLASSIC ,
248- [ VLT_LOCK_JSON ] : VLT ,
249- // Lastly, look for a hidden lockfile which is present if .npmrc has package-lock=false:
250- // https://docs.npmjs.com/cli/v10/configuring-npm/package-lock-json#hidden-lockfiles
251- //
252- // Unlike the other LOCKS keys this key contains a directory AND filename so
253- // it has to be handled differently.
254- [ `${ NODE_MODULES } /${ DOT_PACKAGE_LOCK_JSON } ` ] : NPM ,
255- }
256-
257- export function resolveBinPathSync ( binPath : string ) : string {
258- // Simple implementation that tries to resolve a bin path to its actual entry point.
259- // This is used on Windows to resolve shims like `npm` or `npm.cmd` to their .js entry point.
260- if ( ! fs . existsSync ( binPath ) ) {
261- return binPath
262- }
263-
264- try {
265- // Try to read the file synchronously
266- const content = fs . readFileSync ( binPath , 'utf8' )
267- // Look for common patterns in npm/node shims:
268- // - node "C:\path\to\npm-cli.js" "$@"
269- // - "%_prog%" "%dp0%\node_modules\npm\bin\npm-cli.js" %*
270- const nodePathMatch = content . match (
271- / (?: n o d e \s + [ " ' ] | " % d p 0 % \\ ) ( [ ^ " ' \s ] + (?: n p m - c l i | p n p m | y a r n ) \. (?: c ? j s | m j s ) ) [ " ' \s ] / i,
272- )
273- if ( nodePathMatch && nodePathMatch . length > 1 && nodePathMatch [ 1 ] ) {
274- const matchedPath = nodePathMatch [ 1 ]
275- const resolvedPath = path . isAbsolute ( matchedPath )
276- ? matchedPath
277- : path . resolve ( path . dirname ( binPath ) , matchedPath )
278- return resolvedPath
279- }
280- } catch {
281- // If we can't read/parse the file, just return the original path
282- }
283- return binPath
284- }
285-
286- export function preferWindowsCmdShim ( binPath : string , binName : string ) : string {
287- // Only Windows uses .cmd shims
288- if ( ! WIN32 ) {
289- return binPath
290- }
291-
292- // Relative paths might be shell commands or aliases, not file paths with potential shims
293- if ( ! path . isAbsolute ( binPath ) ) {
294- return binPath
295- }
296-
297- // If the path already has an extension (.exe, .bat, etc.), it is probably a Windows executable
298- if ( path . extname ( binPath ) !== '' ) {
299- return binPath
300- }
149+ // Lockfile registration + per-agent reader Map extracted to keep this file
150+ // under the 1000-line cap. Re-export ReadLockFile for back-compat.
151+ import {
152+ LOCKS ,
153+ readLockFileByAgent ,
154+ } from './lockfile-readers.mts'
301155
302- // Ensures binPath actually points to the expected binary, not a parent directory that happens to match `binName`
303- // For example, if binPath is C:\foo\npm\something and binName is npm, we shouldn't replace it
304- if ( path . basename ( binPath ) . toLowerCase ( ) !== binName . toLowerCase ( ) ) {
305- return binPath
306- }
156+ export type { ReadLockFile } from './lockfile-readers.mts'
307157
308- // Finally attempt to construct a .cmd shim from binPath
309- const cmdShim = path . join ( path . dirname ( binPath ) , `${ binName } .cmd` )
158+ // Windows-shim helpers extracted to keep this file under the 1000-line cap.
159+ // Imported for local use AND re-exported so existing import paths keep working.
160+ import {
161+ preferWindowsCmdShim ,
162+ resolveBinPathSync ,
163+ } from './windows-shims.mts'
310164
311- // Ensure shim exists, otherwise fallback to binPath
312- return fs . existsSync ( cmdShim ) ? cmdShim : binPath
313- }
165+ export { preferWindowsCmdShim , resolveBinPathSync }
314166
315167export async function getAgentExecPath ( agent : Agent ) : Promise < string > {
316168 const binName = binByAgent . get ( agent ) !
0 commit comments