@nice-code/error 0.0.20 → 0.1.0

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/README.md CHANGED
@@ -1 +1,5 @@
1
1
  # @nice-code/error
2
+
3
+ Typed, serializable errors with domain hierarchies, pattern matching, and safe transport across API boundaries.
4
+
5
+ See the [main README](../../README.md) for full documentation and examples.
package/build/index.js CHANGED
@@ -388,6 +388,7 @@ class NiceError extends Error {
388
388
  ids;
389
389
  wasntNice;
390
390
  httpStatusCode;
391
+ timeCreated;
391
392
  originError;
392
393
  _packedState;
393
394
  _errorDataMap;
@@ -401,6 +402,7 @@ class NiceError extends Error {
401
402
  if (options.originError != null) {
402
403
  this.originError = options.originError;
403
404
  }
405
+ this.timeCreated = options.timeCreated ?? Date.now();
404
406
  }
405
407
  hasId(id) {
406
408
  return id in this._errorDataMap;
@@ -478,7 +480,12 @@ class NiceError extends Error {
478
480
  } else {
479
481
  contextState = data.contextState;
480
482
  }
481
- errorData[id] = { contextState, message: data.message, httpStatusCode: data.httpStatusCode };
483
+ errorData[id] = {
484
+ contextState,
485
+ message: data.message,
486
+ httpStatusCode: data.httpStatusCode,
487
+ timeAdded: data.timeAdded
488
+ };
482
489
  }
483
490
  return {
484
491
  name: "NiceError",
@@ -488,34 +495,49 @@ class NiceError extends Error {
488
495
  wasntNice: this.wasntNice,
489
496
  message: this.message,
490
497
  httpStatusCode: this.httpStatusCode,
498
+ timeCreated: this.timeCreated,
491
499
  ...this.stack != null ? { stack: this.stack } : {},
492
500
  originError
493
501
  };
494
502
  }
503
+ toJsonString() {
504
+ return JSON.stringify(this.toJsonObject());
505
+ }
506
+ toHttpResponse() {
507
+ return new Response(this.toJsonString(), {
508
+ status: this.httpStatusCode,
509
+ headers: { "Content-Type": "application/json" }
510
+ });
511
+ }
495
512
  hydrate(definedNiceError) {
496
513
  return definedNiceError.hydrate(this);
497
514
  }
498
- handleWith(cases) {
499
- for (const c of cases) {
500
- if (!c._domain.isExact(this))
501
- continue;
502
- if (c._ids != null && !this.hasOneOfIds(c._ids))
503
- continue;
504
- c._handler(c._domain.hydrate(this));
505
- return true;
515
+ handleWithSync(handlerInput, handlerOptions = {}) {
516
+ const handlersArray = Array.isArray(handlerInput) ? handlerInput : [handlerInput];
517
+ for (const handler of handlersArray) {
518
+ const result = handler.handleErrorWithPromiseInspection(this, handlerOptions);
519
+ if (result.matched) {
520
+ if (result.isPromise) {
521
+ console.warn(`[NiceError.handleWith] Handler ${result.target.identifier} returned a Promise but was called via \`handleWith\` (synchronous). ` + `The Promise will not be awaited. Use \`handleWithAsync\` for async handlers.`);
522
+ }
523
+ return result.isPromise ? undefined : result.handlerResponse;
524
+ }
506
525
  }
507
- return false;
526
+ if (handlerOptions.throwOnUnhandled === true)
527
+ throw this;
528
+ return;
508
529
  }
509
- async handleWithAsync(cases) {
510
- for (const c of cases) {
511
- if (!c._domain.isExact(this))
512
- continue;
513
- if (c._ids != null && !this.hasOneOfIds(c._ids))
514
- continue;
515
- await c._handler(c._domain.hydrate(this));
516
- return true;
530
+ async handleWithAsync(handlerInput, handlerOptions = {}) {
531
+ const handlersArray = Array.isArray(handlerInput) ? handlerInput : [handlerInput];
532
+ for (const handler of handlersArray) {
533
+ const result = handler.handleErrorWithPromiseInspection(this, handlerOptions);
534
+ if (result.matched) {
535
+ return result.isPromise ? await result.handlerPromise : result.handlerResponse;
536
+ }
517
537
  }
518
- return false;
538
+ if (handlerOptions.throwOnUnhandled === true)
539
+ throw this;
540
+ return;
519
541
  }
520
542
  get isPacked() {
521
543
  return this._packedState != null;
@@ -595,7 +617,7 @@ class NiceErrorHydrated extends NiceError {
595
617
  }
596
618
 
597
619
  // src/NiceErrorDefined/NiceErrorDefined.ts
598
- class NiceErrorDefined {
620
+ class NiceErrorDomain {
599
621
  domain;
600
622
  allDomains;
601
623
  defaultHttpStatusCode;
@@ -620,7 +642,7 @@ class NiceErrorDefined {
620
642
  }
621
643
  }
622
644
  createChildDomain(subErrorDef) {
623
- const child = new NiceErrorDefined({
645
+ const child = new NiceErrorDomain({
624
646
  domain: subErrorDef.domain,
625
647
  allDomains: [subErrorDef.domain, ...this.allDomains],
626
648
  schema: subErrorDef.schema,
@@ -676,9 +698,10 @@ class NiceErrorDefined {
676
698
  if (errDef.domain !== this.domain) {
677
699
  throw new Error(`[NiceErrorDefined.hydrate] Domain mismatch: this definition is "${this.domain}" ` + `but the error belongs to "${errDef.domain}". ` + `Call \`niceErrorDefined.is(error)\` before hydrating to ensure compatibility.`);
678
700
  }
701
+ const finalError = error instanceof NiceError ? error : new NiceError(error);
679
702
  const reconciledErrorData = {};
680
- for (const id of error.getIds()) {
681
- const existingData = error.getErrorDataForId(id);
703
+ for (const id of finalError.getIds()) {
704
+ const existingData = finalError.getErrorDataForId(id);
682
705
  if (existingData == null)
683
706
  continue;
684
707
  let contextState = existingData.contextState;
@@ -696,18 +719,20 @@ class NiceErrorDefined {
696
719
  reconciledErrorData[id] = {
697
720
  contextState,
698
721
  message: existingData.message,
699
- httpStatusCode: existingData.httpStatusCode
722
+ httpStatusCode: existingData.httpStatusCode,
723
+ timeAdded: existingData.timeAdded
700
724
  };
701
725
  }
702
726
  return new NiceErrorHydrated({
703
727
  def: this._buildDef(),
704
728
  niceErrorDefined: this,
705
- ids: error.ids,
729
+ ids: finalError.ids,
706
730
  errorData: reconciledErrorData,
707
- message: error.message,
708
- httpStatusCode: error.httpStatusCode,
709
- wasntNice: error.wasntNice,
710
- originError: error.originError
731
+ message: finalError.message,
732
+ httpStatusCode: finalError.httpStatusCode,
733
+ wasntNice: finalError.wasntNice,
734
+ originError: finalError.originError,
735
+ timeCreated: finalError.timeCreated
711
736
  });
712
737
  }
713
738
  fromId(...args) {
@@ -798,13 +823,13 @@ class NiceErrorDefined {
798
823
  } else {
799
824
  contextState = { kind: "serde_unset" /* serde_unset */, value: context };
800
825
  }
801
- return { contextState, message, httpStatusCode };
826
+ return { contextState, message, httpStatusCode, timeAdded: Date.now() };
802
827
  }
803
828
  }
804
829
 
805
830
  // src/NiceErrorDefined/defineNiceError.ts
806
831
  var defineNiceError = (definition) => {
807
- return new NiceErrorDefined({
832
+ return new NiceErrorDomain({
808
833
  domain: definition.domain,
809
834
  allDomains: [definition.domain],
810
835
  schema: definition.schema,
@@ -880,6 +905,124 @@ var err_cast_not_nice = err_nice.createChildDomain({
880
905
  })
881
906
  }
882
907
  });
908
+ var err_nice_handler = err_nice.createChildDomain({
909
+ domain: "err_nice_handler",
910
+ schema: {}
911
+ });
912
+ // src/NiceErrorHandler/NiceErrorHandler.types.ts
913
+ var EErrorHandlerTargetType;
914
+ ((EErrorHandlerTargetType2) => {
915
+ EErrorHandlerTargetType2["ids"] = "ids";
916
+ EErrorHandlerTargetType2["domain"] = "domain";
917
+ EErrorHandlerTargetType2["default"] = "default";
918
+ })(EErrorHandlerTargetType ||= {});
919
+
920
+ // src/NiceErrorHandler/NiceErrorHandler.ts
921
+ class NiceErrorHandler {
922
+ handlerConfigs = [];
923
+ _defaultRequester;
924
+ handleErrorWithPromiseInspection(error, options) {
925
+ for (const handlerConfig of this.handlerConfigs) {
926
+ if (!handlerConfig._matcher(error))
927
+ continue;
928
+ const errorResult = handlerConfig._requester(error);
929
+ if (errorResult instanceof Promise) {
930
+ return {
931
+ isPromise: true,
932
+ matched: true,
933
+ target: handlerConfig.target,
934
+ handlerPromise: errorResult
935
+ };
936
+ }
937
+ return {
938
+ isPromise: false,
939
+ matched: true,
940
+ target: handlerConfig.target,
941
+ handlerResponse: errorResult
942
+ };
943
+ }
944
+ if (this._defaultRequester) {
945
+ const defaultResult = this._defaultRequester(error);
946
+ if (defaultResult instanceof Promise) {
947
+ return {
948
+ isPromise: true,
949
+ matched: true,
950
+ target: {
951
+ type: "default" /* default */,
952
+ identifier: "[matched:default]"
953
+ },
954
+ handlerPromise: defaultResult
955
+ };
956
+ }
957
+ return {
958
+ isPromise: false,
959
+ matched: true,
960
+ target: { type: "default" /* default */, identifier: "[matched:default]" },
961
+ handlerResponse: defaultResult
962
+ };
963
+ }
964
+ if (options?.throwOnUnhandled === true) {
965
+ throw error;
966
+ }
967
+ return {
968
+ matched: false,
969
+ attemptedTargets: this.handlerConfigs.map((config) => config.target)
970
+ };
971
+ }
972
+ forDomain(domain, handler) {
973
+ this.handlerConfigs.push({
974
+ target: {
975
+ type: "domain" /* domain */,
976
+ domain: domain.domain,
977
+ identifier: `[matched:domain:${domain.domain}]`
978
+ },
979
+ _matcher: (error) => domain.isExact(error),
980
+ _requester: (error) => handler(domain.hydrate(error))
981
+ });
982
+ return this;
983
+ }
984
+ forId(domain, id, handler) {
985
+ this.handlerConfigs.push({
986
+ target: {
987
+ type: "ids" /* ids */,
988
+ domain: domain.domain,
989
+ ids: [id],
990
+ identifier: `[matched:ids:${domain.domain}:${id}]`
991
+ },
992
+ _matcher: (error) => domain.isExact(error) && error.hasId(id),
993
+ _requester: (error) => handler(domain.hydrate(error))
994
+ });
995
+ return this;
996
+ }
997
+ forIds(domain, ids, handler) {
998
+ this.handlerConfigs.push({
999
+ target: {
1000
+ type: "ids" /* ids */,
1001
+ domain: domain.domain,
1002
+ ids,
1003
+ identifier: `[matched:ids:${domain.domain}:${ids.join(",")}]`
1004
+ },
1005
+ _matcher: (error) => domain.isExact(error) && ids.some((id) => error.hasId(id)),
1006
+ _requester: (error) => handler(domain.hydrate(error))
1007
+ });
1008
+ return this;
1009
+ }
1010
+ setDefaultHandler(handler) {
1011
+ this._defaultRequester = handler;
1012
+ return this;
1013
+ }
1014
+ }
1015
+
1016
+ // src/NiceErrorHandler/handleWith.ts
1017
+ function forDomain(domain, handler) {
1018
+ return new NiceErrorHandler().forDomain(domain, handler);
1019
+ }
1020
+ function forId(domain, id, handler) {
1021
+ return new NiceErrorHandler().forId(domain, id, handler);
1022
+ }
1023
+ function forIds(domain, ids, handler) {
1024
+ return new NiceErrorHandler().forIds(domain, ids, handler);
1025
+ }
883
1026
  // src/utils/isNiceErrorObject.ts
884
1027
  function isNiceErrorObject(obj) {
885
1028
  if (typeof obj !== "object" || obj == null)
@@ -2704,13 +2847,6 @@ function castAndHydrate(value, niceErrorDefined) {
2704
2847
  }
2705
2848
  return casted;
2706
2849
  }
2707
- // src/utils/handleWith.ts
2708
- function forDomain(domain, handler) {
2709
- return { _domain: domain, _ids: undefined, _handler: handler };
2710
- }
2711
- function forIds(domain, ids, handler) {
2712
- return { _domain: domain, _ids: ids, _handler: handler };
2713
- }
2714
2850
  // src/utils/matchFirst.ts
2715
2851
  function matchFirst(error, handlers) {
2716
2852
  for (const id of error.getIds()) {
@@ -2731,7 +2867,9 @@ export {
2731
2867
  isRegularErrorJsonObject,
2732
2868
  isNiceErrorObject,
2733
2869
  forIds,
2870
+ forId,
2734
2871
  forDomain,
2872
+ err_nice_handler,
2735
2873
  err_nice,
2736
2874
  err_cast_not_nice,
2737
2875
  err,
@@ -2740,8 +2878,10 @@ export {
2740
2878
  castNiceError,
2741
2879
  castAndHydrate,
2742
2880
  NiceErrorHydrated,
2743
- NiceErrorDefined,
2881
+ NiceErrorHandler,
2882
+ NiceErrorDomain,
2744
2883
  NiceError,
2745
2884
  EErrorPackType,
2885
+ EErrorHandlerTargetType,
2746
2886
  EErrId_CastNotNice
2747
2887
  };
@@ -1,11 +1,12 @@
1
- import type { NiceErrorDefined } from "../NiceErrorDefined/NiceErrorDefined";
2
- import type { IErrorCase } from "../utils/handleWith";
1
+ import type { NiceErrorDomain } from "../NiceErrorDefined/NiceErrorDefined";
2
+ import type { NiceErrorHandler } from "../NiceErrorHandler/NiceErrorHandler";
3
+ import type { IHandleErrorOptions } from "../NiceErrorHandler/NiceErrorHandler.types";
3
4
  import { EErrorPackType } from "../utils/packError/packError.enums";
4
- import { type INiceErrorDefinedProps, type INiceErrorJsonObject, type IRegularErrorJsonObject, type TErrorDataForIdMap, type TErrorReconciledData, type TExtractContextType, type TNiceErrorSchema, type TUnknownNiceErrorDef } from "./NiceError.types";
5
+ import { type INiceErrorDomainProps, type INiceErrorJsonObject, type IRegularErrorJsonObject, type TDomainNiceErrorId, type TErrorDataForIdMap, type TErrorReconciledData, type TExtractContextType, type TNiceErrorSchema, type TUnknownNiceErrorDef } from "./NiceError.types";
5
6
  import type { NiceErrorHydrated } from "./NiceErrorHydrated";
6
7
  type ContextOf<S extends TNiceErrorSchema, K extends keyof S> = TExtractContextType<S[K]>;
7
8
  /** Full-featured construction from NiceErrorDefined.fromId / fromContext. */
8
- export interface INiceErrorOptions<ERR_DEF extends INiceErrorDefinedProps, ID extends keyof ERR_DEF["schema"]> {
9
+ export interface INiceErrorOptions<ERR_DEF extends INiceErrorDomainProps, ID extends TDomainNiceErrorId<ERR_DEF> = TDomainNiceErrorId<ERR_DEF>> {
9
10
  def: Omit<ERR_DEF, "schema">;
10
11
  /** Primary id is first entry in ids. */
11
12
  ids: ID[];
@@ -15,8 +16,9 @@ export interface INiceErrorOptions<ERR_DEF extends INiceErrorDefinedProps, ID ex
15
16
  wasntNice?: boolean;
16
17
  httpStatusCode?: number;
17
18
  originError?: IRegularErrorJsonObject | undefined;
19
+ timeCreated?: number;
18
20
  }
19
- export declare class NiceError<ERR_DEF extends INiceErrorDefinedProps = TUnknownNiceErrorDef,
21
+ export declare class NiceError<ERR_DEF extends INiceErrorDomainProps = TUnknownNiceErrorDef,
20
22
  /**
21
23
  * Union of active error-id keys.
22
24
  * - After `fromId(id)`: exactly one key.
@@ -24,13 +26,14 @@ export declare class NiceError<ERR_DEF extends INiceErrorDefinedProps = TUnknown
24
26
  * - After `hasOneOfIds([a,b])`: narrows to that subset.
25
27
  * - Default (bare construction / castNiceError): `TUnknownNiceErrorId`.
26
28
  */
27
- ACTIVE_IDS extends keyof ERR_DEF["schema"] & string = keyof ERR_DEF["schema"] & string> extends Error {
29
+ ACTIVE_IDS extends TDomainNiceErrorId<ERR_DEF> = TDomainNiceErrorId<ERR_DEF>> extends Error {
28
30
  readonly name: "NiceError";
29
31
  readonly def: Omit<ERR_DEF, "schema">;
30
32
  /** Primary id is first entry in ids. */
31
33
  readonly ids: ACTIVE_IDS[];
32
34
  readonly wasntNice: boolean;
33
35
  readonly httpStatusCode: number;
36
+ readonly timeCreated: number;
34
37
  originError?: IRegularErrorJsonObject;
35
38
  _packedState?: {
36
39
  packedAs: EErrorPackType.cause_pack;
@@ -88,7 +91,9 @@ ACTIVE_IDS extends keyof ERR_DEF["schema"] & string = keyof ERR_DEF["schema"] &
88
91
  */
89
92
  matches(other: NiceError<any, any>): boolean;
90
93
  toJsonObject(): INiceErrorJsonObject<ERR_DEF>;
91
- hydrate(definedNiceError: NiceErrorDefined<ERR_DEF>): NiceErrorHydrated<ERR_DEF, ACTIVE_IDS>;
94
+ toJsonString(): string;
95
+ toHttpResponse(): Response;
96
+ hydrate(definedNiceError: NiceErrorDomain<ERR_DEF>): NiceErrorHydrated<ERR_DEF, ACTIVE_IDS>;
92
97
  /**
93
98
  * Iterates `cases` in order, finds the first whose domain matches this error
94
99
  * (via `is()`), optionally further filters by active ids, hydrates the error,
@@ -117,7 +122,7 @@ ACTIVE_IDS extends keyof ERR_DEF["schema"] & string = keyof ERR_DEF["schema"] &
117
122
  * if (!handled) next(error);
118
123
  * ```
119
124
  */
120
- handleWith(cases: ReadonlyArray<IErrorCase<any, any>>): boolean;
125
+ handleWithSync<RD, R>(handlerInput: NiceErrorHandler<RD, R> | ReadonlyArray<NiceErrorHandler<RD, R>>, handlerOptions?: IHandleErrorOptions): R | RD | undefined;
121
126
  /**
122
127
  * Same matching logic as `handleWith`, but `await`s the handler's returned
123
128
  * Promise before resolving. Use this when your handlers perform async work
@@ -133,7 +138,7 @@ ACTIVE_IDS extends keyof ERR_DEF["schema"] & string = keyof ERR_DEF["schema"] &
133
138
  * ]);
134
139
  * ```
135
140
  */
136
- handleWithAsync(cases: ReadonlyArray<IErrorCase<any, any>>): Promise<boolean>;
141
+ handleWithAsync<RD, R>(handlerInput: NiceErrorHandler<RD, R> | ReadonlyArray<NiceErrorHandler<RD, R>>, handlerOptions?: IHandleErrorOptions): Promise<R | RD | undefined>;
137
142
  get isPacked(): boolean;
138
143
  pack(packType?: EErrorPackType): this;
139
144
  unpack(): this;
@@ -111,6 +111,7 @@ export type TErrorReconciledData<SCHEMA extends TNiceErrorSchema, K extends keyo
111
111
  contextState: TContextState<TExtractContextType<SCHEMA[K]>>;
112
112
  message: string;
113
113
  httpStatusCode: number;
114
+ timeAdded: number;
114
115
  };
115
116
  /**
116
117
  * Wire-safe reconciled data — uses `TSerializedContextState` (no `"hydrated"`).
@@ -118,24 +119,25 @@ export type TErrorReconciledData<SCHEMA extends TNiceErrorSchema, K extends keyo
118
119
  * over the wire. `"hydrated"` is excluded so that the serialization state can
119
120
  * never be trusted after a JSON round-trip.
120
121
  */
121
- export type TSerializedErrorReconciledData<SCHEMA extends TNiceErrorSchema, K extends keyof SCHEMA> = {
122
+ export type TSerializedErrorReconciledData<SCHEMA extends TNiceErrorSchema, K extends TSchemaNiceErrorId<SCHEMA>> = {
122
123
  contextState: TSerializedContextState<TExtractContextType<SCHEMA[K]>>;
123
124
  message: string;
124
125
  httpStatusCode: number;
126
+ timeAdded: number;
125
127
  };
126
- export type TErrorDataForIdMap<SCHEMA extends TNiceErrorSchema> = {
127
- [K in keyof SCHEMA]?: TErrorReconciledData<SCHEMA, K>;
128
+ export type TErrorDataForIdMap<SCHEMA extends TNiceErrorSchema, K extends TSchemaNiceErrorId<SCHEMA> = TSchemaNiceErrorId<SCHEMA>> = {
129
+ [key in K]?: TErrorReconciledData<SCHEMA, K>;
128
130
  };
129
131
  /** Wire-safe version of `TErrorDataForIdMap`. Used in `INiceErrorJsonObject`. */
130
132
  export type TSerializedErrorDataMap<SCHEMA extends TNiceErrorSchema> = {
131
- [K in keyof SCHEMA]?: TSerializedErrorReconciledData<SCHEMA, K>;
133
+ [K in TSchemaNiceErrorId<SCHEMA>]?: TSerializedErrorReconciledData<SCHEMA, K>;
132
134
  };
133
135
  /**
134
136
  * The Partial record that `fromContext` accepts: callers supply one or more
135
137
  * { [errorId]: contextValue } entries and NiceError stores them all.
136
138
  */
137
139
  export type TFromContextInput<SCHEMA extends TNiceErrorSchema> = {
138
- [K in keyof SCHEMA]?: TExtractContextType<SCHEMA[K]> | undefined;
140
+ [K in TSchemaNiceErrorId<SCHEMA>]?: TExtractContextType<SCHEMA[K]> | undefined;
139
141
  };
140
142
  /**
141
143
  * Resolves the args tuple for `fromId` / `addId`:
@@ -144,7 +146,7 @@ export type TFromContextInput<SCHEMA extends TNiceErrorSchema> = {
144
146
  * - Context defined, `required: true` → `[id, context]`
145
147
  * - Context defined, `required` absent/false → `[id] | [id, context]`
146
148
  */
147
- export type FromIdArgs<ERR_DEF extends INiceErrorDefinedProps, K extends keyof ERR_DEF["schema"]> = [ExtractFromIdContextArg<ERR_DEF["schema"][K]>] extends [undefined] ? [id: K] : [undefined] extends [ExtractFromIdContextArg<ERR_DEF["schema"][K]>] ? [id: K] | [id: K, context: NonNullable<ExtractFromIdContextArg<ERR_DEF["schema"][K]>>] : [id: K, context: ExtractFromIdContextArg<ERR_DEF["schema"][K]>];
149
+ export type FromIdArgs<ERR_DEF extends INiceErrorDomainProps, K extends TDomainNiceErrorId<ERR_DEF>> = [ExtractFromIdContextArg<ERR_DEF["schema"][K]>] extends [undefined] ? [id: K] : [undefined] extends [ExtractFromIdContextArg<ERR_DEF["schema"][K]>] ? [id: K] | [id: K, context: NonNullable<ExtractFromIdContextArg<ERR_DEF["schema"][K]>>] : [id: K, context: ExtractFromIdContextArg<ERR_DEF["schema"][K]>];
148
150
  export interface IPackErrorAs_Base {
149
151
  packAs: EErrorPackType;
150
152
  }
@@ -158,7 +160,7 @@ export interface IDefineNewNiceErrorDomainOptions<ERR_DOMAIN extends string = st
158
160
  domain: ERR_DOMAIN;
159
161
  schema: SCHEMA;
160
162
  }
161
- export interface INiceErrorDefinedProps<ERR_DOMAINS extends string[] = string[], SCHEMA extends TNiceErrorSchema = TNiceErrorSchema> {
163
+ export interface INiceErrorDomainProps<ERR_DOMAINS extends string[] = string[], SCHEMA extends TNiceErrorSchema = TNiceErrorSchema> {
162
164
  packAs?: () => EErrorPackType | void;
163
165
  defaultHttpStatusCode?: number;
164
166
  defaultMessage?: string;
@@ -166,7 +168,7 @@ export interface INiceErrorDefinedProps<ERR_DOMAINS extends string[] = string[],
166
168
  allDomains: ERR_DOMAINS;
167
169
  schema: SCHEMA;
168
170
  }
169
- export interface INiceErrorJsonObject<ERR_DEF extends INiceErrorDefinedProps = INiceErrorDefinedProps, ID extends keyof ERR_DEF["schema"] & string = keyof ERR_DEF["schema"] & string> {
171
+ export interface INiceErrorJsonObject<ERR_DEF extends INiceErrorDomainProps = INiceErrorDomainProps, ID extends TDomainNiceErrorId<ERR_DEF> = TDomainNiceErrorId<ERR_DEF>> {
170
172
  name: "NiceError";
171
173
  def: Omit<ERR_DEF, "schema">;
172
174
  ids: ID[];
@@ -179,7 +181,10 @@ export interface INiceErrorJsonObject<ERR_DEF extends INiceErrorDefinedProps = I
179
181
  stack?: string;
180
182
  cause?: unknown;
181
183
  originError?: IRegularErrorJsonObject | undefined;
184
+ timeCreated: number;
182
185
  }
186
+ export type TSchemaNiceErrorId<SCHEMA extends TNiceErrorSchema> = keyof SCHEMA & string;
187
+ export type TDomainNiceErrorId<ERR_DEF extends INiceErrorDomainProps> = TSchemaNiceErrorId<ERR_DEF["schema"]>;
183
188
  /**
184
189
  * The widest ERR_DEF used when creating a NiceError without a definition
185
190
  * (bare construction, castNiceError, etc.).
@@ -189,7 +194,7 @@ export interface INiceErrorJsonObject<ERR_DEF extends INiceErrorDefinedProps = I
189
194
  * correctly — `string & "specific_domain"` narrows to `"specific_domain"`
190
195
  * instead of collapsing the intersection to `never`.
191
196
  */
192
- export type TUnknownNiceErrorDef = INiceErrorDefinedProps;
197
+ export type TUnknownNiceErrorDef = INiceErrorDomainProps;
193
198
  /**
194
199
  * Wide id type for bare / cast NiceErrors that have no schema.
195
200
  * Using `string` (rather than a literal `"unknown"`) ensures that
@@ -1,6 +1,6 @@
1
- import type { NiceErrorDefined } from "../NiceErrorDefined/NiceErrorDefined";
1
+ import type { NiceErrorDomain } from "../NiceErrorDefined/NiceErrorDefined";
2
2
  import { type INiceErrorOptions, NiceError } from "./NiceError";
3
- import type { ExtractFromIdContextArg, INiceErrorDefinedProps, TFromContextInput, TUnknownNiceErrorDef } from "./NiceError.types";
3
+ import type { ExtractFromIdContextArg, INiceErrorDomainProps, TDomainNiceErrorId, TFromContextInput, TUnknownNiceErrorDef } from "./NiceError.types";
4
4
  /**
5
5
  * Resolves the args tuple for `addId` — mirrors `FromIdArgs` exactly so that
6
6
  * optional vs required context is consistent across both `fromId` and `addId`.
@@ -9,13 +9,15 @@ import type { ExtractFromIdContextArg, INiceErrorDefinedProps, TFromContextInput
9
9
  * - Context defined, `required: true` → `[id, context]`
10
10
  * - Context defined, `required` absent/false → `[id] | [id, context]`
11
11
  */
12
- type AddIdArgs<ERR_DEF extends INiceErrorDefinedProps, K extends keyof ERR_DEF["schema"] & string> = [ExtractFromIdContextArg<ERR_DEF["schema"][K]>] extends [undefined] ? [id: K] : [undefined] extends [ExtractFromIdContextArg<ERR_DEF["schema"][K]>] ? [id: K] | [id: K, context: NonNullable<ExtractFromIdContextArg<ERR_DEF["schema"][K]>>] : [id: K, context: ExtractFromIdContextArg<ERR_DEF["schema"][K]>];
12
+ type AddIdArgs<ERR_DEF extends INiceErrorDomainProps, K extends TDomainNiceErrorId<ERR_DEF>> = [
13
+ ExtractFromIdContextArg<ERR_DEF["schema"][K]>
14
+ ] extends [undefined] ? [id: K] : [undefined] extends [ExtractFromIdContextArg<ERR_DEF["schema"][K]>] ? [id: K] | [id: K, context: NonNullable<ExtractFromIdContextArg<ERR_DEF["schema"][K]>>] : [id: K, context: ExtractFromIdContextArg<ERR_DEF["schema"][K]>];
13
15
  /** Full-featured construction from NiceErrorDefined.fromId / fromContext. */
14
- export interface INiceErrorHydratedOptions<ERR_DEF extends INiceErrorDefinedProps, ID extends keyof ERR_DEF["schema"] & string> extends INiceErrorOptions<ERR_DEF, ID> {
16
+ export interface INiceErrorHydratedOptions<ERR_DEF extends INiceErrorDomainProps, ID extends TDomainNiceErrorId<ERR_DEF>> extends INiceErrorOptions<ERR_DEF, ID> {
15
17
  def: ERR_DEF;
16
- niceErrorDefined: NiceErrorDefined<ERR_DEF>;
18
+ niceErrorDefined: NiceErrorDomain<ERR_DEF>;
17
19
  }
18
- export declare class NiceErrorHydrated<ERR_DEF extends INiceErrorDefinedProps = TUnknownNiceErrorDef,
20
+ export declare class NiceErrorHydrated<ERR_DEF extends INiceErrorDomainProps = TUnknownNiceErrorDef,
19
21
  /**
20
22
  * Union of active error-id keys.
21
23
  * - After `fromId(id)`: exactly one key.
@@ -23,7 +25,7 @@ export declare class NiceErrorHydrated<ERR_DEF extends INiceErrorDefinedProps =
23
25
  * - After `hasOneOfIds([a,b])`: narrows to that subset.
24
26
  * - Default (bare construction / castNiceError): `TUnknownNiceErrorId`.
25
27
  */
26
- ACTIVE_IDS extends keyof ERR_DEF["schema"] & string = keyof ERR_DEF["schema"] & string> extends NiceError<ERR_DEF, ACTIVE_IDS> {
28
+ ACTIVE_IDS extends TDomainNiceErrorId<ERR_DEF> = TDomainNiceErrorId<ERR_DEF>> extends NiceError<ERR_DEF, ACTIVE_IDS> {
27
29
  readonly def: ERR_DEF;
28
30
  private readonly niceErrorDefined;
29
31
  constructor(options: INiceErrorHydratedOptions<ERR_DEF, ACTIVE_IDS>);
@@ -44,6 +46,6 @@ ACTIVE_IDS extends keyof ERR_DEF["schema"] & string = keyof ERR_DEF["schema"] &
44
46
  * if the schema requires one). Equivalent to `addContext({ [id]: context })`
45
47
  * but mirrors the `fromId` ergonomics for single-id additions.
46
48
  */
47
- addId<K extends keyof ERR_DEF["schema"] & string>(...args: AddIdArgs<ERR_DEF, K>): NiceErrorHydrated<ERR_DEF, ACTIVE_IDS | K>;
49
+ addId<K extends TDomainNiceErrorId<ERR_DEF>>(...args: AddIdArgs<ERR_DEF, K>): NiceErrorHydrated<ERR_DEF, ACTIVE_IDS | K>;
48
50
  }
49
51
  export {};
@@ -1,8 +1,8 @@
1
1
  import { NiceError } from "../NiceError/NiceError";
2
- import { type FromIdArgs, type IDefineNewNiceErrorDomainOptions, type INiceErrorDefinedProps, type TErrorReconciledData, type TFromContextInput } from "../NiceError/NiceError.types";
2
+ import { type FromIdArgs, type IDefineNewNiceErrorDomainOptions, type INiceErrorDomainProps, type INiceErrorJsonObject, type TDomainNiceErrorId, type TErrorReconciledData, type TFromContextInput } from "../NiceError/NiceError.types";
3
3
  import { NiceErrorHydrated } from "../NiceError/NiceErrorHydrated";
4
4
  import { type EErrorPackType } from "../utils/packError/packError.enums";
5
- type ChildDef<PARENT_DEF extends INiceErrorDefinedProps, SUB extends IDefineNewNiceErrorDomainOptions> = {
5
+ type ChildDef<PARENT_DEF extends INiceErrorDomainProps, SUB extends IDefineNewNiceErrorDomainOptions> = {
6
6
  domain: SUB["domain"];
7
7
  allDomains: [SUB["domain"], ...PARENT_DEF["allDomains"]];
8
8
  schema: SUB["schema"];
@@ -25,7 +25,7 @@ type KeysOfContextInput<INPUT> = keyof INPUT & string;
25
25
  * // → NiceError<{ domain: "err_user_auth"; ... }, keyof schema>
26
26
  * ```
27
27
  */
28
- export type InferNiceError<T extends NiceErrorDefined<any>> = T extends NiceErrorDefined<infer ERR_DEF> ? NiceError<ERR_DEF, keyof ERR_DEF["schema"] & string> : never;
28
+ export type InferNiceError<T extends NiceErrorDomain<any>> = T extends NiceErrorDomain<infer ERR_DEF> ? NiceError<ERR_DEF, keyof ERR_DEF["schema"] & string> : never;
29
29
  /**
30
30
  * Infers the strongly-typed `NiceErrorHydrated` class type from a `NiceErrorDefined` instance.
31
31
  *
@@ -39,8 +39,8 @@ export type InferNiceError<T extends NiceErrorDefined<any>> = T extends NiceErro
39
39
  * // → NiceErrorHydrated<{ domain: "err_user_auth"; ... }, keyof schema>
40
40
  * ```
41
41
  */
42
- export type InferNiceErrorHydrated<T extends NiceErrorDefined<any>> = T extends NiceErrorDefined<infer ERR_DEF> ? NiceErrorHydrated<ERR_DEF, keyof ERR_DEF["schema"] & string> : never;
43
- export declare class NiceErrorDefined<ERR_DEF extends INiceErrorDefinedProps = INiceErrorDefinedProps> {
42
+ export type InferNiceErrorHydrated<T extends NiceErrorDomain<any>> = T extends NiceErrorDomain<infer ERR_DEF> ? NiceErrorHydrated<ERR_DEF, keyof ERR_DEF["schema"] & string> : never;
43
+ export declare class NiceErrorDomain<ERR_DEF extends INiceErrorDomainProps = INiceErrorDomainProps> {
44
44
  readonly domain: ERR_DEF["domain"];
45
45
  readonly allDomains: ERR_DEF["allDomains"];
46
46
  readonly defaultHttpStatusCode?: number;
@@ -60,9 +60,9 @@ export declare class NiceErrorDefined<ERR_DEF extends INiceErrorDefinedProps = I
60
60
  */
61
61
  createChildDomain<SUB extends IDefineNewNiceErrorDomainOptions>(subErrorDef: SUB & {
62
62
  [K in Exclude<keyof SUB, keyof IDefineNewNiceErrorDomainOptions>]: never;
63
- }): NiceErrorDefined<ChildDef<ERR_DEF, SUB>>;
64
- protected addParentNiceErrorDefined<PARENT_DEF extends INiceErrorDefinedProps>(parentError: NiceErrorDefined<PARENT_DEF>): void;
65
- protected addChildNiceErrorDefined<CHILD_DEF extends INiceErrorDefinedProps>(child: NiceErrorDefined<CHILD_DEF>): void;
63
+ }): NiceErrorDomain<ChildDef<ERR_DEF, SUB>>;
64
+ protected addParentNiceErrorDefined<PARENT_DEF extends INiceErrorDomainProps>(parentError: NiceErrorDomain<PARENT_DEF>): void;
65
+ protected addChildNiceErrorDefined<CHILD_DEF extends INiceErrorDomainProps>(child: NiceErrorDomain<CHILD_DEF>): void;
66
66
  packAs(pack: EErrorPackType): this;
67
67
  private createError;
68
68
  /**
@@ -88,7 +88,7 @@ export declare class NiceErrorDefined<ERR_DEF extends INiceErrorDefinedProps = I
88
88
  * }
89
89
  * ```
90
90
  */
91
- hydrate<ACTIVE_IDS extends keyof ERR_DEF["schema"] & string>(error: NiceError<ERR_DEF, ACTIVE_IDS>): NiceErrorHydrated<ERR_DEF, ACTIVE_IDS>;
91
+ hydrate<ACTIVE_IDS extends TDomainNiceErrorId<ERR_DEF> = TDomainNiceErrorId<ERR_DEF>>(error: NiceError<ERR_DEF, ACTIVE_IDS> | INiceErrorJsonObject<ERR_DEF, ACTIVE_IDS>): NiceErrorHydrated<ERR_DEF, ACTIVE_IDS>;
92
92
  /**
93
93
  * Creates a `NiceErrorHydrated` for a single error id.
94
94
  *
@@ -126,7 +126,7 @@ export declare class NiceErrorDefined<ERR_DEF extends INiceErrorDefinedProps = I
126
126
  * Accepts either a `NiceErrorDefined` (domain definition) or a `NiceError`
127
127
  * instance (extracts the domain from its `def`).
128
128
  */
129
- isParentOf(target: NiceErrorDefined<any> | NiceError<any, any>): boolean;
129
+ isParentOf(target: NiceErrorDomain<any> | NiceError<any, any>): boolean;
130
130
  private _buildDef;
131
131
  private _resolveMessage;
132
132
  private _resolveHttpStatusCode;
@@ -1,6 +1,6 @@
1
1
  import type { IDefineNewNiceErrorDomainOptions, TNiceErrorSchema } from "../NiceError/NiceError.types";
2
- import { NiceErrorDefined } from "./NiceErrorDefined";
3
- export declare const defineNiceError: <ERR_DOMAIN extends string, SCHEMA extends TNiceErrorSchema>(definition: IDefineNewNiceErrorDomainOptions<ERR_DOMAIN, SCHEMA>) => NiceErrorDefined<{
2
+ import { NiceErrorDomain } from "./NiceErrorDefined";
3
+ export declare const defineNiceError: <ERR_DOMAIN extends string, SCHEMA extends TNiceErrorSchema>(definition: IDefineNewNiceErrorDomainOptions<ERR_DOMAIN, SCHEMA>) => NiceErrorDomain<{
4
4
  domain: ERR_DOMAIN;
5
5
  allDomains: [ERR_DOMAIN];
6
6
  schema: SCHEMA;
@@ -0,0 +1,23 @@
1
+ import type { NiceError } from "../NiceError/NiceError";
2
+ import type { INiceErrorDomainProps, TDomainNiceErrorId } from "../NiceError/NiceError.types";
3
+ import type { NiceErrorHydrated } from "../NiceError/NiceErrorHydrated";
4
+ import type { NiceErrorDomain } from "../NiceErrorDefined/NiceErrorDefined";
5
+ import { type IHandleErrorOptions, type MaybePromise, type THandleErrorWithPromiseInspection } from "./NiceErrorHandler.types";
6
+ export declare class NiceErrorHandler<RES_DEF = never, RES = never> {
7
+ private handlerConfigs;
8
+ private _defaultRequester?;
9
+ handleErrorWithPromiseInspection(error: NiceError<any, any>, options?: IHandleErrorOptions): THandleErrorWithPromiseInspection<RES | RES_DEF>;
10
+ /**
11
+ * Register a handler that fires for **any** error whose domain matches `domain`.
12
+ * The handler receives a fully hydrated error — `getContext`, `addId`, and `addContext`
13
+ * are all available. First matching case wins.
14
+ */
15
+ forDomain<DEF extends INiceErrorDomainProps, H_RES = void>(domain: NiceErrorDomain<DEF>, handler: (error: NiceErrorHydrated<DEF, TDomainNiceErrorId<DEF>>) => MaybePromise<H_RES>): NiceErrorHandler<RES_DEF, RES | H_RES>;
16
+ forId<DEF extends INiceErrorDomainProps, ID extends TDomainNiceErrorId<DEF>, H_RES = void>(domain: NiceErrorDomain<DEF>, id: ID, handler: (error: NiceErrorHydrated<DEF, ID>) => MaybePromise<H_RES>): NiceErrorHandler<RES_DEF, RES | H_RES>;
17
+ forIds<DEF extends INiceErrorDomainProps, IDS extends TDomainNiceErrorId<DEF>[], H_RES = void>(domain: NiceErrorDomain<DEF>, ids: IDS, handler: (error: NiceErrorHydrated<DEF, IDS[number]>) => MaybePromise<H_RES>): NiceErrorHandler<RES_DEF, RES | H_RES>;
18
+ /**
19
+ * Register a fallback handler that fires when no other case matches.
20
+ * Only one default handler can be registered — calling this twice replaces the previous one.
21
+ */
22
+ setDefaultHandler<H_RES>(handler: (error: NiceError<any, any>) => MaybePromise<H_RES>): NiceErrorHandler<H_RES, RES>;
23
+ }
@@ -0,0 +1,82 @@
1
+ import type { NiceError } from "../NiceError/NiceError";
2
+ import type { INiceErrorDomainProps, TDomainNiceErrorId } from "../NiceError/NiceError.types";
3
+ import type { NiceErrorHydrated } from "../NiceError/NiceErrorHydrated";
4
+ export type MaybePromise<T> = T | Promise<T>;
5
+ /**
6
+ * Broad handler signature used internally for storage and dispatch.
7
+ */
8
+ export type TBroadErrorHandler<E extends NiceError = NiceError, RES = unknown> = (action: E) => MaybePromise<RES>;
9
+ /**
10
+ * Handler registered via forDomain.
11
+ *
12
+ * `act.input` is typed as the union of input types for every action in `ACT_DOM`,
13
+ * and `act.coreAction` carries the matching schema — the same narrowing you get
14
+ * from `forActionIds` over all action IDs in the domain.
15
+ */
16
+ export type TErrorHandlerForDomain<ERR_DOM extends INiceErrorDomainProps> = (error: NiceErrorHydrated<ERR_DOM>) => MaybePromise<unknown>;
17
+ /**
18
+ * Handler registered via forActionId — receives a specific action ID, with
19
+ * the primed action's input narrowed to that ID's schema.
20
+ */
21
+ export type TErrorIdHandlerForDomain<ERR_DOM extends INiceErrorDomainProps, ID extends TDomainNiceErrorId<ERR_DOM>> = (error: NiceErrorHydrated<ERR_DOM, ID>) => MaybePromise<unknown>;
22
+ export declare enum EErrorHandlerTargetType {
23
+ ids = "ids",
24
+ domain = "domain",
25
+ default = "default"
26
+ }
27
+ export type TErrorHandlerTarget = ({
28
+ type: EErrorHandlerTargetType.ids;
29
+ domain: string;
30
+ ids: string[];
31
+ } | {
32
+ type: EErrorHandlerTargetType.domain;
33
+ domain: string;
34
+ } | {
35
+ type: EErrorHandlerTargetType.default;
36
+ }) & {
37
+ identifier: string;
38
+ };
39
+ /**
40
+ * A single case in a `handleWith` / `handleWithAsync` call.
41
+ *
42
+ * Construct via `forDomain` or `forIds` — do not build this object directly.
43
+ */
44
+ export interface IErrorHandlerConfig<ERR extends NiceError<any, any> = NiceError<any, any>, RES = unknown> {
45
+ readonly _matcher: (action: ERR) => boolean;
46
+ readonly _requester: TBroadErrorHandler<ERR, RES>;
47
+ }
48
+ export interface IErrorHandleAttempt_Success<RES = void> {
49
+ handled: true;
50
+ result: RES;
51
+ target: TErrorHandlerTarget;
52
+ }
53
+ export interface IErrorHandleAttempt_Failure {
54
+ handled: false;
55
+ result?: undefined;
56
+ targets: TErrorHandlerTarget[];
57
+ }
58
+ export type TErrorHandleAttempt<RES = void> = IErrorHandleAttempt_Success<RES> | IErrorHandleAttempt_Failure;
59
+ export interface IHandleErrorOptions {
60
+ throwOnUnhandled?: boolean;
61
+ }
62
+ export type THandleErrorWithPromiseInspection<RES = void> = {
63
+ isPromise: false;
64
+ matched: true;
65
+ target: TErrorHandlerTarget;
66
+ handlerResponse: RES;
67
+ } | {
68
+ isPromise: true;
69
+ matched: true;
70
+ target: TErrorHandlerTarget;
71
+ handlerPromise: Promise<RES>;
72
+ } | {
73
+ matched: false;
74
+ attemptedTargets: TErrorHandlerTarget[];
75
+ };
76
+ export type THandleResponse<RES = unknown> = {
77
+ handled: false;
78
+ } | {
79
+ handled: true;
80
+ isPromise: boolean;
81
+ response: RES;
82
+ };
@@ -0,0 +1,8 @@
1
+ import type { INiceErrorDomainProps, TDomainNiceErrorId } from "../NiceError/NiceError.types";
2
+ import type { NiceErrorHydrated } from "../NiceError/NiceErrorHydrated";
3
+ import type { NiceErrorDomain } from "../NiceErrorDefined/NiceErrorDefined";
4
+ import { NiceErrorHandler } from "./NiceErrorHandler";
5
+ import type { MaybePromise } from "./NiceErrorHandler.types";
6
+ export declare function forDomain<DEF extends INiceErrorDomainProps, H_RES = void>(domain: NiceErrorDomain<DEF>, handler: (error: NiceErrorHydrated<DEF, TDomainNiceErrorId<DEF>>) => MaybePromise<H_RES>): NiceErrorHandler<never, H_RES>;
7
+ export declare function forId<DEF extends INiceErrorDomainProps, ID extends TDomainNiceErrorId<DEF>, H_RES = void>(domain: NiceErrorDomain<DEF>, id: ID, handler: (error: NiceErrorHydrated<DEF, ID>) => MaybePromise<H_RES>): NiceErrorHandler<never, H_RES>;
8
+ export declare function forIds<DEF extends INiceErrorDomainProps, IDS extends TDomainNiceErrorId<DEF>[], H_RES = void>(domain: NiceErrorDomain<DEF>, ids: IDS, handler: (error: NiceErrorHydrated<DEF, IDS[number]>) => MaybePromise<H_RES>): NiceErrorHandler<never, H_RES>;
@@ -1,4 +1,4 @@
1
- export declare const err_example_app: import("..").NiceErrorDefined<{
1
+ export declare const err_example_app: import("..").NiceErrorDomain<{
2
2
  domain: "err_example_app";
3
3
  allDomains: ["err_example_app"];
4
4
  schema: {};
@@ -7,7 +7,7 @@ export declare enum EErrId_UserAuth {
7
7
  invalid_credentials = "invalid_credentials",
8
8
  account_locked = "account_locked"
9
9
  }
10
- export declare const err_user_auth: import("..").NiceErrorDefined<{
10
+ export declare const err_user_auth: import("..").NiceErrorDomain<{
11
11
  domain: string;
12
12
  allDomains: [string, "err_example_app"];
13
13
  schema: {
@@ -25,7 +25,7 @@ export declare enum EErrId_UserAuth_Registration {
25
25
  password_error = "password_error",
26
26
  password_too_short = "password_too_short"
27
27
  }
28
- export declare const err_user_auth_registration: import("..").NiceErrorDefined<{
28
+ export declare const err_user_auth_registration: import("..").NiceErrorDomain<{
29
29
  domain: string;
30
30
  allDomains: [string, string, "err_example_app"];
31
31
  schema: {
@@ -5,9 +5,11 @@ export * from "./NiceError/NiceErrorHydrated";
5
5
  export * from "./NiceErrorDefined/defineNiceError";
6
6
  export * from "./NiceErrorDefined/err";
7
7
  export * from "./NiceErrorDefined/NiceErrorDefined";
8
+ export * from "./NiceErrorHandler/handleWith";
9
+ export * from "./NiceErrorHandler/NiceErrorHandler";
10
+ export * from "./NiceErrorHandler/NiceErrorHandler.types";
8
11
  export * from "./utils/castAndHydrate";
9
12
  export * from "./utils/castNiceError";
10
- export * from "./utils/handleWith";
11
13
  export * from "./utils/isNiceErrorObject";
12
14
  export * from "./utils/isRegularErrorObject";
13
15
  export * from "./utils/matchFirst";
@@ -1,5 +1,5 @@
1
1
  import type { IInspectErrorResult_JsError, IInspectErrorResult_JsErrorObject, IInspectErrorResult_JsOther, IInspectErrorResult_Nullish, TInspectErrorResult_JsDataType } from "../utils/inspectPotentialError/inspectPotentialError.types";
2
- export declare const err_nice: import("..").NiceErrorDefined<{
2
+ export declare const err_nice: import("..").NiceErrorDomain<{
3
3
  domain: "err_nice";
4
4
  allDomains: ["err_nice"];
5
5
  schema: {};
@@ -11,7 +11,7 @@ export declare enum EErrId_CastNotNice {
11
11
  js_data_type = "js_data_type",
12
12
  js_other = "js_other"
13
13
  }
14
- export declare const err_cast_not_nice: import("..").NiceErrorDefined<{
14
+ export declare const err_cast_not_nice: import("..").NiceErrorDomain<{
15
15
  domain: string;
16
16
  allDomains: [string, "err_nice"];
17
17
  schema: {
@@ -42,3 +42,8 @@ export declare const err_cast_not_nice: import("..").NiceErrorDefined<{
42
42
  };
43
43
  };
44
44
  }>;
45
+ export declare const err_nice_handler: import("..").NiceErrorDomain<{
46
+ domain: string;
47
+ allDomains: [string, "err_nice"];
48
+ schema: {};
49
+ }>;
@@ -1,3 +1,3 @@
1
1
  import type { INiceErrorOptions } from "../../NiceError/NiceError";
2
- import type { INiceErrorDefinedProps } from "../../NiceError/NiceError.types";
3
- export declare const nice_error_test_options: INiceErrorOptions<INiceErrorDefinedProps, keyof INiceErrorDefinedProps["schema"]>;
2
+ import type { INiceErrorDomainProps } from "../../NiceError/NiceError.types";
3
+ export declare const nice_error_test_options: INiceErrorOptions<INiceErrorDomainProps, keyof INiceErrorDomainProps["schema"]>;
@@ -1,7 +1,7 @@
1
1
  import { NiceError } from "../NiceError/NiceError";
2
- import type { INiceErrorDefinedProps } from "../NiceError/NiceError.types";
2
+ import type { INiceErrorDomainProps } from "../NiceError/NiceError.types";
3
3
  import { NiceErrorHydrated } from "../NiceError/NiceErrorHydrated";
4
- import type { NiceErrorDefined } from "../NiceErrorDefined/NiceErrorDefined";
4
+ import type { NiceErrorDomain } from "../NiceErrorDefined/NiceErrorDefined";
5
5
  /**
6
6
  * Combines `castNiceError`, `is()`, and `hydrate()` in a single call — the
7
7
  * idiomatic way to handle an unknown value arriving from a remote boundary
@@ -32,4 +32,4 @@ import type { NiceErrorDefined } from "../NiceErrorDefined/NiceErrorDefined";
32
32
  * });
33
33
  * ```
34
34
  */
35
- export declare function castAndHydrate<ERR_DEF extends INiceErrorDefinedProps>(value: unknown, niceErrorDefined: NiceErrorDefined<ERR_DEF>): NiceErrorHydrated<ERR_DEF, keyof ERR_DEF["schema"] & string> | NiceError;
35
+ export declare function castAndHydrate<ERR_DEF extends INiceErrorDomainProps>(value: unknown, niceErrorDefined: NiceErrorDomain<ERR_DEF>): NiceErrorHydrated<ERR_DEF, keyof ERR_DEF["schema"] & string> | NiceError;
@@ -1,12 +1,12 @@
1
1
  import { NiceError } from "../NiceError/NiceError";
2
- import type { INiceErrorDefinedProps, TExtractContextType } from "../NiceError/NiceError.types";
2
+ import type { INiceErrorDomainProps, TExtractContextType } from "../NiceError/NiceError.types";
3
3
  /**
4
4
  * Handler map for `matchFirst`. Each key is an error id (from `ACTIVE_IDS`) and
5
5
  * the value is a function that receives the typed context for that id.
6
6
  *
7
7
  * The `_` key is an optional fallback that runs when no id-specific handler matched.
8
8
  */
9
- export type TMatchFirstHandlers<ERR_DEF extends INiceErrorDefinedProps, ACTIVE_IDS extends keyof ERR_DEF["schema"] & string, RESULT> = {
9
+ export type TMatchFirstHandlers<ERR_DEF extends INiceErrorDomainProps, ACTIVE_IDS extends keyof ERR_DEF["schema"] & string, RESULT> = {
10
10
  [K in ACTIVE_IDS]?: (context: TExtractContextType<ERR_DEF["schema"][K]>) => RESULT;
11
11
  } & {
12
12
  _?: () => RESULT;
@@ -32,4 +32,4 @@ export type TMatchFirstHandlers<ERR_DEF extends INiceErrorDefinedProps, ACTIVE_I
32
32
  * });
33
33
  * ```
34
34
  */
35
- export declare function matchFirst<ERR_DEF extends INiceErrorDefinedProps, ACTIVE_IDS extends keyof ERR_DEF["schema"] & string, RESULT>(error: NiceError<ERR_DEF, ACTIVE_IDS>, handlers: TMatchFirstHandlers<ERR_DEF, ACTIVE_IDS, RESULT>): RESULT | undefined;
35
+ export declare function matchFirst<ERR_DEF extends INiceErrorDomainProps, ACTIVE_IDS extends keyof ERR_DEF["schema"] & string, RESULT>(error: NiceError<ERR_DEF, ACTIVE_IDS>, handlers: TMatchFirstHandlers<ERR_DEF, ACTIVE_IDS, RESULT>): RESULT | undefined;
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "module": "build/index.js",
5
5
  "types": "build/types/index.d.ts",
6
6
  "type": "module",
7
- "version": "0.0.20",
7
+ "version": "0.1.0",
8
8
  "exports": {
9
9
  ".": {
10
10
  "types": "./build/types/index.d.ts",
@@ -1,49 +0,0 @@
1
- import type { INiceErrorDefinedProps } from "../NiceError/NiceError.types";
2
- import type { NiceErrorHydrated } from "../NiceError/NiceErrorHydrated";
3
- import type { NiceErrorDefined } from "../NiceErrorDefined/NiceErrorDefined";
4
- /**
5
- * A single case in a `handleWith` / `handleWithAsync` call.
6
- *
7
- * Construct via `forDomain` or `forIds` — do not build this object directly.
8
- */
9
- export interface IErrorCase<DEF extends INiceErrorDefinedProps, IDS extends keyof DEF["schema"] & string> {
10
- }
11
- /**
12
- * Builds a case that fires for any error whose domain exactly matches `domain`.
13
- * The handler receives the fully-hydrated error, narrowed to all schema ids.
14
- *
15
- * Use with `error.handleWith([...])` (sync) or `error.handleWithAsync([...])` (async).
16
- *
17
- * @example
18
- * ```ts
19
- * error.handleWith([
20
- * forDomain(err_payments, (h) => {
21
- * matchFirst(h, {
22
- * payment_failed: ({ reason }) => res.status(402).json({ reason }),
23
- * card_expired: () => res.status(402).json({ expired: true }),
24
- * });
25
- * }),
26
- * ]);
27
- * ```
28
- */
29
- export declare function forDomain<DEF extends INiceErrorDefinedProps>(domain: NiceErrorDefined<DEF>, handler: (error: NiceErrorHydrated<DEF, keyof DEF["schema"] & string>) => void | Promise<void>): IErrorCase<DEF, keyof DEF["schema"] & string>;
30
- /**
31
- * Builds a case that fires only if the error's domain matches `domain` **and**
32
- * at least one of `ids` is active on the error.
33
- * The handler receives the fully-hydrated error, narrowed to `IDS[number]`.
34
- *
35
- * @example
36
- * ```ts
37
- * error.handleWith([
38
- * forIds(err_feature, ["not_found", "forbidden"], (h) => {
39
- * // h.getContext("not_found") and h.getContext("forbidden") are both available
40
- * if (h.hasId("not_found")) res.status(404).json({ missing: h.getContext("not_found").resource });
41
- * if (h.hasId("forbidden")) res.status(403).json({ denied: true });
42
- * }),
43
- *
44
- * // Fallback: any other err_feature error
45
- * forDomain(err_feature, (h) => res.status(500).json({ error: h.message })),
46
- * ]);
47
- * ```
48
- */
49
- export declare function forIds<DEF extends INiceErrorDefinedProps, IDS extends ReadonlyArray<keyof DEF["schema"] & string>>(domain: NiceErrorDefined<DEF>, ids: IDS, handler: (error: NiceErrorHydrated<DEF, IDS[number]>) => void | Promise<void>): IErrorCase<DEF, IDS[number]>;