@devp0nt/error0 1.0.0-next.40 → 1.0.0-next.41

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 CHANGED
@@ -1,9 +1,13 @@
1
1
  export type ErrorExtensionPropOptions<TInputValue, TOutputValue, TError extends Error0 = Error0> = {
2
- input: (value: TInputValue) => TOutputValue
3
- output: (error: TError) => TOutputValue
4
- serialize: (value: TOutputValue, error: TError, isPublic: boolean) => unknown
2
+ init: (input: TInputValue) => TOutputValue
3
+ resolve: (options: {
4
+ value: TOutputValue | undefined
5
+ flow: Array<TOutputValue | undefined>
6
+ error: TError
7
+ }) => TOutputValue | undefined
8
+ serialize: (options: { value: TOutputValue; error: TError; isPublic: boolean }) => unknown
9
+ deserialize: (options: { value: unknown; serialized: Record<string, unknown> }) => TOutputValue | undefined
5
10
  }
6
- export type ErrorExtensionCopmputedFn<TOutputValue, TError extends Error0 = Error0> = (error: TError) => TOutputValue
7
11
  export type ErrorExtensionMethodFn<
8
12
  TOutputValue,
9
13
  TArgs extends unknown[] = unknown[],
@@ -20,16 +24,13 @@ type ErrorMethodRecord = {
20
24
  }
21
25
 
22
26
  export type ErrorExtensionProps = { [key: string]: ErrorExtensionPropOptions<any, any> }
23
- export type ErrorExtensionComputed = { [key: string]: ErrorExtensionCopmputedFn<any> }
24
27
  export type ErrorExtensionMethods = { [key: string]: ErrorExtensionMethodFn<any, any[]> }
25
28
 
26
29
  export type ErrorExtension<
27
30
  TProps extends ErrorExtensionProps = Record<never, never>,
28
- TComputed extends ErrorExtensionComputed = Record<never, never>,
29
31
  TMethods extends ErrorExtensionMethods = Record<never, never>,
30
32
  > = {
31
33
  props?: TProps
32
- computed?: TComputed
33
34
  methods?: TMethods
34
35
  refine?: Array<ErrorExtensionRefineFn<Error0, ExtensionOutputProps<TProps>>>
35
36
  }
@@ -39,11 +40,6 @@ type AddPropToExtensionProps<
39
40
  TInputValue,
40
41
  TOutputValue,
41
42
  > = TProps & Record<TKey, ErrorExtensionPropOptions<TInputValue, TOutputValue>>
42
- type AddComputedToExtensionComputed<
43
- TComputed extends ErrorExtensionComputed,
44
- TKey extends string,
45
- TOutputValue,
46
- > = TComputed & Record<TKey, ErrorExtensionCopmputedFn<TOutputValue>>
47
43
  type AddMethodToExtensionMethods<
48
44
  TMethods extends ErrorExtensionMethods,
49
45
  TKey extends string,
@@ -54,8 +50,7 @@ type ExtensionOutputProps<TProps extends ErrorExtensionProps> = {
54
50
  [TKey in keyof TProps]: TProps[TKey] extends ErrorExtensionPropOptions<any, infer TOutputValue> ? TOutputValue : never
55
51
  }
56
52
  export type ErrorExtensionsMap = {
57
- props: Record<string, { input: unknown; output: unknown }>
58
- computed: Record<string, unknown>
53
+ props: Record<string, { init: unknown; resolve: unknown }>
59
54
  methods: Record<string, ErrorMethodRecord>
60
55
  }
61
56
  export type IsEmptyObject<T> = keyof T extends never ? true : false
@@ -67,14 +62,11 @@ export type ErrorInput<TExtensionsMap extends ErrorExtensionsMap> =
67
62
  ? ErrorInputBase
68
63
  : ErrorInputBase &
69
64
  Partial<{
70
- [TKey in keyof TExtensionsMap['props']]: TExtensionsMap['props'][TKey]['input']
65
+ [TKey in keyof TExtensionsMap['props']]: TExtensionsMap['props'][TKey]['init']
71
66
  }>
72
67
 
73
68
  type ErrorOutputProps<TExtensionsMap extends ErrorExtensionsMap> = {
74
- [TKey in keyof TExtensionsMap['props']]: TExtensionsMap['props'][TKey]['output']
75
- }
76
- type ErrorOutputComputed<TExtensionsMap extends ErrorExtensionsMap> = {
77
- [TKey in keyof TExtensionsMap['computed']]: TExtensionsMap['computed'][TKey]
69
+ [TKey in keyof TExtensionsMap['props']]?: TExtensionsMap['props'][TKey]['resolve']
78
70
  }
