Skip to content

Commit d3cf6cf

Browse files
committed
Cleanup optimize command
1 parent 3fa30e8 commit d3cf6cf

15 files changed

+343
-326
lines changed

src/commands/fix/run-fix.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import {
1818
getPackagesAlerts,
1919
updateNode
2020
} from '../../shadow/arborist/lib/arborist/reify'
21-
// import { detect } from '../../utils/package-manager-detector'
21+
// import { detect } from '../../utils/package-environment-detector'
2222

2323
import type { SafeNode } from '../../shadow/arborist/lib/node'
2424

src/commands/optimize/apply-optimization.ts

Lines changed: 77 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -4,109 +4,82 @@ import npa from 'npm-package-arg'
44
import semver from 'semver'
55
import { glob as tinyGlob } from 'tinyglobby'
66

7-
import { type ManifestEntry } from '@socketsecurity/registry'
7+
import { getManifestData } from '@socketsecurity/registry'
88
import { hasOwn, toSortedObject } from '@socketsecurity/registry/lib/objects'
99
import {
1010
fetchPackageManifest,
1111
readPackageJson
1212
} from '@socketsecurity/registry/lib/packages'
13-
import { type EditablePackageJson } from '@socketsecurity/registry/lib/packages'
1413
import { pEach } from '@socketsecurity/registry/lib/promises'
1514
import { Spinner } from '@socketsecurity/registry/lib/spinner'
1615
import { pluralize } from '@socketsecurity/registry/lib/words'
1716

1817
import { depsIncludesByAgent } from './deps-includes-by-agent'
19-
import { detectAndValidatePackageManager } from './detect-and-validate-package-manager'
18+
import { detectAndValidatePackageEnvironment } from './detect-and-validate-package-environment'
2019
import { getDependencyEntries } from './get-dependency-entries'
21-
import { getOverridesDataByAgent } from './get-overrides-by-agent'
20+
import { overridesDataByAgent } from './get-overrides-by-agent'
2221
import { getWorkspaceGlobs } from './get-workspace-globs'
23-
import {
24-
AgentLockIncludesFn,
25-
lockIncludesByAgent
26-
} from './lock-includes-by-agent'
22+
import { lockIncludesByAgent } from './lock-includes-by-agent'
2723
import { lsByAgent } from './ls-by-agent'
2824
import { updateManifestByAgent } from './update-manifest-by-agent'
2925
import { updatePackageLockJson } from './update-package-lock-json'
3026
import constants from '../../constants'
3127

28+
import type { AgentLockIncludesFn } from './lock-includes-by-agent'
3229
import type {
3330
Agent,
31+
PackageEnvironmentDetails,
3432
StringKeyValueObject
35-
} from '../../utils/package-manager-detector'
36-
37-
type PackageJson = Awaited<ReturnType<typeof readPackageJson>>
33+
} from '../../utils/package-environment-detector'
3834

