@@ -14,6 +14,12 @@ import semver from "semver"
14
14
import { readPatch } from "./patch/read"
15
15
import { packageIsDevDependency } from "./packageIsDevDependency"
16
16
17
+ class PatchApplicationError extends Error {
18
+ constructor ( msg : string ) {
19
+ super ( msg )
20
+ }
21
+ }
22
+
17
23
// don't want to exit(1) on postinsall locally.
18
24
// see https://github.com/ds300/patch-package/issues/86
19
25
const shouldExitPostinstallWithError = isCi || process . env . NODE_ENV === "test"
@@ -46,39 +52,35 @@ function getInstalledPackageVersion({
46
52
if ( process . env . NODE_ENV === "production" && isDevOnly ) {
47
53
return null
48
54
}
49
- console . error (
55
+
56
+ let err =
50
57
`${ chalk . red ( "Error:" ) } Patch file found for package ${ posix . basename (
51
58
pathSpecifier ,
52
- ) } ` + ` which is not present at ${ relative ( "." , packageDir ) } ` ,
53
- )
59
+ ) } ` + ` which is not present at ${ relative ( "." , packageDir ) } `
54
60
55
61
if ( ! isDevOnly && process . env . NODE_ENV === "production" ) {
56
- console . error (
57
- `
62
+ err += `
63
+
58
64
If this package is a dev dependency, rename the patch file to
59
65
60
66
${ chalk . bold ( patchFilename . replace ( ".patch" , ".dev.patch" ) ) }
61
- ` ,
62
- )
67
+ `
63
68
}
64
-
65
- throw new Error ( "applyPatches" )
69
+ throw new PatchApplicationError ( err )
66
70
}
67
71
68
72
const { version } = require ( join ( packageDir , "package.json" ) )
69
73
// normalize version for `npm ci`
70
74
const result = semver . valid ( version )
71
75
if ( result === null ) {
72
- console . error (
76
+ throw new PatchApplicationError (
73
77
`${ chalk . red (
74
78
"Error:" ,
75
79
) } Version string '${ version } ' cannot be parsed from ${ join (
76
80
packageDir ,
77
81
"package.json" ,
78
82
) } `,
79
83
)
80
-
81
- throw new Error ( "applyPatches" )
82
84
}
83
85
84
86
return result as string
@@ -87,12 +89,10 @@ function getInstalledPackageVersion({
87
89
export function applyPatchesForApp ( {
88
90
appPath,
89
91
reverse,
90
- ignoreErrors,
91
92
patchDir,
92
93
} : {
93
94
appPath : string
94
95
reverse : boolean
95
- ignoreErrors : boolean
96
96
patchDir : string
97
97
} ) : void {
98
98
const patchesDirectory = join ( appPath , patchDir )
@@ -103,14 +103,18 @@ export function applyPatchesForApp({
103
103
return
104
104
}
105
105
106
- let hasFailed = false
107
- files . forEach ( ( filename , idx ) => {
106
+ const errors : string [ ] = [ ]
107
+ const warnings : string [ ] = [ ]
108
+
109
+ for ( const filename of files ) {
108
110
try {
109
111
const packageDetails = getPackageDetailsFromPatchFilename ( filename )
110
112
111
113
if ( ! packageDetails ) {
112
- console . warn ( `Unrecognized patch file in patches directory ${ filename } ` )
113
- return
114
+ warnings . push (
115
+ `Unrecognized patch file in patches directory ${ filename } ` ,
116
+ )
117
+ continue
114
118
}
115
119
116
120
const {
@@ -140,7 +144,7 @@ export function applyPatchesForApp({
140
144
pathSpecifier ,
141
145
) } @${ version } ${ chalk . blue ( "✔" ) } `,
142
146
)
143
- return
147
+ continue
144
148
}
145
149
146
150
if (
@@ -154,59 +158,76 @@ export function applyPatchesForApp({
154
158
// yay patch was applied successfully
155
159
// print warning if version mismatch
156
160
if ( installedPackageVersion !== version ) {
157
- printVersionMismatchWarning ( {
158
- packageName : name ,
159
- actualVersion : installedPackageVersion ,
160
- originalVersion : version ,
161
- pathSpecifier,
162
- path,
163
- } )
161
+ warnings . push (
162
+ createVersionMismatchWarning ( {
163
+ packageName : name ,
164
+ actualVersion : installedPackageVersion ,
165
+ originalVersion : version ,
166
+ pathSpecifier,
167
+ path,
168
+ } ) ,
169
+ )
164
170
} else {
165
171
console . log (
166
172
`${ chalk . bold ( pathSpecifier ) } @${ version } ${ chalk . green ( "✔" ) } ` ,
167
173
)
168
174
}
169
- } else {
175
+ } else if ( installedPackageVersion === version ) {
170
176
// completely failed to apply patch
171
177
// TODO: propagate useful error messages from patch application
172
- if ( installedPackageVersion === version ) {
173
- printBrokenPatchFileError ( {
178
+ errors . push (
179
+ createBrokenPatchFileError ( {
174
180
packageName : name ,
175
181
patchFileName : filename ,
176
182
pathSpecifier,
177
183
path,
178
- } )
179
- } else {
180
- printPatchApplictionFailureError ( {
184
+ } ) ,
185
+ )
186
+ } else {
187
+ errors . push (
188
+ createPatchApplictionFailureError ( {
181
189
packageName : name ,
182
190
actualVersion : installedPackageVersion ,
183
191
originalVersion : version ,
184
192
patchFileName : filename ,
185
193
path,
186
194
pathSpecifier,
187
- } )
188
- }
189
-
190
- throw new Error ( "applyPatches" )
191
- }
192
- } catch ( err ) {
193
- if ( err . message !== "applyPatches" ) {
194
- throw err
195
- }
196
- if ( ! ignoreErrors ) {
197
- exit ( )
198
- }
199
- hasFailed = true
200
- if ( idx < files . length - 1 ) {
201
- console . warn (
202
- `${ chalk . yellow ( "Warning:" ) } Option ${ chalk . bold (
203
- "--ignore-errors" ,
204
- ) } was set, moving on to next patch.`,
195
+ } ) ,
205
196
)
206
197
}
198
+ } catch ( error ) {
199
+ if ( error instanceof PatchApplicationError ) {
200
+ errors . push ( error . message )
201
+ } else {
202
+ errors . push ( createUnexpectedError ( { filename, error } ) )
203
+ }
207
204
}
208
- } )
209
- if ( hasFailed ) {
205
+ }
206
+
207
+ for ( const warning of warnings ) {
208
+ console . warn ( warning )
209
+ }
210
+ for ( const error of errors ) {
211
+ console . error ( error )
212
+ }
213
+
214
+ const problemsSummary = [ ]
215
+ if ( warnings . length ) {
216
+ problemsSummary . push ( chalk . yellow ( `${ warnings . length } warning(s)` ) )
217
+ }
218
+ if ( errors . length ) {
219
+ problemsSummary . push ( chalk . red ( `${ errors . length } error(s)` ) )
220
+ }
221
+
222
+ if ( problemsSummary . length ) {
223
+ console . error ( "---" )
224
+ console . error (
225
+ "patch-package finished with" ,
226
+ problemsSummary . join ( ", " ) + "." ,
227
+ )
228
+ }
229
+
230
+ if ( errors . length ) {
210
231
exit ( )
211
232
}
212
233
}
@@ -236,7 +257,7 @@ export function applyPatch({
236
257
return true
237
258
}
238
259
239
- function printVersionMismatchWarning ( {
260
+ function createVersionMismatchWarning ( {
240
261
packageName,
241
262
actualVersion,
242
263
originalVersion,
@@ -249,8 +270,8 @@ function printVersionMismatchWarning({
249
270
pathSpecifier : string
250
271
path : string
251
272
} ) {
252
- console . warn ( `
253
- ${ chalk . red ( "Warning:" ) } patch-package detected a patch file version mismatch
273
+ return `
274
+ ${ chalk . yellow ( "Warning:" ) } patch-package detected a patch file version mismatch
254
275
255
276
Don't worry! This is probably fine. The patch was still applied
256
277
successfully. Here's the deets:
@@ -274,10 +295,10 @@ ${chalk.red("Warning:")} patch-package detected a patch file version mismatch
274
295
${ chalk . bold ( `patch-package ${ pathSpecifier } ` ) }
275
296
276
297
to update the version in the patch file name and make this warning go away.
277
- ` )
298
+ `
278
299
}
279
300
280
- function printBrokenPatchFileError ( {
301
+ function createBrokenPatchFileError ( {
281
302
packageName,
282
303
patchFileName,
283
304
path,
@@ -288,7 +309,7 @@ function printBrokenPatchFileError({
288
309
path : string
289
310
pathSpecifier : string
290
311
} ) {
291
- console . error ( `
312
+ return `
292
313
${ chalk . red . bold ( "**ERROR**" ) } ${ chalk . red (
293
314
`Failed to apply patch for package ${ chalk . bold ( packageName ) } at path` ,
294
315
) }
@@ -310,10 +331,10 @@ ${chalk.red.bold("**ERROR**")} ${chalk.red(
310
331
311
332
https://github.com/ds300/patch-package/issues
312
333
313
- ` )
334
+ `
314
335
}
315
336
316
- function printPatchApplictionFailureError ( {
337
+ function createPatchApplictionFailureError ( {
317
338
packageName,
318
339
actualVersion,
319
340
originalVersion,
@@ -328,7 +349,7 @@ function printPatchApplictionFailureError({
328
349
path : string
329
350
pathSpecifier : string
330
351
} ) {
331
- console . error ( `
352
+ return `
332
353
${ chalk . red . bold ( "**ERROR**" ) } ${ chalk . red (
333
354
`Failed to apply patch for package ${ chalk . bold ( packageName ) } at path` ,
334
355
) }
@@ -356,5 +377,22 @@ ${chalk.red.bold("**ERROR**")} ${chalk.red(
356
377
Patch file: patches/${ patchFileName }
357
378
Patch was made for version: ${ chalk . green . bold ( originalVersion ) }
358
379
Installed version: ${ chalk . red . bold ( actualVersion ) }
359
- ` )
380
+ `
381
+ }
382
+
383
+ function createUnexpectedError ( {
384
+ filename,
385
+ error,
386
+ } : {
387
+ filename : string
388
+ error : Error
389
+ } ) {
390
+ return `
391
+ ${ chalk . red . bold ( "**ERROR**" ) } ${ chalk . red (
392
+ `Failed to apply patch file ${ chalk . bold ( filename ) } ` ,
393
+ ) }
394
+
395
+ ${ error . stack }
396
+
397
+ `
360
398
}
0 commit comments