79
71
  type ErrorOutputMethods<TExtensionsMap extends ErrorExtensionsMap> = {
80
72
  [TKey in keyof TExtensionsMap['methods']]: TExtensionsMap['methods'][TKey] extends {
@@ -85,7 +77,6 @@ type ErrorOutputMethods<TExtensionsMap extends ErrorExtensionsMap> = {
85
77
  : never
86
78
  }
87
79
  export type ErrorOutput<TExtensionsMap extends ErrorExtensionsMap> = ErrorOutputProps<TExtensionsMap> &
88
- ErrorOutputComputed<TExtensionsMap> &
89
80
  ErrorOutputMethods<TExtensionsMap>
90
81
 
91
82
  type ErrorStaticMethods<TExtensionsMap extends ErrorExtensionsMap> = {
@@ -98,14 +89,12 @@ type ErrorStaticMethods<TExtensionsMap extends ErrorExtensionsMap> = {
98
89
  }
99
90
 
100
91
  type EmptyExtensionsMap = {
101
- props: Record<never, { input: never; output: never }>
102
- computed: Record<never, never>
92
+ props: Record<never, { init: never; resolve: never }>
103
93
  methods: Record<never, ErrorMethodRecord>
104
94
  }
105
95
 
106
96
  type ErrorExtensionResolved = {
107
97
  props: Record<string, ErrorExtensionPropOptions<unknown, unknown>>
108
- computed: Record<string, ErrorExtensionCopmputedFn<unknown>>
109
98
  methods: Record<string, ErrorExtensionMethodFn<unknown>>
110
99
  refine: Array<ErrorExtensionRefineFn<Error0, Record<string, unknown>>>
111
100
  }
@@ -114,14 +103,7 @@ type ExtensionPropsMapOf<TExtension extends ErrorExtension> = {
114
103
  [TKey in keyof NonNullable<TExtension['props']>]: NonNullable<
115
104
  TExtension['props']
116
105
  >[TKey] extends ErrorExtensionPropOptions<infer TInputValue, infer TOutputValue>
117
- ? { input: TInputValue; output: TOutputValue }
118
- : never
119
- }
120
- type ExtensionComputedMapOf<TExtension extends ErrorExtension> = {
121
- [TKey in keyof NonNullable<TExtension['computed']>]: NonNullable<
122
- TExtension['computed']
123
- >[TKey] extends ErrorExtensionCopmputedFn<infer TOutputValue>
124
- ? TOutputValue
106
+ ? { init: TInputValue; resolve: TOutputValue }
125
107
  : never
126
108
  }
127
109
  type ExtensionMethodsMapOf<TExtension extends ErrorExtension> = {
@@ -134,12 +116,10 @@ type ExtensionMethodsMapOf<TExtension extends ErrorExtension> = {
134
116
  }
135
117
  type ErrorExtensionsMapOfExtension<TExtension extends ErrorExtension> = {
136
118
  props: ExtensionPropsMapOf<TExtension>
137
- computed: ExtensionComputedMapOf<TExtension>
138
119
  methods: ExtensionMethodsMapOf<TExtension>
139
120
  }
140
121
  type ExtendErrorExtensionsMap<TMap extends ErrorExtensionsMap, TExtension extends ErrorExtension> = {
141
122
  props: TMap['props'] & ErrorExtensionsMapOfExtension<TExtension>['props']
142
- computed: TMap['computed'] & ErrorExtensionsMapOfExtension<TExtension>['computed']
143
123
  methods: TMap['methods'] & ErrorExtensionsMapOfExtension<TExtension>['methods']
144
124
  }
145
125
  type ExtendErrorExtensionsMapWithProp<
@@ -148,14 +128,6 @@ type ExtendErrorExtensionsMapWithProp<
148
128
  TInputValue,
149
129
  TOutputValue,
150
130
  > = ExtendErrorExtensionsMap<TMap, ErrorExtension<Record<TKey, ErrorExtensionPropOptions<TInputValue, TOutputValue>>>>
151
- type ExtendErrorExtensionsMapWithComputed<
152
- TMap extends ErrorExtensionsMap,
153
- TKey extends string,
154
- TOutputValue,
155
- > = ExtendErrorExtensionsMap<
156
- TMap,
157
- ErrorExtension<Record<never, never>, Record<TKey, ErrorExtensionCopmputedFn<TOutputValue>>>
158
- >
159
131
  type ExtendErrorExtensionsMapWithMethod<
160
132
  TMap extends ErrorExtensionsMap,
161
133
  TKey extends string,
@@ -163,7 +135,7 @@ type ExtendErrorExtensionsMapWithMethod<
163
135
  TOutputValue,
164
136
  > = ExtendErrorExtensionsMap<
165
137
  TMap,
166
- ErrorExtension<Record<never, never>, Record<never, never>, Record<TKey, ErrorExtensionMethodFn<TOutputValue, TArgs>>>
138
+ ErrorExtension<Record<never, never>, Record<TKey, ErrorExtensionMethodFn<TOutputValue, TArgs>>>
167
139
  >
168
140
 
169
141
  type ExtensionsMapOf<TClass> = TClass extends { __extensionsMap?: infer TExtensionsMap }
@@ -174,40 +146,29 @@ type ExtensionsMapOf<TClass> = TClass extends { __extensionsMap?: infer TExtensi
174
146
 
175
147
  type ExtensionsMapFromParts<
176
148
  TProps extends ErrorExtensionProps,
177
- TComputed extends ErrorExtensionComputed,
178
149
  TMethods extends ErrorExtensionMethods,
179
- > = ErrorExtensionsMapOfExtension<ErrorExtension<TProps, TComputed, TMethods>>
150
+ > = ErrorExtensionsMapOfExtension<ErrorExtension<TProps, TMethods>>
180
151
  type ErrorInstanceOfMap<TMap extends ErrorExtensionsMap> = Error0 & ErrorOutput<TMap>
181
- type BuilderError0<
182
- TProps extends ErrorExtensionProps,
183
- TComputed extends ErrorExtensionComputed,
184
- TMethods extends ErrorExtensionMethods,
185
- > = Error0 & ErrorOutput<ExtensionsMapFromParts<TProps, TComputed, TMethods>>
152
+ type BuilderError0<TProps extends ErrorExtensionProps, TMethods extends ErrorExtensionMethods> = Error0 &
153
+ ErrorOutput<ExtensionsMapFromParts<TProps, TMethods>>
186
154
 
187
155
  type ExtensionOfBuilder<TBuilder> =
188
- TBuilder extends ExtensionError0<infer TProps, infer TComputed, infer TMethods>
189
- ? ErrorExtension<TProps, TComputed, TMethods>
190
- : never
191
-
192
- export type ErrorFlowPolicy = 'instance' | 'error0' | 'likeError0' | 'all'
156
+ TBuilder extends ExtensionError0<infer TProps, infer TMethods> ? ErrorExtension<TProps, TMethods> : never
193
157
 
194
158
  export class ExtensionError0<
195
159
  TProps extends ErrorExtensionProps = Record<never, never>,
196
- TComputed extends ErrorExtensionComputed = Record<never, never>,
197
160
  TMethods extends ErrorExtensionMethods = Record<never, never>,
198
161
  > {
199
- private readonly _extension: ErrorExtension<ErrorExtensionProps, ErrorExtensionComputed, ErrorExtensionMethods>
162
+ private readonly _extension: ErrorExtension<ErrorExtensionProps, ErrorExtensionMethods>
200
163
 
201
164
  readonly Infer = undefined as unknown as {
202
165
  props: TProps
203
- computed: TComputed
204
166
  methods: TMethods
205
167
  }
206
168
 
207
- constructor(extension?: ErrorExtension<ErrorExtensionProps, ErrorExtensionComputed, ErrorExtensionMethods>) {
169
+ constructor(extension?: ErrorExtension<ErrorExtensionProps, ErrorExtensionMethods>) {
208
170
  this._extension = {
209
171
  props: { ...(extension?.props ?? {}) },
210
- computed: { ...(extension?.computed ?? {}) },
211
172
  methods: { ...(extension?.methods ?? {}) },
212
173
  refine: [...(extension?.refine ?? [])],
213
174
  }
@@ -215,60 +176,44 @@ export class ExtensionError0<
215
176
 
216
177
  prop<TKey extends string, TInputValue, TOutputValue>(
217
178
  key: TKey,
218
- value: ErrorExtensionPropOptions<TInputValue, TOutputValue, BuilderError0<TProps, TComputed, TMethods>>,
219
- ): ExtensionError0<AddPropToExtensionProps<TProps, TKey, TInputValue, TOutputValue>, TComputed, TMethods> {
179
+ value: ErrorExtensionPropOptions<TInputValue, TOutputValue, BuilderError0<TProps, TMethods>>,
180
+ ): ExtensionError0<AddPropToExtensionProps<TProps, TKey, TInputValue, TOutputValue>, TMethods> {
220
181
  return this.extend('prop', key, value)
221
182
  }
222
183
 
223
- computed<TKey extends string, TOutputValue>(
224
- key: TKey,
225
- value: ErrorExtensionCopmputedFn<TOutputValue, BuilderError0<TProps, TComputed, TMethods>>,
226
- ): ExtensionError0<TProps, AddComputedToExtensionComputed<TComputed, TKey, TOutputValue>, TMethods> {
227
- return this.extend('computed', key, value)
228
- }
229
-
230
184
  method<TKey extends string, TArgs extends unknown[], TOutputValue>(
231
185
  key: TKey,
232
- value: ErrorExtensionMethodFn<TOutputValue, TArgs, BuilderError0<TProps, TComputed, TMethods>>,
233
- ): ExtensionError0<TProps, TComputed, AddMethodToExtensionMethods<TMethods, TKey, TArgs, TOutputValue>> {
186
+ value: ErrorExtensionMethodFn<TOutputValue, TArgs, BuilderError0<TProps, TMethods>>,
187
+ ): ExtensionError0<TProps, AddMethodToExtensionMethods<TMethods, TKey, TArgs, TOutputValue>> {
234
188
  return this.extend('method', key, value)
235
189
  }
236
190
 
237
191
  refine(
238
- value: ErrorExtensionRefineFn<BuilderError0<TProps, TComputed, TMethods>, ExtensionOutputProps<TProps>>,
239
- ): ExtensionError0<TProps, TComputed, TMethods> {
192
+ value: ErrorExtensionRefineFn<BuilderError0<TProps, TMethods>, ExtensionOutputProps<TProps>>,
193
+ ): ExtensionError0<TProps, TMethods> {
240
194
  return this.extend('refine', value)
241
195
  }
242
196
 
243
197
  extend<TKey extends string, TInputValue, TOutputValue>(
244
198
  kind: 'prop',
245
199
  key: TKey,
246
- value: ErrorExtensionPropOptions<TInputValue, TOutputValue, BuilderError0<TProps, TComputed, TMethods>>,
247
- ): ExtensionError0<AddPropToExtensionProps<TProps, TKey, TInputValue, TOutputValue>, TComputed, TMethods>
248
- extend<TKey extends string, TOutputValue>(
249
- kind: 'computed',
250
- key: TKey,
251
- value: ErrorExtensionCopmputedFn<TOutputValue, BuilderError0<TProps, TComputed, TMethods>>,
252
- ): ExtensionError0<TProps, AddComputedToExtensionComputed<TComputed, TKey, TOutputValue>, TMethods>
200
+ value: ErrorExtensionPropOptions<TInputValue, TOutputValue, BuilderError0<TProps, TMethods>>,
201
+ ): ExtensionError0<AddPropToExtensionProps<TProps, TKey, TInputValue, TOutputValue>, TMethods>
253
202
  extend<TKey extends string, TArgs extends unknown[], TOutputValue>(
254
203
  kind: 'method',
255
204
  key: TKey,
256
- value: ErrorExtensionMethodFn<TOutputValue, TArgs, BuilderError0<TProps, TComputed, TMethods>>,
257
- ): ExtensionError0<TProps, TComputed, AddMethodToExtensionMethods<TMethods, TKey, TArgs, TOutputValue>>
205
+ value: ErrorExtensionMethodFn<TOutputValue, TArgs, BuilderError0<TProps, TMethods>>,
206
+ ): ExtensionError0<TProps, AddMethodToExtensionMethods<TMethods, TKey, TArgs, TOutputValue>>
258
207
  extend(
259
208
  kind: 'refine',
260
- value: ErrorExtensionRefineFn<BuilderError0<TProps, TComputed, TMethods>, ExtensionOutputProps<TProps>>,
261
- ): ExtensionError0<TProps, TComputed, TMethods>
209
+ value: ErrorExtensionRefineFn<BuilderError0<TProps, TMethods>, ExtensionOutputProps<TProps>>,
210
+ ): ExtensionError0<TProps, TMethods>
262
211
  extend(
263
- kind: 'prop' | 'computed' | 'method' | 'refine',
212
+ kind: 'prop' | 'method' | 'refine',
264
213
  keyOrValue: string | ErrorExtensionRefineFn<any, any>,
265
- value?:
266
- | ErrorExtensionPropOptions<unknown, unknown, any>
267
- | ErrorExtensionCopmputedFn<unknown, any>
268
- | ErrorExtensionMethodFn<unknown, unknown[], any>,
269
- ): ExtensionError0<any, any, any> {
214
+ value?: ErrorExtensionPropOptions<unknown, unknown, any> | ErrorExtensionMethodFn<unknown, unknown[], any>,
215
+ ): ExtensionError0<any, any> {
270
216
  const nextProps: ErrorExtensionProps = { ...(this._extension.props ?? {}) }
271
- const nextComputed: ErrorExtensionComputed = { ...(this._extension.computed ?? {}) }
272
217
  const nextMethods: ErrorExtensionMethods = { ...(this._extension.methods ?? {}) }
273
218
  const nextRefine: Array<ErrorExtensionRefineFn<Error0, Record<string, unknown>>> = [
274
219
  ...(this._extension.refine ?? []),
@@ -279,12 +224,6 @@ export class ExtensionError0<
279
224
  throw new Error('ExtensionError0.extend("prop", key, value) requires value')
280
225
  }
281
226
  nextProps[key] = value as ErrorExtensionPropOptions<any, any>
282
- } else if (kind === 'computed') {
283
- const key = keyOrValue as string
284
- if (value === undefined) {
285
- throw new Error('ExtensionError0.extend("computed", key, value) requires value')
286
- }
287
- nextComputed[key] = value as ErrorExtensionCopmputedFn<any>
288
227
  } else if (kind === 'method') {
289
228
  const key = keyOrValue as string
290
229
  if (value === undefined) {
@@ -296,7 +235,6 @@ export class ExtensionError0<
296
235
  }
297
236
  return new ExtensionError0({
298
237
  props: nextProps,
299
- computed: nextComputed,
300
238
  methods: nextMethods,
301
239
  refine: nextRefine,
302
240
  })
@@ -308,7 +246,18 @@ export type ClassError0<TExtensionsMap extends ErrorExtensionsMap = EmptyExtensi
308
246
  new (input: { message: string } & ErrorInput<TExtensionsMap>): Error0 & ErrorOutput<TExtensionsMap>
309
247
  readonly __extensionsMap?: TExtensionsMap
310
248
  from: (error: unknown) => Error0 & ErrorOutput<TExtensionsMap>
311
- serialize: (error: unknown, isPublic?: boolean) => object
249
+ serialize: (error: unknown, isPublic?: boolean) => Record<string, unknown>
250
+ prop: <TKey extends string, TInputValue, TOutputValue>(
251
+ key: TKey,
252
+ value: ErrorExtensionPropOptions<TInputValue, TOutputValue, ErrorInstanceOfMap<TExtensionsMap>>,
253
+ ) => ClassError0<ExtendErrorExtensionsMapWithProp<TExtensionsMap, TKey, TInputValue, TOutputValue>>
254
+ method: <TKey extends string, TArgs extends unknown[], TOutputValue>(
255
+ key: TKey,
256
+ value: ErrorExtensionMethodFn<TOutputValue, TArgs, ErrorInstanceOfMap<TExtensionsMap>>,
257
+ ) => ClassError0<ExtendErrorExtensionsMapWithMethod<TExtensionsMap, TKey, TArgs, TOutputValue>>
258
+ refine: (
259
+ value: ErrorExtensionRefineFn<ErrorInstanceOfMap<TExtensionsMap>, ErrorOutputProps<TExtensionsMap>>,
260
+ ) => ClassError0<TExtensionsMap>
312
261
  extend: {
313
262
  <TBuilder extends ExtensionError0>(
314
263
  extension: TBuilder,
@@ -318,11 +267,6 @@ export type ClassError0<TExtensionsMap extends ErrorExtensionsMap = EmptyExtensi
318
267
  key: TKey,
319
268
  value: ErrorExtensionPropOptions<TInputValue, TOutputValue, ErrorInstanceOfMap<TExtensionsMap>>,
320
269
  ): ClassError0<ExtendErrorExtensionsMapWithProp<TExtensionsMap, TKey, TInputValue, TOutputValue>>
321
- <TKey extends string, TOutputValue>(
322
- kind: 'computed',
323
- key: TKey,
324
- value: ErrorExtensionCopmputedFn<TOutputValue, ErrorInstanceOfMap<TExtensionsMap>>,
325
- ): ClassError0<ExtendErrorExtensionsMapWithComputed<TExtensionsMap, TKey, TOutputValue>>
326
270
  <TKey extends string, TArgs extends unknown[], TOutputValue>(
327
271
  kind: 'method',
328
272
  key: TKey,
@@ -342,7 +286,6 @@ export class Error0 extends Error {
342
286
 
343
287
  private static readonly _emptyExtension: ErrorExtensionResolved = {
344
288
  props: {},
345
- computed: {},
346
289
  methods: {},
347
290
  refine: [],
348
291
  }
@@ -350,13 +293,11 @@ export class Error0 extends Error {
350
293
  private static _getResolvedExtension(this: typeof Error0): ErrorExtensionResolved {
351
294
  const resolved: ErrorExtensionResolved = {
352
295
  props: {},
353
- computed: {},
354
296
  methods: {},
355
297
  refine: [],
356
298
  }
357
299
  for (const extension of this._extensions) {
358
300
  Object.assign(resolved.props, extension.props ?? this._emptyExtension.props)
359
- Object.assign(resolved.computed, extension.computed ?? this._emptyExtension.computed)
360
301
  Object.assign(resolved.methods, extension.methods ?? this._emptyExtension.methods)
361
302
  resolved.refine.push(...(extension.refine ?? this._emptyExtension.refine))
362
303
  }
@@ -382,10 +323,10 @@ export class Error0 extends Error {
382
323
  for (const [key, prop] of Object.entries(extension.props)) {
383
324
  if (key in input) {
384
325
  const ownValue = (input as Record<string, unknown>)[key]
385
- ;(this as Record<string, unknown>)[key] = prop.input(ownValue)
326
+ ;(this as Record<string, unknown>)[key] = prop.init(ownValue)
386
327
  } else {
387
328
  Object.defineProperty(this, key, {
388
- get: () => prop.output(this),
329
+ get: () => prop.resolve({ value: undefined, flow: this.flow(key), error: this }),
389
330
  set: (value) => {
390
331
  Object.defineProperty(this, key, {
391
332
  value,
@@ -399,22 +340,6 @@ export class Error0 extends Error {
399
340
  })
400
341
  }
401
342
  }
402
-
403
- for (const [key, computed] of Object.entries(extension.computed)) {
404
- Object.defineProperty(this, key, {
405
- get: () => computed(this),
406
- set: (value) => {
407
- Object.defineProperty(this, key, {
408
- value,
409
- writable: true,
410
- enumerable: true,
411
- configurable: true,
412
- })
413
- },
414
- enumerable: true,
415
- configurable: true,
416
- })
417
- }
418
343
  }
419
344
 
420
345
  private static readonly isSelfProperty = (object: object, key: string): boolean => {
@@ -441,79 +366,62 @@ export class Error0 extends Error {
441
366
  return ctor.own(this, key)
442
367
  }
443
368
 
444
- static flow(error: object, key: string, policy: ErrorFlowPolicy = 'likeError0'): unknown[] {
445
- return this.causes(error, policy).map((cause) => {
446
- const causeRecord = cause as Record<string, unknown>
447
- if (this.isSelfProperty(causeRecord, key)) {
448
- return causeRecord[key]
449
- }
450
- return undefined
369
+ static flow(error: object, key: string): unknown[] {
370
+ return this.causes(error, true).map((cause) => {
371
+ return this.own(cause, key)
451
372
  })
452
373
  }
453
- flow(key: string, policy: ErrorFlowPolicy = 'likeError0'): unknown[] {
374
+ flow(key: string): unknown[] {
454
375
  const ctor = this.constructor as typeof Error0
455
- return ctor.flow(this, key, policy)
376
+ return ctor.flow(this, key)
456
377
  }
457
378
 
458
- static causes(error: object, policy: ErrorFlowPolicy = 'all'): object[] {
459
- const causes: object[] = []
379
+ static causes(error: unknown, instancesOnly?: false): unknown[]
380
+ static causes<T extends typeof Error0>(this: T, error: unknown, instancesOnly: true): Array<InstanceType<T>>
381
+ static causes(error: unknown, instancesOnly?: boolean): unknown[] {
382
+ const causes: unknown[] = []
460
383
  let current: unknown = error
461
384
  const maxDepth = 99
462
385
  const seen = new Set<unknown>()
463
-
464
386
  for (let depth = 0; depth < maxDepth; depth += 1) {
465
- if (!current || typeof current !== 'object') {
466
- break
467
- }
468
387
  if (seen.has(current)) {
469
388
  break
470
389
  }
471
- if (policy === 'instance') {
472
- if (!this.is(current)) {
473
- break
474
- }
475
- } else if (policy === 'error0') {
476
- if (!this.isError0(current)) {
477
- break
478
- }
479
- } else if (policy === 'likeError0') {
480
- if (!this.isLikeError0(current)) {
481
- break
482
- }
483
- }
484
390
  seen.add(current)
485
- causes.push(current)
391
+ if (!instancesOnly || this.is(current)) {
392
+ causes.push(current)
393
+ }
394
+ if (!current || typeof current !== 'object') {
395
+ break
396
+ }
486
397
  current = (current as { cause?: unknown }).cause
487
398
  }
488
-
489
399
  return causes
490
400
  }
491
- causes(policy: ErrorFlowPolicy = 'all'): object[] {
401
+ causes<T extends typeof Error0>(this: T, instancesOnly?: false): [InstanceType<T>, ...unknown[]]
402
+ causes<T extends typeof Error0>(this: T, instancesOnly: true): [InstanceType<T>, ...Array<InstanceType<T>>]
403
+ causes(instancesOnly?: boolean): unknown[] {
492
404
  const ctor = this.constructor as typeof Error0
493
- return ctor.causes(this, policy)
405
+ if (instancesOnly) {
406
+ return ctor.causes(this, true)
407
+ }
408
+ return ctor.causes(this)
494
409
  }
495
410
 
496
- static is(error: unknown): error is Error0 {
411
+ static is<T extends typeof Error0>(this: T, error: unknown): error is InstanceType<T> {
497
412
  return error instanceof this
498
413
  }
499
414
 
500
- static isError0(error: unknown): error is Error0 {
501
- return error instanceof Error0
502
- }
503
-
504
- static isLikeError0(error: unknown): error is Error0 | object {
505
- return (
506
- error instanceof Error0 ||
507
- (typeof error === 'object' && error !== null && 'name' in error && error.name === 'Error0')
508
- )
415
+ static isSerialized(error: unknown): error is Record<string, unknown> {
416
+ return !this.is(error) && typeof error === 'object' && error !== null && 'name' in error && error.name === 'Error0'
509
417
  }
510
418
 
511
419
  static from(error: unknown): Error0 {
512
420
  if (this.is(error)) {
513
421
  return error
514
422
  }
515
- if (this.isLikeError0(error)) {
516
- return this._fromLikeError0(error)
423
+ if (this.isSerialized(error)) {
424
+ return this._fromSerialized(error)
517
425
  }
518
426
  return this._fromNonError0(error)
519
427
  }
@@ -529,27 +437,33 @@ export class Error0 extends Error {
529
437
  return error
530
438
  }
531
439
 
532
- private static _fromLikeError0(error: unknown): Error0 {
440
+ private static _fromSerialized(error: unknown): Error0 {
533
441
  const message = this._extractMessage(error)
534
442
  if (typeof error !== 'object' || error === null) {
535
443
  return this._applyRefine(new this(message, { cause: error }))
536
444
  }
537
-
538
445
  const errorRecord = error as Record<string, unknown>
539
446
  const recreated = new this(message)
540
- const temp = new this(message, { cause: errorRecord })
541
447
  const extension = this._getResolvedExtension()
542
- for (const [key, prop] of Object.entries(extension.props)) {
543
- const value = prop.output(temp)
544
- if (value !== undefined) {
448
+ const propsEntries = Object.entries(extension.props)
449
+ for (const [key, prop] of propsEntries) {
450
+ if (!(key in errorRecord)) {
451
+ continue
452
+ }
453
+ try {
454
+ const value = prop.deserialize({ value: errorRecord[key], serialized: errorRecord })
545
455
  ;(recreated as unknown as Record<string, unknown>)[key] = value
456
+ } catch {
457
+ // ignore
546
458
  }
547
459
  }
548
- ;(recreated as unknown as { cause?: unknown }).cause = errorRecord.cause
549
- if (typeof errorRecord.stack === 'string') {
460
+ // we do not serialize causes
461
+ // ;(recreated as unknown as { cause?: unknown }).cause = errorRecord.cause
462
+ const isStackInProps = propsEntries.some(([key]) => key === 'stack')
463
+ if (typeof errorRecord.stack === 'string' && !isStackInProps) {
550
464
  recreated.stack = errorRecord.stack
551
465
  }
552
- return this._applyRefine(recreated)
466
+ return recreated
553
467
  }
554
468
 
555
469
  private static _fromNonError0(error: unknown): Error0 {
@@ -569,7 +483,7 @@ export class Error0 extends Error {
569
483
 
570
484
  private static _extendWithExtension(
571
485
  this: typeof Error0,
572
- extension: ErrorExtension<ErrorExtensionProps, ErrorExtensionComputed, ErrorExtensionMethods>,
486
+ extension: ErrorExtension<ErrorExtensionProps, ErrorExtensionMethods>,
573
487
  ): ClassError0 {
574
488
  const Base = this as unknown as typeof Error0
575
489
  const Error0Extended = class Error0 extends Base {}
@@ -600,18 +514,40 @@ export class Error0 extends Error {
600
514
 
601
515
  private static _extensionFromBuilder(
602
516
  extension: ExtensionError0,
603
- ): ErrorExtension<ErrorExtensionProps, ErrorExtensionComputed, ErrorExtensionMethods> {
517
+ ): ErrorExtension<ErrorExtensionProps, ErrorExtensionMethods> {
604
518
  const extensionRecord = extension as unknown as {
605
- _extension: ErrorExtension<ErrorExtensionProps, ErrorExtensionComputed, ErrorExtensionMethods>
519
+ _extension: ErrorExtension<ErrorExtensionProps, ErrorExtensionMethods>
606
520
  }
607
521
  return {
608
522
  props: { ...(extensionRecord._extension.props ?? {}) },
609
- computed: { ...(extensionRecord._extension.computed ?? {}) },
610
523
  methods: { ...(extensionRecord._extension.methods ?? {}) },
611
524
  refine: [...(extensionRecord._extension.refine ?? [])],
612
525
  }
613
526
  }
614
527
 
528
+ static prop<TThis extends typeof Error0, TKey extends string, TInputValue, TOutputValue>(
529
+ this: TThis,
530
+ key: TKey,
531
+ value: ErrorExtensionPropOptions<TInputValue, TOutputValue, ErrorInstanceOfMap<ExtensionsMapOf<TThis>>>,
532
+ ): ClassError0<ExtendErrorExtensionsMapWithProp<ExtensionsMapOf<TThis>, TKey, TInputValue, TOutputValue>> {
533
+ return this.extend('prop', key, value)
534
+ }
535
+
536
+ static method<TThis extends typeof Error0, TKey extends string, TArgs extends unknown[], TOutputValue>(
537
+ this: TThis,
538
+ key: TKey,
539
+ value: ErrorExtensionMethodFn<TOutputValue, TArgs, ErrorInstanceOfMap<ExtensionsMapOf<TThis>>>,
540
+ ): ClassError0<ExtendErrorExtensionsMapWithMethod<ExtensionsMapOf<TThis>, TKey, TArgs, TOutputValue>> {
541
+ return this.extend('method', key, value)
542
+ }
543
+
544
+ static refine<TThis extends typeof Error0>(
545
+ this: TThis,
546
+ value: ErrorExtensionRefineFn<ErrorInstanceOfMap<ExtensionsMapOf<TThis>>, ErrorOutputProps<ExtensionsMapOf<TThis>>>,
547
+ ): ClassError0<ExtensionsMapOf<TThis>> {
548
+ return this.extend('refine', value)
549
+ }
550
+
615
551
  static extend<TThis extends typeof Error0, TBuilder extends ExtensionError0>(
616
552
  this: TThis,
617
553
  extension: TBuilder,
@@ -622,12 +558,6 @@ export class Error0 extends Error {
622
558
  key: TKey,
623
559
  value: ErrorExtensionPropOptions<TInputValue, TOutputValue, ErrorInstanceOfMap<ExtensionsMapOf<TThis>>>,
624
560
  ): ClassError0<ExtendErrorExtensionsMapWithProp<ExtensionsMapOf<TThis>, TKey, TInputValue, TOutputValue>>
625
- static extend<TThis extends typeof Error0, TKey extends string, TOutputValue>(
626
- this: TThis,
627
- kind: 'computed',
628
- key: TKey,
629
- value: ErrorExtensionCopmputedFn<TOutputValue, ErrorInstanceOfMap<ExtensionsMapOf<TThis>>>,
630
- ): ClassError0<ExtendErrorExtensionsMapWithComputed<ExtensionsMapOf<TThis>, TKey, TOutputValue>>
631
561
  static extend<TThis extends typeof Error0, TKey extends string, TArgs extends unknown[], TOutputValue>(
632
562
  this: TThis,
633
563
  kind: 'method',
@@ -641,12 +571,9 @@ export class Error0 extends Error {
641
571
  ): ClassError0<ExtensionsMapOf<TThis>>
642
572
  static extend(
643
573
  this: typeof Error0,
644
- first: ExtensionError0 | 'prop' | 'computed' | 'method' | 'refine',
574
+ first: ExtensionError0 | 'prop' | 'method' | 'refine',
645
575
  key?: string | ErrorExtensionRefineFn<any, any>,
646
- value?:
647
- | ErrorExtensionPropOptions<unknown, unknown>
648
- | ErrorExtensionCopmputedFn<unknown>
649
- | ErrorExtensionMethodFn<unknown>,
576
+ value?: ErrorExtensionPropOptions<unknown, unknown> | ErrorExtensionMethodFn<unknown>,
650
577
  ): ClassError0 {
651
578
  if (first instanceof ExtensionError0) {
652
579
  return this._extendWithExtension(this._extensionFromBuilder(first))
@@ -668,11 +595,6 @@ export class Error0 extends Error {
668
595
  props: { [key]: value as ErrorExtensionPropOptions<unknown, unknown> },
669
596
  })
670
597
  }
671
- if (first === 'computed') {
672
- return this._extendWithExtension({
673
- computed: { [key]: value as ErrorExtensionCopmputedFn<unknown> },
674
- })
675
- }
676
598
  return this._extendWithExtension({
677
599
  methods: { [key]: value as ErrorExtensionMethodFn<unknown> },
678
600
  })
@@ -682,31 +604,36 @@ export class Error0 extends Error {
682
604
  return new ExtensionError0()
683
605
  }
684
606
 
685
- static serialize(error: unknown, isPublic = true): object {
607
+ static serialize(error: unknown, isPublic = true): Record<string, unknown> {
686
608
  const error0 = this.from(error)
687
- const jsonWithUndefined: Record<string, unknown> = {
609
+ const json: Record<string, unknown> = {
688
610
  name: error0.name,
689
611
  message: error0.message,
690
- cause: error0.cause,
691
- stack: error0.stack,
612
+ // we do not serialize causes, it is enough that we have floated props and refine helper
613
+ // cause: error0.cause,
692
614
  }
693
615
 
694
616
  const extension = this._getResolvedExtension()
695
- for (const [key, prop] of Object.entries(extension.props)) {
696
- const value = prop.output(error0)
697
- const jsonValue = prop.serialize(value, error0, isPublic)
698
- if (jsonValue !== undefined) {
699
- jsonWithUndefined[key] = jsonValue
700
- } else {
701
- try {
702
- // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
703
- delete jsonWithUndefined[key]
704
- } catch {
705
- // ignore
617
+ const propsEntries = Object.entries(extension.props)
618
+ for (const [key, prop] of propsEntries) {
619
+ try {
620
+ const value = prop.resolve({ value: error0.own(key), flow: error0.flow(key), error: error0 })
621
+ const jsonValue = prop.serialize({ value, error: error0, isPublic })
622
+ if (jsonValue !== undefined) {
623
+ json[key] = jsonValue
706
624
  }
625
+ } catch {
626
+ // ignore
707
627
  }
708
628
  }
709
- return Object.fromEntries(Object.entries(jsonWithUndefined).filter(([, value]) => value !== undefined)) as object
629
+ const isStackInProps = propsEntries.some(([key]) => key === 'stack')
630
+ if (!isStackInProps && typeof error0.stack === 'string') {
631
+ json.stack = error0.stack
632
+ }
633
+ return Object.fromEntries(Object.entries(json).filter(([, value]) => value !== undefined)) as Record<
634
+ string,
635
+ unknown
636
+ >
710
637
  }
711
638
 
712
639
  serialize(isPublic = true): object {