39-
type AddOverridesConfig = {
40-
agent: Agent
41-
agentExecPath: string
42-
lockBasename: string
43-
lockSrc: string
44-
manifestEntries: ManifestEntry[]
45-
npmExecPath: string
46-
pkgJson?: EditablePackageJson | undefined
47-
pkgPath: string
35+
type AddOverridesOptions = {
36+
logger?: Console | undefined
4837
pin?: boolean | undefined
4938
prod?: boolean | undefined
50-
rootPath: string
39+
spinner?: Spinner | undefined
40+
state?: AddOverridesState | undefined
5141
}
52-
5342
type AddOverridesState = {
5443
added: Set<string>
5544
addedInWorkspaces: Set<string>
56-
spinner: Spinner
5745
updated: Set<string>
5846
updatedInWorkspaces: Set<string>
5947
warnedPnpmWorkspaceRequiresNpm: boolean
6048
}
61-
49+
type GetOverridesResult = { type: Agent; overrides: Overrides }
6250
type NpmOverrides = { [key: string]: string | StringKeyValueObject }
51+
type PackageJson = Awaited<ReturnType<typeof readPackageJson>>
6352
type PnpmOrYarnOverrides = { [key: string]: string }
6453
type Overrides = NpmOverrides | PnpmOrYarnOverrides
65-
type GetOverridesResult = { type: Agent; overrides: Overrides }
6654

6755
const { NPM, PNPM, YARN_CLASSIC } = constants
6856

6957
const COMMAND_TITLE = 'Socket Optimize'
7058

59+
const manifestNpmOverrides = getManifestData(NPM)
60+
7161
export async function applyOptimization(
7262
cwd: string,
7363
pin: boolean,
7464
prod: boolean
7565
) {
76-
const pkgMgrData = await detectAndValidatePackageManager(cwd, prod)
77-
if (!pkgMgrData) return
78-
79-
const {
80-
agent,
81-
agentExecPath,
82-
lockBasename,
83-
lockName,
84-
lockSrc,
85-
manifestEntries,
86-
npmExecPath,
87-
pkgJson,
88-
pkgPath
89-
} = pkgMgrData
90-
66+
const logger = console
67+
const pkgEnvDetails = await detectAndValidatePackageEnvironment(cwd, {
68+
logger,
69+
prod
70+
})
71+
if (!pkgEnvDetails) {
72+
return
73+
}
9174
const spinner = new Spinner({ text: 'Socket optimizing...' })
9275
spinner.start()
9376

94-
const state = await addOverrides(
95-
{
96-
agent,
97-
agentExecPath,
98-
lockBasename,
99-
lockSrc,
100-
manifestEntries,
101-
npmExecPath,
102-
pin,
103-
pkgJson,
104-
pkgPath,
105-
prod,
106-
rootPath: pkgPath
107-
},
108-
createAddOverridesState(spinner)
109-
)
77+
const state = await addOverrides(pkgEnvDetails.pkgPath, pkgEnvDetails, {
78+
logger,
79+
pin,
80+
prod,
81+
spinner
82+
})
11083

11184
spinner.stop()
11285

@@ -115,23 +88,23 @@ export async function applyOptimization(
11588
const pkgJsonChanged = addedCount > 0 || updatedCount > 0
11689
if (pkgJsonChanged) {
11790
if (updatedCount > 0) {
118-
console.log(
91+
logger?.log(
11992
`${createActionMessage('Updated', updatedCount, state.updatedInWorkspaces.size)}${addedCount ? '.' : '🚀'}`
12093
)
12194
}
12295
if (addedCount > 0) {
123-
console.log(
96+
logger?.log(
12497
`${createActionMessage('Added', addedCount, state.addedInWorkspaces.size)} 🚀`
12598
)
12699
}
127100
} else {
128-
console.log('Congratulations! Already Socket.dev optimized 🎉')
101+
logger?.log('Congratulations! Already Socket.dev optimized 🎉')
129102
}
130103

131-
if (agent === NPM || pkgJsonChanged) {
104+
if (pkgEnvDetails.agent === NPM || pkgJsonChanged) {
132105
// Always update package-lock.json until the npm overrides PR lands:
133106
// https://github.com/npm/cli/pull/8089
134-
await updatePackageLockJson(lockName, agentExecPath, agent, spinner)
107+
await updatePackageLockJson(pkgEnvDetails, { logger, spinner })
135108
}
136109
}
137110

@@ -143,37 +116,36 @@ function createActionMessage(
143116
return `${verb} ${overrideCount} Socket.dev optimized ${pluralize('override', overrideCount)}${workspaceCount ? ` in ${workspaceCount} ${pluralize('workspace', workspaceCount)}` : ''}`
144117
}
145118

146-
function createAddOverridesState(spinner: Spinner): AddOverridesState {
147-
return {
148-
added: new Set(),
149-
addedInWorkspaces: new Set(),
150-
spinner,
151-
updated: new Set(),
152-
updatedInWorkspaces: new Set(),
153-
warnedPnpmWorkspaceRequiresNpm: false
154-
}
155-
}
156-
157119
async function addOverrides(
158-
{
120+
pkgPath: string,
121+
pkgEnvDetails: PackageEnvironmentDetails,
122+
options?: AddOverridesOptions | undefined
123+
): Promise<AddOverridesState> {
124+
const {
159125
agent,
160126
agentExecPath,
161-
lockBasename,
127+
lockName,
162128
lockSrc,
163-
manifestEntries,
164129
npmExecPath,
130+
pkgPath: rootPath
131+
} = pkgEnvDetails
132+
const {
133+
logger,
165134
pin,
166-
pkgJson: editablePkgJson,
167-
pkgPath,
168135
prod,
169-
rootPath
170-
}: AddOverridesConfig,
171-
state: AddOverridesState
172-
): Promise<AddOverridesState> {
136+
spinner,
137+
state = {
138+
added: new Set(),
139+
addedInWorkspaces: new Set(),
140+
updated: new Set(),
141+
updatedInWorkspaces: new Set(),
142+
warnedPnpmWorkspaceRequiresNpm: false
143+
}
144+
} = <AddOverridesOptions>{ __proto__: null, ...options }
145+
let { pkgJson: editablePkgJson } = pkgEnvDetails
173146
if (editablePkgJson === undefined) {
174147
editablePkgJson = await readPackageJson(pkgPath, { editable: true })
175148
}
176-
const { spinner } = state
177149
const { content: pkgJson } = editablePkgJson
178150
const isRoot = pkgPath === rootPath
179151
const isLockScanned = isRoot && !prod
@@ -187,35 +159,42 @@ async function addOverrides(
187159
!state.warnedPnpmWorkspaceRequiresNpm
188160
) {
189161
state.warnedPnpmWorkspaceRequiresNpm = true
190-
console.warn(
162+
logger?.warn(
191163
`⚠️ ${COMMAND_TITLE}: pnpm workspace support requires \`npm ls\`, falling back to \`pnpm list\``
192164
)
193165
}
194166
const thingToScan = isLockScanned
195167
? lockSrc
196-
: await lsByAgent[agent](agentExecPath, pkgPath, { npmExecPath })
168+
: await lsByAgent[agent]!(agentExecPath, pkgPath, { npmExecPath })
197169
// The AgentDepsIncludesFn and AgentLockIncludesFn types overlap in their
198170
// first two parameters. AgentLockIncludesFn accepts an optional third
199171
// parameter which AgentDepsIncludesFn will ignore so we cast thingScanner
200172
// as an AgentLockIncludesFn type.
201173
const thingScanner = <AgentLockIncludesFn>(
202-
(isLockScanned ? lockIncludesByAgent[agent] : depsIncludesByAgent[agent])
174+
(isLockScanned
175+
? lockIncludesByAgent.get(agent)
176+
: depsIncludesByAgent.get(agent))
203177
)
204178
const depEntries = getDependencyEntries(pkgJson)
205179

206180
const overridesDataObjects = <GetOverridesResult[]>[]
207181
if (pkgJson['private'] || isWorkspace) {
208-
overridesDataObjects.push(getOverridesDataByAgent[agent](pkgJson))
182+
overridesDataObjects.push(overridesDataByAgent.get(agent)!(pkgJson))
209183
} else {
210184
overridesDataObjects.push(
211-
getOverridesDataByAgent[NPM](pkgJson),
212-
getOverridesDataByAgent[YARN_CLASSIC](pkgJson)
185+
overridesDataByAgent.get(NPM)!(pkgJson),
186+
overridesDataByAgent.get(YARN_CLASSIC)!(pkgJson)
213187
)
214188
}
215189
if (spinner) {
216190
spinner.text = `Adding overrides${workspaceName ? ` to ${workspaceName}` : ''}...`
217191
}
218192
const depAliasMap = new Map<string, string>()
193+
194+
const nodeRange = `>=${pkgEnvDetails.minimumNodeVersion}`
195+
const manifestEntries = manifestNpmOverrides.filter(({ 1: data }) =>
196+
semver.satisfies(semver.coerce(data.engines.node)!, nodeRange)
197+
)
219198
// Chunk package names to process them in parallel 3 at a time.
220199
await pEach(manifestEntries, 3, async ({ 1: data }) => {
221200
const { name: sockRegPkgName, package: origPkgName, version } = data
@@ -258,7 +237,7 @@ async function addOverrides(
258237
const overrideExists = hasOwn(overrides, origPkgName)
259238
if (
260239
overrideExists ||
261-
thingScanner(thingToScan, origPkgName, lockBasename)
240+
thingScanner(thingToScan, origPkgName, lockName)
262241
) {
263242
const oldSpec = overrideExists ? overrides[origPkgName]! : undefined
264243
const origDepAlias = depAliasMap.get(origPkgName)
@@ -313,19 +292,14 @@ async function addOverrides(
313292
// Chunk package names to process them in parallel 3 at a time.
314293
await pEach(workspacePkgJsonPaths, 3, async workspacePkgJsonPath => {
315294
const otherState = await addOverrides(
295+
path.dirname(workspacePkgJsonPath),
296+
pkgEnvDetails,
316297
{
317-
agent,
318-
agentExecPath,
319-
lockBasename,
320-
lockSrc,
321-
manifestEntries,
322-
npmExecPath,
298+
logger,
323299
pin,
324-
pkgPath: path.dirname(workspacePkgJsonPath),
325300
prod,
326-
rootPath
327-
},
328-
createAddOverridesState(spinner)
301+
spinner
302+
}
329303
)
330304
for (const key of [
331305
'added',
@@ -351,7 +325,10 @@ async function addOverrides(
351325
if (state.added.size > 0 || state.updated.size > 0) {
352326
editablePkgJson.update(<PackageJson>Object.fromEntries(depEntries))
353327
for (const { overrides, type } of overridesDataObjects) {
354-
updateManifestByAgent[type](editablePkgJson, toSortedObject(overrides))
328+
updateManifestByAgent.get(type)!(
329+
editablePkgJson,
330+
toSortedObject(overrides)
331+
)
355332
}
356333
await editablePkgJson.save()
357334
}

src/commands/optimize/cmd-optimize.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,9 @@ async function run(
5757

5858
const cwd = process.cwd()
5959

60-
if (cli.flags['dryRun']) return console.log('[DryRun] Bailing now')
60+
if (cli.flags['dryRun']) {
61+
return console.log('[DryRun] Bailing now')
62+
}
6163

6264
await applyOptimization(
6365
cwd,
Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import constants from '../../constants'
22

3-
import type { Agent } from '../../utils/package-manager-detector'
3+
import type { Agent } from '../../utils/package-environment-detector'
44

55
type AgentDepsIncludesFn = (stdout: string, name: string) => boolean
66

@@ -14,14 +14,11 @@ function matchQueryStdout(stdout: string, name: string) {
1414
return stdout.includes(`"${name}"`)
1515
}
1616

17-
export const depsIncludesByAgent: Record<Agent, AgentDepsIncludesFn> = {
18-
// @ts-ignore
19-
__proto__: null,
20-
21-
[BUN]: matchHumanStdout,
22-
[NPM]: matchQueryStdout,
23-
[PNPM]: matchQueryStdout,
24-
[VLT]: matchQueryStdout,
25-
[YARN_BERRY]: matchHumanStdout,
26-
[YARN_CLASSIC]: matchHumanStdout
27-
}
17+
export const depsIncludesByAgent = new Map<Agent, AgentDepsIncludesFn>([
18+
[BUN, matchHumanStdout],
19+
[NPM, matchQueryStdout],
20+
[PNPM, matchQueryStdout],
21+
[VLT, matchQueryStdout],
22+
[YARN_BERRY, matchHumanStdout],
23+
[YARN_CLASSIC, matchHumanStdout]
24+
])

0 commit comments

Comments
 (0)