@@ -5,53 +5,55 @@ import EditablePackageJson from '@npmcli/package-json'
5
5
import { getManifestData } from '@socketsecurity/registry'
6
6
import meow from 'meow'
7
7
import ora from 'ora'
8
+ import semver from 'semver'
8
9
9
10
import { printFlagList } from '../utils/formatting'
10
- import { hasOwn , isObjectObject } from '../utils/objects'
11
+ import { hasOwn } from '../utils/objects'
11
12
import { detect } from '../utils/package-manager-detector'
12
13
import { escapeRegExp } from '../utils/regexps'
13
14
import { toSortedObject } from '../utils/sorts'
14
15
15
- import type { Content as PackageJsonContentType } from '@npmcli/package-json'
16
+ import type { Content as PackageJsonContent } from '@npmcli/package-json'
16
17
import type { CliSubcommand } from '../utils/meow-with-subcommands'
17
18
import type {
18
19
Agent ,
19
- PackageJSONObject ,
20
20
StringKeyValueObject
21
21
} from '../utils/package-manager-detector'
22
22
23
23
const distPath = __dirname
24
24
25
25
const OVERRIDES_FIELD_NAME = 'overrides'
26
-
27
26
const RESOLUTIONS_FIELD_NAME = 'resolutions'
28
27
29
- const SOCKET_REGISTRY_NAME = '@socketregistry'
30
-
31
- const SOCKET_REGISTRY_MAJOR_VERSION = '^1'
32
-
33
- const allPackages = getManifestData ( 'npm' ) !
34
- . filter ( ( { 1 : d } ) => d . engines ?. node ?. startsWith ( '>=18' ) )
35
- . map ( ( { 1 : d } ) => d . package )
28
+ const availableOverrides = getManifestData ( 'npm' ) ! . filter ( ( { 1 : d } ) =>
29
+ d . engines ?. node ?. startsWith ( '>=18' )
30
+ )
36
31
37
32
type NpmOverrides = { [ key : string ] : string | StringKeyValueObject }
38
33
type PnpmOrYarnOverrides = { [ key : string ] : string }
39
34
type Overrides = NpmOverrides | PnpmOrYarnOverrides
35
+ type GetOverrides = ( pkg : PackageJsonContent ) => GetOverridesResult | undefined
36
+ type GetOverridesResult = { type : Agent ; overrides : Overrides }
40
37
41
- type GetManifestOverrides = ( pkg : PackageJSONObject ) => Overrides | undefined
42
-
43
- const getManifestOverridesByAgent : Record < Agent , GetManifestOverrides > = {
38
+ const getOverridesDataByAgent : Record < Agent , GetOverrides > = {
44
39
// npm overrides documentation:
45
40
// https://docs.npmjs.com/cli/v10/configuring-npm/package-json#overrides
46
- npm : ( pkgJson : PackageJSONObject ) => ( pkgJson as any ) ?. overrides ?? undefined ,
41
+ npm : ( pkgJson : PackageJsonContent ) => {
42
+ const overrides = ( pkgJson as any ) ?. overrides ?? { }
43
+ return { type : 'npm' , overrides }
44
+ } ,
47
45
// pnpm overrides documentation:
48
46
// https://pnpm.io/package_json#pnpmoverrides
49
- pnpm : ( pkgJson : PackageJSONObject ) =>
50
- ( pkgJson as any ) ?. pnpm ?. overrides ?? undefined ,
47
+ pnpm : ( pkgJson : PackageJsonContent ) => {
48
+ const overrides = ( pkgJson as any ) ?. pnpm ?. overrides ?? undefined
49
+ return overrides ? { type : 'pnpm' , overrides } : undefined
50
+ } ,
51
51
// Yarn resolutions documentation:
52
52
// https://yarnpkg.com/configuration/manifest#resolutions
53
- yarn : ( pkgJson : PackageJSONObject ) =>
54
- ( pkgJson as any ) ?. resolutions ?? undefined
53
+ yarn : ( pkgJson : PackageJsonContent ) => {
54
+ const overrides = ( pkgJson as any ) ?. resolutions ?? { }
55
+ return { type : 'yarn' , overrides }
56
+ }
55
57
}
56
58
57
59
type LockIncludes = ( lockSrc : string , name : string ) => boolean
@@ -96,16 +98,22 @@ const updateManifestByAgent: Record<Agent, ModifyManifest> = (<any>{
96
98
__proto__ : null ,
97
99
npm ( editablePkgJson : EditablePackageJson , overrides : Overrides ) {
98
100
editablePkgJson . update ( {
101
+ __proto__ : null ,
99
102
[ OVERRIDES_FIELD_NAME ] : overrides
100
103
} )
101
104
} ,
102
105
pnpm ( editablePkgJson : EditablePackageJson , overrides : Overrides ) {
103
106
editablePkgJson . update ( {
104
- [ OVERRIDES_FIELD_NAME ] : overrides
107
+ pnpm : {
108
+ __proto__ : null ,
109
+ ...( < object > editablePkgJson . content [ 'pnpm' ] ) ,
110
+ [ OVERRIDES_FIELD_NAME ] : overrides
111
+ }
105
112
} )
106
113
} ,
107
114
yarn ( editablePkgJson : EditablePackageJson , overrides : PnpmOrYarnOverrides ) {
108
115
editablePkgJson . update ( {
116
+ __proto__ : null ,
109
117
[ RESOLUTIONS_FIELD_NAME ] : overrides
110
118
} )
111
119
}
@@ -119,7 +127,7 @@ type AddOverridesConfig = {
119
127
lockIncludes : LockIncludes
120
128
pkgJsonPath : string
121
129
pkgJsonStr : string
122
- pkgJson : PackageJSONObject
130
+ pkgJson : PackageJsonContent
123
131
overrides ?: Overrides | undefined
124
132
}
125
133
@@ -135,55 +143,77 @@ async function addOverrides(
135
143
isWorkspace,
136
144
lockSrc,
137
145
lockIncludes,
138
- pkgJsonPath,
139
- overrides
146
+ pkgJsonPath
140
147
} : AddOverridesConfig ,
141
148
aoState : AddOverridesState
142
149
) : Promise < AddOverridesState > {
143
150
const { packageNames } = aoState
144
- let addedCount = 0
145
- let clonedOverrides : Overrides | undefined
146
- for ( const name of allPackages ) {
147
- if ( ! hasOwn ( overrides , name ) && lockIncludes ( lockSrc , name ) ) {
148
- if ( clonedOverrides === undefined ) {
149
- clonedOverrides = ( < unknown > {
150
- __proto__ : null ,
151
- ...overrides
152
- } ) as Overrides
151
+ const editablePkgJson = await EditablePackageJson . load (
152
+ path . dirname ( pkgJsonPath )
153
+ )
154
+ const {
155
+ dependencies,
156
+ devDependencies,
157
+ peerDependencies,
158
+ optionalDependencies
159
+ } = editablePkgJson . content
160
+ const depEntries = < [ string , NonNullable < typeof dependencies > ] [ ] > [
161
+ [
162
+ 'dependencies' ,
163
+ dependencies ? { __proto__ : null , ...dependencies } : undefined
164
+ ] ,
165
+ [
166
+ 'devDependencies' ,
167
+ devDependencies ? { __proto__ : null , ...devDependencies } : undefined
168
+ ] ,
169
+ [
170
+ 'peerDependencies' ,
171
+ peerDependencies ? { __proto__ : null , ...peerDependencies } : undefined
172
+ ] ,
173
+ [
174
+ 'optionalDependencies' ,
175
+ optionalDependencies
176
+ ? { __proto__ : null , ...optionalDependencies }
177
+ : undefined
178
+ ]
179
+ ] . filter ( ( { 1 : o } ) => o )
180
+ const overridesDataObjects = < GetOverridesResult [ ] > [
181
+ getOverridesDataByAgent [ 'npm' ] ( editablePkgJson . content )
182
+ ]
183
+ const isApp = isPrivate || isWorkspace
184
+ const overridesData =
185
+ ! isApp || agent !== 'npm'
186
+ ? getOverridesDataByAgent [ isApp ? agent : 'yarn' ] ( editablePkgJson . content )
187
+ : undefined
188
+ if ( overridesData ) {
189
+ overridesDataObjects . push ( overridesData )
190
+ }
191
+ for ( const { 1 : data } of availableOverrides ) {
192
+ const { name : regPkgName , package : origPkgName , version } = data
193
+ for ( const { 1 : depObj } of depEntries ) {
194
+ const pkgSpec = depObj [ origPkgName ]
195
+ if ( pkgSpec ) {
196
+ if ( ! pkgSpec . startsWith ( `npm:${ regPkgName } @` ) ) {
197
+ packageNames . add ( regPkgName )
198
+ depObj [ origPkgName ] = `npm:${ regPkgName } @^${ version } `
199
+ }
153
200
}
154
- addedCount += 1
155
- packageNames . add ( name )
156
- clonedOverrides [ name ] =
157
- `npm:${ SOCKET_REGISTRY_NAME } /${ name } @${ SOCKET_REGISTRY_MAJOR_VERSION } `
158
201
}
159
- }
160
- if ( addedCount ) {
161
- const editablePkgJson = await EditablePackageJson . load (
162
- path . dirname ( pkgJsonPath )
163
- )
164
- const sortedOverrides = toSortedObject ( clonedOverrides ! )
165
- updateManifestByAgent [ agent ] ( editablePkgJson , sortedOverrides )
166
- if ( ! isPrivate && ! isWorkspace ) {
202
+ for ( const { overrides } of overridesDataObjects ) {
167
203
if (
168
- hasOwn ( editablePkgJson . content , 'pnpm' ) &&
169
- isObjectObject ( editablePkgJson . content [ 'pnpm' ] )
204
+ overrides &&
205
+ ! hasOwn ( overrides , origPkgName ) &&
206
+ lockIncludes ( lockSrc , origPkgName )
170
207
) {
171
- const pnpmKeys = Object . keys ( editablePkgJson . content [ 'pnpm' ] )
172
- editablePkgJson . update (
173
- ( < unknown > ( pnpmKeys . length === 1 && pnpmKeys [ 0 ] === 'overrides'
174
- ? // Properties with undefined values are omitted when saved as JSON.
175
- { pnpm : undefined }
176
- : {
177
- pnpm : {
178
- __proto__ : null ,
179
- ...( < object > editablePkgJson . content [ 'pnpm' ] ) ,
180
- overrides : undefined
181
- }
182
- } ) ) as PackageJsonContentType
183
- )
208
+ packageNames . add ( regPkgName )
209
+ overrides [ origPkgName ] = `npm:${ regPkgName } @^${ semver . major ( version ) } `
184
210
}
185
- updateManifestByAgent . npm ( editablePkgJson , sortedOverrides )
186
- updateManifestByAgent . yarn ( editablePkgJson , sortedOverrides )
211
+ }
212
+ }
213
+ if ( packageNames . size ) {
214
+ editablePkgJson . update ( < PackageJsonContent > Object . fromEntries ( depEntries ) )
215
+ for ( const { type, overrides } of overridesDataObjects ) {
216
+ updateManifestByAgent [ type ] ( editablePkgJson , toSortedObject ( overrides ) )
187
217
}
188
218
await editablePkgJson . save ( )
189
219
}
@@ -232,47 +262,24 @@ export const optimize: CliSubcommand = {
232
262
packageNames : new Set ( )
233
263
}
234
264
if ( lockSrc ) {
235
- const configs : {
236
- agent : Agent
237
- lockIncludes : LockIncludes
238
- overrides : Overrides | undefined
239
- } [ ] =
265
+ const lockIncludes =
240
266
agent === 'bun'
241
- ? [
242
- {
243
- agent : 'npm' ,
244
- lockIncludes : lockIncludesByAgent . yarn ,
245
- overrides : getManifestOverridesByAgent . npm ( pkgJson )
246
- } ,
247
- {
248
- agent : 'yarn' ,
249
- lockIncludes : lockIncludesByAgent . yarn ,
250
- overrides : getManifestOverridesByAgent . yarn ( pkgJson )
251
- }
252
- ]
253
- : [
254
- {
255
- agent,
256
- lockIncludes : lockIncludesByAgent [ agent ] ,
257
- overrides : getManifestOverridesByAgent [ agent ] ( pkgJson )
258
- }
259
- ]
260
-
261
- for ( const config of configs ) {
262
- await addOverrides (
263
- < AddOverridesConfig > {
264
- __proto__ : null ,
265
- isPrivate,
266
- isWorkspace,
267
- lockSrc,
268
- pkgJsonPath,
269
- pkgJsonStr,
270
- pkgJson,
271
- ...config
272
- } ,
273
- aoState
274
- )
275
- }
267
+ ? lockIncludesByAgent . yarn
268
+ : lockIncludesByAgent [ agent ]
269
+ await addOverrides (
270
+ < AddOverridesConfig > {
271
+ __proto__ : null ,
272
+ agent : agent === 'bun' ? 'yarn' : agent ,
273
+ isPrivate,
274
+ isWorkspace,
275
+ lockIncludes,
276
+ lockSrc,
277
+ pkgJsonPath,
278
+ pkgJsonStr,
279
+ pkgJson
280
+ } ,
281
+ aoState
282
+ )
276
283
}
277
284
const { size : count } = aoState . packageNames
278
285
if ( count ) {
0 commit comments