@devp0nt/error0 1.0.0-next.43 → 1.0.0-next.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.cjs +197 -19
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +75 -12
- package/dist/esm/index.d.ts +75 -12
- package/dist/esm/index.js +197 -19
- package/dist/esm/index.js.map +1 -1
- package/package.json +1 -1
- package/src/index.test.ts +247 -12
- package/src/index.ts +327 -36
package/src/index.ts
CHANGED
|
@@ -20,7 +20,7 @@ type ErrorPluginPropDeserialize<TOutputValue> =
|
|
|
20
20
|
| false
|
|
21
21
|
type ErrorPluginPropOptionsBase<TOutputValue, TError extends Error0, TResolveValue extends TOutputValue | undefined> = {
|
|
22
22
|
resolve: (options: {
|
|
23
|
-
|
|
23
|
+
own: TOutputValue | undefined
|
|
24
24
|
flow: Array<TOutputValue | undefined>
|
|
25
25
|
error: TError
|
|
26
26
|
}) => TResolveValue
|
|
@@ -59,6 +59,15 @@ export type ErrorPluginAdaptFn<
|
|
|
59
59
|
TError extends Error0 = Error0,
|
|
60
60
|
TOutputProps extends Record<string, unknown> = Record<never, never>,
|
|
61
61
|
> = ((error: TError) => void) | ((error: TError) => ErrorPluginAdaptResult<TOutputProps>)
|
|
62
|
+
export type ErrorPluginStackSerialize<TError extends Error0> =
|
|
63
|
+
| ((options: { value: string | undefined; error: TError; isPublic: boolean }) => unknown)
|
|
64
|
+
| boolean
|
|
65
|
+
| 'merge'
|
|
66
|
+
export type ErrorPluginStack<TError extends Error0 = Error0> = ErrorPluginStackSerialize<TError>
|
|
67
|
+
export type ErrorPluginCauseSerialize<TError extends Error0> =
|
|
68
|
+
| ((options: { value: unknown; error: TError; isPublic: boolean }) => unknown)
|
|
69
|
+
| boolean
|
|
70
|
+
export type ErrorPluginCause<TError extends Error0 = Error0> = ErrorPluginCauseSerialize<TError>
|
|
62
71
|
type ErrorMethodRecord = {
|
|
63
72
|
args: unknown[]
|
|
64
73
|
output: unknown
|
|
@@ -74,6 +83,8 @@ export type ErrorPlugin<
|
|
|
74
83
|
props?: TProps
|
|
75
84
|
methods?: TMethods
|
|
76
85
|
adapt?: Array<ErrorPluginAdaptFn<Error0, PluginOutputProps<TProps>>>
|
|
86
|
+
stack?: ErrorPluginStack
|
|
87
|
+
cause?: ErrorPluginCause
|
|
77
88
|
}
|
|
78
89
|
type AddPropToPluginProps<
|
|
79
90
|
TProps extends ErrorPluginProps,
|
|
@@ -94,7 +105,7 @@ type PluginOutputProps<TProps extends ErrorPluginProps> = {
|
|
|
94
105
|
: never
|
|
95
106
|
}
|
|
96
107
|
export type ErrorPluginsMap = {
|
|
97
|
-
props: Record<string, { init: unknown; resolve: unknown }>
|
|
108
|
+
props: Record<string, { init: unknown; output: unknown; resolve: unknown }>
|
|
98
109
|
methods: Record<string, ErrorMethodRecord>
|
|
99
110
|
}
|
|
100
111
|
export type IsEmptyObject<T> = keyof T extends never ? true : false
|
|
@@ -114,6 +125,19 @@ export type ErrorInput<TPluginsMap extends ErrorPluginsMap> =
|
|
|
114
125
|
type ErrorResolvedProps<TPluginsMap extends ErrorPluginsMap> = {
|
|
115
126
|
[TKey in keyof TPluginsMap['props']]: TPluginsMap['props'][TKey]['resolve']
|
|
116
127
|
}
|
|
128
|
+
type ErrorOwnProps<TPluginsMap extends ErrorPluginsMap> = {
|
|
129
|
+
[TKey in keyof TPluginsMap['props']]: TPluginsMap['props'][TKey]['output'] | undefined
|
|
130
|
+
}
|
|
131
|
+
type ErrorOwnMethods<TPluginsMap extends ErrorPluginsMap> = {
|
|
132
|
+
own: {
|
|
133
|
+
(): ErrorOwnProps<TPluginsMap>
|
|
134
|
+
<TKey extends keyof TPluginsMap['props'] & string>(key: TKey): ErrorOwnProps<TPluginsMap>[TKey]
|
|
135
|
+
}
|
|
136
|
+
flow: <TKey extends keyof TPluginsMap['props'] & string>(key: TKey) => Array<ErrorOwnProps<TPluginsMap>[TKey]>
|
|
137
|
+
}
|
|
138
|
+
type ErrorResolveMethods<TPluginsMap extends ErrorPluginsMap> = {
|
|
139
|
+
resolve: () => ErrorResolvedProps<TPluginsMap>
|
|
140
|
+
}
|
|
117
141
|
type ErrorMethods<TPluginsMap extends ErrorPluginsMap> = {
|
|
118
142
|
[TKey in keyof TPluginsMap['methods']]: TPluginsMap['methods'][TKey] extends {
|
|
119
143
|
args: infer TArgs extends unknown[]
|
|
@@ -135,7 +159,7 @@ type ErrorStaticMethods<TPluginsMap extends ErrorPluginsMap> = {
|
|
|
135
159
|
}
|
|
136
160
|
|
|
137
161
|
type EmptyPluginsMap = {
|
|
138
|
-
props: Record<never, { init: never; resolve: never }>
|
|
162
|
+
props: Record<never, { init: never; output: never; resolve: never }>
|
|
139
163
|
methods: Record<never, ErrorMethodRecord>
|
|
140
164
|
}
|
|
141
165
|
|
|
@@ -143,16 +167,23 @@ type ErrorPluginResolved = {
|
|
|
143
167
|
props: Record<string, ErrorPluginPropOptions<unknown>>
|
|
144
168
|
methods: Record<string, ErrorPluginMethodFn<unknown>>
|
|
145
169
|
adapt: Array<ErrorPluginAdaptFn<Error0, Record<string, unknown>>>
|
|
170
|
+
stack?: ErrorPluginStack
|
|
171
|
+
cause?: ErrorPluginCause
|
|
146
172
|
}
|
|
173
|
+
const RESERVED_STACK_PROP_ERROR = 'Error0: "stack" is a reserved prop key. Use .stack(...) plugin API instead'
|
|
147
174
|
|
|
148
175
|
type PluginPropsMapOf<TPlugin extends ErrorPlugin> = {
|
|
149
176
|
[TKey in keyof NonNullable<TPlugin['props']>]: NonNullable<TPlugin['props']>[TKey] extends ErrorPluginPropOptions<
|
|
150
177
|
any,
|
|
151
|
-
|
|
178
|
+
infer TOutputValue,
|
|
152
179
|
any,
|
|
153
180
|
infer TResolveValue
|
|
154
181
|
>
|
|
155
|
-
? {
|
|
182
|
+
? {
|
|
183
|
+
init: InferPluginPropInput<NonNullable<TPlugin['props']>[TKey]>
|
|
184
|
+
output: TOutputValue
|
|
185
|
+
resolve: TResolveValue
|
|
186
|
+
}
|
|
156
187
|
: never
|
|
157
188
|
}
|
|
158
189
|
type PluginMethodsMapOf<TPlugin extends ErrorPlugin> = {
|
|
@@ -196,6 +227,11 @@ type PluginsMapOf<TClass> = TClass extends { __pluginsMap?: infer TPluginsMap }
|
|
|
196
227
|
? TPluginsMap
|
|
197
228
|
: EmptyPluginsMap
|
|
198
229
|
: EmptyPluginsMap
|
|
230
|
+
type PluginsMapOfInstance<TInstance> = TInstance extends { constructor: { __pluginsMap?: infer TPluginsMap } }
|
|
231
|
+
? TPluginsMap extends ErrorPluginsMap
|
|
232
|
+
? TPluginsMap
|
|
233
|
+
: EmptyPluginsMap
|
|
234
|
+
: EmptyPluginsMap
|
|
199
235
|
|
|
200
236
|
type PluginsMapFromParts<
|
|
201
237
|
TProps extends ErrorPluginProps,
|
|
@@ -224,6 +260,8 @@ export class PluginError0<
|
|
|
224
260
|
props: { ...(plugin?.props ?? {}) },
|
|
225
261
|
methods: { ...(plugin?.methods ?? {}) },
|
|
226
262
|
adapt: [...(plugin?.adapt ?? [])],
|
|
263
|
+
stack: plugin?.stack,
|
|
264
|
+
cause: plugin?.cause,
|
|
227
265
|
}
|
|
228
266
|
}
|
|
229
267
|
|
|
@@ -252,6 +290,14 @@ export class PluginError0<
|
|
|
252
290
|
return this.use('adapt', value)
|
|
253
291
|
}
|
|
254
292
|
|
|
293
|
+
stack(value: ErrorPluginStack<BuilderError0<TProps, TMethods>>): PluginError0<TProps, TMethods> {
|
|
294
|
+
return this.use('stack', value)
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
cause(value: ErrorPluginCause<BuilderError0<TProps, TMethods>>): PluginError0<TProps, TMethods> {
|
|
298
|
+
return this.use('cause', value)
|
|
299
|
+
}
|
|
300
|
+
|
|
255
301
|
use<
|
|
256
302
|
TKey extends string,
|
|
257
303
|
TInputValue = undefined,
|
|
@@ -271,16 +317,23 @@ export class PluginError0<
|
|
|
271
317
|
kind: 'adapt',
|
|
272
318
|
value: ErrorPluginAdaptFn<BuilderError0<TProps, TMethods>, PluginOutputProps<TProps>>,
|
|
273
319
|
): PluginError0<TProps, TMethods>
|
|
320
|
+
use(kind: 'stack', value: ErrorPluginStack<BuilderError0<TProps, TMethods>>): PluginError0<TProps, TMethods>
|
|
321
|
+
use(kind: 'cause', value: ErrorPluginCause<BuilderError0<TProps, TMethods>>): PluginError0<TProps, TMethods>
|
|
274
322
|
use(
|
|
275
|
-
kind: 'prop' | 'method' | 'adapt',
|
|
276
|
-
keyOrValue:
|
|
323
|
+
kind: 'prop' | 'method' | 'adapt' | 'stack' | 'cause',
|
|
324
|
+
keyOrValue: unknown,
|
|
277
325
|
value?: ErrorPluginPropOptions<unknown, unknown, any> | ErrorPluginMethodFn<unknown, unknown[], any>,
|
|
278
326
|
): PluginError0<any, any> {
|
|
279
327
|
const nextProps: ErrorPluginProps = { ...(this._plugin.props ?? {}) }
|
|
280
328
|
const nextMethods: ErrorPluginMethods = { ...(this._plugin.methods ?? {}) }
|
|
281
329
|
const nextAdapt: Array<ErrorPluginAdaptFn<Error0, Record<string, unknown>>> = [...(this._plugin.adapt ?? [])]
|
|
330
|
+
let nextStack: ErrorPluginStack | undefined = this._plugin.stack
|
|
331
|
+
let nextCause: ErrorPluginCause | undefined = this._plugin.cause
|
|
282
332
|
if (kind === 'prop') {
|
|
283
333
|
const key = keyOrValue as string
|
|
334
|
+
if (key === 'stack') {
|
|
335
|
+
throw new Error(RESERVED_STACK_PROP_ERROR)
|
|
336
|
+
}
|
|
284
337
|
if (value === undefined) {
|
|
285
338
|
throw new Error('PluginError0.use("prop", key, value) requires value')
|
|
286
339
|
}
|
|
@@ -291,23 +344,45 @@ export class PluginError0<
|
|
|
291
344
|
throw new Error('PluginError0.use("method", key, value) requires value')
|
|
292
345
|
}
|
|
293
346
|
nextMethods[key] = value as ErrorPluginMethodFn<any, any[]>
|
|
294
|
-
} else {
|
|
347
|
+
} else if (kind === 'adapt') {
|
|
295
348
|
nextAdapt.push(keyOrValue as ErrorPluginAdaptFn<Error0, Record<string, unknown>>)
|
|
349
|
+
} else if (kind === 'stack') {
|
|
350
|
+
nextStack = keyOrValue as ErrorPluginStack
|
|
351
|
+
} else {
|
|
352
|
+
nextCause = keyOrValue as ErrorPluginCause
|
|
296
353
|
}
|
|
297
354
|
return new PluginError0({
|
|
298
355
|
props: nextProps,
|
|
299
356
|
methods: nextMethods,
|
|
300
357
|
adapt: nextAdapt,
|
|
358
|
+
stack: nextStack,
|
|
359
|
+
cause: nextCause,
|
|
301
360
|
})
|
|
302
361
|
}
|
|
303
362
|
}
|
|
304
363
|
|
|
305
364
|
export type ClassError0<TPluginsMap extends ErrorPluginsMap = EmptyPluginsMap> = {
|
|
306
|
-
new (
|
|
307
|
-
|
|
365
|
+
new (
|
|
366
|
+
message: string,
|
|
367
|
+
input?: ErrorInput<TPluginsMap>,
|
|
368
|
+
): Error0 & ErrorResolved<TPluginsMap> & ErrorOwnMethods<TPluginsMap> & ErrorResolveMethods<TPluginsMap>
|
|
369
|
+
new (
|
|
370
|
+
input: { message: string } & ErrorInput<TPluginsMap>,
|
|
371
|
+
): Error0 & ErrorResolved<TPluginsMap> & ErrorOwnMethods<TPluginsMap> & ErrorResolveMethods<TPluginsMap>
|
|
308
372
|
readonly __pluginsMap?: TPluginsMap
|
|
309
|
-
from: (
|
|
373
|
+
from: (
|
|
374
|
+
error: unknown,
|
|
375
|
+
) => Error0 & ErrorResolved<TPluginsMap> & ErrorOwnMethods<TPluginsMap> & ErrorResolveMethods<TPluginsMap>
|
|
376
|
+
resolve: (error: unknown) => ErrorResolvedProps<TPluginsMap>
|
|
310
377
|
serialize: (error: unknown, isPublic?: boolean) => Record<string, unknown>
|
|
378
|
+
own: {
|
|
379
|
+
(error: object): ErrorOwnProps<TPluginsMap>
|
|
380
|
+
<TKey extends keyof TPluginsMap['props'] & string>(error: object, key: TKey): ErrorOwnProps<TPluginsMap>[TKey]
|
|
381
|
+
}
|
|
382
|
+
flow: <TKey extends keyof TPluginsMap['props'] & string>(
|
|
383
|
+
error: object,
|
|
384
|
+
key: TKey,
|
|
385
|
+
) => Array<ErrorOwnProps<TPluginsMap>[TKey]>
|
|
311
386
|
prop: <
|
|
312
387
|
TKey extends string,
|
|
313
388
|
TInputValue = undefined,
|
|
@@ -324,6 +399,8 @@ export type ClassError0<TPluginsMap extends ErrorPluginsMap = EmptyPluginsMap> =
|
|
|
324
399
|
adapt: (
|
|
325
400
|
value: ErrorPluginAdaptFn<ErrorInstanceOfMap<TPluginsMap>, ErrorResolvedProps<TPluginsMap>>,
|
|
326
401
|
) => ClassError0<TPluginsMap>
|
|
402
|
+
stack: (value: ErrorPluginStack<ErrorInstanceOfMap<TPluginsMap>>) => ClassError0<TPluginsMap>
|
|
403
|
+
cause: (value: ErrorPluginCause<ErrorInstanceOfMap<TPluginsMap>>) => ClassError0<TPluginsMap>
|
|
327
404
|
use: {
|
|
328
405
|
<TBuilder extends PluginError0>(
|
|
329
406
|
plugin: TBuilder,
|
|
@@ -347,6 +424,8 @@ export type ClassError0<TPluginsMap extends ErrorPluginsMap = EmptyPluginsMap> =
|
|
|
347
424
|
kind: 'adapt',
|
|
348
425
|
value: ErrorPluginAdaptFn<ErrorInstanceOfMap<TPluginsMap>, ErrorResolvedProps<TPluginsMap>>,
|
|
349
426
|
): ClassError0<TPluginsMap>
|
|
427
|
+
(kind: 'stack', value: ErrorPluginStack<ErrorInstanceOfMap<TPluginsMap>>): ClassError0<TPluginsMap>
|
|
428
|
+
(kind: 'cause', value: ErrorPluginCause<ErrorInstanceOfMap<TPluginsMap>>): ClassError0<TPluginsMap>
|
|
350
429
|
}
|
|
351
430
|
plugin: () => PluginError0
|
|
352
431
|
} & ErrorStaticMethods<TPluginsMap>
|
|
@@ -359,6 +438,8 @@ export class Error0 extends Error {
|
|
|
359
438
|
props: {},
|
|
360
439
|
methods: {},
|
|
361
440
|
adapt: [],
|
|
441
|
+
stack: undefined,
|
|
442
|
+
cause: undefined,
|
|
362
443
|
}
|
|
363
444
|
|
|
364
445
|
private static _getResolvedPlugin(this: typeof Error0): ErrorPluginResolved {
|
|
@@ -368,9 +449,18 @@ export class Error0 extends Error {
|
|
|
368
449
|
adapt: [],
|
|
369
450
|
}
|
|
370
451
|
for (const plugin of this._plugins) {
|
|
452
|
+
if (plugin.props && 'stack' in plugin.props) {
|
|
453
|
+
throw new Error(RESERVED_STACK_PROP_ERROR)
|
|
454
|
+
}
|
|
371
455
|
Object.assign(resolved.props, plugin.props ?? this._emptyPlugin.props)
|
|
372
456
|
Object.assign(resolved.methods, plugin.methods ?? this._emptyPlugin.methods)
|
|
373
457
|
resolved.adapt.push(...(plugin.adapt ?? this._emptyPlugin.adapt))
|
|
458
|
+
if (typeof plugin.stack !== 'undefined') {
|
|
459
|
+
resolved.stack = plugin.stack
|
|
460
|
+
}
|
|
461
|
+
if (typeof plugin.cause !== 'undefined') {
|
|
462
|
+
resolved.cause = plugin.cause
|
|
463
|
+
}
|
|
374
464
|
}
|
|
375
465
|
return resolved
|
|
376
466
|
}
|
|
@@ -392,6 +482,9 @@ export class Error0 extends Error {
|
|
|
392
482
|
const plugin = ctor._getResolvedPlugin()
|
|
393
483
|
|
|
394
484
|
for (const [key, prop] of Object.entries(plugin.props)) {
|
|
485
|
+
if (key === 'stack') {
|
|
486
|
+
continue
|
|
487
|
+
}
|
|
395
488
|
if (key in input) {
|
|
396
489
|
const ownValue = (input as Record<string, unknown>)[key]
|
|
397
490
|
if (typeof prop.init === 'function') {
|
|
@@ -401,7 +494,7 @@ export class Error0 extends Error {
|
|
|
401
494
|
}
|
|
402
495
|
} else {
|
|
403
496
|
Object.defineProperty(this, key, {
|
|
404
|
-
get: () => prop.resolve({
|
|
497
|
+
get: () => prop.resolve({ own: undefined, flow: this.flow(key), error: this }),
|
|
405
498
|
set: (value) => {
|
|
406
499
|
Object.defineProperty(this, key, {
|
|
407
500
|
value,
|
|
@@ -429,26 +522,105 @@ export class Error0 extends Error {
|
|
|
429
522
|
}
|
|
430
523
|
return true
|
|
431
524
|
}
|
|
432
|
-
|
|
433
|
-
static own(error: object, key: string): unknown {
|
|
525
|
+
private static _ownByKey(error: object, key: string): unknown {
|
|
434
526
|
if (this.isSelfProperty(error, key)) {
|
|
435
527
|
return (error as Record<string, unknown>)[key]
|
|
436
528
|
}
|
|
437
529
|
return undefined
|
|
438
530
|
}
|
|
439
|
-
|
|
531
|
+
private static _flowByKey(error: object, key: string): unknown[] {
|
|
532
|
+
return this.causes(error, true).map((cause) => {
|
|
533
|
+
return this._ownByKey(cause, key)
|
|
534
|
+
})
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
static own<TThis extends typeof Error0>(this: TThis, error: unknown): ErrorOwnProps<PluginsMapOf<TThis>>
|
|
538
|
+
static own<TThis extends typeof Error0, TKey extends keyof PluginsMapOf<TThis>['props'] & string>(
|
|
539
|
+
this: TThis,
|
|
540
|
+
error: unknown,
|
|
541
|
+
key: TKey,
|
|
542
|
+
): ErrorOwnProps<PluginsMapOf<TThis>>[TKey]
|
|
543
|
+
static own(error: unknown, key?: string): unknown {
|
|
544
|
+
const error0 = this.from(error)
|
|
545
|
+
if (key === undefined) {
|
|
546
|
+
const ownValues: Record<string, unknown> = {}
|
|
547
|
+
const plugin = this._getResolvedPlugin()
|
|
548
|
+
for (const ownKey of Object.keys(plugin.props)) {
|
|
549
|
+
ownValues[ownKey] = this._ownByKey(error0, ownKey)
|
|
550
|
+
}
|
|
551
|
+
return ownValues
|
|
552
|
+
}
|
|
553
|
+
return this._ownByKey(error0, key)
|
|
554
|
+
}
|
|
555
|
+
own<TThis extends Error0>(this: TThis): ErrorOwnProps<PluginsMapOfInstance<TThis>>
|
|
556
|
+
own<TThis extends Error0, TKey extends keyof PluginsMapOfInstance<TThis>['props'] & string>(
|
|
557
|
+
this: TThis,
|
|
558
|
+
key: TKey,
|
|
559
|
+
): ErrorOwnProps<PluginsMapOfInstance<TThis>>[TKey]
|
|
560
|
+
own(key?: string): unknown {
|
|
440
561
|
const ctor = this.constructor as typeof Error0
|
|
441
|
-
|
|
562
|
+
if (key === undefined) {
|
|
563
|
+
return ctor.own(this)
|
|
564
|
+
}
|
|
565
|
+
return ctor._ownByKey(this, key)
|
|
442
566
|
}
|
|
443
567
|
|
|
444
|
-
static flow
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
568
|
+
static flow<TThis extends typeof Error0, TKey extends keyof PluginsMapOf<TThis>['props'] & string>(
|
|
569
|
+
this: TThis,
|
|
570
|
+
error: unknown,
|
|
571
|
+
key: TKey,
|
|
572
|
+
): Array<ErrorOwnProps<PluginsMapOf<TThis>>[TKey]>
|
|
573
|
+
static flow(error: unknown, key: string): unknown[]
|
|
574
|
+
static flow(error: unknown, key: string): unknown[] {
|
|
575
|
+
const error0 = this.from(error)
|
|
576
|
+
return this._flowByKey(error0, key)
|
|
448
577
|
}
|
|
578
|
+
flow<TThis extends Error0, TKey extends keyof PluginsMapOfInstance<TThis>['props'] & string>(
|
|
579
|
+
this: TThis,
|
|
580
|
+
key: TKey,
|
|
581
|
+
): Array<ErrorOwnProps<PluginsMapOfInstance<TThis>>[TKey]>
|
|
582
|
+
flow(key: string): unknown[]
|
|
449
583
|
flow(key: string): unknown[] {
|
|
450
584
|
const ctor = this.constructor as typeof Error0
|
|
451
|
-
return ctor.
|
|
585
|
+
return ctor._flowByKey(this, key)
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
static resolve<TThis extends typeof Error0>(this: TThis, error: unknown): ErrorResolvedProps<PluginsMapOf<TThis>>
|
|
589
|
+
static resolve(error: unknown): Record<string, unknown>
|
|
590
|
+
static resolve(error: unknown): Record<string, unknown> {
|
|
591
|
+
const error0 = this.from(error)
|
|
592
|
+
const resolved: Record<string, unknown> = {}
|
|
593
|
+
const plugin = this._getResolvedPlugin()
|
|
594
|
+
for (const [key, prop] of Object.entries(plugin.props)) {
|
|
595
|
+
try {
|
|
596
|
+
// resolved[key] = (error0 as unknown as Record<string, unknown>)[key]
|
|
597
|
+
const options = Object.defineProperties(
|
|
598
|
+
{
|
|
599
|
+
error: error0,
|
|
600
|
+
},
|
|
601
|
+
{
|
|
602
|
+
own: {
|
|
603
|
+
get: () => error0.own(key as never),
|
|
604
|
+
},
|
|
605
|
+
flow: {
|
|
606
|
+
get: () => error0.flow(key),
|
|
607
|
+
},
|
|
608
|
+
},
|
|
609
|
+
)
|
|
610
|
+
resolved[key] = prop.resolve(options as never)
|
|
611
|
+
// resolved[key] = prop.resolve({ own: error0.own(key as never), flow: error0.flow(key), error: error0 })
|
|
612
|
+
} catch {
|
|
613
|
+
// eslint-disable-next-line no-console
|
|
614
|
+
console.error(`Error0: failed to resolve property ${key}`, error0)
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
return resolved
|
|
618
|
+
}
|
|
619
|
+
resolve<TThis extends Error0>(this: TThis): ErrorResolvedProps<PluginsMapOfInstance<TThis>>
|
|
620
|
+
resolve(): Record<string, unknown>
|
|
621
|
+
resolve(): Record<string, unknown> {
|
|
622
|
+
const ctor = this.constructor as typeof Error0
|
|
623
|
+
return ctor.resolve(this)
|
|
452
624
|
}
|
|
453
625
|
|
|
454
626
|
static causes(error: unknown, instancesOnly?: false): unknown[]
|
|
@@ -473,8 +645,8 @@ export class Error0 extends Error {
|
|
|
473
645
|
}
|
|
474
646
|
return causes
|
|
475
647
|
}
|
|
476
|
-
causes<
|
|
477
|
-
causes<
|
|
648
|
+
causes<TThis extends Error0>(this: TThis, instancesOnly?: false): [TThis, ...unknown[]]
|
|
649
|
+
causes<TThis extends Error0>(this: TThis, instancesOnly: true): [TThis, ...TThis[]]
|
|
478
650
|
causes(instancesOnly?: boolean): unknown[] {
|
|
479
651
|
const ctor = this.constructor as typeof Error0
|
|
480
652
|
if (instancesOnly) {
|
|
@@ -532,14 +704,35 @@ export class Error0 extends Error {
|
|
|
532
704
|
const value = prop.deserialize({ value: errorRecord[key], serialized: errorRecord })
|
|
533
705
|
;(recreated as unknown as Record<string, unknown>)[key] = value
|
|
534
706
|
} catch {
|
|
535
|
-
//
|
|
707
|
+
// eslint-disable-next-line no-console
|
|
708
|
+
console.error(`Error0: failed to deserialize property ${key}`, errorRecord)
|
|
536
709
|
}
|
|
537
710
|
}
|
|
538
711
|
// we do not serialize causes
|
|
539
712
|
// ;(recreated as unknown as { cause?: unknown }).cause = errorRecord.cause
|
|
540
|
-
const
|
|
541
|
-
if (
|
|
542
|
-
|
|
713
|
+
const stackPlugin = plugin.stack
|
|
714
|
+
if (stackPlugin !== false && 'stack' in errorRecord) {
|
|
715
|
+
try {
|
|
716
|
+
if (typeof errorRecord.stack === 'string') {
|
|
717
|
+
recreated.stack = errorRecord.stack
|
|
718
|
+
}
|
|
719
|
+
} catch {
|
|
720
|
+
// eslint-disable-next-line no-console
|
|
721
|
+
console.error('Error0: failed to deserialize stack', errorRecord)
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
const causePlugin = plugin.cause ?? false
|
|
725
|
+
if (causePlugin && 'cause' in errorRecord) {
|
|
726
|
+
try {
|
|
727
|
+
if (this.isSerialized(errorRecord.cause)) {
|
|
728
|
+
;(recreated as { cause?: unknown }).cause = this._fromSerialized(errorRecord.cause)
|
|
729
|
+
} else {
|
|
730
|
+
;(recreated as { cause?: unknown }).cause = errorRecord.cause
|
|
731
|
+
}
|
|
732
|
+
} catch {
|
|
733
|
+
// eslint-disable-next-line no-console
|
|
734
|
+
console.error('Error0: failed to deserialize cause', errorRecord)
|
|
735
|
+
}
|
|
543
736
|
}
|
|
544
737
|
return recreated
|
|
545
738
|
}
|
|
@@ -598,6 +791,8 @@ export class Error0 extends Error {
|
|
|
598
791
|
props: { ...(pluginRecord._plugin.props ?? {}) },
|
|
599
792
|
methods: { ...(pluginRecord._plugin.methods ?? {}) },
|
|
600
793
|
adapt: [...(pluginRecord._plugin.adapt ?? [])],
|
|
794
|
+
stack: pluginRecord._plugin.stack,
|
|
795
|
+
cause: pluginRecord._plugin.cause,
|
|
601
796
|
}
|
|
602
797
|
}
|
|
603
798
|
|
|
@@ -630,6 +825,20 @@ export class Error0 extends Error {
|
|
|
630
825
|
return this.use('adapt', value)
|
|
631
826
|
}
|
|
632
827
|
|
|
828
|
+
static stack<TThis extends typeof Error0>(
|
|
829
|
+
this: TThis,
|
|
830
|
+
value: ErrorPluginStack<ErrorInstanceOfMap<PluginsMapOf<TThis>>>,
|
|
831
|
+
): ClassError0<PluginsMapOf<TThis>> {
|
|
832
|
+
return this.use('stack', value)
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
static cause<TThis extends typeof Error0>(
|
|
836
|
+
this: TThis,
|
|
837
|
+
value: ErrorPluginCause<ErrorInstanceOfMap<PluginsMapOf<TThis>>>,
|
|
838
|
+
): ClassError0<PluginsMapOf<TThis>> {
|
|
839
|
+
return this.use('cause', value)
|
|
840
|
+
}
|
|
841
|
+
|
|
633
842
|
static use<TThis extends typeof Error0, TBuilder extends PluginError0>(
|
|
634
843
|
this: TThis,
|
|
635
844
|
plugin: TBuilder,
|
|
@@ -657,21 +866,53 @@ export class Error0 extends Error {
|
|
|
657
866
|
kind: 'adapt',
|
|
658
867
|
value: ErrorPluginAdaptFn<ErrorInstanceOfMap<PluginsMapOf<TThis>>, ErrorResolvedProps<PluginsMapOf<TThis>>>,
|
|
659
868
|
): ClassError0<PluginsMapOf<TThis>>
|
|
869
|
+
static use<TThis extends typeof Error0>(
|
|
870
|
+
this: TThis,
|
|
871
|
+
kind: 'stack',
|
|
872
|
+
value: ErrorPluginStack<ErrorInstanceOfMap<PluginsMapOf<TThis>>>,
|
|
873
|
+
): ClassError0<PluginsMapOf<TThis>>
|
|
874
|
+
static use<TThis extends typeof Error0>(
|
|
875
|
+
this: TThis,
|
|
876
|
+
kind: 'cause',
|
|
877
|
+
value: ErrorPluginCause<ErrorInstanceOfMap<PluginsMapOf<TThis>>>,
|
|
878
|
+
): ClassError0<PluginsMapOf<TThis>>
|
|
660
879
|
static use(
|
|
661
880
|
this: typeof Error0,
|
|
662
|
-
first: PluginError0 | 'prop' | 'method' | 'adapt',
|
|
663
|
-
key?:
|
|
881
|
+
first: PluginError0 | 'prop' | 'method' | 'adapt' | 'stack' | 'cause',
|
|
882
|
+
key?: unknown,
|
|
664
883
|
value?: ErrorPluginPropOptions<unknown> | ErrorPluginMethodFn<unknown>,
|
|
665
884
|
): ClassError0 {
|
|
666
885
|
if (first instanceof PluginError0) {
|
|
667
886
|
return this._useWithPlugin(this._pluginFromBuilder(first))
|
|
668
887
|
}
|
|
888
|
+
if (first === 'stack') {
|
|
889
|
+
if (typeof key === 'undefined') {
|
|
890
|
+
throw new Error('Error0.use("stack", value) requires stack plugin value')
|
|
891
|
+
}
|
|
892
|
+
if (key !== 'merge' && typeof key !== 'boolean' && typeof key !== 'function') {
|
|
893
|
+
throw new Error('Error0.use("stack", value) expects function | boolean | "merge"')
|
|
894
|
+
}
|
|
895
|
+
return this._useWithPlugin({
|
|
896
|
+
stack: key as ErrorPluginStack,
|
|
897
|
+
})
|
|
898
|
+
}
|
|
899
|
+
if (first === 'cause') {
|
|
900
|
+
if (typeof key === 'undefined') {
|
|
901
|
+
throw new Error('Error0.use("cause", value) requires cause plugin value')
|
|
902
|
+
}
|
|
903
|
+
if (typeof key !== 'boolean' && typeof key !== 'function') {
|
|
904
|
+
throw new Error('Error0.use("cause", value) expects function | boolean')
|
|
905
|
+
}
|
|
906
|
+
return this._useWithPlugin({
|
|
907
|
+
cause: key as ErrorPluginCause,
|
|
908
|
+
})
|
|
909
|
+
}
|
|
669
910
|
if (first === 'adapt') {
|
|
670
911
|
if (typeof key !== 'function') {
|
|
671
912
|
throw new Error('Error0.use("adapt", value) requires adapt function')
|
|
672
913
|
}
|
|
673
914
|
return this._useWithPlugin({
|
|
674
|
-
adapt: [key],
|
|
915
|
+
adapt: [key as ErrorPluginAdaptFn<Error0, Record<string, unknown>>],
|
|
675
916
|
})
|
|
676
917
|
}
|
|
677
918
|
if (typeof key !== 'string' || value === undefined) {
|
|
@@ -679,6 +920,9 @@ export class Error0 extends Error {
|
|
|
679
920
|
}
|
|
680
921
|
|
|
681
922
|
if (first === 'prop') {
|
|
923
|
+
if (key === 'stack') {
|
|
924
|
+
throw new Error(RESERVED_STACK_PROP_ERROR)
|
|
925
|
+
}
|
|
682
926
|
return this._useWithPlugin({
|
|
683
927
|
props: { [key]: value as ErrorPluginPropOptions<unknown> },
|
|
684
928
|
})
|
|
@@ -694,6 +938,8 @@ export class Error0 extends Error {
|
|
|
694
938
|
|
|
695
939
|
static serialize(error: unknown, isPublic = true): Record<string, unknown> {
|
|
696
940
|
const error0 = this.from(error)
|
|
941
|
+
const resolvedProps = this.resolve(error0)
|
|
942
|
+
const resolvedRecord = resolvedProps as Record<string, unknown>
|
|
697
943
|
const json: Record<string, unknown> = {
|
|
698
944
|
name: error0.name,
|
|
699
945
|
message: error0.message,
|
|
@@ -708,18 +954,63 @@ export class Error0 extends Error {
|
|
|
708
954
|
continue
|
|
709
955
|
}
|
|
710
956
|
try {
|
|
711
|
-
const value =
|
|
957
|
+
const value = resolvedRecord[key]
|
|
712
958
|
const jsonValue = prop.serialize({ value, error: error0, isPublic })
|
|
713
959
|
if (jsonValue !== undefined) {
|
|
714
960
|
json[key] = jsonValue
|
|
715
961
|
}
|
|
716
962
|
} catch {
|
|
717
|
-
//
|
|
963
|
+
// eslint-disable-next-line no-console
|
|
964
|
+
console.error(`Error0: failed to serialize property ${key}`, resolvedRecord)
|
|
718
965
|
}
|
|
719
966
|
}
|
|
720
|
-
const
|
|
721
|
-
if (
|
|
722
|
-
|
|
967
|
+
const stackSerialize = plugin.stack
|
|
968
|
+
if (stackSerialize !== false) {
|
|
969
|
+
try {
|
|
970
|
+
let serializedStack: unknown
|
|
971
|
+
if (stackSerialize === 'merge') {
|
|
972
|
+
serializedStack = error0
|
|
973
|
+
.causes()
|
|
974
|
+
.map((cause) => {
|
|
975
|
+
return cause instanceof Error ? cause.stack : undefined
|
|
976
|
+
})
|
|
977
|
+
.filter((value): value is string => typeof value === 'string')
|
|
978
|
+
.join('\n')
|
|
979
|
+
} else if (typeof stackSerialize === 'function') {
|
|
980
|
+
serializedStack = stackSerialize({ value: error0.stack, error: error0, isPublic })
|
|
981
|
+
} else {
|
|
982
|
+
serializedStack = error0.stack
|
|
983
|
+
}
|
|
984
|
+
if (serializedStack !== undefined) {
|
|
985
|
+
json.stack = serializedStack
|
|
986
|
+
}
|
|
987
|
+
} catch {
|
|
988
|
+
// eslint-disable-next-line no-console
|
|
989
|
+
console.error('Error0: failed to serialize stack', error0)
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
const causeSerialize = plugin.cause ?? false
|
|
993
|
+
if (causeSerialize) {
|
|
994
|
+
try {
|
|
995
|
+
if (causeSerialize === true) {
|
|
996
|
+
const causeValue = (error0 as { cause?: unknown }).cause
|
|
997
|
+
if (this.is(causeValue)) {
|
|
998
|
+
json.cause = this.serialize(causeValue, isPublic)
|
|
999
|
+
}
|
|
1000
|
+
} else {
|
|
1001
|
+
const serializedCause = causeSerialize({
|
|
1002
|
+
value: (error0 as { cause?: unknown }).cause,
|
|
1003
|
+
error: error0,
|
|
1004
|
+
isPublic,
|
|
1005
|
+
})
|
|
1006
|
+
if (serializedCause !== undefined) {
|
|
1007
|
+
json.cause = serializedCause
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
} catch {
|
|
1011
|
+
// eslint-disable-next-line no-console
|
|
1012
|
+
console.error('Error0: failed to serialize cause', error0)
|
|
1013
|
+
}
|
|
723
1014
|
}
|
|
724
1015
|
return Object.fromEntries(Object.entries(json).filter(([, value]) => value !== undefined)) as Record<
|
|
725
1016
|
string,
|
|
@@ -727,7 +1018,7 @@ export class Error0 extends Error {
|
|
|
727
1018
|
>
|
|
728
1019
|
}
|
|
729
1020
|
|
|
730
|
-
serialize(isPublic = true):
|
|
1021
|
+
serialize(isPublic = true): Record<string, unknown> {
|
|
731
1022
|
const ctor = this.constructor as typeof Error0
|
|
732
1023
|
return ctor.serialize(this, isPublic)
|
|
733
1024
|
}
|