@devp0nt/error0 1.0.0-next.53 → 1.0.0-next.54

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,3 +1,9 @@
1
+ // Проверить как в браузере такая ошибка выводится
2
+
3
+ // ? стек плагин переименовать в просто стек плагин и там добавить опцию для мержа и не мержа, чтобы можно было изПаблик там легко определять
4
+ // ? В эрор0 добавить тоже срезку тчк сервер после которой для клиента всё обрежется, потому резолв всегда может быть андефайнед
5
+ // ? В эррор0 добавить вайт/бан плагин
6
+
1
7
  type IsUnknown<T> = unknown extends T ? ([T] extends [unknown] ? true : false) : false
2
8
  type NormalizeUnknownToUndefined<T> = IsUnknown<T> extends true ? undefined : T
3
9
  type IsOnlyUndefined<T> = [Exclude<T, undefined>] extends [never] ? true : false
@@ -54,7 +60,7 @@ type ErrorPluginPropOptionsWithoutInit<
54
60
  > = ErrorPluginPropOptionsBase<TOutputValue, TError, TResolveValue> & {
55
61
  init?: undefined
56
62
  }
57
- export type ErrorPluginPropOptions<
63
+ type ErrorPluginPropOptions<
58
64
  TInputValue = undefined,
59
65
  TOutputValue = unknown,
60
66
  TError extends Error0 = Error0,
@@ -62,49 +68,83 @@ export type ErrorPluginPropOptions<
62
68
  > =
63
69
  | ErrorPluginPropOptionsWithInit<TInputValue, TOutputValue, TError, TResolveValue>
64
70
  | ErrorPluginPropOptionsWithoutInit<TOutputValue, TError, TResolveValue>
