@devp0nt/error0 1.0.0-next.55 → 1.0.0-next.57

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/src/index.ts DELETED
@@ -1,1264 +0,0 @@
1
- type IsUnknown<T> = unknown extends T ? ([T] extends [unknown] ? true : false) : false
2
- type NormalizeUnknownToUndefined<T> = IsUnknown<T> extends true ? undefined : T
3
- type IsOnlyUndefined<T> = [Exclude<T, undefined>] extends [never] ? true : false
4
- type InferFirstArg<TFn> = TFn extends (...args: infer TArgs) => unknown
5
- ? TArgs extends [infer TFirst, ...unknown[]]
6
- ? TFirst
7
- : undefined
8
- : undefined
9
- type InferPluginPropInput<TProp extends ErrorPluginPropOptions<any, any, any, any>> = TProp extends {
10
- init: infer TInit
11
- }
12
- ? NormalizeUnknownToUndefined<InferFirstArg<TInit>>
13
- : undefined
14
- type ErrorPluginPropInit<TInputValue, TOutputValue> = ((input: TInputValue) => TOutputValue) | (() => TOutputValue)
15
- type ErrorPluginPropSerializeOptions<
16
- TOutputValue,
17
- TError extends Error0,
18
- TResolveValue extends TOutputValue | undefined,
19
- > = {
20
- own: TOutputValue | undefined
21
- flow: Array<TOutputValue | undefined>
22
- resolved: TResolveValue
23
- error: TError
24
- isPublic: boolean
25
- }
26
- type ErrorPluginPropSerialize<TOutputValue, TError extends Error0, TResolveValue extends TOutputValue | undefined> =
27
- | ((options: ErrorPluginPropSerializeOptions<TOutputValue, TError, TResolveValue>) => unknown)
28
- | false
29
- type ErrorPluginPropDeserialize<TOutputValue> =
30
- | ((options: { value: unknown; record: Record<string, unknown> }) => TOutputValue | undefined)
31
- | false
32
- type ErrorPluginPropOptionsResolveOptions<TOutputValue, TError extends Error0> = {
33
- own: TOutputValue | undefined
34
- flow: Array<TOutputValue | undefined>
35
- error: TError
36
- }
37
- type ErrorPluginPropOptionsBase<TOutputValue, TError extends Error0, TResolveValue extends TOutputValue | undefined> = {
38
- resolve: (options: ErrorPluginPropOptionsResolveOptions<TOutputValue, TError>) => TResolveValue
39
- serialize: ErrorPluginPropSerialize<TOutputValue, TError, TResolveValue>
40
- deserialize: ErrorPluginPropDeserialize<TOutputValue>
41
- }
42
- type ErrorPluginPropOptionsWithInit<
43
- TInputValue,
44
- TOutputValue,
45
- TError extends Error0,
46
- TResolveValue extends TOutputValue | undefined,
47
- > = ErrorPluginPropOptionsBase<TOutputValue, TError, TResolveValue> & {
48
- init: ErrorPluginPropInit<TInputValue, TOutputValue>
49
- }
50
- type ErrorPluginPropOptionsWithoutInit<
51
- TOutputValue,
52
- TError extends Error0,
53
- TResolveValue extends TOutputValue | undefined,
54
- > = ErrorPluginPropOptionsBase<TOutputValue, TError, TResolveValue> & {
55
- init?: undefined
56
- }
57
- type ErrorPluginPropOptions<
58
- TInputValue = undefined,
59
- TOutputValue = unknown,
60
- TError extends Error0 = Error0,
61
- TResolveValue extends TOutputValue | undefined = TOutputValue | undefined,
62
- > =
63
- | ErrorPluginPropOptionsWithInit<TInputValue, TOutputValue, TError, TResolveValue>
64
- | ErrorPluginPropOptionsWithoutInit<TOutputValue, TError, TResolveValue>
65
-
66
- type ErrorPluginPropOptionsBaseDefinition<
67
- TOutputValue,
68
- TError extends Error0,
69
- TResolveValue extends TOutputValue | undefined,
70
- > = {
71
- resolve?: ((options: ErrorPluginPropOptionsResolveOptions<TOutputValue, TError>) => TResolveValue) | boolean
72
- serialize?: ErrorPluginPropSerialize<TOutputValue, TError, TResolveValue>
73
- deserialize?: ErrorPluginPropDeserialize<TOutputValue>
74
- }
75
- type ErrorPluginPropOptionsWithInitDefinition<
76
- TInputValue,
77
- TOutputValue,
78
- TError extends Error0,
79
- TResolveValue extends TOutputValue | undefined,
80
- > = ErrorPluginPropOptionsBaseDefinition<TOutputValue, TError, TResolveValue> & {
81
- init: ErrorPluginPropInit<TInputValue, TOutputValue>
82
- }
83
- type ErrorPluginPropOptionsWithoutInitDefinition<
84
- TOutputValue,
85
- TError extends Error0,
86
- TResolveValue extends TOutputValue | undefined,
87
- > = ErrorPluginPropOptionsBaseDefinition<TOutputValue, TError, TResolveValue> & {
88
- init?: undefined
89
- }
90
- type ErrorPluginPropOptionsDefinition<
91
- TInputValue = undefined,
92
- TOutputValue = unknown,
93
- TError extends Error0 = Error0,
94
- TResolveValue extends TOutputValue | undefined = TOutputValue | undefined,
95
- > =
96
- | ErrorPluginPropOptionsWithInitDefinition<TInputValue, TOutputValue, TError, TResolveValue>
97
- | ErrorPluginPropOptionsWithoutInitDefinition<TOutputValue, TError, TResolveValue>
98
-
99
- type ErrorPluginMethodFn<TOutputValue, TArgs extends unknown[] = unknown[], TError extends Error0 = Error0> = (
100
- error: TError,
101
- ...args: TArgs
102
- ) => TOutputValue
103
- type ErrorPluginAnyMethodFn = (error: any, ...args: any[]) => any
104
- type ErrorPluginAdaptResult<TOutputProps extends Record<string, unknown>> = Partial<TOutputProps> | undefined
105
- type ErrorPluginAdaptFn<
106
- TError extends Error0 = Error0,
107
- TOutputProps extends Record<string, unknown> = Record<never, never>,
108
- > = ((error: TError) => void) | ((error: TError) => ErrorPluginAdaptResult<TOutputProps>)
109
- type ErrorPluginStackSerialize<TError extends Error0> = (options: {
110
- value: string | undefined
111
- error: TError
112
- isPublic: boolean
113
- }) => unknown
114
- type ErrorPluginStack<TError extends Error0 = Error0> = { serialize: ErrorPluginStackSerialize<TError> }
115
- type ErrorPluginCauseSerialize<TError extends Error0> = (options: {
116
- cause: unknown
117
- error: TError
118
- isPublic: boolean
119
- is: (cause: unknown) => boolean
120
- serialize: (cause: unknown) => Record<string, unknown>
121
- }) => unknown
122
- type ErrorPluginCauseDeserialize = (options: {
123
- cause: unknown
124
- error: Record<string, unknown>
125
- isSerialized: (serializedCause: unknown) => boolean
126
- fromSerialized: (serializedCause: unknown) => Error0
127
- }) => unknown
128
- type ErrorPluginCause<TError extends Error0 = Error0> = {
129
- serialize: ErrorPluginCauseSerialize<TError>
130
- deserialize: ErrorPluginCauseDeserialize
131
- }
132
- type ErrorPluginMessageSerialize<TError extends Error0> = (options: {
133
- value: string
134
- error: TError
135
- isPublic: boolean
136
- }) => unknown
137
- type ErrorPluginMessage<TError extends Error0 = Error0> = { serialize: ErrorPluginMessageSerialize<TError> }
138
- type ErrorMethodRecord = { fn: ErrorPluginAnyMethodFn }
139
-
140
- type ErrorPluginProps = { [key: string]: ErrorPluginPropOptions<any, any> }
141
- type ErrorPluginMethods = { [key: string]: ErrorPluginAnyMethodFn }
142
-
143
- export type ErrorPlugin<
144
- TProps extends ErrorPluginProps = Record<never, never>,
145
- TMethods extends ErrorPluginMethods = Record<never, never>,
146
- > = {
147
- props?: TProps
148
- methods?: TMethods
149
- adapt?: Array<ErrorPluginAdaptFn<Error0, PluginOutputProps<TProps>>>
150
- stack?: ErrorPluginStack
151
- cause?: ErrorPluginCause
152
- message?: ErrorPluginMessage
153
- }
154
- type AddPropToPluginProps<
155
- TProps extends ErrorPluginProps,
156
- TKey extends string,
157
- TInputValue,
158
- TOutputValue,
159
- TResolveValue extends TOutputValue | undefined = TOutputValue | undefined,
160
- > = TProps & Record<TKey, ErrorPluginPropOptions<TInputValue, TOutputValue, Error0, TResolveValue>>
161
- type AddMethodToPluginMethods<
162
- TMethods extends ErrorPluginMethods,
163
- TKey extends string,
164
- TMethod extends ErrorPluginAnyMethodFn,
165
- > = TMethods & Record<TKey, TMethod>
166
- type PluginOutputProps<TProps extends ErrorPluginProps> = {
167
- [TKey in keyof TProps]: TProps[TKey] extends ErrorPluginPropOptions<any, any, any, infer TResolveValue>
168
- ? TResolveValue
169
- : never
170
- }
171
- type ErrorPluginsMap = {
172
- props: Record<string, { init: unknown; output: unknown; resolve: unknown }>
173
- methods: Record<string, ErrorMethodRecord>
174
- }
175
- type IsEmptyObject<T> = keyof T extends never ? true : false
176
- type ErrorInputBase = {
177
- cause?: unknown
178
- }
179
- type ErrorInputPluginProps<TPluginsMap extends ErrorPluginsMap> = {
180
- [TKey in keyof TPluginsMap['props'] as IsOnlyUndefined<TPluginsMap['props'][TKey]['init']> extends true
181
- ? never
182
- : TKey]?: TPluginsMap['props'][TKey]['init']
183
- }
184
- type ErrorInput<TPluginsMap extends ErrorPluginsMap> =
185
- IsEmptyObject<TPluginsMap['props']> extends true
186
- ? ErrorInputBase
187
- : ErrorInputBase & ErrorInputPluginProps<TPluginsMap>
188
-
189
- type ErrorResolvedProps<TPluginsMap extends ErrorPluginsMap> = {
190
- [TKey in keyof TPluginsMap['props']]: TPluginsMap['props'][TKey]['resolve']
191
- }
192
- type ErrorOwnProps<TPluginsMap extends ErrorPluginsMap> = {
193
- [TKey in keyof TPluginsMap['props']]: TPluginsMap['props'][TKey]['output'] | undefined
194
- }
195
- type ErrorResolveMethods<TPluginsMap extends ErrorPluginsMap> = {
196
- resolve: () => ErrorResolvedProps<TPluginsMap>
197
- }
198
- type Error0ResolvedInstance<TPluginsMap extends ErrorPluginsMap> = Error0 &
199
- ErrorResolved<TPluginsMap> &
200
- ErrorResolveMethods<TPluginsMap>
201
- type ErrorOwnMethods<TPluginsMap extends ErrorPluginsMap> = {
202
- own?: Partial<ErrorOwnProps<TPluginsMap>>
203
- flow: <TKey extends keyof TPluginsMap['props'] & string>(key: TKey) => Array<ErrorOwnProps<TPluginsMap>[TKey]>
204
- assign: (props: Partial<ErrorOwnProps<TPluginsMap>>) => Error0ResolvedInstance<TPluginsMap>
205
- }
206
- export type InstanceError0<TPluginsMap extends ErrorPluginsMap> = Error0ResolvedInstance<TPluginsMap> &
207
- ErrorOwnMethods<TPluginsMap> & { readonly __pluginsMap?: TPluginsMap }
208
- // type BindInstanceMethod<TMethod> = TMethod extends {
209
- // (error: any, ...args: infer TArgs1): infer TOutput1
210
- // (error: any, ...args: infer TArgs2): infer TOutput2
211
- // (error: any, ...args: infer TArgs3): infer TOutput3
212
- // (error: any, ...args: infer TArgs4): infer TOutput4
213
- // }
214
- // ? {
215
- // (...args: TArgs1): TOutput1
216
- // (...args: TArgs2): TOutput2
217
- // (...args: TArgs3): TOutput3
218
- // (...args: TArgs4): TOutput4
219
- // }
220
- // : TMethod extends {
221
- // (error: any, ...args: infer TArgs1): infer TOutput1
222
- // (error: any, ...args: infer TArgs2): infer TOutput2
223
- // (error: any, ...args: infer TArgs3): infer TOutput3
224
- // }
225
- // ? {
226
- // (...args: TArgs1): TOutput1
227
- // (...args: TArgs2): TOutput2
228
- // (...args: TArgs3): TOutput3
229
- // }
230
- // : TMethod extends {
231
- // (error: any, ...args: infer TArgs1): infer TOutput1
232
- // (error: any, ...args: infer TArgs2): infer TOutput2
233
- // }
234
- // ? {
235
- // (...args: TArgs1): TOutput1
236
- // (...args: TArgs2): TOutput2
237
- // }
238
- // : TMethod extends (error: any, ...args: infer TArgs) => infer TOutput
239
- // ? (...args: TArgs) => TOutput
240
- // : never
241
- // type BindStaticMethod<TMethod> = TMethod extends {
242
- // (error: any, ...args: infer TArgs1): infer TOutput1
243
- // (error: any, ...args: infer TArgs2): infer TOutput2
244
- // (error: any, ...args: infer TArgs3): infer TOutput3
245
- // (error: any, ...args: infer TArgs4): infer TOutput4
246
- // }
247
- // ? {
248
- // (error: unknown, ...args: TArgs1): TOutput1
249
- // (error: unknown, ...args: TArgs2): TOutput2
250
- // (error: unknown, ...args: TArgs3): TOutput3
251
- // (error: unknown, ...args: TArgs4): TOutput4
252
- // }
253
- // : TMethod extends {
254
- // (error: any, ...args: infer TArgs1): infer TOutput1
255
- // (error: any, ...args: infer TArgs2): infer TOutput2
256
- // (error: any, ...args: infer TArgs3): infer TOutput3
257
- // }
258
- // ? {
259
- // (error: unknown, ...args: TArgs1): TOutput1
260
- // (error: unknown, ...args: TArgs2): TOutput2
261
- // (error: unknown, ...args: TArgs3): TOutput3
262
- // }
263
- // : TMethod extends {
264
- // (error: any, ...args: infer TArgs1): infer TOutput1
265
- // (error: any, ...args: infer TArgs2): infer TOutput2
266
- // }
267
- // ? {
268
- // (error: unknown, ...args: TArgs1): TOutput1
269
- // (error: unknown, ...args: TArgs2): TOutput2
270
- // }
271
- // : TMethod extends (error: any, ...args: infer TArgs) => infer TOutput
272
- // ? (error: unknown, ...args: TArgs) => TOutput
273
- // : never
274
- type BindInstanceMethod<TMethod> = TMethod extends (error: any, ...args: infer TArgs) => infer TOutput
275
- ? (...args: TArgs) => TOutput
276
- : never
277
- type BindStaticMethod<TMethod> = TMethod extends (error: any, ...args: infer TArgs) => infer TOutput
278
- ? (error: unknown, ...args: TArgs) => TOutput
279
- : never
280
- type ErrorMethods<TPluginsMap extends ErrorPluginsMap> = {
281
- [TKey in keyof TPluginsMap['methods']]: BindInstanceMethod<TPluginsMap['methods'][TKey]['fn']>
282
- }
283
- type ErrorResolved<TPluginsMap extends ErrorPluginsMap> = ErrorResolvedProps<TPluginsMap> & ErrorMethods<TPluginsMap>
284
-
285
- type ErrorStaticMethods<TPluginsMap extends ErrorPluginsMap> = {
286
- [TKey in keyof TPluginsMap['methods']]: BindStaticMethod<TPluginsMap['methods'][TKey]['fn']>
287
- }
288
-
289
- type EmptyPluginsMap = {
290
- props: Record<never, { init: never; output: never; resolve: never }>
291
- methods: Record<never, ErrorMethodRecord>
292
- }
293
-
294
- type ErrorPluginResolved = {
295
- props: Record<string, ErrorPluginPropOptions<unknown>>
296
- methods: Record<string, ErrorPluginMethodFn<unknown>>
297
- adapt: Array<ErrorPluginAdaptFn<Error0, Record<string, unknown>>>
298
- stack?: ErrorPluginStack
299
- cause?: ErrorPluginCause
300
- message?: ErrorPluginMessage
301
- propKeys: string[]
302
- propEntries: Array<[string, ErrorPluginPropOptions<unknown>]>
303
- methodEntries: Array<[string, ErrorPluginMethodFn<unknown>]>
304
- }
305
- const RESERVED_STACK_PROP_ERROR = 'Error0: "stack" is a reserved prop key. Use .stack(...) plugin API instead'
306
- const RESERVED_MESSAGE_PROP_ERROR = 'Error0: "message" is a reserved prop key. Use .message(...) plugin API instead'
307
-
308
- const fromPropOptionsDefinition = (
309
- options: ErrorPluginPropOptionsDefinition<any, any, any, any>,
310
- ): ErrorPluginPropOptions<any, any, any, any> => {
311
- let resolver: ErrorPluginPropOptions<unknown>['resolve']
312
- if (!options.resolve) {
313
- resolver = (options: ErrorPluginPropOptionsResolveOptions<any, any>) => options.own
314
- } else if (options.resolve === true) {
315
- resolver = (options: ErrorPluginPropOptionsResolveOptions<any, any>) => options.flow.find((v) => v !== undefined)
316
- } else if (typeof options.resolve === 'function') {
317
- resolver = options.resolve
318
- } else {
319
- throw new Error('Invalid resolve option')
320
- }
321
- const serializer: ErrorPluginPropOptions<unknown>['serialize'] = options.serialize ?? false
322
- const deserializer: ErrorPluginPropOptions<unknown>['deserialize'] = options.deserialize ?? false
323
- return {
324
- ...options,
325
- resolve: resolver,
326
- serialize: serializer,
327
- deserialize: deserializer,
328
- }
329
- }
330
-
331
- type PluginPropsMapOf<TPlugin extends ErrorPlugin> = {
332
- [TKey in keyof NonNullable<TPlugin['props']>]: NonNullable<TPlugin['props']>[TKey] extends ErrorPluginPropOptions<
333
- any,
334
- infer TOutputValue,
335
- any,
336
- infer TResolveValue
337
- >
338
- ? {
339
- init: InferPluginPropInput<NonNullable<TPlugin['props']>[TKey]>
340
- output: TOutputValue
341
- resolve: TResolveValue
342
- }
343
- : never
344
- }
345
- type PluginMethodsMapOf<TPlugin extends ErrorPlugin> = {
346
- [TKey in keyof NonNullable<TPlugin['methods']>]: {
347
- fn: NonNullable<TPlugin['methods']>[TKey] extends ErrorPluginAnyMethodFn
348
- ? NonNullable<TPlugin['methods']>[TKey]
349
- : never
350
- }
351
- }
352
- type ErrorPluginsMapOfPlugin<TPlugin extends ErrorPlugin> = {
353
- props: PluginPropsMapOf<TPlugin>
354
- methods: PluginMethodsMapOf<TPlugin>
355
- }
356
- type ExtendErrorPluginsMap<TMap extends ErrorPluginsMap, TPlugin extends ErrorPlugin> = {
357
- props: TMap['props'] & ErrorPluginsMapOfPlugin<TPlugin>['props']
358
- methods: TMap['methods'] & ErrorPluginsMapOfPlugin<TPlugin>['methods']
359
- }
360
- type ExtendErrorPluginsMapWithProp<
361
- TMap extends ErrorPluginsMap,
362
- TKey extends string,
363
- TInputValue,
364
- TOutputValue,
365
- TResolveValue extends TOutputValue | undefined = TOutputValue | undefined,
366
- > = ExtendErrorPluginsMap<
367
- TMap,
368
- ErrorPlugin<Record<TKey, ErrorPluginPropOptions<TInputValue, TOutputValue, Error0, TResolveValue>>>
369
- >
370
- type ExtendErrorPluginsMapWithMethod<
371
- TMap extends ErrorPluginsMap,
372
- TKey extends string,
373
- TMethod extends ErrorPluginAnyMethodFn,
374
- > = ExtendErrorPluginsMap<TMap, ErrorPlugin<Record<never, never>, Record<TKey, TMethod>>>
375
-
376
- type PluginsMapOf<TClass> = TClass extends { __pluginsMap?: infer TPluginsMap }
377
- ? TPluginsMap extends ErrorPluginsMap
378
- ? TPluginsMap
379
- : EmptyPluginsMap
380
- : EmptyPluginsMap
381
- type PluginsMapOfInstance<TInstance> = TInstance extends { __pluginsMap?: infer TPluginsMap }
382
- ? TPluginsMap extends ErrorPluginsMap
383
- ? TPluginsMap
384
- : EmptyPluginsMap
385
- : EmptyPluginsMap
386
-
387
- type PluginsMapFromParts<
388
- TProps extends ErrorPluginProps,
389
- TMethods extends ErrorPluginMethods,
390
- > = ErrorPluginsMapOfPlugin<ErrorPlugin<TProps, TMethods>>
391
- type ErrorInstanceOfMap<TMap extends ErrorPluginsMap> = InstanceError0<TMap>
392
- type BuilderError0<TProps extends ErrorPluginProps, TMethods extends ErrorPluginMethods> = InstanceError0<
393
- PluginsMapFromParts<TProps, TMethods>
394
- >
395
-
396
- type PluginOfBuilder<TBuilder> =
397
- TBuilder extends PluginError0<infer TProps, infer TMethods> ? ErrorPlugin<TProps, TMethods> : never
398
-
399
- export class PluginError0<
400
- TProps extends ErrorPluginProps = Record<never, never>,
401
- TMethods extends ErrorPluginMethods = Record<never, never>,
402
- > {
403
- private readonly _plugin: ErrorPlugin<ErrorPluginProps, ErrorPluginMethods>
404
-
405
- readonly Infer = undefined as unknown as {
406
- props: TProps
407
- methods: TMethods
408
- }
409
-
410
- constructor(plugin?: ErrorPlugin<ErrorPluginProps, ErrorPluginMethods>) {
411
- this._plugin = {
412
- props: { ...(plugin?.props ?? {}) },
413
- methods: { ...(plugin?.methods ?? {}) },
414
- adapt: [...(plugin?.adapt ?? [])],
415
- stack: plugin?.stack,
416
- cause: plugin?.cause,
417
- message: plugin?.message,
418
- }
419
- }
420
-
421
- prop<
422
- TKey extends string,
423
- TInputValue = undefined,
424
- TOutputValue = unknown,
425
- TResolveValue extends TOutputValue | undefined = TOutputValue | undefined,
426
- >(
427
- key: TKey,
428
- value: ErrorPluginPropOptionsDefinition<TInputValue, TOutputValue, BuilderError0<TProps, TMethods>, TResolveValue>,
429
- ): PluginError0<AddPropToPluginProps<TProps, TKey, TInputValue, TOutputValue, TResolveValue>, TMethods> {
430
- return this.use('prop', key, value)
431
- }
432
-
433
- method<TKey extends string, TMethod extends (error: BuilderError0<TProps, TMethods>, ...args: any[]) => any>(
434
- key: TKey,
435
- value: TMethod,
436
- ): PluginError0<TProps, AddMethodToPluginMethods<TMethods, TKey, TMethod>> {
437
- return this.use('method', key, value)
438
- }
439
-
440
- adapt(
441
- value: ErrorPluginAdaptFn<BuilderError0<TProps, TMethods>, PluginOutputProps<TProps>>,
442
- ): PluginError0<TProps, TMethods> {
443
- return this.use('adapt', value)
444
- }
445
-
446
- stack(value: ErrorPluginStack<BuilderError0<TProps, TMethods>>): PluginError0<TProps, TMethods> {
447
- return this.use('stack', value)
448
- }
449
-
450
- cause(value: ErrorPluginCause<BuilderError0<TProps, TMethods>>): PluginError0<TProps, TMethods> {
451
- return this.use('cause', value)
452
- }
453
-
454
- message(value: ErrorPluginMessage<BuilderError0<TProps, TMethods>>): PluginError0<TProps, TMethods> {
455
- return this.use('message', value)
456
- }
457
-
458
- use<
459
- TKey extends string,
460
- TInputValue = undefined,
461
- TOutputValue = unknown,
462
- TResolveValue extends TOutputValue | undefined = TOutputValue | undefined,
463
- >(
464
- kind: 'prop',
465
- key: TKey,
466
- value: ErrorPluginPropOptionsDefinition<TInputValue, TOutputValue, BuilderError0<TProps, TMethods>, TResolveValue>,
467
- ): PluginError0<AddPropToPluginProps<TProps, TKey, TInputValue, TOutputValue, TResolveValue>, TMethods>
468
- use<TKey extends string, TMethod extends (error: BuilderError0<TProps, TMethods>, ...args: any[]) => any>(
469
- kind: 'method',
470
- key: TKey,
471
- value: TMethod,
472
- ): PluginError0<TProps, AddMethodToPluginMethods<TMethods, TKey, TMethod>>
473
- use(
474
- kind: 'adapt',
475
- value: ErrorPluginAdaptFn<BuilderError0<TProps, TMethods>, PluginOutputProps<TProps>>,
476
- ): PluginError0<TProps, TMethods>
477
- use(kind: 'stack', value: ErrorPluginStack<BuilderError0<TProps, TMethods>>): PluginError0<TProps, TMethods>
478
- use(kind: 'cause', value: ErrorPluginCause<BuilderError0<TProps, TMethods>>): PluginError0<TProps, TMethods>
479
- use(kind: 'message', value: ErrorPluginMessage<BuilderError0<TProps, TMethods>>): PluginError0<TProps, TMethods>
480
- use(
481
- kind: 'prop' | 'method' | 'adapt' | 'stack' | 'cause' | 'message',
482
- keyOrValue: unknown,
483
- value?: ErrorPluginPropOptionsDefinition<unknown, unknown, any> | ErrorPluginMethodFn<unknown, unknown[], any>,
484
- ): PluginError0<any, any> {
485
- const nextProps: ErrorPluginProps = { ...(this._plugin.props ?? {}) }
486
- const nextMethods: ErrorPluginMethods = { ...(this._plugin.methods ?? {}) }
487
- const nextAdapt: Array<ErrorPluginAdaptFn<Error0, Record<string, unknown>>> = [...(this._plugin.adapt ?? [])]
488
- let nextStack: ErrorPluginStack | undefined = this._plugin.stack
489
- let nextCause: ErrorPluginCause | undefined = this._plugin.cause
490
- let nextMessage: ErrorPluginMessage | undefined = this._plugin.message
491
- if (kind === 'prop') {
492
- const key = keyOrValue as string
493
- if (key === 'stack') {
494
- throw new Error(RESERVED_STACK_PROP_ERROR)
495
- }
496
- if (key === 'message') {
497
- throw new Error(RESERVED_MESSAGE_PROP_ERROR)
498
- }
499
- if (value === undefined) {
500
- throw new Error('PluginError0.use("prop", key, value) requires value')
501
- }
502
- nextProps[key] = fromPropOptionsDefinition(value as ErrorPluginPropOptionsDefinition<any, any>)
503
- } else if (kind === 'method') {
504
- const key = keyOrValue as string
505
- if (value === undefined) {
506
- throw new Error('PluginError0.use("method", key, value) requires value')
507
- }
508
- nextMethods[key] = value as ErrorPluginMethodFn<any, any[]>
509
- } else if (kind === 'adapt') {
510
- nextAdapt.push(keyOrValue as ErrorPluginAdaptFn<Error0, Record<string, unknown>>)
511
- } else if (kind === 'stack') {
512
- nextStack = keyOrValue as ErrorPluginStack
513
- } else if (kind === 'cause') {
514
- nextCause = keyOrValue as ErrorPluginCause
515
- } else {
516
- nextMessage = keyOrValue as ErrorPluginMessage
517
- }
518
- return new PluginError0({
519
- props: nextProps,
520
- methods: nextMethods,
521
- adapt: nextAdapt,
522
- stack: nextStack,
523
- cause: nextCause,
524
- message: nextMessage,
525
- })
526
- }
527
- }
528
-
529
- type ErrorOwnStore = Record<string, unknown>
530
-
531
- export type ClassError0<TPluginsMap extends ErrorPluginsMap = EmptyPluginsMap> = {
532
- MAX_CAUSES_DEPTH: number
533
- new (message: string, input?: ErrorInput<TPluginsMap>): InstanceError0<TPluginsMap>
534
- new (input: { message: string } & ErrorInput<TPluginsMap>): InstanceError0<TPluginsMap>
535
- readonly __pluginsMap?: TPluginsMap
536
- from: <TThis extends ClassError0<any>>(this: TThis, error: unknown) => InstanceType<TThis>
537
- round: <TThis extends ClassError0<any>>(this: TThis, error: unknown, isPublic?: boolean) => InstanceType<TThis>
538
- // flat: <TThis extends ClassError0<any>>(this: TThis, error: unknown, keepCauses?: boolean) => InstanceType<TThis>
539
- causes: {
540
- (error: unknown, instancesOnly?: false): unknown[]
541
- (error: unknown, instancesOnly: true): Array<InstanceError0<TPluginsMap>>
542
- }
543
- resolve: (error: unknown) => ErrorResolvedProps<TPluginsMap>
544
- serialize: (error: unknown, isPublic?: boolean) => Record<string, unknown>
545
- assign: <TThis extends ClassError0<any>>(
546
- this: TThis,
547
- error: unknown,
548
- props: Partial<ErrorOwnProps<PluginsMapOf<TThis>>>,
549
- ) => InstanceError0<PluginsMapOf<TThis>>
550
- own: {
551
- (error: object): ErrorOwnProps<TPluginsMap>
552
- <TKey extends keyof TPluginsMap['props'] & string>(error: object, key: TKey): ErrorOwnProps<TPluginsMap>[TKey]
553
- }
554
- flow: <TKey extends keyof TPluginsMap['props'] & string>(
555
- error: object,
556
- key: TKey,
557
- ) => Array<ErrorOwnProps<TPluginsMap>[TKey]>
558
- use: {
559
- <TBuilder extends PluginError0>(
560
- plugin: TBuilder,
561
- ): ClassError0<ExtendErrorPluginsMap<TPluginsMap, PluginOfBuilder<TBuilder>>>
562
- <
563
- TKey extends string,
564
- TInputValue = undefined,
565
- TOutputValue = unknown,
566
- TResolveValue extends TOutputValue | undefined = TOutputValue | undefined,
567
- >(
568
- kind: 'prop',
569
- key: TKey,
570
- value: ErrorPluginPropOptions<TInputValue, TOutputValue, ErrorInstanceOfMap<TPluginsMap>, TResolveValue>,
571
- ): ClassError0<ExtendErrorPluginsMapWithProp<TPluginsMap, TKey, TInputValue, TOutputValue, TResolveValue>>
572
- <TKey extends string, TMethod extends (error: ErrorInstanceOfMap<TPluginsMap>, ...args: any[]) => any>(
573
- kind: 'method',
574
- key: TKey,
575
- value: TMethod,
576
- ): ClassError0<ExtendErrorPluginsMapWithMethod<TPluginsMap, TKey, TMethod>>
577
- (
578
- kind: 'adapt',
579
- value: ErrorPluginAdaptFn<ErrorInstanceOfMap<TPluginsMap>, ErrorResolvedProps<TPluginsMap>>,
580
- ): ClassError0<TPluginsMap>
581
- (kind: 'stack', value: ErrorPluginStack<ErrorInstanceOfMap<TPluginsMap>>): ClassError0<TPluginsMap>
582
- (kind: 'cause', value: ErrorPluginCause<ErrorInstanceOfMap<TPluginsMap>>): ClassError0<TPluginsMap>
583
- (kind: 'message', value: ErrorPluginMessage<ErrorInstanceOfMap<TPluginsMap>>): ClassError0<TPluginsMap>
584
- }
585
- plugin: () => PluginError0
586
- } & ErrorStaticMethods<TPluginsMap>
587
-
588
- export class Error0 extends Error {
589
- static readonly __pluginsMap?: EmptyPluginsMap
590
- declare readonly __pluginsMap?: EmptyPluginsMap
591
- static MAX_CAUSES_DEPTH = 99
592
- protected static _plugins: ErrorPlugin[] = []
593
- protected static _resolvedPlugin?: ErrorPluginResolved
594
- declare own?: ErrorOwnStore
595
-
596
- private static readonly _emptyPlugin: ErrorPluginResolved = {
597
- props: {},
598
- methods: {},
599
- adapt: [],
600
- stack: undefined,
601
- cause: undefined,
602
- message: undefined,
603
- propKeys: [],
604
- propEntries: [],
605
- methodEntries: [],
606
- }
607
-
608
- private static _indexResolvedPlugin(
609
- resolved: Omit<ErrorPluginResolved, 'propKeys' | 'propEntries' | 'methodEntries'>,
610
- ): ErrorPluginResolved {
611
- return {
612
- ...resolved,
613
- propKeys: Object.keys(resolved.props),
614
- propEntries: Object.entries(resolved.props),
615
- methodEntries: Object.entries(resolved.methods),
616
- }
617
- }
618
-
619
- private static _applyPlugin(
620
- resolved: Omit<ErrorPluginResolved, 'propKeys' | 'propEntries' | 'methodEntries'>,
621
- plugin: ErrorPlugin,
622
- ): void {
623
- if (plugin.props && 'stack' in plugin.props) {
624
- throw new Error(RESERVED_STACK_PROP_ERROR)
625
- }
626
- if (plugin.props && 'message' in plugin.props) {
627
- throw new Error(RESERVED_MESSAGE_PROP_ERROR)
628
- }
629
- Object.assign(resolved.props, plugin.props ?? this._emptyPlugin.props)
630
- Object.assign(resolved.methods, plugin.methods ?? this._emptyPlugin.methods)
631
- resolved.adapt.push(...(plugin.adapt ?? this._emptyPlugin.adapt))
632
- if (typeof plugin.stack !== 'undefined') {
633
- resolved.stack = plugin.stack
634
- }
635
- if (typeof plugin.cause !== 'undefined') {
636
- resolved.cause = plugin.cause
637
- }
638
- if (typeof plugin.message !== 'undefined') {
639
- resolved.message = plugin.message
640
- }
641
- }
642
-
643
- private static _mergeResolvedPlugin(
644
- this: typeof Error0,
645
- base: ErrorPluginResolved,
646
- plugin: ErrorPlugin,
647
- ): ErrorPluginResolved {
648
- const merged: Omit<ErrorPluginResolved, 'propKeys' | 'propEntries' | 'methodEntries'> = {
649
- props: { ...base.props },
650
- methods: { ...base.methods },
651
- adapt: [...base.adapt],
652
- stack: base.stack,
653
- cause: base.cause,
654
- message: base.message,
655
- }
656
- this._applyPlugin(merged, plugin)
657
- return this._indexResolvedPlugin(merged)
658
- }
659
-
660
- private static _getResolvedPlugin(this: typeof Error0): ErrorPluginResolved {
661
- if (Object.prototype.hasOwnProperty.call(this, '_resolvedPlugin') && this._resolvedPlugin) {
662
- return this._resolvedPlugin
663
- }
664
- const resolved: ErrorPluginResolved = {
665
- props: {},
666
- methods: {},
667
- adapt: [],
668
- propKeys: [],
669
- propEntries: [],
670
- methodEntries: [],
671
- }
672
- for (const plugin of this._plugins) {
673
- this._applyPlugin(resolved, plugin)
674
- }
675
- const indexed = this._indexResolvedPlugin(resolved)
676
- Object.defineProperty(this, '_resolvedPlugin', {
677
- value: indexed,
678
- writable: true,
679
- enumerable: false,
680
- configurable: true,
681
- })
682
- return indexed
683
- }
684
-
685
- constructor(message: string, input?: ErrorInput<EmptyPluginsMap>)
686
- constructor(input: { message: string } & ErrorInput<EmptyPluginsMap>)
687
- constructor(
688
- ...args:
689
- | [message: string, input?: ErrorInput<EmptyPluginsMap>]
690
- | [{ message: string } & ErrorInput<EmptyPluginsMap>]
691
- ) {
692
- const [first, second] = args
693
- const input = typeof first === 'string' ? { message: first, ...(second ?? {}) } : first
694
-
695
- super(input.message, { cause: input.cause })
696
- this.name = 'Error0'
697
-
698
- const ctor = this.constructor as typeof Error0
699
- const plugin = ctor._getResolvedPlugin()
700
- // const ownStore = Object.create(null) as ErrorOwnStore
701
- // Object.defineProperty(this, OWN_SYMBOL, { value: ownStore, writable: true, enumerable: false, configurable: true })
702
-
703
- for (const [key, prop] of plugin.propEntries) {
704
- if (key === 'stack') {
705
- continue
706
- }
707
- Object.defineProperty(this, key, {
708
- get: () => this._resolveByKey(key, plugin),
709
- set: (value) => {
710
- this.assign({ [key]: value } as never)
711
- },
712
- enumerable: true,
713
- configurable: true,
714
- })
715
- if (key in input) {
716
- const inputValue = (input as Record<string, unknown>)[key]
717
- const ownValue = typeof prop.init === 'function' ? prop.init(inputValue) : inputValue
718
- this.assign({ [key]: ownValue } as never)
719
- }
720
- }
721
- Error0.fixStack(input.cause)
722
- }
723
-
724
- private static fixStack(cause: unknown): void {
725
- try {
726
- if (process.env.NODE_ENV !== 'production') {
727
- let nextCause = cause
728
- let depth = 0
729
- const maxDepth = 99
730
- while (nextCause && depth < maxDepth) {
731
- ;(globalThis as any).__ERROR0_FIX_STACKTRACE__(nextCause)
732
- nextCause = (nextCause as any).cause
733
- depth++
734
- }
735
- }
736
- } catch {}
737
- }
738
-
739
- static own<TThis extends typeof Error0>(this: TThis, error: unknown): ErrorOwnProps<PluginsMapOf<TThis>>
740
- static own<TThis extends typeof Error0, TKey extends keyof PluginsMapOf<TThis>['props'] & string>(
741
- this: TThis,
742
- error: unknown,
743
- key: TKey,
744
- ): ErrorOwnProps<PluginsMapOf<TThis>>[TKey]
745
- static own(error: unknown, key?: string): unknown {
746
- const error0 = this.from(error)
747
- if (key === undefined) {
748
- return error0.own ?? {}
749
- }
750
- return error0.own?.[key]
751
- }
752
-
753
- static flow<TThis extends typeof Error0, TKey extends keyof PluginsMapOf<TThis>['props'] & string>(
754
- this: TThis,
755
- error: unknown,
756
- key: TKey,
757
- ): Array<ErrorOwnProps<PluginsMapOf<TThis>>[TKey]>
758
- static flow(error: unknown, key: string): unknown[] {
759
- const error0 = this.from(error)
760
- return error0.flow(key as never)
761
- }
762
- flow<TThis extends Error0, TKey extends keyof PluginsMapOfInstance<TThis>['props'] & string>(
763
- this: TThis,
764
- key: TKey,
765
- ): Array<ErrorOwnProps<PluginsMapOfInstance<TThis>>[TKey]>
766
- flow(key: string): unknown[] {
767
- const causes = this.causes(true)
768
- const values = new Array<unknown>(causes.length)
769
- for (let i = 0; i < causes.length; i += 1) {
770
- values[i] = causes[i].own?.[key]
771
- }
772
- return values
773
- }
774
-
775
- private readonly _resolveByKeyCache = new Map<string, unknown>()
776
- private _resolveByKey(key: string, plugin: ErrorPluginResolved): unknown {
777
- // eslint-disable-next-line consistent-this, @typescript-eslint/no-this-alias
778
- const error = this
779
- if (this._resolveByKeyCache.has(key)) {
780
- return this._resolveByKeyCache.get(key)
781
- }
782
- const value = (() => {
783
- try {
784
- const options = {
785
- get flow() {
786
- return error.flow(key as never)
787
- },
788
- own: error.own?.[key],
789
- error,
790
- }
791
- const prop = plugin.props[key]
792
- const resolver = prop.resolve
793
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
794
- if (!resolver) {
795
- return (error as any)[key]
796
- }
797
- return resolver(options as ErrorPluginPropOptionsResolveOptions<any, any>)
798
- } catch {
799
- // eslint-disable-next-line no-console
800
- console.error(`Error0: failed to resolve property ${key}`, error)
801
- return undefined
802
- }
803
- })()
804
- this._resolveByKeyCache.set(key, value)
805
- return value
806
- }
807
-
808
- static resolve<TThis extends typeof Error0>(this: TThis, error: unknown): ErrorResolvedProps<PluginsMapOf<TThis>>
809
- static resolve(error: unknown): Record<string, unknown>
810
- static resolve(error: unknown): Record<string, unknown> {
811
- return this.from(error).resolve()
812
- }
813
- resolve<TThis extends Error0>(this: TThis): ErrorResolvedProps<PluginsMapOfInstance<TThis>>
814
- resolve(): Record<string, unknown> {
815
- const ctor = this.constructor as typeof Error0
816
- const plugin = ctor._getResolvedPlugin()
817
- const resolved: Record<string, unknown> = {}
818
- for (const key of plugin.propKeys) {
819
- resolved[key] = this._resolveByKey(key, plugin)
820
- }
821
- return resolved
822
- }
823
-
824
- static causes(error: unknown, instancesOnly?: false): unknown[]
825
- static causes<T extends typeof Error0>(this: T, error: unknown, instancesOnly: true): Array<InstanceType<T>>
826
- static causes(error: unknown, instancesOnly?: boolean): unknown[] {
827
- const causes: unknown[] = []
828
- let current: unknown = error
829
- const seen = new Set<unknown>()
830
- let depth = 0
831
- while (depth < this.MAX_CAUSES_DEPTH) {
832
- if (seen.has(current)) {
833
- break
834
- }
835
- seen.add(current)
836
- if (!instancesOnly || this.is(current)) {
837
- causes.push(current)
838
- }
839
- if (!current || typeof current !== 'object') {
840
- break
841
- }
842
- current = (current as { cause?: unknown }).cause
843
- depth += 1
844
- }
845
- return causes
846
- }
847
- causes<TThis extends Error0>(this: TThis, instancesOnly?: false): [TThis, ...unknown[]]
848
- causes<TThis extends Error0>(this: TThis, instancesOnly: true): [TThis, ...TThis[]]
849
- causes(instancesOnly?: boolean): unknown[] {
850
- const ctor = this.constructor as typeof Error0
851
- if (instancesOnly) {
852
- return ctor.causes(this, true)
853
- }
854
- return ctor.causes(this)
855
- }
856
-
857
- static is<T extends typeof Error0>(this: T, error: unknown): error is InstanceType<T> {
858
- return error instanceof this
859
- }
860
-
861
- static isSerialized(error: unknown): error is Record<string, unknown> {
862
- return !this.is(error) && typeof error === 'object' && error !== null && 'name' in error && error.name === 'Error0'
863
- }
864
-
865
- static from<TThis extends typeof Error0>(this: TThis, error: unknown): InstanceType<TThis>
866
- static from(error: unknown): Error0 {
867
- if (this.is(error)) {
868
- return error
869
- }
870
- if (this.isSerialized(error)) {
871
- return this._fromSerialized(error)
872
- }
873
- return this._fromNonError0(error)
874
- }
875
-
876
- static round<TThis extends typeof Error0>(this: TThis, error: unknown, isPublic?: boolean): InstanceType<TThis>
877
- static round(error: unknown, isPublic = false): Error0 {
878
- return this.from(error).round(isPublic)
879
- }
880
- round<TThis extends Error0>(this: TThis, isPublic = true): TThis {
881
- const ctor = this.constructor as typeof Error0
882
- return ctor.from(this.serialize(isPublic)) as TThis
883
- }
884
-
885
- // static flat<TThis extends typeof Error0>(this: TThis, error: unknown, keepCauses?: boolean): InstanceType<TThis>
886
- // static flat(error: unknown, keepCauses = false): Error0 {
887
- // return this.from(error).flat(keepCauses)
888
- // }
889
- // flat<TThis extends Error0>(this: TThis, keepCauses = false): TThis {
890
- // const ctor = this.constructor as typeof Error0
891
- // // eslint-disable-next-line new-cap
892
- // const error = new ctor(this.message) as TThis
893
- // if (keepCauses) {
894
- // error.cause = this.cause
895
- // }
896
- // error.assign({
897
- // // ...this.own,
898
- // ...this.resolve(),
899
- // } as never)
900
- // error.stack =
901
- // this.causes()
902
- // .map((cause, index) => {
903
- // return cause instanceof Error && cause.stack && typeof cause.stack === 'string'
904
- // ? index === 0
905
- // ? cause.stack
906
- // : cause.stack.split('\n').slice(1).join('\n')
907
- // : undefined
908
- // })
909
- // .join('\n') || undefined
910
- // return error
911
- // }
912
-
913
- static assign<TThis extends typeof Error0>(
914
- this: TThis,
915
- error: unknown,
916
- props: Partial<ErrorOwnProps<PluginsMapOf<TThis>>>,
917
- ): InstanceType<TThis>
918
- static assign(error: unknown, props: Record<string, unknown>): Error0 {
919
- const error0 = this.from(error)
920
- return error0.assign(props)
921
- }
922
- assign<TThis extends Error0>(this: TThis, props: Partial<ErrorOwnProps<PluginsMapOfInstance<TThis>>>): TThis
923
- assign(props: Record<string, unknown>): this {
924
- this.own = Object.assign(this.own ?? {}, props)
925
- this._resolveByKeyCache.clear()
926
- // const values = Object.values(props)
927
- // if (values.every((value) => value === undefined)) {
928
- // this.own = undefined
929
- // }
930
- return this
931
- }
932
-
933
- private static _applyAdapt(error: Error0): Error0 {
934
- const plugin = this._getResolvedPlugin()
935
- for (const adapt of plugin.adapt) {
936
- const adapted = adapt(error as any)
937
- if (adapted && typeof adapted === 'object') {
938
- error.assign(adapted)
939
- }
940
- }
941
- return error
942
- }
943
-
944
- private static _fromSerialized(error: unknown): Error0 {
945
- const message = this._extractMessage(error)
946
- if (typeof error !== 'object' || error === null) {
947
- return this._applyAdapt(new this(message, { cause: error }))
948
- }
949
- const errorRecord = error as Record<string, unknown>
950
- const recreated = new this(message)
951
- const plugin = this._getResolvedPlugin()
952
- for (const [key, prop] of plugin.propEntries) {
953
- if (prop.deserialize === false) {
954
- continue
955
- }
956
- if (!(key in errorRecord)) {
957
- continue
958
- }
959
- try {
960
- const value = prop.deserialize({ value: errorRecord[key], record: errorRecord })
961
- ;(recreated as unknown as Record<string, unknown>)[key] = value
962
- } catch {
963
- // eslint-disable-next-line no-console
964
- console.error(`Error0: failed to deserialize property ${key}`, errorRecord)
965
- }
966
- }
967
- if ('stack' in errorRecord && typeof errorRecord.stack === 'string') {
968
- recreated.stack = errorRecord.stack
969
- }
970
- const causePlugin = plugin.cause
971
- if (causePlugin && 'cause' in errorRecord) {
972
- try {
973
- ;(recreated as { cause?: unknown }).cause = causePlugin.deserialize({
974
- cause: errorRecord.cause,
975
- error: errorRecord,
976
- isSerialized: (serializedCause) => this.isSerialized(serializedCause),
977
- fromSerialized: (serializedCause) => this._fromSerialized(serializedCause),
978
- })
979
- } catch {
980
- // eslint-disable-next-line no-console
981
- console.error('Error0: failed to deserialize cause', errorRecord)
982
- }
983
- }
984
- return recreated
985
- }
986
-
987
- private static _fromNonError0(error: unknown): Error0 {
988
- const message = this._extractMessage(error)
989
- return this._applyAdapt(new this(message, { cause: error }))
990
- }
991
-
992
- private static _extractMessage(error: unknown): string {
993
- return (
994
- (typeof error === 'string'
995
- ? error
996
- : typeof error === 'object' && error !== null && 'message' in error && typeof error.message === 'string'
997
- ? error.message
998
- : undefined) || 'Unknown error'
999
- )
1000
- }
1001
-
1002
- private static _useWithPlugin(
1003
- this: typeof Error0,
1004
- plugin: ErrorPlugin<ErrorPluginProps, ErrorPluginMethods>,
1005
- ): ClassError0 {
1006
- const Base = this as unknown as typeof Error0
1007
- const Error0Extended = class Error0 extends Base {}
1008
- ;(Error0Extended as typeof Error0)._plugins = [...Base._plugins, plugin]
1009
- const resolved = this._mergeResolvedPlugin(Base._getResolvedPlugin(), plugin)
1010
- ;(Error0Extended as typeof Error0)._resolvedPlugin = resolved
1011
- for (const [key, method] of resolved.methodEntries) {
1012
- Object.defineProperty((Error0Extended as typeof Error0).prototype, key, {
1013
- value: function (...args: unknown[]) {
1014
- return method(this as Error0, ...args)
1015
- },
1016
- writable: true,
1017
- enumerable: true,
1018
- configurable: true,
1019
- })
1020
- Object.defineProperty(Error0Extended, key, {
1021
- value: function (error: unknown, ...args: unknown[]) {
1022
- return method(this.from(error), ...args)
1023
- },
1024
- writable: true,
1025
- enumerable: true,
1026
- configurable: true,
1027
- })
1028
- }
1029
-
1030
- return Error0Extended as unknown as ClassError0
1031
- }
1032
-
1033
- private static _pluginFromBuilder(plugin: PluginError0): ErrorPlugin<ErrorPluginProps, ErrorPluginMethods> {
1034
- const pluginRecord = plugin as unknown as {
1035
- _plugin: ErrorPlugin<ErrorPluginProps, ErrorPluginMethods>
1036
- }
1037
- return {
1038
- props: { ...(pluginRecord._plugin.props ?? {}) },
1039
- methods: { ...(pluginRecord._plugin.methods ?? {}) },
1040
- adapt: [...(pluginRecord._plugin.adapt ?? [])],
1041
- stack: pluginRecord._plugin.stack,
1042
- cause: pluginRecord._plugin.cause,
1043
- message: pluginRecord._plugin.message,
1044
- }
1045
- }
1046
-
1047
- static use<TThis extends typeof Error0, TBuilder extends PluginError0>(
1048
- this: TThis,
1049
- plugin: TBuilder,
1050
- ): ClassError0<ExtendErrorPluginsMap<PluginsMapOf<TThis>, PluginOfBuilder<TBuilder>>>
1051
- static use<
1052
- TThis extends typeof Error0,
1053
- TKey extends string,
1054
- TInputValue = undefined,
1055
- TOutputValue = unknown,
1056
- TResolveValue extends TOutputValue | undefined = TOutputValue | undefined,
1057
- >(
1058
- this: TThis,
1059
- kind: 'prop',
1060
- key: TKey,
1061
- value: ErrorPluginPropOptionsDefinition<
1062
- TInputValue,
1063
- TOutputValue,
1064
- ErrorInstanceOfMap<PluginsMapOf<TThis>>,
1065
- TResolveValue
1066
- >,
1067
- ): ClassError0<ExtendErrorPluginsMapWithProp<PluginsMapOf<TThis>, TKey, TInputValue, TOutputValue, TResolveValue>>
1068
- static use<
1069
- TThis extends typeof Error0,
1070
- TKey extends string,
1071
- TMethod extends (error: ErrorInstanceOfMap<PluginsMapOf<TThis>>, ...args: any[]) => any,
1072
- >(
1073
- this: TThis,
1074
- kind: 'method',
1075
- key: TKey,
1076
- value: TMethod,
1077
- ): ClassError0<ExtendErrorPluginsMapWithMethod<PluginsMapOf<TThis>, TKey, TMethod>>
1078
- static use<TThis extends typeof Error0>(
1079
- this: TThis,
1080
- kind: 'adapt',
1081
- value: ErrorPluginAdaptFn<ErrorInstanceOfMap<PluginsMapOf<TThis>>, ErrorResolvedProps<PluginsMapOf<TThis>>>,
1082
- ): ClassError0<PluginsMapOf<TThis>>
1083
- static use<TThis extends typeof Error0>(
1084
- this: TThis,
1085
- kind: 'stack',
1086
- value: ErrorPluginStack<ErrorInstanceOfMap<PluginsMapOf<TThis>>>,
1087
- ): ClassError0<PluginsMapOf<TThis>>
1088
- static use<TThis extends typeof Error0>(
1089
- this: TThis,
1090
- kind: 'cause',
1091
- value: ErrorPluginCause<ErrorInstanceOfMap<PluginsMapOf<TThis>>>,
1092
- ): ClassError0<PluginsMapOf<TThis>>
1093
- static use<TThis extends typeof Error0>(
1094
- this: TThis,
1095
- kind: 'message',
1096
- value: ErrorPluginMessage<ErrorInstanceOfMap<PluginsMapOf<TThis>>>,
1097
- ): ClassError0<PluginsMapOf<TThis>>
1098
- static use(
1099
- this: typeof Error0,
1100
- first: PluginError0 | 'prop' | 'method' | 'adapt' | 'stack' | 'cause' | 'message',
1101
- key?: unknown,
1102
- value?: ErrorPluginPropOptionsDefinition<unknown> | ErrorPluginMethodFn<unknown>,
1103
- ): ClassError0<any> {
1104
- if (first instanceof PluginError0) {
1105
- return this._useWithPlugin(this._pluginFromBuilder(first))
1106
- }
1107
- if (first === 'stack') {
1108
- if (typeof key === 'undefined') {
1109
- throw new Error('Error0.use("stack", value) requires stack plugin value')
1110
- }
1111
- if (typeof key !== 'object' || key === null || typeof (key as { serialize?: unknown }).serialize !== 'function') {
1112
- throw new Error('Error0.use("stack", value) expects { serialize: function }')
1113
- }
1114
- return this._useWithPlugin({
1115
- stack: key as ErrorPluginStack,
1116
- })
1117
- }
1118
- if (first === 'cause') {
1119
- if (typeof key === 'undefined') {
1120
- throw new Error('Error0.use("cause", value) requires cause plugin value')
1121
- }
1122
- if (
1123
- typeof key !== 'object' ||
1124
- key === null ||
1125
- typeof (key as { serialize?: unknown }).serialize !== 'function' ||
1126
- typeof (key as { deserialize?: unknown }).deserialize !== 'function'
1127
- ) {
1128
- throw new Error('Error0.use("cause", value) expects { serialize: function, deserialize: function }')
1129
- }
1130
- return this._useWithPlugin({
1131
- cause: key as ErrorPluginCause,
1132
- })
1133
- }
1134
- if (first === 'message') {
1135
- if (typeof key === 'undefined') {
1136
- throw new Error('Error0.use("message", value) requires message plugin value')
1137
- }
1138
- if (typeof key !== 'object' || key === null || typeof (key as { serialize?: unknown }).serialize !== 'function') {
1139
- throw new Error('Error0.use("message", value) expects { serialize: function }')
1140
- }
1141
- return this._useWithPlugin({
1142
- message: key as ErrorPluginMessage,
1143
- })
1144
- }
1145
- if (first === 'adapt') {
1146
- if (typeof key !== 'function') {
1147
- throw new Error('Error0.use("adapt", value) requires adapt function')
1148
- }
1149
- return this._useWithPlugin({
1150
- adapt: [key as ErrorPluginAdaptFn<Error0, Record<string, unknown>>],
1151
- })
1152
- }
1153
- if (typeof key !== 'string' || value === undefined) {
1154
- throw new Error('Error0.use(kind, key, value) requires key and value')
1155
- }
1156
-
1157
- if (first === 'prop') {
1158
- if (key === 'stack') {
1159
- throw new Error(RESERVED_STACK_PROP_ERROR)
1160
- }
1161
- if (key === 'message') {
1162
- throw new Error(RESERVED_MESSAGE_PROP_ERROR)
1163
- }
1164
- return this._useWithPlugin({
1165
- props: { [key]: fromPropOptionsDefinition(value as ErrorPluginPropOptionsDefinition<any, any>) },
1166
- })
1167
- }
1168
- return this._useWithPlugin({
1169
- methods: { [key]: value as ErrorPluginMethodFn<unknown> },
1170
- })
1171
- }
1172
-
1173
- static plugin(): PluginError0 {
1174
- return new PluginError0()
1175
- }
1176
-
1177
- static serialize(error: unknown, isPublic = true): Record<string, unknown> {
1178
- return this.from(error).serialize(isPublic)
1179
- }
1180
-
1181
- serialize(isPublic = true): Record<string, unknown> {
1182
- // eslint-disable-next-line consistent-this, @typescript-eslint/no-this-alias
1183
- const error0 = this
1184
- const ctor = error0.constructor as typeof Error0
1185
- const plugin = ctor._getResolvedPlugin()
1186
- const messagePlugin = plugin.message
1187
- let serializedMessage: unknown = error0.message
1188
- try {
1189
- if (messagePlugin) {
1190
- serializedMessage = messagePlugin.serialize({ value: error0.message, error: error0, isPublic })
1191
- }
1192
- } catch {
1193
- // eslint-disable-next-line no-console
1194
- console.error('Error0: failed to serialize message', error0)
1195
- serializedMessage = error0.message
1196
- }
1197
- const json: Record<string, unknown> = {
1198
- name: error0.name,
1199
- }
1200
- if (serializedMessage !== undefined) {
1201
- json.message = serializedMessage
1202
- }
1203
-
1204
- for (const [key, prop] of plugin.propEntries) {
1205
- if (prop.serialize === false) {
1206
- continue
1207
- }
1208
- try {
1209
- const options = {
1210
- get flow() {
1211
- return error0.flow(key as never)
1212
- },
1213
- get resolved() {
1214
- return error0._resolveByKey(key, plugin)
1215
- },
1216
- own: error0.own?.[key],
1217
- error: error0,
1218
- isPublic,
1219
- }
1220
- const jsonValue = prop.serialize(options as ErrorPluginPropSerializeOptions<any, any, any>)
1221
- if (jsonValue !== undefined) {
1222
- json[key] = jsonValue
1223
- }
1224
- } catch {
1225
- // eslint-disable-next-line no-console
1226
- console.error(`Error0: failed to serialize property ${key}`, error0)
1227
- }
1228
- }
1229
- const stackPlugin = plugin.stack
1230
- try {
1231
- let serializedStack: unknown
1232
- if (stackPlugin) {
1233
- serializedStack = stackPlugin.serialize({ value: error0.stack, error: error0, isPublic })
1234
- } else {
1235
- serializedStack = isPublic ? undefined : error0.stack
1236
- }
1237
- if (serializedStack !== undefined) {
1238
- json.stack = serializedStack
1239
- }
1240
- } catch {
1241
- // eslint-disable-next-line no-console
1242
- console.error('Error0: failed to serialize stack', error0)
1243
- }
1244
- const causePlugin = plugin.cause
1245
- if (causePlugin?.serialize) {
1246
- try {
1247
- const serializedCause = causePlugin.serialize({
1248
- cause: (error0 as { cause?: unknown }).cause,
1249
- error: error0,
1250
- isPublic,
1251
- is: (cause) => ctor.is(cause),
1252
- serialize: (cause) => ctor.serialize(cause, isPublic),
1253
- })
1254
- if (serializedCause !== undefined) {
1255
- json.cause = serializedCause
1256
- }
1257
- } catch {
1258
- // eslint-disable-next-line no-console
1259
- console.error('Error0: failed to serialize cause', error0)
1260
- }
1261
- }
1262
- return json
1263
- }
1264
- }