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

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