65
- export type ErrorPluginMethodFn<TOutputValue, TArgs extends unknown[] = unknown[], TError extends Error0 = Error0> = (
71
+
72
+ type ErrorPluginPropOptionsBaseDefinition<
73
+ TOutputValue,
74
+ TError extends Error0,
75
+ TResolveValue extends TOutputValue | undefined,
76
+ > = {
77
+ resolve?: ((options: ErrorPluginPropOptionsResolveOptions<TOutputValue, TError>) => TResolveValue) | boolean
78
+ serialize?: ErrorPluginPropSerialize<TOutputValue, TError, TResolveValue>
79
+ deserialize?: ErrorPluginPropDeserialize<TOutputValue>
80
+ }
81
+ type ErrorPluginPropOptionsWithInitDefinition<
82
+ TInputValue,
83
+ TOutputValue,
84
+ TError extends Error0,
85
+ TResolveValue extends TOutputValue | undefined,
86
+ > = ErrorPluginPropOptionsBaseDefinition<TOutputValue, TError, TResolveValue> & {
87
+ init: ErrorPluginPropInit<TInputValue, TOutputValue>
88
+ }
89
+ type ErrorPluginPropOptionsWithoutInitDefinition<
90
+ TOutputValue,
91
+ TError extends Error0,
92
+ TResolveValue extends TOutputValue | undefined,
93
+ > = ErrorPluginPropOptionsBaseDefinition<TOutputValue, TError, TResolveValue> & {
94
+ init?: undefined
95
+ }
96
+ type ErrorPluginPropOptionsDefinition<
97
+ TInputValue = undefined,
98
+ TOutputValue = unknown,
99
+ TError extends Error0 = Error0,
100
+ TResolveValue extends TOutputValue | undefined = TOutputValue | undefined,
101
+ > =
102
+ | ErrorPluginPropOptionsWithInitDefinition<TInputValue, TOutputValue, TError, TResolveValue>
103
+ | ErrorPluginPropOptionsWithoutInitDefinition<TOutputValue, TError, TResolveValue>
104
+
105
+ type ErrorPluginMethodFn<TOutputValue, TArgs extends unknown[] = unknown[], TError extends Error0 = Error0> = (
66
106
  error: TError,
67
107
  ...args: TArgs
68
108
  ) => TOutputValue
69
109
  type ErrorPluginAnyMethodFn = (error: any, ...args: any[]) => any
70
- export type ErrorPluginAdaptResult<TOutputProps extends Record<string, unknown>> = Partial<TOutputProps> | undefined
71
- export type ErrorPluginAdaptFn<
110
+ type ErrorPluginAdaptResult<TOutputProps extends Record<string, unknown>> = Partial<TOutputProps> | undefined
111
+ type ErrorPluginAdaptFn<
72
112
  TError extends Error0 = Error0,
73
113
  TOutputProps extends Record<string, unknown> = Record<never, never>,
74
114
  > = ((error: TError) => void) | ((error: TError) => ErrorPluginAdaptResult<TOutputProps>)
75
- export type ErrorPluginStackSerialize<TError extends Error0> = (options: {
115
+ type ErrorPluginStackSerialize<TError extends Error0> = (options: {
76
116
  value: string | undefined
77
117
  error: TError
78
118
  isPublic: boolean
79
119
  }) => unknown
80
- export type ErrorPluginStack<TError extends Error0 = Error0> = { serialize: ErrorPluginStackSerialize<TError> }
81
- export type ErrorPluginCauseSerialize<TError extends Error0> = (options: {
120
+ type ErrorPluginStack<TError extends Error0 = Error0> = { serialize: ErrorPluginStackSerialize<TError> }
121
+ type ErrorPluginCauseSerialize<TError extends Error0> = (options: {
82
122
  cause: unknown
83
123
  error: TError
84
124
  isPublic: boolean
85
125
  is: (cause: unknown) => boolean
86
126
  serialize: (cause: unknown) => Record<string, unknown>
87
127
  }) => unknown
88
- export type ErrorPluginCauseDeserialize = (options: {
128
+ type ErrorPluginCauseDeserialize = (options: {
89
129
  cause: unknown
90
130
  error: Record<string, unknown>
91
131
  isSerialized: (serializedCause: unknown) => boolean
92
132
  fromSerialized: (serializedCause: unknown) => Error0
93
133
  }) => unknown
94
- export type ErrorPluginCause<TError extends Error0 = Error0> = {
134
+ type ErrorPluginCause<TError extends Error0 = Error0> = {
95
135
  serialize: ErrorPluginCauseSerialize<TError>
96
136
  deserialize: ErrorPluginCauseDeserialize
97
137
  }
98
- export type ErrorPluginMessageSerialize<TError extends Error0> = (options: {
138
+ type ErrorPluginMessageSerialize<TError extends Error0> = (options: {
99
139
  value: string
100
140
  error: TError
101
141
  isPublic: boolean
102
142
  }) => unknown
103
- export type ErrorPluginMessage<TError extends Error0 = Error0> = { serialize: ErrorPluginMessageSerialize<TError> }
143
+ type ErrorPluginMessage<TError extends Error0 = Error0> = { serialize: ErrorPluginMessageSerialize<TError> }
104
144
  type ErrorMethodRecord = { fn: ErrorPluginAnyMethodFn }
105
145
 
106
- export type ErrorPluginProps = { [key: string]: ErrorPluginPropOptions<any, any> }
107
- export type ErrorPluginMethods = { [key: string]: ErrorPluginAnyMethodFn }
146
+ type ErrorPluginProps = { [key: string]: ErrorPluginPropOptions<any, any> }
147
+ type ErrorPluginMethods = { [key: string]: ErrorPluginAnyMethodFn }
108
148
 
109
149
  export type ErrorPlugin<
110
150
  TProps extends ErrorPluginProps = Record<never, never>,
@@ -134,12 +174,12 @@ type PluginOutputProps<TProps extends ErrorPluginProps> = {
134
174
  ? TResolveValue
135
175
  : never
136
176
  }
137
- export type ErrorPluginsMap = {
177
+ type ErrorPluginsMap = {
138
178
  props: Record<string, { init: unknown; output: unknown; resolve: unknown }>
139
179
  methods: Record<string, ErrorMethodRecord>
140
180
  }
141
- export type IsEmptyObject<T> = keyof T extends never ? true : false
142
- export type ErrorInputBase = {
181
+ type IsEmptyObject<T> = keyof T extends never ? true : false
182
+ type ErrorInputBase = {
143
183
  cause?: unknown
144
184
  }
145
185
  type ErrorInputPluginProps<TPluginsMap extends ErrorPluginsMap> = {
@@ -147,7 +187,7 @@ type ErrorInputPluginProps<TPluginsMap extends ErrorPluginsMap> = {
147
187
  ? never
148
188
  : TKey]?: TPluginsMap['props'][TKey]['init']
149
189
  }
150
- export type ErrorInput<TPluginsMap extends ErrorPluginsMap> =
190
+ type ErrorInput<TPluginsMap extends ErrorPluginsMap> =
151
191
  IsEmptyObject<TPluginsMap['props']> extends true
152
192
  ? ErrorInputBase
153
193
  : ErrorInputBase & ErrorInputPluginProps<TPluginsMap>
@@ -158,16 +198,19 @@ type ErrorResolvedProps<TPluginsMap extends ErrorPluginsMap> = {
158
198
  type ErrorOwnProps<TPluginsMap extends ErrorPluginsMap> = {
159
199
  [TKey in keyof TPluginsMap['props']]: TPluginsMap['props'][TKey]['output'] | undefined
160
200
  }
161
- type ErrorOwnMethods<TPluginsMap extends ErrorPluginsMap> = {
162
- own: {
163
- (): ErrorOwnProps<TPluginsMap>
164
- <TKey extends keyof TPluginsMap['props'] & string>(key: TKey): ErrorOwnProps<TPluginsMap>[TKey]
165
- }
166
- flow: <TKey extends keyof TPluginsMap['props'] & string>(key: TKey) => Array<ErrorOwnProps<TPluginsMap>[TKey]>
167
- }
168
201
  type ErrorResolveMethods<TPluginsMap extends ErrorPluginsMap> = {
169
202
  resolve: () => ErrorResolvedProps<TPluginsMap>
170
203
  }
204
+ type Error0ResolvedInstance<TPluginsMap extends ErrorPluginsMap> = Error0 &
205
+ ErrorResolved<TPluginsMap> &
206
+ ErrorResolveMethods<TPluginsMap>
207
+ type ErrorOwnMethods<TPluginsMap extends ErrorPluginsMap> = {
208
+ own?: Partial<ErrorOwnProps<TPluginsMap>>
209
+ flow: <TKey extends keyof TPluginsMap['props'] & string>(key: TKey) => Array<ErrorOwnProps<TPluginsMap>[TKey]>
210
+ assign: (props: Partial<ErrorOwnProps<TPluginsMap>>) => Error0ResolvedInstance<TPluginsMap>
211
+ }
212
+ export type InstanceError0<TPluginsMap extends ErrorPluginsMap> = Error0ResolvedInstance<TPluginsMap> &
213
+ ErrorOwnMethods<TPluginsMap> & { readonly __pluginsMap?: TPluginsMap }
171
214
  // type BindInstanceMethod<TMethod> = TMethod extends {
172
215
  // (error: any, ...args: infer TArgs1): infer TOutput1
173
216
  // (error: any, ...args: infer TArgs2): infer TOutput2
@@ -243,8 +286,7 @@ type BindStaticMethod<TMethod> = TMethod extends (error: any, ...args: infer TAr
243
286
  type ErrorMethods<TPluginsMap extends ErrorPluginsMap> = {
244
287
  [TKey in keyof TPluginsMap['methods']]: BindInstanceMethod<TPluginsMap['methods'][TKey]['fn']>
245
288
  }
246
- export type ErrorResolved<TPluginsMap extends ErrorPluginsMap> = ErrorResolvedProps<TPluginsMap> &
247
- ErrorMethods<TPluginsMap>
289
+ type ErrorResolved<TPluginsMap extends ErrorPluginsMap> = ErrorResolvedProps<TPluginsMap> & ErrorMethods<TPluginsMap>
248
290
 
249
291
  type ErrorStaticMethods<TPluginsMap extends ErrorPluginsMap> = {
250
292
  [TKey in keyof TPluginsMap['methods']]: BindStaticMethod<TPluginsMap['methods'][TKey]['fn']>
@@ -269,6 +311,29 @@ type ErrorPluginResolved = {
269
311
  const RESERVED_STACK_PROP_ERROR = 'Error0: "stack" is a reserved prop key. Use .stack(...) plugin API instead'
270
312
  const RESERVED_MESSAGE_PROP_ERROR = 'Error0: "message" is a reserved prop key. Use .message(...) plugin API instead'
271
313
 
314
+ const fromPropOptionsDefinition = (
315
+ options: ErrorPluginPropOptionsDefinition<any, any, any, any>,
316
+ ): ErrorPluginPropOptions<any, any, any, any> => {
317
+ let resolver: ErrorPluginPropOptions<unknown>['resolve']
318
+ if (!options.resolve) {
319
+ resolver = (options: ErrorPluginPropOptionsResolveOptions<any, any>) => options.own
320
+ } else if (options.resolve === true) {
321
+ resolver = (options: ErrorPluginPropOptionsResolveOptions<any, any>) => options.flow.find((v) => v !== undefined)
322
+ } else if (typeof options.resolve === 'function') {
323
+ resolver = options.resolve
324
+ } else {
325
+ throw new Error('Invalid resolve option')
326
+ }
327
+ const serializer: ErrorPluginPropOptions<unknown>['serialize'] = options.serialize ?? false
328
+ const deserializer: ErrorPluginPropOptions<unknown>['deserialize'] = options.deserialize ?? false
329
+ return {
330
+ ...options,
331
+ resolve: resolver,
332
+ serialize: serializer,
333
+ deserialize: deserializer,
334
+ }
335
+ }
336
+
272
337
  type PluginPropsMapOf<TPlugin extends ErrorPlugin> = {
273
338
  [TKey in keyof NonNullable<TPlugin['props']>]: NonNullable<TPlugin['props']>[TKey] extends ErrorPluginPropOptions<
274
339
  any,
@@ -329,16 +394,10 @@ type PluginsMapFromParts<
329
394
  TProps extends ErrorPluginProps,
330
395
  TMethods extends ErrorPluginMethods,
331
396
  > = ErrorPluginsMapOfPlugin<ErrorPlugin<TProps, TMethods>>
332
- type ErrorInstanceOfMap<TMap extends ErrorPluginsMap> = Error0 &
333
- ErrorResolved<TMap> &
334
- ErrorOwnMethods<TMap> &
335
- ErrorResolveMethods<TMap> & { readonly __pluginsMap?: TMap }
336
- type BuilderError0<TProps extends ErrorPluginProps, TMethods extends ErrorPluginMethods> = Error0 &
337
- ErrorResolved<PluginsMapFromParts<TProps, TMethods>> &
338
- ErrorOwnMethods<PluginsMapFromParts<TProps, TMethods>> &
339
- ErrorResolveMethods<PluginsMapFromParts<TProps, TMethods>> & {
340
- readonly __pluginsMap?: PluginsMapFromParts<TProps, TMethods>
341
- }
397
+ type ErrorInstanceOfMap<TMap extends ErrorPluginsMap> = InstanceError0<TMap>
398
+ type BuilderError0<TProps extends ErrorPluginProps, TMethods extends ErrorPluginMethods> = InstanceError0<
399
+ PluginsMapFromParts<TProps, TMethods>
400
+ >
342
401
 
343
402
  type PluginOfBuilder<TBuilder> =
344
403
  TBuilder extends PluginError0<infer TProps, infer TMethods> ? ErrorPlugin<TProps, TMethods> : never
@@ -372,7 +431,7 @@ export class PluginError0<
372
431
  TResolveValue extends TOutputValue | undefined = TOutputValue | undefined,
373
432
  >(
374
433
  key: TKey,
375
- value: ErrorPluginPropOptions<TInputValue, TOutputValue, BuilderError0<TProps, TMethods>, TResolveValue>,
434
+ value: ErrorPluginPropOptionsDefinition<TInputValue, TOutputValue, BuilderError0<TProps, TMethods>, TResolveValue>,
376
435
  ): PluginError0<AddPropToPluginProps<TProps, TKey, TInputValue, TOutputValue, TResolveValue>, TMethods> {
377
436
  return this.use('prop', key, value)
378
437
  }
@@ -410,7 +469,7 @@ export class PluginError0<
410
469
  >(
411
470
  kind: 'prop',
412
471
  key: TKey,
413
- value: ErrorPluginPropOptions<TInputValue, TOutputValue, BuilderError0<TProps, TMethods>, TResolveValue>,
472
+ value: ErrorPluginPropOptionsDefinition<TInputValue, TOutputValue, BuilderError0<TProps, TMethods>, TResolveValue>,
414
473
  ): PluginError0<AddPropToPluginProps<TProps, TKey, TInputValue, TOutputValue, TResolveValue>, TMethods>
415
474
  use<TKey extends string, TMethod extends (error: BuilderError0<TProps, TMethods>, ...args: any[]) => any>(
416
475
  kind: 'method',
@@ -427,7 +486,7 @@ export class PluginError0<
427
486
  use(
428
487
  kind: 'prop' | 'method' | 'adapt' | 'stack' | 'cause' | 'message',
429
488
  keyOrValue: unknown,
430
- value?: ErrorPluginPropOptions<unknown, unknown, any> | ErrorPluginMethodFn<unknown, unknown[], any>,
489
+ value?: ErrorPluginPropOptionsDefinition<unknown, unknown, any> | ErrorPluginMethodFn<unknown, unknown[], any>,
431
490
  ): PluginError0<any, any> {
432
491
  const nextProps: ErrorPluginProps = { ...(this._plugin.props ?? {}) }
433
492
  const nextMethods: ErrorPluginMethods = { ...(this._plugin.methods ?? {}) }
@@ -446,7 +505,7 @@ export class PluginError0<
446
505
  if (value === undefined) {
447
506
  throw new Error('PluginError0.use("prop", key, value) requires value')
448
507
  }
449
- nextProps[key] = value as ErrorPluginPropOptions<any, any>
508
+ nextProps[key] = fromPropOptionsDefinition(value as ErrorPluginPropOptionsDefinition<any, any>)
450
509
  } else if (kind === 'method') {
451
510
  const key = keyOrValue as string
452
511
  if (value === undefined) {
@@ -473,41 +532,27 @@ export class PluginError0<
473
532
  }
474
533
  }
475
534
 
476
- const OWN_SYMBOL: unique symbol = Symbol('Error0.own')
477
535
  type ErrorOwnStore = Record<string, unknown>
478
536
 
479
537
  export type ClassError0<TPluginsMap extends ErrorPluginsMap = EmptyPluginsMap> = {
480
538
  MAX_CAUSES_DEPTH: number
481
- new (
482
- message: string,
483
- input?: ErrorInput<TPluginsMap>,
484
- ): Error0 &
485
- ErrorResolved<TPluginsMap> &
486
- ErrorOwnMethods<TPluginsMap> &
487
- ErrorResolveMethods<TPluginsMap> & { readonly __pluginsMap?: TPluginsMap }
488
- new (
489
- input: { message: string } & ErrorInput<TPluginsMap>,
490
- ): Error0 &
491
- ErrorResolved<TPluginsMap> &
492
- ErrorOwnMethods<TPluginsMap> &
493
- ErrorResolveMethods<TPluginsMap> & { readonly __pluginsMap?: TPluginsMap }
539
+ new (message: string, input?: ErrorInput<TPluginsMap>): InstanceError0<TPluginsMap>
540
+ new (input: { message: string } & ErrorInput<TPluginsMap>): InstanceError0<TPluginsMap>
494
541
  readonly __pluginsMap?: TPluginsMap
495
- from: (
496
- error: unknown,
497
- ) => Error0 & ErrorResolved<TPluginsMap> & ErrorOwnMethods<TPluginsMap> & ErrorResolveMethods<TPluginsMap>
498
- round: (
499
- error: unknown,
500
- isPublic?: boolean,
501
- ) => Error0 & ErrorResolved<TPluginsMap> & ErrorOwnMethods<TPluginsMap> & ErrorResolveMethods<TPluginsMap>
542
+ from: <TThis extends ClassError0<any>>(this: TThis, error: unknown) => InstanceType<TThis>
543
+ round: <TThis extends ClassError0<any>>(this: TThis, error: unknown, isPublic?: boolean) => InstanceType<TThis>
544
+ // flat: <TThis extends ClassError0<any>>(this: TThis, error: unknown, keepCauses?: boolean) => InstanceType<TThis>
502
545
  causes: {
503
546
  (error: unknown, instancesOnly?: false): unknown[]
504
- (
505
- error: unknown,
506
- instancesOnly: true,
507
- ): Array<Error0 & ErrorResolved<TPluginsMap> & ErrorOwnMethods<TPluginsMap> & ErrorResolveMethods<TPluginsMap>>
547
+ (error: unknown, instancesOnly: true): Array<InstanceError0<TPluginsMap>>
508
548
  }
509
549
  resolve: (error: unknown) => ErrorResolvedProps<TPluginsMap>
510
550
  serialize: (error: unknown, isPublic?: boolean) => Record<string, unknown>
551
+ assign: <TThis extends ClassError0<any>>(
552
+ this: TThis,
553
+ error: unknown,
554
+ props: Partial<ErrorOwnProps<PluginsMapOf<TThis>>>,
555
+ ) => InstanceError0<PluginsMapOf<TThis>>
511
556
  own: {
512
557
  (error: object): ErrorOwnProps<TPluginsMap>
513
558
  <TKey extends keyof TPluginsMap['props'] & string>(error: object, key: TKey): ErrorOwnProps<TPluginsMap>[TKey]
@@ -516,24 +561,6 @@ export type ClassError0<TPluginsMap extends ErrorPluginsMap = EmptyPluginsMap> =
516
561
  error: object,
517
562
  key: TKey,
518
563
  ) => Array<ErrorOwnProps<TPluginsMap>[TKey]>
519
- // prop: <
520
- // TKey extends string,
521
- // TInputValue = undefined,
522
- // TOutputValue = unknown,
523
- // TResolveValue extends TOutputValue | undefined = TOutputValue | undefined,
524
- // >(
525
- // key: TKey,
526
- // value: ErrorPluginPropOptions<TInputValue, TOutputValue, ErrorInstanceOfMap<TPluginsMap>, TResolveValue>,
527
- // ) => ClassError0<ExtendErrorPluginsMapWithProp<TPluginsMap, TKey, TInputValue, TOutputValue, TResolveValue>>
528
- // method: <TKey extends string, TMethod extends (error: ErrorInstanceOfMap<TPluginsMap>, ...args: any[]) => any>(
529
- // key: TKey,
530
- // value: TMethod,
531
- // ) => ClassError0<ExtendErrorPluginsMapWithMethod<TPluginsMap, TKey, TMethod>>
532
- // adapt: (
533
- // value: ErrorPluginAdaptFn<ErrorInstanceOfMap<TPluginsMap>, ErrorResolvedProps<TPluginsMap>>,
534
- // ) => ClassError0<TPluginsMap>
535
- // stack: (value: ErrorPluginStack<ErrorInstanceOfMap<TPluginsMap>>) => ClassError0<TPluginsMap>
536
- // cause: (value: ErrorPluginCause<ErrorInstanceOfMap<TPluginsMap>>) => ClassError0<TPluginsMap>
537
564
  use: {
538
565
  <TBuilder extends PluginError0>(
539
566
  plugin: TBuilder,
@@ -566,10 +593,11 @@ export type ClassError0<TPluginsMap extends ErrorPluginsMap = EmptyPluginsMap> =
566
593
 
567
594
  export class Error0 extends Error {
568
595
  static readonly __pluginsMap?: EmptyPluginsMap
569
- readonly __pluginsMap?: EmptyPluginsMap
596
+ declare readonly __pluginsMap?: EmptyPluginsMap
570
597
  static MAX_CAUSES_DEPTH = 99
571
598
  protected static _plugins: ErrorPlugin[] = []
572
599
  protected static _resolvedPlugin?: ErrorPluginResolved
600
+ declare own?: ErrorOwnStore
573
601
 
574
602
  private static readonly _emptyPlugin: ErrorPluginResolved = {
575
603
  props: {},
@@ -675,63 +703,43 @@ export class Error0 extends Error {
675
703
 
676
704
  const ctor = this.constructor as typeof Error0
677
705
  const plugin = ctor._getResolvedPlugin()
678
- const ownStore = Object.create(null) as ErrorOwnStore
679
- Object.defineProperty(this, OWN_SYMBOL, { value: ownStore, writable: true, enumerable: false, configurable: true })
706
+ // const ownStore = Object.create(null) as ErrorOwnStore
707
+ // Object.defineProperty(this, OWN_SYMBOL, { value: ownStore, writable: true, enumerable: false, configurable: true })
680
708
 
681
709
  for (const [key, prop] of plugin.propEntries) {
682
710
  if (key === 'stack') {
683
711
  continue
684
712
  }
685
713
  Object.defineProperty(this, key, {
686
- get: () =>
687
- prop.resolve({
688
- own: ownStore[key],
689
- flow: this.flow(key as never),
690
- error: this,
691
- }),
714
+ get: () => this._resolveByKey(key, plugin),
692
715
  set: (value) => {
693
- ownStore[key] = value
716
+ this.assign({ [key]: value } as never)
694
717
  },
695
718
  enumerable: true,
696
719
  configurable: true,
697
720
  })
698
721
  if (key in input) {
699
- const ownValue = (input as Record<string, unknown>)[key]
700
- ownStore[key] = typeof prop.init === 'function' ? prop.init(ownValue) : ownValue
722
+ const inputValue = (input as Record<string, unknown>)[key]
723
+ const ownValue = typeof prop.init === 'function' ? prop.init(inputValue) : inputValue
724
+ this.assign({ [key]: ownValue } as never)
701
725
  }
702
726
  }
727
+ Error0.fixStack(input.cause)
703
728
  }
704
729
 
705
- private static _getOwnStore(object: object): ErrorOwnStore | undefined {
706
- const record = object as Record<string | symbol, unknown>
707
- const existing = record[OWN_SYMBOL]
708
- if (existing && typeof existing === 'object') {
709
- return existing as ErrorOwnStore
710
- }
711
- return undefined
712
- }
713
-
714
- private static readonly isOwnProperty = (object: object, key: string): boolean => {
715
- const ownStore = this._getOwnStore(object)
716
- if (ownStore) {
717
- return Object.prototype.hasOwnProperty.call(ownStore, key)
718
- }
719
- return !!Object.getOwnPropertyDescriptor(object, key)
720
- }
721
- private static _ownByKey(error: object, key: string): unknown {
722
- const ownStore = this._getOwnStore(error)
723
- if (ownStore) {
724
- return ownStore[key]
725
- }
726
- return (error as Record<string, unknown>)[key]
727
- }
728
- private static _flowByKey(error: object, key: string): unknown[] {
729
- const causes = this.causes(error, true)
730
- const values = new Array<unknown>(causes.length)
731
- for (let i = 0; i < causes.length; i += 1) {
732
- values[i] = this._ownByKey(causes[i], key)
733
- }
734
- return values
730
+ private static fixStack(cause: unknown): void {
731
+ try {
732
+ if (process.env.NODE_ENV !== 'production') {
733
+ let nextCause = cause
734
+ let depth = 0
735
+ const maxDepth = 99
736
+ while (nextCause && depth < maxDepth) {
737
+ ;(globalThis as any).__ERROR0_FIX_STACKTRACE__(nextCause)
738
+ nextCause = (nextCause as any).cause
739
+ depth++
740
+ }
741
+ }
742
+ } catch {}
735
743
  }
736
744
 
737
745
  static own<TThis extends typeof Error0>(this: TThis, error: unknown): ErrorOwnProps<PluginsMapOf<TThis>>
@@ -743,26 +751,9 @@ export class Error0 extends Error {
743
751
  static own(error: unknown, key?: string): unknown {
744
752
  const error0 = this.from(error)
745
753
  if (key === undefined) {
746
- const ownValues: Record<string, unknown> = {}
747
- const plugin = this._getResolvedPlugin()
748
- for (const ownKey of plugin.propKeys) {
749
- ownValues[ownKey] = this._ownByKey(error0, ownKey)
750
- }
751
- return ownValues
754
+ return error0.own ?? {}
752
755
  }
753
- return this._ownByKey(error0, key)
754
- }
755
- own<TThis extends Error0>(this: TThis): ErrorOwnProps<PluginsMapOfInstance<TThis>>
756
- own<TThis extends Error0, TKey extends keyof PluginsMapOfInstance<TThis>['props'] & string>(
757
- this: TThis,
758
- key: TKey,
759
- ): ErrorOwnProps<PluginsMapOfInstance<TThis>>[TKey]
760
- own(key?: string): unknown {
761
- const ctor = this.constructor as typeof Error0
762
- if (key === undefined) {
763
- return ctor.own(this)
764
- }
765
- return ctor._ownByKey(this, key)
756
+ return error0.own?.[key]
766
757
  }
767
758
 
768
759
  static flow<TThis extends typeof Error0, TKey extends keyof PluginsMapOf<TThis>['props'] & string>(
@@ -772,57 +763,68 @@ export class Error0 extends Error {
772
763
  ): Array<ErrorOwnProps<PluginsMapOf<TThis>>[TKey]>
773
764
  static flow(error: unknown, key: string): unknown[] {
774
765
  const error0 = this.from(error)
775
- return this._flowByKey(error0, key)
766
+ return error0.flow(key as never)
776
767
  }
777
768
  flow<TThis extends Error0, TKey extends keyof PluginsMapOfInstance<TThis>['props'] & string>(
778
769
  this: TThis,
779
770
  key: TKey,
780
771
  ): Array<ErrorOwnProps<PluginsMapOfInstance<TThis>>[TKey]>
781
772
  flow(key: string): unknown[] {
782
- const ctor = this.constructor as typeof Error0
783
- return ctor._flowByKey(this, key)
773
+ const causes = this.causes(true)
774
+ const values = new Array<unknown>(causes.length)
775
+ for (let i = 0; i < causes.length; i += 1) {
776
+ values[i] = causes[i].own?.[key]
777
+ }
778
+ return values
784
779
  }
785
780
 
786
- static _resolveByKey(error: Error0, key: string, plugin: ErrorPluginResolved): unknown {
787
- try {
788
- const options = {
789
- get own() {
790
- return error.own(key as never)
791
- },
792
- get flow() {
793
- return error.flow(key as never)
794
- },
795
- error,
796
- }
797
- const prop = plugin.props[key]
798
- const resolver = prop.resolve
799
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
800
- if (!resolver) {
801
- return (error as any)[key]
802
- }
803
- return resolver(options as ErrorPluginPropOptionsResolveOptions<any, any>)
804
- } catch {
805
- // eslint-disable-next-line no-console
806
- console.error(`Error0: failed to resolve property ${key}`, error)
807
- return undefined
781
+ private readonly _resolveByKeyCache = new Map<string, unknown>()
782
+ private _resolveByKey(key: string, plugin: ErrorPluginResolved): unknown {
783
+ // eslint-disable-next-line consistent-this, @typescript-eslint/no-this-alias
784
+ const error = this
785
+ if (this._resolveByKeyCache.has(key)) {
786
+ return this._resolveByKeyCache.get(key)
808
787
  }
788
+ const value = (() => {
789
+ try {
790
+ const options = {
791
+ get flow() {
792
+ return error.flow(key as never)
793
+ },
794
+ own: error.own?.[key],
795
+ error,
796
+ }
797
+ const prop = plugin.props[key]
798
+ const resolver = prop.resolve
799
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
800
+ if (!resolver) {
801
+ return (error as any)[key]
802
+ }
803
+ return resolver(options as ErrorPluginPropOptionsResolveOptions<any, any>)
804
+ } catch {
805
+ // eslint-disable-next-line no-console
806
+ console.error(`Error0: failed to resolve property ${key}`, error)
807
+ return undefined
808
+ }
809
+ })()
810
+ this._resolveByKeyCache.set(key, value)
811
+ return value
809
812
  }
810
813
 
811
814
  static resolve<TThis extends typeof Error0>(this: TThis, error: unknown): ErrorResolvedProps<PluginsMapOf<TThis>>
812
815
  static resolve(error: unknown): Record<string, unknown>
813
816
  static resolve(error: unknown): Record<string, unknown> {
814
- const error0 = this.from(error)
815
- const resolved: Record<string, unknown> = {}
816
- const plugin = this._getResolvedPlugin()
817
- for (const key of plugin.propKeys) {
818
- resolved[key] = this._resolveByKey(error0, key, plugin)
819
- }
820
- return resolved
817
+ return this.from(error).resolve()
821
818
  }
822
819
  resolve<TThis extends Error0>(this: TThis): ErrorResolvedProps<PluginsMapOfInstance<TThis>>
823
820
  resolve(): Record<string, unknown> {
824
821
  const ctor = this.constructor as typeof Error0
825
- return ctor.resolve(this)
822
+ const plugin = ctor._getResolvedPlugin()
823
+ const resolved: Record<string, unknown> = {}
824
+ for (const key of plugin.propKeys) {
825
+ resolved[key] = this._resolveByKey(key, plugin)
826
+ }
827
+ return resolved
826
828
  }
827
829
 
828
830
  static causes(error: unknown, instancesOnly?: false): unknown[]
@@ -866,6 +868,7 @@ export class Error0 extends Error {
866
868
  return !this.is(error) && typeof error === 'object' && error !== null && 'name' in error && error.name === 'Error0'
867
869
  }
868
870
 
871
+ static from<TThis extends typeof Error0>(this: TThis, error: unknown): InstanceType<TThis>
869
872
  static from(error: unknown): Error0 {
870
873
  if (this.is(error)) {
871
874
  return error
@@ -876,8 +879,61 @@ export class Error0 extends Error {
876
879
  return this._fromNonError0(error)
877
880
  }
878
881
 
882
+ static round<TThis extends typeof Error0>(this: TThis, error: unknown, isPublic?: boolean): InstanceType<TThis>
879
883
  static round(error: unknown, isPublic = false): Error0 {
880
- return this.from(this.serialize(error, isPublic))
884
+ return this.from(error).round(isPublic)
885
+ }
886
+ round<TThis extends Error0>(this: TThis, isPublic = true): TThis {
887
+ const ctor = this.constructor as typeof Error0
888
+ return ctor.from(this.serialize(isPublic)) as TThis
889
+ }
890
+
891
+ // static flat<TThis extends typeof Error0>(this: TThis, error: unknown, keepCauses?: boolean): InstanceType<TThis>
892
+ // static flat(error: unknown, keepCauses = false): Error0 {
893
+ // return this.from(error).flat(keepCauses)
894
+ // }
895
+ // flat<TThis extends Error0>(this: TThis, keepCauses = false): TThis {
896
+ // const ctor = this.constructor as typeof Error0
897
+ // // eslint-disable-next-line new-cap
898
+ // const error = new ctor(this.message) as TThis
899
+ // if (keepCauses) {
900
+ // error.cause = this.cause
901
+ // }
902
+ // error.assign({
903
+ // // ...this.own,
904
+ // ...this.resolve(),
905
+ // } as never)
906
+ // error.stack =
907
+ // this.causes()
908
+ // .map((cause, index) => {
909
+ // return cause instanceof Error && cause.stack && typeof cause.stack === 'string'
910
+ // ? index === 0
911
+ // ? cause.stack
912
+ // : cause.stack.split('\n').slice(1).join('\n')
913
+ // : undefined
914
+ // })
915
+ // .join('\n') || undefined
916
+ // return error
917
+ // }
918
+
919
+ static assign<TThis extends typeof Error0>(
920
+ this: TThis,
921
+ error: unknown,
922
+ props: Partial<ErrorOwnProps<PluginsMapOf<TThis>>>,
923
+ ): InstanceType<TThis>
924
+ static assign(error: unknown, props: Record<string, unknown>): Error0 {
925
+ const error0 = this.from(error)
926
+ return error0.assign(props)
927
+ }
928
+ assign<TThis extends Error0>(this: TThis, props: Partial<ErrorOwnProps<PluginsMapOfInstance<TThis>>>): TThis
929
+ assign(props: Record<string, unknown>): this {
930
+ this.own = Object.assign(this.own ?? {}, props)
931
+ this._resolveByKeyCache.clear()
932
+ // const values = Object.values(props)
933
+ // if (values.every((value) => value === undefined)) {
934
+ // this.own = undefined
935
+ // }
936
+ return this
881
937
  }
882
938
 
883
939
  private static _applyAdapt(error: Error0): Error0 {
@@ -885,7 +941,7 @@ export class Error0 extends Error {
885
941
  for (const adapt of plugin.adapt) {
886
942
  const adapted = adapt(error as any)
887
943
  if (adapted && typeof adapted === 'object') {
888
- Object.assign(error as unknown as Record<string, unknown>, adapted)
944
+ error.assign(adapted)
889
945
  }
890
946
  }
891
947
  return error
@@ -994,49 +1050,6 @@ export class Error0 extends Error {
994
1050
  }
995
1051
  }
996
1052
 
997
- // static prop<
998
- // TThis extends typeof Error0,
999
- // TKey extends string,
1000
- // TInputValue = undefined,
1001
- // TOutputValue = unknown,
1002
- // TResolveValue extends TOutputValue | undefined = TOutputValue | undefined,
1003
- // >(
1004
- // this: TThis,
1005
- // key: TKey,
1006
- // value: ErrorPluginPropOptions<TInputValue, TOutputValue, ErrorInstanceOfMap<PluginsMapOf<TThis>>, TResolveValue>,
1007
- // ): ClassError0<ExtendErrorPluginsMapWithProp<PluginsMapOf<TThis>, TKey, TInputValue, TOutputValue, TResolveValue>> {
1008
- // return this.use('prop', key, value)
1009
- // }
1010
-
1011
- // static method<TThis extends typeof Error0, TKey extends string, TMethod extends (error: ErrorInstanceOfMap<PluginsMapOf<TThis>>, ...args: any[]) => any>(
1012
- // this: TThis,
1013
- // key: TKey,
1014
- // value: TMethod,
1015
- // ): ClassError0<ExtendErrorPluginsMapWithMethod<PluginsMapOf<TThis>, TKey, TMethod>> {
1016
- // return this.use('method', key, value)
1017
- // }
1018
-
1019
- // static adapt<TThis extends typeof Error0>(
1020
- // this: TThis,
1021
- // value: ErrorPluginAdaptFn<ErrorInstanceOfMap<PluginsMapOf<TThis>>, ErrorResolvedProps<PluginsMapOf<TThis>>>,
1022
- // ): ClassError0<PluginsMapOf<TThis>> {
1023
- // return this.use('adapt', value)
1024
- // }
1025
-
1026
- // static stack<TThis extends typeof Error0>(
1027
- // this: TThis,
1028
- // value: ErrorPluginStack<ErrorInstanceOfMap<PluginsMapOf<TThis>>>,
1029
- // ): ClassError0<PluginsMapOf<TThis>> {
1030
- // return this.use('stack', value)
1031
- // }
1032
-
1033
- // static cause<TThis extends typeof Error0>(
1034
- // this: TThis,
1035
- // value: ErrorPluginCause<ErrorInstanceOfMap<PluginsMapOf<TThis>>>,
1036
- // ): ClassError0<PluginsMapOf<TThis>> {
1037
- // return this.use('cause', value)
1038
- // }
1039
-
1040
1053
  static use<TThis extends typeof Error0, TBuilder extends PluginError0>(
1041
1054
  this: TThis,
1042
1055
  plugin: TBuilder,
@@ -1051,7 +1064,12 @@ export class Error0 extends Error {
1051
1064
  this: TThis,
1052
1065
  kind: 'prop',
1053
1066
  key: TKey,
1054
- value: ErrorPluginPropOptions<TInputValue, TOutputValue, ErrorInstanceOfMap<PluginsMapOf<TThis>>, TResolveValue>,
1067
+ value: ErrorPluginPropOptionsDefinition<
1068
+ TInputValue,
1069
+ TOutputValue,
1070
+ ErrorInstanceOfMap<PluginsMapOf<TThis>>,
1071
+ TResolveValue
1072
+ >,
1055
1073
  ): ClassError0<ExtendErrorPluginsMapWithProp<PluginsMapOf<TThis>, TKey, TInputValue, TOutputValue, TResolveValue>>
1056
1074
  static use<
1057
1075
  TThis extends typeof Error0,
@@ -1087,8 +1105,8 @@ export class Error0 extends Error {
1087
1105
  this: typeof Error0,
1088
1106
  first: PluginError0 | 'prop' | 'method' | 'adapt' | 'stack' | 'cause' | 'message',
1089
1107
  key?: unknown,
1090
- value?: ErrorPluginPropOptions<unknown> | ErrorPluginMethodFn<unknown>,
1091
- ): ClassError0 {
1108
+ value?: ErrorPluginPropOptionsDefinition<unknown> | ErrorPluginMethodFn<unknown>,
1109
+ ): ClassError0<any> {
1092
1110
  if (first instanceof PluginError0) {
1093
1111
  return this._useWithPlugin(this._pluginFromBuilder(first))
1094
1112
  }
@@ -1150,7 +1168,7 @@ export class Error0 extends Error {
1150
1168
  throw new Error(RESERVED_MESSAGE_PROP_ERROR)
1151
1169
  }
1152
1170
  return this._useWithPlugin({
1153
- props: { [key]: value as ErrorPluginPropOptions<unknown> },
1171
+ props: { [key]: fromPropOptionsDefinition(value as ErrorPluginPropOptionsDefinition<any, any>) },
1154
1172
  })
1155
1173
  }
1156
1174
  return this._useWithPlugin({
@@ -1163,10 +1181,14 @@ export class Error0 extends Error {
1163
1181
  }
1164
1182
 
1165
1183
  static serialize(error: unknown, isPublic = true): Record<string, unknown> {
1166
- const error0 = this.from(error)
1167
- const plugin = this._getResolvedPlugin()
1168
- const resolveByKey = (targetError: Error0, key: string, targetPlugin: ErrorPluginResolved): unknown =>
1169
- this._resolveByKey(targetError, key, targetPlugin)
1184
+ return this.from(error).serialize(isPublic)
1185
+ }
1186
+
1187
+ serialize(isPublic = true): Record<string, unknown> {
1188
+ // eslint-disable-next-line consistent-this, @typescript-eslint/no-this-alias
1189
+ const error0 = this
1190
+ const ctor = error0.constructor as typeof Error0
1191
+ const plugin = ctor._getResolvedPlugin()
1170
1192
  const messagePlugin = plugin.message
1171
1193
  let serializedMessage: unknown = error0.message
1172
1194
  try {
@@ -1191,15 +1213,13 @@ export class Error0 extends Error {
1191
1213
  }
1192
1214
  try {
1193
1215
  const options = {
1194
- get own() {
1195
- return error0.own(key as never)
1196
- },
1197
1216
  get flow() {
1198
1217
  return error0.flow(key as never)
1199
1218
  },
1200
1219
  get resolved() {
1201
- return resolveByKey(error0, key, plugin)
1220
+ return error0._resolveByKey(key, plugin)
1202
1221
  },
1222
+ own: error0.own?.[key],
1203
1223
  error: error0,
1204
1224
  isPublic,
1205
1225
  }
@@ -1234,8 +1254,8 @@ export class Error0 extends Error {
1234
1254
  cause: (error0 as { cause?: unknown }).cause,
1235
1255
  error: error0,
1236
1256
  isPublic,
1237
- is: (cause) => this.is(cause),
1238
- serialize: (cause) => this.serialize(cause, isPublic),
1257
+ is: (cause) => ctor.is(cause),
1258
+ serialize: (cause) => ctor.serialize(cause, isPublic),
1239
1259
  })
1240
1260
  if (serializedCause !== undefined) {
1241
1261
  json.cause = serializedCause
@@ -1247,14 +1267,4 @@ export class Error0 extends Error {
1247
1267
  }
1248
1268
  return json
1249
1269
  }
1250
-
1251
- serialize(isPublic = true): Record<string, unknown> {
1252
- const ctor = this.constructor as typeof Error0
1253
- return ctor.serialize(this, isPublic)
1254
- }
1255
-
1256
- round<TThis extends Error0>(this: TThis, isPublic = true): TThis {
1257
- const ctor = this.constructor as typeof Error0
1258
- return ctor.round(this, isPublic) as TThis
1259
- }
1260
1270
  }