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