Skip to content

Commit f1d5458

Browse files
committed
Insert overrides in a place that makes sense in the package.json
1 parent bba10f4 commit f1d5458

File tree

1 file changed

+118
-17
lines changed

1 file changed

+118
-17
lines changed

src/commands/optimize.ts

Lines changed: 118 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { parse as yamlParse } from 'yaml'
1313
import { getManifestData } from '@socketsecurity/registry'
1414
import {
1515
hasOwn,
16-
objectFromEntries,
16+
isObject,
1717
toSortedObject
1818
} from '@socketsecurity/registry/lib/objects'
1919
import { fetchPackageManifest } from '@socketsecurity/registry/lib/packages'
@@ -37,6 +37,7 @@ import type { Ora } from 'ora'
3737

3838
const COMMAND_TITLE = 'Socket Optimize'
3939
const OVERRIDES_FIELD_NAME = 'overrides'
40+
const PNPM_FIELD_NAME = 'pnpm'
4041
const PNPM_WORKSPACE = 'pnpm-workspace'
4142
const RESOLUTIONS_FIELD_NAME = 'resolutions'
4243

@@ -138,31 +139,131 @@ type AgentModifyManifestFn = (
138139
) => void
139140

140141
const updateManifestByAgent: Record<Agent, AgentModifyManifestFn> = (() => {
141-
function updateOverrides(pkgJson: EditablePackageJson, overrides: Overrides) {
142-
pkgJson.update({
143-
[OVERRIDES_FIELD_NAME]: overrides
144-
})
142+
const depFields = [
143+
'dependencies',
144+
'devDependencies',
145+
'peerDependencies',
146+
'peerDependenciesMeta',
147+
'optionalDependencies',
148+
'bundleDependencies'
149+
]
150+
151+
function getEntryIndexes(
152+
entries: [string | symbol, any][],
153+
keys: (string | symbol)[]
154+
): number[] {
155+
return keys
156+
.map(n => entries.findIndex(p => p[0] === n))
157+
.filter(n => n !== -1)
158+
.sort((a, b) => a - b)
159+
}
160+
161+
function getLowestEntryIndex(
162+
entries: [string | symbol, any][],
163+
keys: (string | symbol)[]
164+
) {
165+
return getEntryIndexes(entries, keys)?.[0] ?? -1
166+
}
167+
168+
function getHighestEntryIndex(
169+
entries: [string | symbol, any][],
170+
keys: (string | symbol)[]
171+
) {
172+
return getEntryIndexes(entries, keys).at(-1) ?? -1
173+
}
174+
175+
function updatePkgJson(
176+
editablePkgJson: EditablePackageJson,
177+
field: string,
178+
value: any
179+
) {
180+
const pkgJson = editablePkgJson.content
181+
const oldValue = pkgJson[field]
182+
if (oldValue) {
183+
// The field already exists so we simply update the field value.
184+
if (field === PNPM_FIELD_NAME) {
185+
editablePkgJson.update({
186+
[field]: {
187+
...(isObject(oldValue) ? oldValue : {}),
188+
overrides: value
189+
}
190+
})
191+
} else {
192+
editablePkgJson.update({ [field]: value })
193+
}
194+
return
195+
}
196+
// Since the field doesn't exist we want to insert it into the package.json
197+
// in a place that makes sense, e.g. close to the "dependencies" field. If
198+
// we can't find a place to insert the field we'll add it to the bottom.
199+
const entries = Object.entries(pkgJson)
200+
let insertIndex = -1
201+
let isPlacingHigher = false
202+
if (field === OVERRIDES_FIELD_NAME) {
203+
insertIndex = getLowestEntryIndex(entries, ['resolutions'])
204+
if (insertIndex === -1) {
205+
isPlacingHigher = true
206+
insertIndex = getHighestEntryIndex(entries, [...depFields, 'pnpm'])
207+
}
208+
} else if (field === RESOLUTIONS_FIELD_NAME) {
209+
isPlacingHigher = true
210+
insertIndex = getHighestEntryIndex(entries, [
211+
...depFields,
212+
'overrides',
213+
'pnpm'
214+
])
215+
} else if (field === PNPM_FIELD_NAME) {
216+
insertIndex = getLowestEntryIndex(entries, ['overrides', 'resolutions'])
217+
if (insertIndex === -1) {
218+
isPlacingHigher = true
219+
insertIndex = getHighestEntryIndex(entries, depFields)
220+
}
221+
}
222+
if (insertIndex === -1) {
223+
insertIndex = getLowestEntryIndex(entries, ['engines', 'files'])
224+
}
225+
if (insertIndex === -1) {
226+
isPlacingHigher = true
227+
insertIndex = getHighestEntryIndex(entries, [
228+
'exports',
229+
'imports',
230+
'main'
231+
])
232+
}
233+
if (insertIndex === -1) {
234+
insertIndex = entries.length
235+
} else if (isPlacingHigher) {
236+
insertIndex += 1
237+
}
238+
entries.splice(insertIndex, 0, [field, value])
239+
editablePkgJson.fromJSON(
240+
`${JSON.stringify(Object.fromEntries(entries), null, 2)}\n`
241+
)
242+
}
243+
244+
function updateOverrides(
245+
editablePkgJson: EditablePackageJson,
246+
overrides: Overrides
247+
) {
248+
updatePkgJson(editablePkgJson, OVERRIDES_FIELD_NAME, overrides)
145249
}
146250

147251
function updateResolutions(
148-
pkgJson: EditablePackageJson,
252+
editablePkgJson: EditablePackageJson,
149253
overrides: Overrides
150254
) {
151-
pkgJson.update({
152-
[RESOLUTIONS_FIELD_NAME]: <PnpmOrYarnOverrides>overrides
153-
})
255+
updatePkgJson(
256+
editablePkgJson,
257+
RESOLUTIONS_FIELD_NAME,
258+
<PnpmOrYarnOverrides>overrides
259+
)
154260
}
155261

156262
return {
157263
bun: updateResolutions,
158264
npm: updateOverrides,
159-
pnpm(pkgJson: EditablePackageJson, overrides: Overrides) {
160-
pkgJson.update({
161-
pnpm: {
162-
...(<object>pkgJson.content['pnpm']),
163-
[OVERRIDES_FIELD_NAME]: overrides
164-
}
165-
})
265+
pnpm(editablePkgJson: EditablePackageJson, overrides: Overrides) {
266+
updatePkgJson(editablePkgJson, PNPM_FIELD_NAME, overrides)
166267
},
167268
vlt: updateOverrides,
168269
'yarn/berry': updateResolutions,
@@ -622,7 +723,7 @@ async function addOverrides(
622723
})
623724
}
624725
if (state.added.size > 0 || state.updated.size > 0) {
625-
editablePkgJson.update(<NPMCliPackageJson>objectFromEntries(depEntries))
726+
editablePkgJson.update(<NPMCliPackageJson>Object.fromEntries(depEntries))
626727
for (const { overrides, type } of overridesDataObjects) {
627728
updateManifestByAgent[type](editablePkgJson, toSortedObject(overrides))
628729
}

0 commit comments

Comments
 (0)