-
Notifications
You must be signed in to change notification settings - Fork 38
Expand file tree
/
Copy pathpath-resolve.mts
More file actions
130 lines (121 loc) · 4.37 KB
/
path-resolve.mts
File metadata and controls
130 lines (121 loc) · 4.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
import { existsSync } from 'node:fs'
import path from 'node:path'
import {
resolveBinPathSync,
whichBinSync,
} from '@socketsecurity/registry/lib/bin'
import { isDirSync } from '@socketsecurity/registry/lib/fs'
import constants, { NODE_MODULES, NPM } from '../constants.mts'
import {
createSupportedFilesFilter,
globWithGitIgnore,
pathsToGlobPatterns,
} from './glob.mts'
import type { SocketYml } from '@socketsecurity/config'
import type { SocketSdkSuccessResult } from '@socketsecurity/sdk'
export function findBinPathDetailsSync(binName: string): {
name: string
path: string | undefined
shadowed: boolean
} {
const rawBinPaths =
whichBinSync(binName, {
all: true,
nothrow: true,
}) ?? []
// whichBinSync may return a string when only one result is found, even with all: true.
// This handles both the current published version and future versions.
const binPaths = Array.isArray(rawBinPaths)
? rawBinPaths
: typeof rawBinPaths === 'string'
? [rawBinPaths]
: []
const { shadowBinPath } = constants
let shadowIndex = -1
let theBinPath: string | undefined
for (let i = 0, { length } = binPaths; i < length; i += 1) {
const binPath = binPaths[i]!
// Skip our bin directory if it's in the front.
if (path.dirname(binPath) === shadowBinPath) {
shadowIndex = i
} else {
theBinPath = resolveBinPathSync(binPath)
break
}
}
return { name: binName, path: theBinPath, shadowed: shadowIndex !== -1 }
}
export function findNpmDirPathSync(npmBinPath: string): string | undefined {
const { WIN32 } = constants
let thePath = npmBinPath
while (true) {
const libNmNpmPath = path.join(thePath, `lib/${NODE_MODULES}/${NPM}`)
// mise, which uses opaque binaries, puts its npm bin in a path like:
// /Users/SomeUsername/.local/share/mise/installs/node/vX.X.X/bin/npm.
// HOWEVER, the location of the npm install is:
// /Users/SomeUsername/.local/share/mise/installs/node/vX.X.X/lib/node_modules/npm.
if (
// Use existsSync here because statsSync, even with { throwIfNoEntry: false },
// will throw an ENOTDIR error for paths like ./a-file-that-exists/a-directory-that-does-not.
// See https://github.com/nodejs/node/issues/56993.
isDirSync(libNmNpmPath)
) {
thePath = libNmNpmPath
}
const hasNmInCurrPath = isDirSync(path.join(thePath, NODE_MODULES))
const hasNmInParentPath =
!hasNmInCurrPath && isDirSync(path.join(thePath, `../${NODE_MODULES}`))
if (
// npm bin paths may look like:
// /usr/local/share/npm/bin/npm
// /Users/SomeUsername/.nvm/versions/node/vX.X.X/bin/npm
// C:\Users\SomeUsername\AppData\Roaming\npm\bin\npm.cmd
// OR
// C:\Program Files\nodejs\npm.cmd
//
// In practically all cases the npm path contains a node_modules folder:
// /usr/local/share/npm/bin/npm/node_modules
// C:\Program Files\nodejs\node_modules
(hasNmInCurrPath ||
// In some bespoke cases the node_modules folder is in the parent directory.
hasNmInParentPath) &&
// Optimistically look for the default location.
(path.basename(thePath) === NPM ||
// Chocolatey installs npm bins in the same directory as node bins.
(WIN32 && existsSync(path.join(thePath, `${NPM}.cmd`))))
) {
return hasNmInParentPath ? path.dirname(thePath) : thePath
}
const parent = path.dirname(thePath)
if (parent === thePath) {
return undefined
}
thePath = parent
}
}
export type PackageFilesForScanOptions = {
cwd?: string | undefined
config?: SocketYml | undefined
}
export async function getPackageFilesForScan(
inputPaths: string[],
supportedFiles: SocketSdkSuccessResult<'getReportSupportedFiles'>['data'],
options?: PackageFilesForScanOptions | undefined,
): Promise<string[]> {
const { config: socketConfig, cwd = process.cwd() } = {
__proto__: null,
...options,
} as PackageFilesForScanOptions
// Apply the supported files filter during streaming to avoid accumulating
// all files in memory. This is critical for large monorepos with 100k+ files
// where accumulating all paths before filtering causes OOM errors.
const filter = createSupportedFilesFilter(supportedFiles)
return await globWithGitIgnore(
pathsToGlobPatterns(inputPaths, options?.cwd),
{
cwd,
filter,
socketConfig,
},
)
}