-
Notifications
You must be signed in to change notification settings - Fork 800
/
.pnpmfile.cjs
244 lines (220 loc) · 7.93 KB
/
.pnpmfile.cjs
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
/**
* Fix package dependencies.
*
* We could generally do the same with pnpm.overrides in packages.json, but this allows for comments.
*
* @param {object} pkg - Dependency package.json contents.
* @return {object} Modified pkg.
*/
function fixDeps( pkg ) {
// Deps tend to get outdated due to a slow release cycle.
// So change `^` to `>=` and hope any breaking changes will not really break.
if (
pkg.name === '@automattic/social-previews' ||
pkg.name === '@automattic/page-pattern-modal'
) {
for ( const [ dep, ver ] of Object.entries( pkg.dependencies ) ) {
if ( dep.startsWith( '@wordpress/' ) && ver.startsWith( '^' ) ) {
pkg.dependencies[ dep ] = '>=' + ver.substring( 1 );
}
}
}
// Missing dep or peer dep on react.
// https://github.com/WordPress/gutenberg/issues/55171
if (
pkg.name === '@wordpress/icons' &&
! pkg.dependencies?.react &&
! pkg.peerDependencies?.react
) {
pkg.peerDependencies.react = '^18';
}
// Missing dep or peer dep.
// https://github.com/actions/toolkit/issues/1684
if (
pkg.name === '@actions/github' &&
! pkg.dependencies?.undici &&
! pkg.peerDependencies?.undici
) {
pkg.dependencies.undici = '*';
}
// Turn @wordpress/eslint-plugin's eslint plugin deps into peer deps.
// https://github.com/WordPress/gutenberg/issues/39810
if ( pkg.name === '@wordpress/eslint-plugin' ) {
for ( const [ dep, ver ] of Object.entries( pkg.dependencies ) ) {
if (
dep.startsWith( 'eslint-plugin-' ) ||
dep.endsWith( '/eslint-plugin' ) ||
dep.startsWith( 'eslint-config-' ) ||
dep.endsWith( '/eslint-config' ) ||
dep.startsWith( '@typescript-eslint/' )
) {
delete pkg.dependencies[ dep ];
pkg.peerDependencies[ dep ] = ver.replace( /^\^?/, '>=' );
}
}
// Doesn't really need these at all with eslint 9 and our config.
pkg.peerDependenciesMeta ??= {};
pkg.peerDependenciesMeta[ '@typescript-eslint/eslint-plugin' ] = { optional: true };
pkg.peerDependenciesMeta[ '@typescript-eslint/parser' ] = { optional: true };
}
// Unnecessarily explicit deps. I don't think we really even need @wordpress/babel-preset-default at all.
if ( pkg.name === '@wordpress/babel-preset-default' || pkg.name === '@wordpress/eslint-plugin' ) {
for ( const [ dep, ver ] of Object.entries( pkg.dependencies ) ) {
if ( dep.startsWith( '@babel/' ) && ! ver.startsWith( '^' ) && ! ver.startsWith( '>' ) ) {
pkg.dependencies[ dep ] = '^' + ver;
}
}
}
// Update localtunnel axios dep to avoid CVE
// https://github.com/localtunnel/localtunnel/issues/632
if ( pkg.name === 'localtunnel' && pkg.dependencies.axios === '0.21.4' ) {
pkg.dependencies.axios = '^1.6.0';
}
// Avoid annoying flip-flopping of sub-dep peer deps.
// https://github.com/localtunnel/localtunnel/issues/481
if ( pkg.name === 'localtunnel' ) {
for ( const [ dep, ver ] of Object.entries( pkg.dependencies ) ) {
if ( ver.match( /^\d+(\.\d+)+$/ ) ) {
pkg.dependencies[ dep ] = '^' + ver;
}
}
}
// Seemingly unmaintained upstream, and has strict deps that are outdated.
// https://github.com/mbalabash/estimo/issues/50
if ( pkg.name === 'estimo' ) {
for ( const [ dep, ver ] of Object.entries( pkg.dependencies ) ) {
if ( ver.match( /^\d+(\.\d+)+$/ ) ) {
pkg.dependencies[ dep ] = '^' + ver;
}
}
}
// Outdated dependency.
// No upstream bug link yet.
if ( pkg.name === 'rollup-plugin-postcss' && pkg.dependencies.cssnano === '^5.0.1' ) {
pkg.dependencies.cssnano = '^5.0.1 || ^6';
}
// Outdated dependency. And it doesn't really use it in our configuration anyway.
// No upstream bug link yet.
if ( pkg.name === 'rollup-plugin-svelte-svg' && pkg.dependencies.svgo === '^2.3.1' ) {
pkg.dependencies.svgo = '*';
}
// Missing dep or peer dep on @babel/runtime
// https://github.com/zillow/react-slider/issues/296
if (
pkg.name === 'react-slider' &&
! pkg.dependencies?.[ '@babel/runtime' ] &&
! pkg.peerDependencies?.[ '@babel/runtime' ]
) {
pkg.peerDependencies[ '@babel/runtime' ] = '^7';
}
// Apparently this package tried to switch from a dep to a peer dep, but screwed it up.
// The screwed-up-ness makes pnpm 8.15.2 behave differently from earlier versions.
// https://github.com/ajv-validator/ajv-formats/issues/80
if ( pkg.name === 'ajv-formats' && pkg.dependencies?.ajv && pkg.peerDependencies?.ajv ) {
delete pkg.dependencies.ajv;
delete pkg.peerDependenciesMeta?.ajv;
}
// Gutenberg is intending to get rid of this. For now, let's just not upgrade it.
// https://github.com/WordPress/gutenberg/issues/60975
if ( pkg.name === '@wordpress/components' && pkg.dependencies?.[ 'framer-motion' ] ) {
pkg.dependencies[ 'framer-motion' ] += ' <11.5.0';
}
// Types packages have outdated deps. Reset all their `@wordpress/*` deps to star-version,
// which pnpm should 🤞 dedupe to match whatever is in use elsewhere in the monorepo.
// https://github.com/Automattic/jetpack/pull/35904#discussion_r1508681777
if ( pkg.name.startsWith( '@types/wordpress__' ) && pkg.dependencies ) {
for ( const k of Object.keys( pkg.dependencies ) ) {
if ( k.startsWith( '@wordpress/' ) ) {
pkg.dependencies[ k ] = '*';
}
}
}
return pkg;
}
/**
* Fix package peer dependencies.
*
* This can't be done with pnpm.overrides.
*
* @param {object} pkg - Dependency package.json contents.
* @return {object} Modified pkg.
*/
function fixPeerDeps( pkg ) {
// Indirect deps that still depend on React <18.
const reactOldPkgs = new Set( [
// Still on 16.
'react-autosize-textarea', // @wordpress/block-editor <https://github.com/WordPress/gutenberg/issues/39619>
] );
if ( reactOldPkgs.has( pkg.name ) ) {
for ( const p of [ 'react', 'react-dom' ] ) {
if ( ! pkg.peerDependencies?.[ p ] ) {
continue;
}
if (
pkg.peerDependencies[ p ].match( /(?:^|\|\|\s*)(?:\^16|16\.x)/ ) &&
! pkg.peerDependencies[ p ].match( /(?:^|\|\|\s*)(?:\^17|17\.x)/ )
) {
pkg.peerDependencies[ p ] += ' || ^17';
}
if (
pkg.peerDependencies[ p ].match( /(?:^|\|\|\s*)(?:\^17|17\.x)/ ) &&
! pkg.peerDependencies[ p ].match( /(?:^|\|\|\s*)(?:\^18|18\.x)/ )
) {
pkg.peerDependencies[ p ] += ' || ^18';
}
}
}
// It assumes hoisting to find its plugins. Sigh. Add peer deps for the plugins we use.
// https://github.com/ai/size-limit/issues/366
if ( pkg.name === 'size-limit' ) {
pkg.peerDependencies ??= {};
pkg.peerDependencies[ '@size-limit/preset-app' ] = '*';
pkg.peerDependenciesMeta ??= {};
pkg.peerDependenciesMeta[ '@size-limit/preset-app' ] = { optional: true };
}
return pkg;
}
/**
* Pnpm package hook.
*
* @see https://pnpm.io/pnpmfile#hooksreadpackagepkg-context-pkg--promisepkg
* @param {object} pkg - Dependency package.json contents.
* @param {object} context - Pnpm object of some sort.
* @return {object} Modified pkg.
*/
function readPackage( pkg, context ) {
if ( pkg.name ) {
pkg = fixDeps( pkg, context );
pkg = fixPeerDeps( pkg, context );
}
return pkg;
}
/**
* Pnpm lockfile hook.
*
* @see https://pnpm.io/pnpmfile#hooksafterallresolvedlockfile-context-lockfile--promiselockfile
* @param {object} lockfile - Lockfile data.
* @return {object} Modified lockfile.
*/
function afterAllResolved( lockfile ) {
// If there's only one "importer", it's probably pnpx rather than the monorepo. Don't interfere.
if ( Object.keys( lockfile.importers ).length === 1 ) {
return lockfile;
}
for ( const [ k, v ] of Object.entries( lockfile.packages ) ) {
// Forbid installing webpack without webpack-cli. It results in lots of spurious lockfile changes.
// https://github.com/pnpm/pnpm/issues/3935
if ( k.startsWith( 'webpack@' ) && ! v.optionalDependencies?.[ 'webpack-cli' ] ) {
throw new Error(
"Something you've done is trying to add a dependency on webpack without webpack-cli.\nThis is not allowed, as it tends to result in pnpm lockfile flip-flopping.\nSee https://github.com/pnpm/pnpm/issues/3935 for the upstream bug report.\n"
);
}
}
return lockfile;
}
module.exports = {
hooks: {
readPackage,
afterAllResolved,
},
};