@@ -13,7 +13,7 @@ import { parse as yamlParse } from 'yaml'
13
13
import { getManifestData } from '@socketsecurity/registry'
14
14
import {
15
15
hasOwn ,
16
- objectFromEntries ,
16
+ isObject ,
17
17
toSortedObject
18
18
} from '@socketsecurity/registry/lib/objects'
19
19
import { fetchPackageManifest } from '@socketsecurity/registry/lib/packages'
@@ -37,6 +37,7 @@ import type { Ora } from 'ora'
37
37
38
38
const COMMAND_TITLE = 'Socket Optimize'
39
39
const OVERRIDES_FIELD_NAME = 'overrides'
40
+ const PNPM_FIELD_NAME = 'pnpm'
40
41
const PNPM_WORKSPACE = 'pnpm-workspace'
41
42
const RESOLUTIONS_FIELD_NAME = 'resolutions'
42
43
@@ -138,31 +139,131 @@ type AgentModifyManifestFn = (
138
139
) => void
139
140
140
141
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 )
145
249
}
146
250
147
251
function updateResolutions (
148
- pkgJson : EditablePackageJson ,
252
+ editablePkgJson : EditablePackageJson ,
149
253
overrides : Overrides
150
254
) {
151
- pkgJson . update ( {
152
- [ RESOLUTIONS_FIELD_NAME ] : < PnpmOrYarnOverrides > overrides
153
- } )
255
+ updatePkgJson (
256
+ editablePkgJson ,
257
+ RESOLUTIONS_FIELD_NAME ,
258
+ < PnpmOrYarnOverrides > overrides
259
+ )
154
260
}
155
261
156
262
return {
157
263
bun : updateResolutions ,
158
264
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 )
166
267
} ,
167
268
vlt : updateOverrides ,
168
269
'yarn/berry' : updateResolutions ,
@@ -622,7 +723,7 @@ async function addOverrides(
622
723
} )
623
724
}
624
725
if ( state . added . size > 0 || state . updated . size > 0 ) {
625
- editablePkgJson . update ( < NPMCliPackageJson > objectFromEntries ( depEntries ) )
726
+ editablePkgJson . update ( < NPMCliPackageJson > Object . fromEntries ( depEntries ) )
626
727
for ( const { overrides, type } of overridesDataObjects ) {
627
728
updateManifestByAgent [ type ] ( editablePkgJson , toSortedObject ( overrides ) )
628
729
}
0 commit comments