@nice-code/error 0.8.0 → 0.9.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.
Files changed (35) hide show
  1. package/build/index.d.ts +913 -0
  2. package/build/index.js +1004 -933
  3. package/build/index.js.map +1 -0
  4. package/package.json +5 -4
  5. package/build/types/NiceError/NiceError.d.ts +0 -148
  6. package/build/types/NiceError/NiceError.enums.d.ts +0 -5
  7. package/build/types/NiceError/NiceError.types.d.ts +0 -204
  8. package/build/types/NiceError/NiceErrorHydrated.d.ts +0 -51
  9. package/build/types/NiceError/nice_error.static.d.ts +0 -2
  10. package/build/types/NiceErrorDefined/NiceErrorDefined.d.ts +0 -135
  11. package/build/types/NiceErrorDefined/defineNiceError.d.ts +0 -7
  12. package/build/types/NiceErrorDefined/err.d.ts +0 -59
  13. package/build/types/NiceErrorHandler/NiceErrorHandler.d.ts +0 -23
  14. package/build/types/NiceErrorHandler/NiceErrorHandler.types.d.ts +0 -82
  15. package/build/types/NiceErrorHandler/handleWith.d.ts +0 -8
  16. package/build/types/example/error_usage_example.d.ts +0 -41
  17. package/build/types/index.d.ts +0 -18
  18. package/build/types/internal/index.d.ts +0 -1
  19. package/build/types/internal/nice_core_errors.d.ts +0 -49
  20. package/build/types/test/helpers/nice_error_testing.static.d.ts +0 -3
  21. package/build/types/test/helpers/test_utils.d.ts +0 -1
  22. package/build/types/utils/castAndHydrate.d.ts +0 -35
  23. package/build/types/utils/castNiceError.d.ts +0 -15
  24. package/build/types/utils/inspectPotentialError/inspectPotentialError.d.ts +0 -2
  25. package/build/types/utils/inspectPotentialError/inspectPotentialError.enums.d.ts +0 -9
  26. package/build/types/utils/inspectPotentialError/inspectPotentialError.types.d.ts +0 -51
  27. package/build/types/utils/isNiceErrorObject.d.ts +0 -12
  28. package/build/types/utils/isRegularErrorObject.d.ts +0 -2
  29. package/build/types/utils/jsErrorOrCastJsError.d.ts +0 -1
  30. package/build/types/utils/logger.d.ts +0 -3
  31. package/build/types/utils/matchFirst.d.ts +0 -35
  32. package/build/types/utils/packError/causePack.d.ts +0 -2
  33. package/build/types/utils/packError/msgPack.d.ts +0 -2
  34. package/build/types/utils/packError/packError.d.ts +0 -3
  35. package/build/types/utils/packError/packError.enums.d.ts +0 -5
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["e"],"sources":["../src/utils/jsErrorOrCastJsError.ts","../src/NiceError/nice_error.static.ts","../src/utils/packError/packError.enums.ts","../src/utils/packError/causePack.ts","../src/utils/packError/msgPack.ts","../src/utils/packError/packError.ts","../src/NiceError/NiceError.ts","../src/NiceError/NiceErrorHydrated.ts","../src/NiceErrorDefined/NiceErrorDefined.ts","../src/NiceErrorDefined/defineNiceError.ts","../src/NiceErrorDefined/err.ts","../src/internal/nice_core_errors.ts","../src/NiceErrorHandler/NiceErrorHandler.types.ts","../src/NiceErrorHandler/NiceErrorHandler.ts","../src/NiceErrorHandler/handleWith.ts","../src/utils/isNiceErrorObject.ts","../src/utils/isRegularErrorObject.ts","../src/utils/logger.ts","../src/utils/inspectPotentialError/inspectPotentialError.ts","../src/utils/castNiceError.ts","../src/utils/castAndHydrate.ts","../src/utils/matchFirst.ts"],"sourcesContent":["export function jsErrorOrCastJsError(error: unknown, logMessage = true): Error {\n if (error instanceof Error) {\n return Object.assign(error, {\n message: error.message,\n });\n }\n\n const message =\n (error as Error | undefined)?.message ??\n (typeof error === \"string\" ? error : \"No error message found\");\n\n if (logMessage) {\n console.error(`An unknown and unstructured error was thrown: ${message}`, error);\n }\n\n return {\n ...new Error(message),\n ...(error as Error | undefined),\n };\n}\n","export const DUR_OBJ_PACK_PREFIX = \"NE_DUROBJ[[\";\nexport const DUR_OBJ_PACK_SUFFIX = \"]]NE_DUROBJ\";\n","export enum EErrorPackType {\n no_pack = \"no_pack\",\n msg_pack = \"msg_pack\",\n cause_pack = \"cause_pack\",\n}\n","import type { NiceError } from \"../../NiceError/NiceError\";\nimport { DUR_OBJ_PACK_PREFIX, DUR_OBJ_PACK_SUFFIX } from \"../../NiceError/nice_error.static\";\nimport { EErrorPackType } from \"./packError.enums\";\n\nexport const causePack = <E extends NiceError<any, any>>(error: E): E => {\n error._packedState = { cause: error.cause, packedAs: EErrorPackType.cause_pack };\n error.cause = `${DUR_OBJ_PACK_PREFIX}${JSON.stringify(error.toJsonObject())}${DUR_OBJ_PACK_SUFFIX}`;\n return error;\n};\n","import type { NiceError } from \"../../NiceError/NiceError\";\nimport { DUR_OBJ_PACK_PREFIX, DUR_OBJ_PACK_SUFFIX } from \"../../NiceError/nice_error.static\";\nimport { EErrorPackType } from \"./packError.enums\";\n\nexport const msgPack = <E extends NiceError<any, any>>(error: E): E => {\n error._packedState = { message: error.cleanMessage, packedAs: EErrorPackType.msg_pack };\n error.message = `${DUR_OBJ_PACK_PREFIX}${JSON.stringify(error.toJsonObject())}${DUR_OBJ_PACK_SUFFIX}`;\n return error;\n};\n","import type { NiceError } from \"../../NiceError/NiceError\";\nimport { causePack } from \"./causePack\";\nimport { msgPack } from \"./msgPack\";\nimport type { EErrorPackType } from \"./packError.enums\";\n\nexport const packError = <E extends NiceError<any, any>>(\n error: E,\n packType: EErrorPackType = \"msg_pack\" as EErrorPackType,\n): E => {\n if (packType === \"no_pack\") {\n return error;\n }\n if (packType === \"msg_pack\") {\n return msgPack(error);\n }\n return causePack(error);\n};\n","import type { NiceErrorDomain } from \"../NiceErrorDefined/NiceErrorDefined\";\r\nimport type { NiceErrorHandler } from \"../NiceErrorHandler/NiceErrorHandler\";\r\nimport type { IHandleErrorOptions } from \"../NiceErrorHandler/NiceErrorHandler.types\";\r\nimport { jsErrorOrCastJsError } from \"../utils/jsErrorOrCastJsError\";\r\nimport { packError } from \"../utils/packError/packError\";\r\nimport { EErrorPackType } from \"../utils/packError/packError.enums\";\r\nimport { EContextSerializedState } from \"./NiceError.enums\";\r\nimport {\r\n type INiceErrorDomainProps,\r\n type INiceErrorJsonObject,\r\n type IRegularErrorJsonObject,\r\n type TDomainNiceErrorId,\r\n type TErrorDataForIdMap,\r\n type TErrorReconciledData,\r\n type TExtractContextType,\r\n type TNiceErrorSchema,\r\n type TSchemaNiceErrorId,\r\n type TSerializedContextState,\r\n type TSerializedErrorDataMap,\r\n type TUnknownNiceErrorDef,\r\n} from \"./NiceError.types\";\r\nimport type { NiceErrorHydrated } from \"./NiceErrorHydrated\";\r\n\r\n// ---------------------------------------------------------------------------\r\n// Internal helpers\r\n// ---------------------------------------------------------------------------\r\n\r\ntype ContextOf<S extends TNiceErrorSchema, K extends keyof S> = TExtractContextType<S[K]>;\r\n\r\n// ---------------------------------------------------------------------------\r\n// Constructor options\r\n// ---------------------------------------------------------------------------\r\n\r\n/** Full-featured construction from NiceErrorDefined.fromId / fromContext. */\r\nexport interface INiceErrorOptions<\r\n ERR_DEF extends INiceErrorDomainProps,\r\n ID extends TDomainNiceErrorId<ERR_DEF> = TDomainNiceErrorId<ERR_DEF>,\r\n> {\r\n def: Omit<ERR_DEF, \"schema\">;\r\n /** Primary id is first entry in ids. */\r\n ids: ID[];\r\n /** All active ids with their messages, http status codes, and context state. */\r\n errorData: TErrorDataForIdMap<ERR_DEF[\"schema\"]>;\r\n message: string;\r\n wasntNice?: boolean;\r\n httpStatusCode?: number;\r\n originError?: IRegularErrorJsonObject | undefined;\r\n timeCreated?: number;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// NiceError\r\n// ---------------------------------------------------------------------------\r\n\r\nexport class NiceError<\r\n ERR_DEF extends INiceErrorDomainProps = TUnknownNiceErrorDef,\r\n /**\r\n * Union of active error-id keys.\r\n * - After `fromId(id)`: exactly one key.\r\n * - After `fromContext({...})`: a union of all supplied keys.\r\n * - After `hasOneOfIds([a,b])`: narrows to that subset.\r\n * - Default (bare construction / castNiceError): `TUnknownNiceErrorId`.\r\n */\r\n ACTIVE_IDS extends TDomainNiceErrorId<ERR_DEF> = TDomainNiceErrorId<ERR_DEF>,\r\n> extends Error {\r\n override readonly name = \"NiceError\" as const;\r\n\r\n readonly def: Omit<ERR_DEF, \"schema\">;\r\n /** Primary id is first entry in ids. */\r\n readonly ids: ACTIVE_IDS[];\r\n readonly wasntNice: boolean;\r\n readonly httpStatusCode: number;\r\n readonly timeCreated: number;\r\n readonly cleanMessage: string;\r\n originError?: IRegularErrorJsonObject;\r\n\r\n _packedState?:\r\n | { packedAs: EErrorPackType.cause_pack; cause: unknown }\r\n | { packedAs: EErrorPackType.msg_pack; message: string }\r\n | undefined;\r\n\r\n /** Internal: all active id → reconciled data pairs. */\r\n protected readonly _errorDataMap: TErrorDataForIdMap<ERR_DEF[\"schema\"]>;\r\n\r\n // -------------------------------------------------------------------------\r\n // Constructor\r\n // -------------------------------------------------------------------------\r\n\r\n constructor(options: INiceErrorOptions<ERR_DEF, ACTIVE_IDS>) {\r\n const messagePure = options.message;\r\n const prefixedMessage = `[${options.def.domain}](${options.ids.join(\",\")}) ${messagePure}`;\r\n\r\n super(prefixedMessage);\r\n\r\n this.cleanMessage = messagePure;\r\n this.def = options.def;\r\n this.ids = options.ids;\r\n this._errorDataMap = options.errorData;\r\n this.wasntNice = options.wasntNice ?? false;\r\n this.httpStatusCode = options.httpStatusCode ?? 500;\r\n\r\n if (options.originError != null) {\r\n this.originError = options.originError;\r\n }\r\n\r\n this.timeCreated = options.timeCreated ?? Date.now();\r\n }\r\n\r\n // -------------------------------------------------------------------------\r\n // hasId — narrows ACTIVE_IDS to exactly ID\r\n // -------------------------------------------------------------------------\r\n\r\n /**\r\n * Type guard: returns `true` if this error was created with (or contains) the\r\n * given `id`. After the guard, `getContext(id)` will be strongly typed.\r\n */\r\n hasId<ID extends keyof ERR_DEF[\"schema\"] & string>(id: ID): this is NiceError<ERR_DEF, ID> {\r\n return id in this._errorDataMap;\r\n }\r\n\r\n // -------------------------------------------------------------------------\r\n // hasOneOfIds — narrows ACTIVE_IDS to the supplied subset\r\n // -------------------------------------------------------------------------\r\n\r\n /**\r\n * Returns `true` if this error contains **at least one** of the supplied ids.\r\n * Narrows `ACTIVE_IDS` to the matching subset of `IDS`.\r\n */\r\n hasOneOfIds<IDS extends ReadonlyArray<keyof ERR_DEF[\"schema\"] & string>>(\r\n ids: IDS,\r\n ): this is NiceError<ERR_DEF, IDS[number]> {\r\n return ids.some((id) => id in this._errorDataMap);\r\n }\r\n\r\n // -------------------------------------------------------------------------\r\n // get hasMultiple\r\n // -------------------------------------------------------------------------\r\n\r\n /** `true` when this error was created with more than one id (via `fromContext`). */\r\n get hasMultiple(): boolean {\r\n return Object.keys(this._errorDataMap).length > 1;\r\n }\r\n\r\n // -------------------------------------------------------------------------\r\n // getIds\r\n // -------------------------------------------------------------------------\r\n\r\n /** Returns all active error ids on this instance. */\r\n getIds(): Array<ACTIVE_IDS> {\r\n return Object.keys(this._errorDataMap) as Array<ACTIVE_IDS>;\r\n }\r\n\r\n // -------------------------------------------------------------------------\r\n // getContext — strongly typed per ACTIVE_IDS\r\n // -------------------------------------------------------------------------\r\n\r\n /**\r\n * Returns the typed context value for the given error id.\r\n *\r\n * TypeScript will only allow you to call this with an id that is part of\r\n * `ACTIVE_IDS` (i.e. an id confirmed via `hasId` / `hasOneOfIds`, or passed\r\n * to `fromId` / `fromContext`).\r\n *\r\n * @throws If the context is in the `\"unhydrated\"` state — the error was\r\n * reconstructed from a JSON payload and its context has a custom serializer\r\n * that hasn't been run yet. Call `niceErrorDefined.hydrate(error)` first.\r\n */\r\n getContext<ID extends ACTIVE_IDS>(id: ID): ContextOf<ERR_DEF[\"schema\"], ID> {\r\n const errorData = this._errorDataMap[id];\r\n const state = errorData?.contextState;\r\n\r\n if (state == null) {\r\n return undefined as ContextOf<ERR_DEF[\"schema\"], ID>;\r\n }\r\n\r\n if (state.kind === \"unhydrated\") {\r\n throw new Error(\r\n `[NiceError.getContext] Context for id \"${String(id)}\" is in the \"unhydrated\" state. ` +\r\n `The error was reconstructed from a serialized payload but has not been deserialized yet. ` +\r\n `Call \\`niceErrorDefined.hydrate(error)\\` to reconstruct the typed context.`,\r\n );\r\n }\r\n\r\n // \"raw_unset\" | \"hydrated\" — both carry `value`\r\n return state.value as ContextOf<ERR_DEF[\"schema\"], ID>;\r\n }\r\n\r\n // -------------------------------------------------------------------------\r\n // getErrorDataForId\r\n // -------------------------------------------------------------------------\r\n\r\n getErrorDataForId<ID extends ACTIVE_IDS>(\r\n id: ID,\r\n ): TErrorReconciledData<ERR_DEF[\"schema\"], ID> | undefined {\r\n return this._errorDataMap[id] as TErrorReconciledData<ERR_DEF[\"schema\"], ID> | undefined;\r\n }\r\n\r\n // -------------------------------------------------------------------------\r\n // withOriginError\r\n // -------------------------------------------------------------------------\r\n\r\n withOriginError(error: unknown): this {\r\n this.originError = jsErrorOrCastJsError(error);\r\n // When the error is cause-packed, `this.cause` holds the packed JSON string.\r\n // Overwriting it would destroy the packed data and break boundary reconstruction.\r\n // In that case we skip mutating `cause` — the packed data stays intact.\r\n if (this._packedState?.packedAs !== EErrorPackType.cause_pack) {\r\n this.cause = this.originError;\r\n }\r\n return this;\r\n }\r\n\r\n // -------------------------------------------------------------------------\r\n // matches — fingerprint comparison\r\n // -------------------------------------------------------------------------\r\n\r\n /**\r\n * Returns `true` if `other` has the same domain and the exact same set of\r\n * active error ids as this error (order-independent).\r\n *\r\n * Useful for deduplication, retry logic, and asserting that two errors\r\n * represent the same \"kind\" of problem without comparing context values.\r\n *\r\n * ```ts\r\n * const a = err_auth.fromId(\"invalid_credentials\", { username: \"alice\" });\r\n * const b = err_auth.fromId(\"invalid_credentials\", { username: \"bob\" });\r\n * a.matches(b); // true — same domain + same id set\r\n *\r\n * const c = err_auth.fromId(\"account_locked\");\r\n * a.matches(c); // false — same domain, different id\r\n * ```\r\n */\r\n matches(other: NiceError<any, any>): boolean {\r\n const myDef = this.def as unknown as INiceErrorDomainProps;\r\n const otherDef = other.def as unknown as INiceErrorDomainProps;\r\n if (myDef.domain !== otherDef.domain) return false;\r\n\r\n const myIds = this.getIds().map(String).sort();\r\n const otherIds = other.getIds().map(String).sort();\r\n if (myIds.length !== otherIds.length) return false;\r\n return myIds.every((id, i) => id === otherIds[i]);\r\n }\r\n\r\n // -------------------------------------------------------------------------\r\n // toJsonObject\r\n // -------------------------------------------------------------------------\r\n\r\n toJsonObject(): INiceErrorJsonObject<ERR_DEF> {\r\n const originError: IRegularErrorJsonObject | undefined = this.originError\r\n ? {\r\n name: this.originError.name,\r\n message: (this.originError as any).cleanMessage ?? this.originError.message,\r\n stack: this.originError.stack,\r\n cause: this.originError.cause,\r\n }\r\n : undefined;\r\n\r\n const def = {\r\n domain: this.def.domain,\r\n allDomains: this.def.allDomains,\r\n } as Omit<ERR_DEF, \"schema\">;\r\n\r\n if (this.def.defaultHttpStatusCode != null) {\r\n def[\"defaultHttpStatusCode\"] = this.def.defaultHttpStatusCode;\r\n }\r\n\r\n if (this.def.defaultMessage != null) {\r\n def[\"defaultMessage\"] = this.def.defaultMessage;\r\n }\r\n\r\n // Downgrade \"hydrated\" → \"unhydrated\" so the serialized form never carries a\r\n // stale `\"hydrated\"` discriminant that would survive a JSON round-trip.\r\n const errorData: TSerializedErrorDataMap<ERR_DEF[\"schema\"]> = {};\r\n\r\n for (const rawId of Object.keys(this._errorDataMap)) {\r\n const id = rawId as TSchemaNiceErrorId<ERR_DEF[\"schema\"]>;\r\n const data = this._errorDataMap[id];\r\n if (data == null) continue;\r\n\r\n let contextState: TSerializedContextState<any>;\r\n\r\n if (data.contextState.kind === EContextSerializedState.hydrated) {\r\n // Drop `value` (may not be JSON-safe); keep `serialized` for later hydration.\r\n contextState = {\r\n kind: EContextSerializedState.unhydrated,\r\n serialized: data.contextState.serialized,\r\n };\r\n } else {\r\n contextState = data.contextState;\r\n }\r\n\r\n errorData[id] = {\r\n contextState,\r\n message: (data as any).cleanMessage ?? data.message,\r\n httpStatusCode: data.httpStatusCode,\r\n timeAdded: data.timeAdded,\r\n };\r\n }\r\n\r\n return {\r\n name: \"NiceError\",\r\n def,\r\n ids: this.ids,\r\n errorData,\r\n wasntNice: this.wasntNice,\r\n message: this.cleanMessage,\r\n httpStatusCode: this.httpStatusCode,\r\n timeCreated: this.timeCreated,\r\n ...(this.stack != null ? { stack: this.stack } : {}),\r\n originError,\r\n };\r\n }\r\n\r\n toJSON(): INiceErrorJsonObject<ERR_DEF> {\r\n return this.toJsonObject();\r\n }\r\n\r\n toJsonString(): string {\r\n return JSON.stringify(this.toJsonObject());\r\n }\r\n\r\n toHttpResponse(): Response {\r\n return new Response(this.toJsonString(), {\r\n status: this.httpStatusCode,\r\n headers: { \"Content-Type\": \"application/json\" },\r\n });\r\n }\r\n\r\n // -------------------------------------------------------------------------\r\n // hydrate — convenience delegation to NiceErrorDefined\r\n // -------------------------------------------------------------------------\r\n\r\n hydrate(definedNiceError: NiceErrorDomain<ERR_DEF>): NiceErrorHydrated<ERR_DEF, ACTIVE_IDS> {\r\n return definedNiceError.hydrate(this);\r\n }\r\n\r\n // -------------------------------------------------------------------------\r\n // handleWithSync — synchronous domain-dispatched error handling\r\n // -------------------------------------------------------------------------\r\n\r\n /**\r\n * Iterates `cases` in order, finds the first whose domain matches this error\r\n * (via `is()`), optionally further filters by active ids, hydrates the error,\r\n * calls the handler, and returns `true`. Returns `false` if no case matched.\r\n *\r\n * Build cases with `forDomain` (any id in the domain) or `forIds` (specific\r\n * id subset). Handlers are invoked synchronously — any returned Promise is\r\n * not awaited. Use `handleWithAsync` when handlers are async.\r\n *\r\n * @example\r\n * ```ts\r\n * const handled = error.handleWith([\r\n * forIds(err_feature, [\"not_found\"], (h) => {\r\n * res.status(404).json({ missing: h.getContext(\"not_found\").resource });\r\n * }),\r\n * forDomain(err_feature, (h) => {\r\n * matchFirst(h, {\r\n * forbidden: ({ userId }) => res.status(403).json({ userId }),\r\n * _: () => res.status(500).end(),\r\n * });\r\n * }),\r\n * forDomain(err_service, (h) => {\r\n * res.status(h.httpStatusCode).json({ error: h.message });\r\n * }),\r\n * ]);\r\n * if (!handled) next(error);\r\n * ```\r\n */\r\n handleWithSync<RD, R>(\r\n handlerInput: NiceErrorHandler<RD, R> | ReadonlyArray<NiceErrorHandler<RD, R>>,\r\n handlerOptions: IHandleErrorOptions = {},\r\n ): R | RD | undefined {\r\n const handlersArray: ReadonlyArray<NiceErrorHandler<RD, R>> = Array.isArray(handlerInput)\r\n ? handlerInput\r\n : [handlerInput];\r\n\r\n for (const handler of handlersArray) {\r\n const result = handler.handleErrorWithPromiseInspection(this, handlerOptions);\r\n if (result.matched) {\r\n if (result.isPromise) {\r\n console.warn(\r\n `[NiceError.handleWith] Handler ${result.target.identifier} returned a Promise but was called via \\`handleWith\\` (synchronous). ` +\r\n `The Promise will not be awaited. Use \\`handleWithAsync\\` for async handlers.`,\r\n );\r\n }\r\n\r\n return result.isPromise ? undefined : result.handlerResponse;\r\n }\r\n }\r\n\r\n if (handlerOptions.throwOnUnhandled === true) throw this;\r\n return undefined;\r\n }\r\n\r\n // -------------------------------------------------------------------------\r\n // handleWithAsync — async domain-dispatched error handling\r\n // -------------------------------------------------------------------------\r\n\r\n /**\r\n * Same matching logic as `handleWith`, but `await`s the handler's returned\r\n * Promise before resolving. Use this when your handlers perform async work\r\n * (database writes, HTTP calls, etc.).\r\n *\r\n * @example\r\n * ```ts\r\n * const handled = await error.handleWithAsync([\r\n * forDomain(err_payments, async (h) => {\r\n * await db.logFailedPayment(h);\r\n * await notifyOps(h.message);\r\n * }),\r\n * ]);\r\n * ```\r\n */\r\n async handleWithAsync<RD, R>(\r\n handlerInput: NiceErrorHandler<RD, R> | ReadonlyArray<NiceErrorHandler<RD, R>>,\r\n handlerOptions: IHandleErrorOptions = {},\r\n ): Promise<R | RD | undefined> {\r\n const handlersArray: ReadonlyArray<NiceErrorHandler<RD, R>> = Array.isArray(handlerInput)\r\n ? handlerInput\r\n : [handlerInput];\r\n\r\n for (const handler of handlersArray) {\r\n const result = handler.handleErrorWithPromiseInspection(this, handlerOptions);\r\n\r\n if (result.matched) {\r\n return result.isPromise ? await result.handlerPromise : result.handlerResponse;\r\n }\r\n }\r\n\r\n if (handlerOptions.throwOnUnhandled === true) throw this;\r\n return undefined;\r\n }\r\n\r\n get isPacked(): boolean {\r\n return this._packedState != null;\r\n }\r\n\r\n pack(packType: EErrorPackType = \"msg_pack\" as EErrorPackType): this {\r\n if (this.isPacked) return this;\r\n return packError(this, packType);\r\n }\r\n\r\n unpack(): this {\r\n if (this._packedState == null) return this;\r\n\r\n if (this._packedState.packedAs === EErrorPackType.msg_pack) {\r\n this.message = this._packedState.message;\r\n }\r\n\r\n if (this._packedState.packedAs === EErrorPackType.cause_pack) {\r\n this.cause = this._packedState.cause;\r\n }\r\n\r\n this._packedState = undefined;\r\n delete this._packedState;\r\n\r\n return this;\r\n }\r\n}\r\n","import type { NiceErrorDomain } from \"../NiceErrorDefined/NiceErrorDefined\";\nimport { type INiceErrorOptions, NiceError } from \"./NiceError\";\nimport type {\n ExtractFromIdContextArg,\n FromIdArgs,\n INiceErrorDomainProps,\n TDomainNiceErrorId,\n TErrorDataForIdMap,\n TFromContextInput,\n TUnknownNiceErrorDef,\n} from \"./NiceError.types\";\n\n/**\n * Resolves the args tuple for `addId` — mirrors `FromIdArgs` exactly so that\n * optional vs required context is consistent across both `fromId` and `addId`.\n *\n * - No context on this id → `[id]`\n * - Context defined, `required: true` → `[id, context]`\n * - Context defined, `required` absent/false → `[id] | [id, context]`\n */\ntype AddIdArgs<ERR_DEF extends INiceErrorDomainProps, K extends TDomainNiceErrorId<ERR_DEF>> = [\n ExtractFromIdContextArg<ERR_DEF[\"schema\"][K]>,\n] extends [undefined]\n ? [id: K]\n : [undefined] extends [ExtractFromIdContextArg<ERR_DEF[\"schema\"][K]>]\n ? [id: K] | [id: K, context: NonNullable<ExtractFromIdContextArg<ERR_DEF[\"schema\"][K]>>]\n : [id: K, context: ExtractFromIdContextArg<ERR_DEF[\"schema\"][K]>];\n\n/** Full-featured construction from NiceErrorDefined.fromId / fromContext. */\nexport interface INiceErrorHydratedOptions<\n ERR_DEF extends INiceErrorDomainProps,\n ID extends TDomainNiceErrorId<ERR_DEF>,\n> extends INiceErrorOptions<ERR_DEF, ID> {\n def: ERR_DEF;\n niceErrorDefined: NiceErrorDomain<ERR_DEF>;\n}\n\nexport class NiceErrorHydrated<\n ERR_DEF extends INiceErrorDomainProps = TUnknownNiceErrorDef,\n /**\n * Union of active error-id keys.\n * - After `fromId(id)`: exactly one key.\n * - After `fromContext({...})`: a union of all supplied keys.\n * - After `hasOneOfIds([a,b])`: narrows to that subset.\n * - Default (bare construction / castNiceError): `TUnknownNiceErrorId`.\n */\n ACTIVE_IDS extends TDomainNiceErrorId<ERR_DEF> = TDomainNiceErrorId<ERR_DEF>,\n> extends NiceError<ERR_DEF, ACTIVE_IDS> {\n override readonly def: ERR_DEF;\n private readonly niceErrorDefined: NiceErrorDomain<ERR_DEF>;\n\n constructor(options: INiceErrorHydratedOptions<ERR_DEF, ACTIVE_IDS>) {\n super(options);\n this.def = options.def;\n this.niceErrorDefined = options.niceErrorDefined;\n }\n\n // -------------------------------------------------------------------------\n // addContext — merge additional id+context entries into this error\n // -------------------------------------------------------------------------\n\n /**\n * Returns a **new** `NiceErrorHydrated` with additional id+context entries merged in.\n * The returned error's `ACTIVE_IDS` is the union of the original ids and the\n * newly supplied keys.\n *\n * ```ts\n * const err = errDef.fromId(\"id_a\", { a: 1 })\n * .addContext({ id_b: { b: \"x\" } });\n * err.getIds(); // [\"id_a\", \"id_b\"]\n * ```\n */\n addContext<INPUT extends TFromContextInput<ERR_DEF[\"schema\"]>>(\n context: INPUT & Record<Exclude<keyof INPUT, keyof ERR_DEF[\"schema\"] & string>, never>,\n ): NiceErrorHydrated<ERR_DEF, ACTIVE_IDS | (keyof INPUT & string)> {\n const newIds = Object.keys(context) as Array<keyof ERR_DEF[\"schema\"] & string>;\n const newErrorData: TErrorDataForIdMap<ERR_DEF[\"schema\"]> = {};\n\n for (const id of newIds) {\n newErrorData[id] = this.niceErrorDefined.reconcileErrorDataForId(id, context[id]);\n }\n\n const mergedErrorData: TErrorDataForIdMap<ERR_DEF[\"schema\"]> = {\n ...this._errorDataMap,\n ...newErrorData,\n };\n\n const mergedIds = Array.from(new Set([...this.getIds(), ...Object.keys(context)])) as Array<\n ACTIVE_IDS | (keyof INPUT & string)\n >;\n\n return new NiceErrorHydrated<ERR_DEF, ACTIVE_IDS | (keyof INPUT & string)>({\n def: this.def,\n niceErrorDefined: this.niceErrorDefined,\n ids: mergedIds,\n errorData: mergedErrorData,\n message: this.cleanMessage,\n wasntNice: this.wasntNice,\n httpStatusCode: this.httpStatusCode,\n originError: this.originError,\n });\n }\n\n // -------------------------------------------------------------------------\n // addId — add a single id (with optional context) to this error\n // -------------------------------------------------------------------------\n\n /**\n * Returns a **new** `NiceErrorHydrated` with an additional error id (and its context,\n * if the schema requires one). Equivalent to `addContext({ [id]: context })`\n * but mirrors the `fromId` ergonomics for single-id additions.\n */\n addId<K extends TDomainNiceErrorId<ERR_DEF>>(\n ...args: AddIdArgs<ERR_DEF, K>\n ): NiceErrorHydrated<ERR_DEF, ACTIVE_IDS | K> {\n const [id, context] = args as FromIdArgs<ERR_DEF, K>;\n\n const reconciledData = this.niceErrorDefined.reconcileErrorDataForId(id, context);\n\n const errorDataMap: TErrorDataForIdMap<ERR_DEF[\"schema\"]> = {};\n errorDataMap[id] = reconciledData;\n\n const mergedContexts: TErrorDataForIdMap<ERR_DEF[\"schema\"]> = {\n ...this._errorDataMap,\n ...errorDataMap,\n };\n const mergedIds = Array.from(new Set([...this.getIds(), id])) as Array<ACTIVE_IDS | K>;\n\n return new NiceErrorHydrated<ERR_DEF, ACTIVE_IDS | K>({\n def: this.def,\n niceErrorDefined: this.niceErrorDefined,\n ids: mergedIds,\n errorData: mergedContexts,\n message: this.cleanMessage,\n wasntNice: this.wasntNice,\n httpStatusCode: this.httpStatusCode,\n originError: this.originError,\n });\n }\n}\n","import { NiceError } from \"../NiceError/NiceError\";\r\nimport { EContextSerializedState } from \"../NiceError/NiceError.enums\";\r\nimport {\r\n type FromIdArgs,\r\n type IDefineNewNiceErrorDomainOptions,\r\n type INiceErrorDomainProps,\r\n type INiceErrorJsonObject,\r\n type TContextState,\r\n type TDomainNiceErrorId,\r\n type TErrorDataForIdMap,\r\n type TErrorReconciledData,\r\n type TFromContextInput,\r\n} from \"../NiceError/NiceError.types\";\r\nimport { type INiceErrorHydratedOptions, NiceErrorHydrated } from \"../NiceError/NiceErrorHydrated\";\r\nimport { type EErrorPackType } from \"../utils/packError/packError.enums\";\r\n\r\n// ---------------------------------------------------------------------------\r\n// Internal type helpers\r\n// ---------------------------------------------------------------------------\r\n\r\ntype ChildDef<\r\n PARENT_DEF extends INiceErrorDomainProps,\r\n SUB extends IDefineNewNiceErrorDomainOptions,\r\n> = {\r\n domain: SUB[\"domain\"];\r\n allDomains: [SUB[\"domain\"], ...PARENT_DEF[\"allDomains\"]];\r\n schema: SUB[\"schema\"];\r\n};\r\n\r\n/**\r\n * Extracts the union of keys present in a `TFromContextInput` object.\r\n * e.g. `{ invalid_credentials: {...} }` → `\"invalid_credentials\"`\r\n */\r\ntype KeysOfContextInput<INPUT> = keyof INPUT & string;\r\n\r\ninterface ILinkedNiceErrorDomain {\r\n domain: string;\r\n definedError: NiceErrorDomain<any>;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// InferNiceError / InferNiceErrorHydrated — utility types\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Infers the strongly-typed `NiceError` class type from a `NiceErrorDefined` instance.\r\n *\r\n * `ACTIVE_IDS` is set to the full union of all schema keys. Use `hasId` /\r\n * `hasOneOfIds` to narrow further at the call site.\r\n *\r\n * @example\r\n * ```ts\r\n * const err_user_auth = defineNiceError({ domain: \"err_user_auth\", schema: { ... } });\r\n * type TUserAuthError = InferNiceError<typeof err_user_auth>;\r\n * // → NiceError<{ domain: \"err_user_auth\"; ... }, keyof schema>\r\n * ```\r\n */\r\nexport type InferNiceError<T extends NiceErrorDomain<any>> =\r\n T extends NiceErrorDomain<infer ERR_DEF>\r\n ? NiceError<ERR_DEF, keyof ERR_DEF[\"schema\"] & string>\r\n : never;\r\n\r\n/**\r\n * Infers the strongly-typed `NiceErrorHydrated` class type from a `NiceErrorDefined` instance.\r\n *\r\n * Use this when you need the builder methods (`addId`, `addContext`) as part of\r\n * the inferred type — e.g. for function return types or variable annotations.\r\n *\r\n * @example\r\n * ```ts\r\n * const err_user_auth = defineNiceError({ domain: \"err_user_auth\", schema: { ... } });\r\n * type TUserAuthErrorHydrated = InferNiceErrorHydrated<typeof err_user_auth>;\r\n * // → NiceErrorHydrated<{ domain: \"err_user_auth\"; ... }, keyof schema>\r\n * ```\r\n */\r\nexport type InferNiceErrorHydrated<T extends NiceErrorDomain<any>> =\r\n T extends NiceErrorDomain<infer ERR_DEF>\r\n ? NiceErrorHydrated<ERR_DEF, keyof ERR_DEF[\"schema\"] & string>\r\n : never;\r\n\r\n// ---------------------------------------------------------------------------\r\n// NiceErrorDefined\r\n// ---------------------------------------------------------------------------\r\n\r\nexport class NiceErrorDomain<ERR_DEF extends INiceErrorDomainProps = INiceErrorDomainProps> {\r\n readonly domain: ERR_DEF[\"domain\"];\r\n readonly allDomains: ERR_DEF[\"allDomains\"];\r\n readonly defaultHttpStatusCode?: number;\r\n readonly defaultMessage?: string;\r\n\r\n /** Kept for runtime use (message resolution, httpStatusCode, context serialization, etc.). */\r\n private readonly _schema: ERR_DEF[\"schema\"];\r\n private _definedChildNiceErrors: ILinkedNiceErrorDomain[] = [];\r\n private _definedParentNiceError?: ILinkedNiceErrorDomain;\r\n /** Set by `.packAs()` — explicit per-instance override, takes priority over `_packAsFn`. */\r\n private _setPack?: EErrorPackType;\r\n /** Set at definition time — called dynamically each time an error is created. */\r\n private _packAsFn?: () => EErrorPackType | void;\r\n\r\n constructor(definition: ERR_DEF) {\r\n this.domain = definition.domain;\r\n this.allDomains = definition.allDomains;\r\n this._schema = definition.schema;\r\n\r\n if (definition.packAs != null) {\r\n this._packAsFn = definition.packAs;\r\n }\r\n\r\n if (definition.defaultHttpStatusCode != null) {\r\n this.defaultHttpStatusCode = definition.defaultHttpStatusCode;\r\n }\r\n\r\n if (definition.defaultMessage != null) {\r\n this.defaultMessage = definition.defaultMessage;\r\n }\r\n }\r\n\r\n // -------------------------------------------------------------------------\r\n // createChildDomain\r\n // -------------------------------------------------------------------------\r\n\r\n /**\r\n * Creates a child domain that inherits this domain in `allDomains`.\r\n * The child has its own schema and its own domain string.\r\n */\r\n createChildDomain<SUB extends IDefineNewNiceErrorDomainOptions>(\r\n subErrorDef: SUB & { [K in Exclude<keyof SUB, keyof IDefineNewNiceErrorDomainOptions>]: never },\r\n ): NiceErrorDomain<ChildDef<ERR_DEF, SUB>> {\r\n const child = new NiceErrorDomain<ChildDef<ERR_DEF, SUB>>({\r\n domain: subErrorDef.domain,\r\n allDomains: [subErrorDef.domain, ...this.allDomains] as [\r\n SUB[\"domain\"],\r\n ...ERR_DEF[\"allDomains\"],\r\n ],\r\n schema: subErrorDef.schema,\r\n defaultHttpStatusCode: subErrorDef.defaultHttpStatusCode,\r\n defaultMessage: subErrorDef.defaultMessage,\r\n } as ChildDef<ERR_DEF, SUB>);\r\n\r\n this.addChildNiceErrorDefined(child);\r\n child.addParentNiceErrorDefined(this);\r\n\r\n // Child's own packAs takes priority; fall back to parent's config.\r\n if (subErrorDef.packAs != null) {\r\n child._packAsFn = subErrorDef.packAs;\r\n } else if (this._setPack) {\r\n child.packAs(this._setPack);\r\n } else if (this._packAsFn) {\r\n child._packAsFn = this._packAsFn;\r\n }\r\n\r\n return child;\r\n }\r\n\r\n protected addParentNiceErrorDefined<PARENT_DEF extends INiceErrorDomainProps>(\r\n parentError: NiceErrorDomain<PARENT_DEF>,\r\n ) {\r\n if (this._definedParentNiceError?.domain === parentError.domain) {\r\n return;\r\n }\r\n this._definedParentNiceError = {\r\n domain: parentError.domain,\r\n definedError: parentError,\r\n };\r\n }\r\n\r\n protected addChildNiceErrorDefined<CHILD_DEF extends INiceErrorDomainProps>(\r\n child: NiceErrorDomain<CHILD_DEF>,\r\n ) {\r\n if (this._definedChildNiceErrors.some((linked) => linked.domain === child.domain)) {\r\n return;\r\n }\r\n\r\n this._definedChildNiceErrors.push({\r\n domain: child.domain,\r\n definedError: child,\r\n });\r\n\r\n if (this._definedParentNiceError) {\r\n this._definedParentNiceError.definedError.addChildNiceErrorDefined(child);\r\n }\r\n }\r\n\r\n packAs(pack: EErrorPackType): this {\r\n this._setPack = pack;\r\n return this;\r\n }\r\n\r\n private createError<K extends TDomainNiceErrorId<ERR_DEF>>(\r\n input: INiceErrorHydratedOptions<any, any> & { message: string | undefined },\r\n ): NiceErrorHydrated<ERR_DEF, K> {\r\n const err = new NiceErrorHydrated<ERR_DEF, K>(input);\r\n\r\n // Explicit .packAs() override takes priority; fall back to the dynamic function.\r\n const packType = this._setPack ?? this._packAsFn?.();\r\n if (packType != null && packType !== \"no_pack\") {\r\n return err.pack(packType) as any;\r\n }\r\n\r\n return err;\r\n }\r\n\r\n // -------------------------------------------------------------------------\r\n // hydrate\r\n // -------------------------------------------------------------------------\r\n\r\n /**\r\n * Promotes a plain `NiceError<ERR_DEF>` back into a `NiceErrorHydrated` so\r\n * that builder methods (`addId`, `addContext`, etc.) are available again.\r\n *\r\n * For each active id, if the context is in the `\"unhydrated\"` state (i.e. the\r\n * error was reconstructed from a JSON payload), `hydrate` calls\r\n * `fromJsonSerializable` to reconstruct the typed value and advances the state\r\n * to `\"hydrated\"`. Ids already in `\"hydrated\"` or `\"raw_unset\"` state\r\n * are passed through unchanged.\r\n *\r\n * @throws If `error.def.domain` does not match this definition's domain. Use\r\n * `niceErrorDefined.is(error)` before calling `hydrate` to ensure compatibility.\r\n *\r\n * ```ts\r\n * const raw = castNiceError(apiResponseBody);\r\n *\r\n * if (err_user_auth.is(raw)) {\r\n * const hydrated = err_user_auth.hydrate(raw);\r\n * // hydrated.getContext(\"invalid_credentials\") — fully typed, no throw\r\n * // hydrated.addId / addContext — available again\r\n * }\r\n * ```\r\n */\r\n hydrate<ACTIVE_IDS extends TDomainNiceErrorId<ERR_DEF> = TDomainNiceErrorId<ERR_DEF>>(\r\n error: NiceError<ERR_DEF, ACTIVE_IDS> | INiceErrorJsonObject<ERR_DEF, ACTIVE_IDS>,\r\n ): NiceErrorHydrated<ERR_DEF, ACTIVE_IDS> {\r\n const errDef = error.def as unknown as INiceErrorDomainProps;\r\n if (errDef.domain !== this.domain) {\r\n throw new Error(\r\n `[NiceErrorDefined.hydrate] Domain mismatch: this definition is \"${this.domain}\" ` +\r\n `but the error belongs to \"${errDef.domain}\". ` +\r\n `Call \\`niceErrorDefined.is(error)\\` before hydrating to ensure compatibility.`,\r\n );\r\n }\r\n\r\n const finalError: NiceError<ERR_DEF, ACTIVE_IDS> =\r\n error instanceof NiceError ? error : new NiceError<ERR_DEF, ACTIVE_IDS>(error);\r\n\r\n const reconciledErrorData: TErrorDataForIdMap<ERR_DEF[\"schema\"]> = {};\r\n\r\n for (const id of finalError.getIds()) {\r\n const existingData = finalError.getErrorDataForId(id);\r\n if (existingData == null) continue;\r\n\r\n let contextState: TContextState<any> = existingData.contextState;\r\n\r\n if (contextState.kind === \"unhydrated\") {\r\n const entry = this._schema[id as keyof ERR_DEF[\"schema\"]];\r\n const deserialize = entry?.context?.serialization?.fromJsonSerializable;\r\n\r\n if (deserialize != null) {\r\n contextState = {\r\n kind: EContextSerializedState.hydrated,\r\n value: deserialize(contextState.serialized),\r\n serialized: contextState.serialized,\r\n };\r\n }\r\n // If no deserializer is found (schema mismatch), leave as \"unhydrated\".\r\n }\r\n\r\n reconciledErrorData[id] = {\r\n contextState,\r\n message: (existingData as any).cleanMessage ?? existingData.message,\r\n httpStatusCode: existingData.httpStatusCode,\r\n timeAdded: existingData.timeAdded,\r\n };\r\n }\r\n\r\n return new NiceErrorHydrated<ERR_DEF, ACTIVE_IDS>({\r\n def: this._buildDef(),\r\n niceErrorDefined: this,\r\n ids: finalError.ids,\r\n errorData: reconciledErrorData,\r\n message: finalError.cleanMessage ?? finalError.message,\r\n httpStatusCode: finalError.httpStatusCode,\r\n wasntNice: finalError.wasntNice,\r\n originError: finalError.originError,\r\n timeCreated: finalError.timeCreated,\r\n });\r\n }\r\n\r\n // -------------------------------------------------------------------------\r\n // fromId — single-id construction\r\n // -------------------------------------------------------------------------\r\n\r\n /**\r\n * Creates a `NiceErrorHydrated` for a single error id.\r\n *\r\n * - `id` autocompletes to the schema keys.\r\n * - The second argument `context` is required / optional / absent based on\r\n * whether the schema entry declares `context.required: true`.\r\n * - The returned error has `ACTIVE_IDS` narrowed to exactly `K`, so\r\n * `getContext(id)` is immediately strongly typed.\r\n */\r\n fromId<K extends keyof ERR_DEF[\"schema\"] & string>(\r\n ...args: FromIdArgs<ERR_DEF, K>\r\n ): NiceErrorHydrated<ERR_DEF, K> {\r\n const [id, context] = args as FromIdArgs<ERR_DEF, K>;\r\n\r\n const reconciledData = this.reconcileErrorDataForId(id, context);\r\n\r\n const errorData: TErrorDataForIdMap<ERR_DEF[\"schema\"]> = {};\r\n errorData[id] = reconciledData;\r\n\r\n const err = this.createError({\r\n def: this._buildDef(),\r\n niceErrorDefined: this,\r\n ids: [id],\r\n errorData,\r\n message: (reconciledData as any).cleanMessage ?? reconciledData.message,\r\n httpStatusCode: reconciledData.httpStatusCode,\r\n }) as unknown as NiceErrorHydrated<ERR_DEF, K>;\r\n\r\n // Strip library-internal frames so the stack starts at the call site.\r\n if (typeof (Error as any).captureStackTrace === \"function\") {\r\n (Error as any).captureStackTrace(err, this.fromId);\r\n }\r\n\r\n return err;\r\n }\r\n\r\n // -------------------------------------------------------------------------\r\n // fromContext — multi-id construction\r\n // -------------------------------------------------------------------------\r\n\r\n fromContext<INPUT extends TFromContextInput<ERR_DEF[\"schema\"]>>(\r\n context: INPUT & Record<Exclude<keyof INPUT, keyof ERR_DEF[\"schema\"]>, never>,\r\n ): NiceErrorHydrated<ERR_DEF, KeysOfContextInput<INPUT>> {\r\n const ids = Object.keys(context) as Array<KeysOfContextInput<INPUT>>;\r\n if (ids.length === 0) {\r\n throw new Error(\r\n \"[NiceErrorDefined.fromContext] context object must contain at least one error id.\",\r\n );\r\n }\r\n\r\n const errorData: TErrorDataForIdMap<ERR_DEF[\"schema\"]> = {};\r\n\r\n for (const id of ids) {\r\n errorData[id] = this.reconcileErrorDataForId(id, context[id]);\r\n }\r\n\r\n const primaryId = ids[0] as KeysOfContextInput<INPUT>;\r\n\r\n const err = this.createError({\r\n def: this._buildDef(),\r\n niceErrorDefined: this,\r\n ids: ids,\r\n errorData,\r\n message: (errorData[primaryId] as any).cleanMessage ?? errorData[primaryId]!.message,\r\n httpStatusCode: errorData[primaryId]!.httpStatusCode,\r\n }) as NiceErrorHydrated<ERR_DEF, KeysOfContextInput<INPUT>>;\r\n\r\n // Strip library-internal frames so the stack starts at the call site.\r\n if (typeof (Error as any).captureStackTrace === \"function\") {\r\n (Error as any).captureStackTrace(err, this.fromContext);\r\n }\r\n\r\n return err;\r\n }\r\n\r\n // -------------------------------------------------------------------------\r\n // is — type-narrowing guard\r\n // -------------------------------------------------------------------------\r\n\r\n /**\r\n * Returns `true` if `error` is a `NiceError` whose `def.domain` exactly matches\r\n * this definition's domain.\r\n *\r\n * Use this after `castNiceError` to narrow an unknown error to this specific\r\n * domain before accessing its typed ids/context:\r\n *\r\n * ```ts\r\n * const caught = castNiceError(e);\r\n *\r\n * if (err_user_auth.is(caught)) {\r\n * // caught is now NiceError<typeof err_user_auth's ERR_DEF>\r\n * const hydrated = err_user_auth.hydrate(caught);\r\n * const { username } = hydrated.getContext(\"invalid_credentials\");\r\n * }\r\n * ```\r\n */\r\n isExact(error: unknown): error is NiceError<ERR_DEF, keyof ERR_DEF[\"schema\"] & string> {\r\n if (!(error instanceof NiceError)) return false;\r\n const errDef = error.def as unknown as INiceErrorDomainProps;\r\n return errDef.domain === this.domain;\r\n }\r\n\r\n isThisOrChild(error: unknown): boolean {\r\n if (!(error instanceof NiceError)) return false;\r\n const errDef = error.def as unknown as INiceErrorDomainProps;\r\n return errDef.domain === this.domain || this.allDomains.includes(errDef.domain);\r\n }\r\n\r\n // -------------------------------------------------------------------------\r\n // isParentOf — ancestry check\r\n // -------------------------------------------------------------------------\r\n\r\n /**\r\n * Returns `true` if this domain appears anywhere in the target's ancestry\r\n * chain (including an exact domain match).\r\n *\r\n * Accepts either a `NiceErrorDefined` (domain definition) or a `NiceError`\r\n * instance (extracts the domain from its `def`).\r\n */\r\n isParentOf(target: NiceErrorDomain<any> | NiceError<any, any>): boolean {\r\n const allDomains: string[] =\r\n target instanceof NiceError\r\n ? (target.def as unknown as INiceErrorDomainProps).allDomains\r\n : (target as NiceErrorDomain<any>).allDomains;\r\n return Array.isArray(allDomains) && allDomains.includes(this.domain);\r\n }\r\n\r\n // -------------------------------------------------------------------------\r\n // Private helpers\r\n // -------------------------------------------------------------------------\r\n\r\n private _buildDef(): ERR_DEF {\r\n return {\r\n domain: this.domain,\r\n allDomains: this.allDomains,\r\n schema: this._schema,\r\n } as unknown as ERR_DEF;\r\n }\r\n\r\n private _resolveMessage(\r\n id: keyof ERR_DEF[\"schema\"] & string,\r\n context: TFromContextInput<ERR_DEF[\"schema\"]>[typeof id],\r\n ): string {\r\n const entry = this._schema[id];\r\n\r\n if (typeof entry?.message === \"function\") {\r\n return (entry.message as (ctx: unknown) => string)(context);\r\n }\r\n if (typeof entry?.message === \"string\") {\r\n return entry.message;\r\n }\r\n return this.defaultMessage ?? `[${this.domain}::${id}] An error occurred.`;\r\n }\r\n\r\n private _resolveHttpStatusCode(\r\n id: keyof ERR_DEF[\"schema\"] & string,\r\n context: TFromContextInput<ERR_DEF[\"schema\"]>[typeof id],\r\n ): number {\r\n const entry = this._schema[id];\r\n let httpStatusCode: number | undefined;\r\n\r\n if (typeof entry?.httpStatusCode === \"function\") {\r\n httpStatusCode = (entry.httpStatusCode as (ctx: unknown) => number)(context);\r\n }\r\n if (typeof entry?.httpStatusCode === \"number\") {\r\n httpStatusCode = entry.httpStatusCode;\r\n }\r\n\r\n return typeof httpStatusCode === \"number\"\r\n ? httpStatusCode\r\n : (this.defaultHttpStatusCode ?? 500);\r\n }\r\n\r\n reconcileErrorDataForId(\r\n id: keyof ERR_DEF[\"schema\"] & string,\r\n context: TFromContextInput<ERR_DEF[\"schema\"]>[typeof id],\r\n ): TErrorReconciledData<ERR_DEF[\"schema\"], typeof id> {\r\n const message = this._resolveMessage(id, context);\r\n const httpStatusCode = this._resolveHttpStatusCode(id, context);\r\n const entry = this._schema[id];\r\n\r\n let contextState: TContextState<any>;\r\n\r\n if (context != null && entry?.context?.serialization != null) {\r\n // Context provided and a custom serializer is defined — build \"hydrated\" state.\r\n const serialized = entry.context.serialization.toJsonSerializable(context as any);\r\n contextState = { kind: EContextSerializedState.hydrated, value: context, serialized };\r\n } else {\r\n // No custom serializer (or context is absent for optional ids) — use \"raw_unset\".\r\n contextState = { kind: EContextSerializedState.serde_unset, value: context };\r\n }\r\n\r\n return { contextState, message, httpStatusCode, timeAdded: Date.now() };\r\n }\r\n}\r\n","import type {\n IDefineNewNiceErrorDomainOptions,\n TNiceErrorSchema,\n} from \"../NiceError/NiceError.types\";\nimport { NiceErrorDomain } from \"./NiceErrorDefined\";\n\nexport const defineNiceError = <ERR_DOMAIN extends string, SCHEMA extends TNiceErrorSchema>(\n definition: IDefineNewNiceErrorDomainOptions<ERR_DOMAIN, SCHEMA>,\n) => {\n // const {} = import(\"./NiceErrorDefined\");\n return new NiceErrorDomain<{\n domain: ERR_DOMAIN;\n allDomains: [ERR_DOMAIN];\n schema: SCHEMA;\n }>({\n domain: definition.domain,\n allDomains: [definition.domain],\n schema: definition.schema,\n ...(definition.packAs != null ? { packAs: definition.packAs } : {}),\n });\n};\n","import type {\r\n INiceErrorContextDefinition,\r\n INiceErrorIdMetadata,\r\n JSONSerializableValue,\r\n} from \"../NiceError/NiceError.types\";\r\n\r\n/**\r\n * Schema entry factory — the idiomatic way to define a single error id in a\r\n * `NiceErrorDefined` schema.\r\n *\r\n * Using `err()` instead of writing schema entries as plain object literals\r\n * ensures TypeScript resolves the context argument as **required** vs **optional**\r\n * correctly in `fromId` / `addId` call sites.\r\n *\r\n * How `required` affects the call site:\r\n *\r\n * | Schema entry | `fromId(\"id\")` | `fromId(\"id\", ctx)` |\r\n * |------------------------------------|----------------|---------------------|\r\n * | `err()` / `err({ ... })` | ✓ | ✗ (no context) |\r\n * | `err<C>({ context: {} })` | ✓ | ✓ (optional ctx) |\r\n * | `err<C>({ context: { required: true } })` | ✗ | ✓ (required ctx) |\r\n *\r\n * @example\r\n * ```ts\r\n * // No context — `fromId(\"not_found\")` takes no second argument.\r\n * not_found: err({ message: \"Resource not found\", httpStatusCode: 404 }),\r\n *\r\n * // Optional context — second arg accepted but not required.\r\n * rate_limited: err<{ retryAfter: number }>({\r\n * message: (ctx) => ctx ? `Retry after ${ctx.retryAfter}s` : \"Rate limited\",\r\n * httpStatusCode: 429,\r\n * context: {},\r\n * }),\r\n *\r\n * // Required context — `fromId(\"invalid_input\", { field: \"email\" })` (second arg is required).\r\n * invalid_input: err<{ field: string }>({\r\n * message: ({ field }) => `Invalid value for field: ${field}`,\r\n * httpStatusCode: 422,\r\n * context: { required: true },\r\n * }),\r\n *\r\n * // Required context with custom serialization (for non-JSON-safe context values).\r\n * fs_error: err<{ cause: NodeJS.ErrnoException }>({\r\n * message: ({ cause }) => `File system error: ${cause.message}`,\r\n * context: {\r\n * required: true,\r\n * serialization: {\r\n * toJsonSerializable: ({ cause }) => ({ code: cause.code, message: cause.message }),\r\n * fromJsonSerializable: (obj) => ({ cause: Object.assign(new Error(obj.message), obj) }),\r\n * },\r\n * },\r\n * }),\r\n * ```\r\n */\r\n\r\n// Overload 1: context.required: true → the context argument will be **required** in fromId/addId.\r\nexport function err<C, D extends JSONSerializableValue = Record<string, any>>(\r\n meta: INiceErrorIdMetadata<C, D> & {\r\n context: INiceErrorContextDefinition<C, D> & { required: true };\r\n },\r\n): INiceErrorIdMetadata<C> & { context: { required: true } };\r\n\r\n// Overload 2: everything else (no context, or optional context) → context arg is optional/absent.\r\nexport function err<C = never>(meta?: INiceErrorIdMetadata<C>): INiceErrorIdMetadata<C>;\r\n\r\n// Implementation (not part of the public overload surface).\r\nexport function err<C = never>(meta?: INiceErrorIdMetadata<C>): INiceErrorIdMetadata<C> {\r\n return meta ?? ({} as INiceErrorIdMetadata<C>);\r\n}\r\n","import { StatusCodes } from \"http-status-codes\";\nimport { defineNiceError } from \"../NiceErrorDefined/defineNiceError\";\nimport { err } from \"../NiceErrorDefined/err\";\nimport type {\n IInspectErrorResult_JsError,\n IInspectErrorResult_JsErrorObject,\n IInspectErrorResult_JsOther,\n IInspectErrorResult_Nullish,\n TInspectErrorResult_JsDataType,\n} from \"../utils/inspectPotentialError/inspectPotentialError.types\";\n\nexport const err_nice = defineNiceError({\n domain: \"err_nice\",\n schema: {},\n});\n\nexport enum EErrId_CastNotNice {\n js_error = \"native_error\",\n js_error_like_object = \"js_error_like_object\",\n nullish_value = \"nullish_value\",\n js_data_type = \"js_data_type\",\n js_other = \"js_other\",\n}\n\nexport const err_cast_not_nice = err_nice.createChildDomain({\n domain: \"err_cast_not_nice\",\n defaultHttpStatusCode: StatusCodes.UNPROCESSABLE_ENTITY,\n schema: {\n [EErrId_CastNotNice.js_error]: err<IInspectErrorResult_JsError>({\n context: {\n required: true,\n },\n message: ({ jsError }) =>\n `A native JavaScript Error was encountered during casting: ${jsError.message}`,\n httpStatusCode: StatusCodes.INTERNAL_SERVER_ERROR,\n }),\n [EErrId_CastNotNice.js_error_like_object]: err<IInspectErrorResult_JsErrorObject>({\n context: {\n required: true,\n },\n message: ({ jsErrorObject }) =>\n `An object resembling a JavaScript Error was encountered during casting: [${jsErrorObject.name}] ${jsErrorObject.message}`,\n httpStatusCode: StatusCodes.INTERNAL_SERVER_ERROR,\n }),\n [EErrId_CastNotNice.nullish_value]: err<IInspectErrorResult_Nullish>({\n context: {\n required: true,\n },\n message: ({ value }) =>\n `A nullish value [${value === null ? \"null\" : \"undefined\"}] was encountered during casting`,\n }),\n [EErrId_CastNotNice.js_data_type]: err<TInspectErrorResult_JsDataType>({\n context: {\n required: true,\n },\n message: ({ jsDataType, jsDataValue }) => {\n let inspectedValue: string | undefined;\n\n try {\n inspectedValue = JSON.stringify(jsDataValue);\n } catch {\n // Ignore JSON.stringify errors, which can happen for circular structures or certain types like BigInt.\n }\n\n return `A value of type [${jsDataType}] with value [${inspectedValue ?? \"UNSERIALIZABLE\"}] was encountered during casting, which is not a valid error type`;\n },\n }),\n [EErrId_CastNotNice.js_other]: err<IInspectErrorResult_JsOther>({\n context: {\n required: true,\n },\n message: ({ jsDataValue }) => {\n let inspectedValue: string | undefined;\n\n try {\n inspectedValue = JSON.stringify(jsDataValue);\n } catch {\n // Ignore JSON.stringify errors, which can happen for circular structures or certain types like BigInt.\n }\n\n return `An unhandled type [${typeof jsDataValue}] with value [${inspectedValue ?? \"UNSERIALIZABLE\"}] was encountered during casting, which is not a valid error type`;\n },\n }),\n },\n});\n\nexport const err_nice_handler = err_nice.createChildDomain({\n domain: \"err_nice_handler\",\n schema: {},\n});\n","import type { NiceError } from \"../NiceError/NiceError\";\r\nimport type { INiceErrorDomainProps, TDomainNiceErrorId } from \"../NiceError/NiceError.types\";\r\nimport type { NiceErrorHydrated } from \"../NiceError/NiceErrorHydrated\";\r\n\r\nexport type MaybePromise<T> = T | Promise<T>;\r\n/**\r\n * Broad handler signature used internally for storage and dispatch.\r\n */\r\nexport type TBroadErrorHandler<E extends NiceError = NiceError, RES = unknown> = (\r\n action: E,\r\n) => MaybePromise<RES>;\r\n\r\n/**\r\n * Handler registered via forDomain.\r\n *\r\n * `act.input` is typed as the union of input types for every action in `ACT_DOM`,\r\n * and `act.coreAction` carries the matching schema — the same narrowing you get\r\n * from `forActionIds` over all action IDs in the domain.\r\n */\r\nexport type TErrorHandlerForDomain<ERR_DOM extends INiceErrorDomainProps> = (\r\n error: NiceErrorHydrated<ERR_DOM>,\r\n) => MaybePromise<unknown>;\r\n\r\n/**\r\n * Handler registered via forActionId — receives a specific action ID, with\r\n * the primed action's input narrowed to that ID's schema.\r\n */\r\nexport type TErrorIdHandlerForDomain<\r\n ERR_DOM extends INiceErrorDomainProps,\r\n ID extends TDomainNiceErrorId<ERR_DOM>,\r\n> = (error: NiceErrorHydrated<ERR_DOM, ID>) => MaybePromise<unknown>;\r\n\r\nexport enum EErrorHandlerTargetType {\r\n ids = \"ids\",\r\n domain = \"domain\",\r\n default = \"default\",\r\n}\r\n\r\nexport type TErrorHandlerTarget = (\r\n | {\r\n type: EErrorHandlerTargetType.ids;\r\n domain: string;\r\n ids: string[]; // if omitted, matches all IDs in the domain\r\n }\r\n | {\r\n type: EErrorHandlerTargetType.domain;\r\n domain: string;\r\n }\r\n | {\r\n type: EErrorHandlerTargetType.default;\r\n }\r\n) & {\r\n identifier: string; // for debugging/logging — not used for matching\r\n};\r\n\r\n/**\r\n * A single case in a `handleWith` / `handleWithAsync` call.\r\n *\r\n * Construct via `forDomain` or `forIds` — do not build this object directly.\r\n */\r\nexport interface IErrorHandlerConfig<\r\n ERR extends NiceError<any, any> = NiceError<any, any>,\r\n RES = unknown,\r\n> {\r\n /**\r\n * Duck-typed reference to the domain definition.\r\n * Needs only `isExact()` and `hydrate()` at runtime — avoids any circular value import.\r\n * @internal\r\n */\r\n // readonly target:\r\n readonly target: TErrorHandlerTarget;\r\n readonly _matcher: (action: ERR) => boolean;\r\n readonly _requester: TBroadErrorHandler<ERR, RES>;\r\n}\r\n\r\nexport interface IErrorHandleAttempt_Success<RES = void> {\r\n handled: true;\r\n result: RES;\r\n target: TErrorHandlerTarget;\r\n}\r\n\r\nexport interface IErrorHandleAttempt_Failure {\r\n handled: false;\r\n result?: undefined;\r\n targets: TErrorHandlerTarget[]; // all attempted targets, for debugging/logging\r\n}\r\n\r\nexport type TErrorHandleAttempt<RES = void> =\r\n | IErrorHandleAttempt_Success<RES>\r\n | IErrorHandleAttempt_Failure;\r\n\r\nexport interface IHandleErrorOptions {\r\n throwOnUnhandled?: boolean;\r\n}\r\n\r\nexport type THandleErrorWithPromiseInspection<RES = void> =\r\n | {\r\n isPromise: false;\r\n matched: true;\r\n target: TErrorHandlerTarget;\r\n handlerResponse: RES;\r\n }\r\n | {\r\n isPromise: true;\r\n matched: true;\r\n target: TErrorHandlerTarget;\r\n handlerPromise: Promise<RES>;\r\n }\r\n | {\r\n matched: false;\r\n attemptedTargets: TErrorHandlerTarget[];\r\n };\r\n\r\nexport type THandleResponse<RES = unknown> =\r\n | {\r\n handled: false;\r\n }\r\n | {\r\n handled: true;\r\n isPromise: boolean;\r\n response: RES;\r\n };\r\n","import type { NiceError } from \"../NiceError/NiceError\";\nimport type { INiceErrorDomainProps, TDomainNiceErrorId } from \"../NiceError/NiceError.types\";\nimport type { NiceErrorHydrated } from \"../NiceError/NiceErrorHydrated\";\nimport type { NiceErrorDomain } from \"../NiceErrorDefined/NiceErrorDefined\";\nimport {\n EErrorHandlerTargetType,\n type IErrorHandlerConfig,\n type IHandleErrorOptions,\n type MaybePromise,\n type TBroadErrorHandler,\n type THandleErrorWithPromiseInspection,\n} from \"./NiceErrorHandler.types\";\n\nexport class NiceErrorHandler<RES_DEF = never, RES = never> {\n private handlerConfigs: IErrorHandlerConfig<any, RES>[] = [];\n private _defaultRequester?: TBroadErrorHandler<NiceError<any, any>, RES_DEF>;\n\n handleErrorWithPromiseInspection(\n error: NiceError<any, any>,\n options?: IHandleErrorOptions,\n ): THandleErrorWithPromiseInspection<RES | RES_DEF> {\n for (const handlerConfig of this.handlerConfigs) {\n if (!handlerConfig._matcher(error)) continue;\n const errorResult = handlerConfig._requester(error);\n\n if (errorResult instanceof Promise) {\n return {\n isPromise: true,\n matched: true,\n target: handlerConfig.target,\n handlerPromise: errorResult,\n };\n }\n\n return {\n isPromise: false,\n matched: true,\n target: handlerConfig.target,\n handlerResponse: errorResult as RES,\n };\n }\n\n if (this._defaultRequester) {\n const defaultResult = this._defaultRequester(error);\n\n if (defaultResult instanceof Promise) {\n return {\n isPromise: true,\n matched: true,\n target: {\n type: EErrorHandlerTargetType.default,\n identifier: \"[matched:default]\",\n },\n handlerPromise: defaultResult,\n };\n }\n\n return {\n isPromise: false,\n matched: true,\n target: { type: EErrorHandlerTargetType.default, identifier: \"[matched:default]\" },\n handlerResponse: defaultResult,\n };\n }\n\n if (options?.throwOnUnhandled === true) {\n throw error;\n }\n\n return {\n matched: false,\n attemptedTargets: this.handlerConfigs.map((config) => config.target),\n };\n }\n\n /**\n * Register a handler that fires for **any** error whose domain matches `domain`.\n * The handler receives a fully hydrated error — `getContext`, `addId`, and `addContext`\n * are all available. First matching case wins.\n */\n forDomain<DEF extends INiceErrorDomainProps, H_RES = void>(\n domain: NiceErrorDomain<DEF>,\n handler: (error: NiceErrorHydrated<DEF, TDomainNiceErrorId<DEF>>) => MaybePromise<H_RES>,\n ): NiceErrorHandler<RES_DEF, RES | H_RES> {\n (this as NiceErrorHandler<RES_DEF, RES | H_RES>).handlerConfigs.push({\n target: {\n type: EErrorHandlerTargetType.domain,\n domain: domain.domain,\n identifier: `[matched:domain:${domain.domain}]`,\n },\n _matcher: (error) => domain.isExact(error),\n _requester: (error) =>\n handler(domain.hydrate(error as unknown as NiceError<DEF, TDomainNiceErrorId<DEF>>)),\n });\n return this;\n }\n\n forId<DEF extends INiceErrorDomainProps, ID extends TDomainNiceErrorId<DEF>, H_RES = void>(\n domain: NiceErrorDomain<DEF>,\n id: ID,\n handler: (error: NiceErrorHydrated<DEF, ID>) => MaybePromise<H_RES>,\n ): NiceErrorHandler<RES_DEF, RES | H_RES> {\n (this as NiceErrorHandler<RES_DEF, RES | H_RES>).handlerConfigs.push({\n target: {\n type: EErrorHandlerTargetType.ids,\n domain: domain.domain,\n ids: [id],\n identifier: `[matched:ids:${domain.domain}:${id}]`,\n },\n _matcher: (error) => domain.isExact(error) && error.hasId(id),\n _requester: (error) =>\n handler(\n domain.hydrate(\n error as unknown as NiceError<DEF, TDomainNiceErrorId<DEF>>,\n ) as NiceErrorHydrated<DEF, ID>,\n ),\n });\n return this;\n }\n\n forIds<DEF extends INiceErrorDomainProps, IDS extends TDomainNiceErrorId<DEF>[], H_RES = void>(\n domain: NiceErrorDomain<DEF>,\n ids: IDS,\n handler: (error: NiceErrorHydrated<DEF, IDS[number]>) => MaybePromise<H_RES>,\n ): NiceErrorHandler<RES_DEF, RES | H_RES> {\n (this as NiceErrorHandler<RES_DEF, RES | H_RES>).handlerConfigs.push({\n target: {\n type: EErrorHandlerTargetType.ids,\n domain: domain.domain,\n ids: ids,\n identifier: `[matched:ids:${domain.domain}:${ids.join(\",\")}]`,\n },\n _matcher: (error) => domain.isExact(error) && ids.some((id) => error.hasId(id)),\n _requester: (error) =>\n handler(\n domain.hydrate(\n error as unknown as NiceError<DEF, TDomainNiceErrorId<DEF>>,\n ) as NiceErrorHydrated<DEF, IDS[number]>,\n ),\n });\n return this;\n }\n\n /**\n * Register a fallback handler that fires when no other case matches.\n * Only one default handler can be registered — calling this twice replaces the previous one.\n */\n setDefaultHandler<H_RES>(\n handler: (error: NiceError<any, any>) => MaybePromise<H_RES>,\n ): NiceErrorHandler<H_RES, RES> {\n (this as unknown as NiceErrorHandler<H_RES, RES>)._defaultRequester = handler;\n return this as unknown as NiceErrorHandler<H_RES, RES>;\n }\n}\n","import type { INiceErrorDomainProps, TDomainNiceErrorId } from \"../NiceError/NiceError.types\";\nimport type { NiceErrorHydrated } from \"../NiceError/NiceErrorHydrated\";\nimport type { NiceErrorDomain } from \"../NiceErrorDefined/NiceErrorDefined\";\nimport { NiceErrorHandler } from \"./NiceErrorHandler\";\nimport type { MaybePromise } from \"./NiceErrorHandler.types\";\n\nexport function forDomain<DEF extends INiceErrorDomainProps, H_RES = void>(\n domain: NiceErrorDomain<DEF>,\n handler: (error: NiceErrorHydrated<DEF, TDomainNiceErrorId<DEF>>) => MaybePromise<H_RES>,\n): NiceErrorHandler<never, H_RES> {\n return new NiceErrorHandler<never, never>().forDomain(domain, handler);\n}\n\nexport function forId<\n DEF extends INiceErrorDomainProps,\n ID extends TDomainNiceErrorId<DEF>,\n H_RES = void,\n>(\n domain: NiceErrorDomain<DEF>,\n id: ID,\n handler: (error: NiceErrorHydrated<DEF, ID>) => MaybePromise<H_RES>,\n): NiceErrorHandler<never, H_RES> {\n return new NiceErrorHandler<never, never>().forId(domain, id, handler);\n}\n\nexport function forIds<\n DEF extends INiceErrorDomainProps,\n IDS extends TDomainNiceErrorId<DEF>[],\n H_RES = void,\n>(\n domain: NiceErrorDomain<DEF>,\n ids: IDS,\n handler: (error: NiceErrorHydrated<DEF, IDS[number]>) => MaybePromise<H_RES>,\n): NiceErrorHandler<never, H_RES> {\n return new NiceErrorHandler<never, never>().forIds(domain, ids, handler);\n}\n","import { EContextSerializedState } from \"../NiceError/NiceError.enums\";\nimport { type INiceErrorJsonObject, type TErrorDataForIdMap } from \"../NiceError/NiceError.types\";\n\n/**\n * Returns `true` if `obj` is a JSON-serialised `NiceError` object matching the\n * current wire format (contextState-based errorData entries).\n *\n * Validates:\n * - Top-level shape (`name`, `message`, `wasntNice`, `httpStatusCode`, `def`)\n * - Each `errorData` entry has a `contextState` with a valid `kind` discriminant\n * (`\"no_serialization\"` or `\"unhydrated\"`) — rejecting payloads in the old\n * format (`context` / `serialized` fields) to prevent silent data corruption.\n */\nexport function isNiceErrorObject(obj: unknown): obj is INiceErrorJsonObject {\n if (typeof obj !== \"object\" || obj == null) return false;\n const o = obj as Record<string, unknown>;\n\n if (\n o[\"name\"] !== \"NiceError\" ||\n typeof o[\"message\"] !== \"string\" ||\n typeof o[\"wasntNice\"] !== \"boolean\" ||\n typeof o[\"httpStatusCode\"] !== \"number\"\n ) {\n return false;\n }\n\n // Validate the `def` property.\n const def = o[\"def\"];\n if (typeof def !== \"object\" || def == null) return false;\n const d = def as Record<string, unknown>;\n if (typeof d[\"domain\"] !== \"string\" || !Array.isArray(d[\"allDomains\"])) return false;\n\n // Validate errorData entries use the current contextState format.\n // An absent / null errorData is acceptable (bare NiceErrors may have an empty map).\n const errorData = o[\"errorData\"] as TErrorDataForIdMap<any>;\n if (errorData != null) {\n if (typeof errorData !== \"object\") return false;\n\n for (const entry of Object.values(errorData)) {\n if (entry == null) continue;\n if (typeof entry !== \"object\") return false;\n\n const e = entry;\n const state = e[\"contextState\"];\n\n // Reject old-format entries that still use the `context` / `serialized` shape.\n if (state == null || typeof state !== \"object\") return false;\n\n const kind = state[\"kind\"];\n if (\n kind !== EContextSerializedState.serde_unset &&\n kind !== EContextSerializedState.unhydrated\n )\n return false;\n }\n }\n\n return true;\n}\n","import type { IRegularErrorJsonObject } from \"../NiceError/NiceError.types\";\n\nexport function isRegularErrorJsonObject(obj: unknown): obj is IRegularErrorJsonObject {\n if (typeof obj !== \"object\" || obj == null) return false;\n const o = obj as Record<string, unknown>;\n return typeof o[\"name\"] === \"string\" && typeof o[\"message\"] === \"string\";\n}\n","import { Logger } from \"tslog\";\n\nexport const logger_NiceError = new Logger({\n name: \"NiceErrorLogger\",\n});\n\nexport const logger_NiceError_testing = logger_NiceError.getSubLogger({\n name: \"NiceErrorTestingLogger\",\n});\n","import { NiceError } from \"../../NiceError/NiceError\";\nimport type { IRegularErrorJsonObject } from \"../../NiceError/NiceError.types\";\nimport { DUR_OBJ_PACK_PREFIX, DUR_OBJ_PACK_SUFFIX } from \"../../NiceError/nice_error.static\";\nimport { isNiceErrorObject } from \"../isNiceErrorObject\";\nimport { isRegularErrorJsonObject } from \"../isRegularErrorObject\";\nimport { logger_NiceError } from \"../logger\";\nimport { EInspectErrorResultType } from \"./inspectPotentialError.enums\";\nimport { type TInspectErrorResult } from \"./inspectPotentialError.types\";\n\nfunction interpretMessagePackedError(\n parsedError: Error | IRegularErrorJsonObject,\n): TInspectErrorResult | null {\n let packedErrorStr: string | undefined;\n\n if (\n typeof parsedError.message === \"string\" &&\n parsedError.message.includes(DUR_OBJ_PACK_PREFIX) &&\n parsedError.message.includes(DUR_OBJ_PACK_SUFFIX)\n ) {\n packedErrorStr = parsedError.message;\n }\n\n if (\n typeof parsedError.cause === \"string\" &&\n parsedError.cause.includes(DUR_OBJ_PACK_PREFIX) &&\n parsedError.cause.includes(DUR_OBJ_PACK_SUFFIX)\n ) {\n packedErrorStr = parsedError.cause;\n }\n\n if (packedErrorStr != null) {\n const jsonStr = packedErrorStr.split(DUR_OBJ_PACK_PREFIX)[1]!.split(DUR_OBJ_PACK_SUFFIX)[0]!;\n try {\n const errorObj = JSON.parse(jsonStr);\n if (isNiceErrorObject(errorObj)) {\n return {\n type: EInspectErrorResultType.niceErrorObject,\n niceErrorObject: errorObj,\n };\n }\n } catch {\n // Not a valid JSON, continue treating as regular Error\n }\n }\n\n return null;\n}\n\nexport const inspectPotentialError = (potentialError: unknown): TInspectErrorResult => {\n if (potentialError == null) {\n return {\n type: EInspectErrorResultType.nullish,\n value: potentialError,\n };\n }\n\n if (typeof potentialError === \"number\") {\n return {\n type: EInspectErrorResultType.jsDataType,\n jsDataType: \"number\",\n jsDataValue: potentialError,\n };\n }\n\n if (typeof potentialError === \"boolean\") {\n return {\n type: EInspectErrorResultType.jsDataType,\n jsDataType: \"boolean\",\n jsDataValue: potentialError,\n };\n }\n\n let parsedError: unknown = potentialError;\n\n if (typeof potentialError === \"string\") {\n if (potentialError.includes(\"{\") && potentialError.includes(\"name\")) {\n try {\n parsedError = JSON.parse(potentialError);\n } catch {\n // Not a JSON string, treat as regular string\n return {\n type: EInspectErrorResultType.jsDataType,\n jsDataType: \"string\",\n jsDataValue: potentialError,\n };\n }\n } else {\n return {\n type: EInspectErrorResultType.jsDataType,\n jsDataType: \"string\",\n jsDataValue: potentialError,\n };\n }\n }\n\n if (typeof parsedError !== \"object\" || parsedError == null) {\n logger_NiceError.warn({\n message:\n \"Received a potential error that is a primitive data type other than string, number, or boolean. This is unexpected and may indicate an issue with error handling in the code.\",\n potentialError,\n });\n\n return {\n jsDataValue: potentialError,\n type: EInspectErrorResultType.jsOther,\n };\n }\n\n if (parsedError instanceof NiceError) {\n return {\n type: EInspectErrorResultType.niceError,\n niceError: parsedError,\n };\n }\n\n if (isNiceErrorObject(parsedError)) {\n return {\n type: EInspectErrorResultType.niceErrorObject,\n niceErrorObject: parsedError,\n };\n }\n\n if (parsedError instanceof Error) {\n const durObjResult = interpretMessagePackedError(parsedError);\n\n if (durObjResult != null) {\n return durObjResult;\n }\n\n return {\n type: EInspectErrorResultType.jsError,\n jsError: parsedError,\n };\n }\n\n if (isRegularErrorJsonObject(parsedError)) {\n const durObjResult = interpretMessagePackedError(parsedError);\n\n if (durObjResult != null) {\n return durObjResult;\n }\n\n return {\n type: EInspectErrorResultType.jsErrorObject,\n jsErrorObject: parsedError as IRegularErrorJsonObject,\n };\n }\n\n return {\n type: EInspectErrorResultType.jsDataType,\n jsDataType: \"object\",\n jsDataValue: parsedError,\n };\n};\n","import { EErrId_CastNotNice, err_cast_not_nice } from \"../internal/nice_core_errors\";\nimport { NiceError } from \"../NiceError/NiceError\";\nimport { inspectPotentialError } from \"./inspectPotentialError/inspectPotentialError\";\nimport { EInspectErrorResultType } from \"./inspectPotentialError/inspectPotentialError.enums\";\n\n/**\n * Casts any unknown value into a `NiceError`.\n *\n * - If the value is already a `NiceError` instance, it is returned as-is.\n * - If the value is a plain `Error`, it is wrapped with the original as `originError`.\n * - If the value is a JSON-serialised `NiceError` object (e.g. from an API\n * response), a best-effort `NiceError` is re-created from it.\n * - For all other values, a generic `NiceError` is created with a descriptive\n * message.\n *\n * After casting, use `NiceErrorDefined.is(error)` to narrow the error to a\n * specific domain and access its strongly-typed ids and context.\n */\nexport const castNiceError = (error: unknown): NiceError => {\n const inspected = inspectPotentialError(error);\n\n switch (inspected.type) {\n case EInspectErrorResultType.niceError:\n // Already a NiceError instance — return as-is.\n return inspected.niceError;\n\n case EInspectErrorResultType.niceErrorObject: {\n // Re-hydrate from a serialised NiceError JSON object.\n const obj = inspected.niceErrorObject;\n return new NiceError(obj);\n }\n\n case EInspectErrorResultType.jsError: {\n // Wrap a native JS Error, preserving the original as context.\n return err_cast_not_nice\n .fromContext({\n [EErrId_CastNotNice.js_error]: inspected,\n })\n .withOriginError(inspected.jsError);\n }\n\n case EInspectErrorResultType.jsErrorObject: {\n const err = err_cast_not_nice.fromContext({\n [EErrId_CastNotNice.js_error_like_object]: inspected,\n });\n err.cause = inspected.jsErrorObject;\n return err;\n }\n\n case EInspectErrorResultType.nullish:\n return err_cast_not_nice.fromContext({\n [EErrId_CastNotNice.nullish_value]: inspected,\n });\n\n case EInspectErrorResultType.jsDataType: {\n return err_cast_not_nice.fromContext({\n [EErrId_CastNotNice.js_data_type]: inspected,\n });\n }\n\n default:\n return err_cast_not_nice.fromContext({\n [EErrId_CastNotNice.js_other]: inspected,\n });\n }\n};\n","import { NiceError } from \"../NiceError/NiceError\";\nimport type { INiceErrorDomainProps } from \"../NiceError/NiceError.types\";\nimport { NiceErrorHydrated } from \"../NiceError/NiceErrorHydrated\";\nimport type { NiceErrorDomain } from \"../NiceErrorDefined/NiceErrorDefined\";\nimport { castNiceError } from \"./castNiceError\";\n\n/**\n * Combines `castNiceError`, `is()`, and `hydrate()` in a single call — the\n * idiomatic way to handle an unknown value arriving from a remote boundary\n * (API response, message queue, IPC, etc.) when you have a specific domain in mind.\n *\n * - Casts `value` to a `NiceError` using `castNiceError`.\n * - If the result belongs to `niceErrorDefined`'s domain (`is()` returns `true`),\n * hydrates it and returns a fully-typed `NiceErrorHydrated`.\n * - Otherwise returns the raw cast `NiceError` (which may be a `wasntNice` error\n * if `value` was not a NiceError at all).\n *\n * @example\n * ```ts\n * // In an Express error handler:\n * app.use((err, req, res, next) => {\n * const error = castAndHydrate(err, err_user_auth);\n *\n * if (err_user_auth.is(error)) {\n * // error is NiceErrorHydrated — getContext / addId available\n * const result = matchFirst(error, {\n * invalid_credentials: ({ username }) => res.status(401).json({ username }),\n * account_locked: () => res.status(403).json({ locked: true }),\n * });\n * if (result) return;\n * }\n *\n * next(err);\n * });\n * ```\n */\nexport function castAndHydrate<ERR_DEF extends INiceErrorDomainProps>(\n value: unknown,\n niceErrorDefined: NiceErrorDomain<ERR_DEF>,\n): NiceErrorHydrated<ERR_DEF, keyof ERR_DEF[\"schema\"] & string> | NiceError {\n const casted = castNiceError(value);\n if (niceErrorDefined.isExact(casted)) {\n return niceErrorDefined.hydrate(casted);\n }\n return casted;\n}\n","import { NiceError } from \"../NiceError/NiceError\";\nimport type { INiceErrorDomainProps, TExtractContextType } from \"../NiceError/NiceError.types\";\n\n/**\n * Handler map for `matchFirst`. Each key is an error id (from `ACTIVE_IDS`) and\n * the value is a function that receives the typed context for that id.\n *\n * The `_` key is an optional fallback that runs when no id-specific handler matched.\n */\nexport type TMatchFirstHandlers<\n ERR_DEF extends INiceErrorDomainProps,\n ACTIVE_IDS extends keyof ERR_DEF[\"schema\"] & string,\n RESULT,\n> = {\n [K in ACTIVE_IDS]?: (context: TExtractContextType<ERR_DEF[\"schema\"][K]>) => RESULT;\n} & { _?: () => RESULT };\n\n/**\n * Pattern-matches an error against a map of id → handler functions, returning the\n * result of the first handler whose id is active on the error.\n *\n * - Ids are tested in the order returned by `error.getIds()`.\n * - If no id-specific handler matched and `_` is provided, the fallback is called.\n * - Returns `undefined` when neither any id handler nor the fallback fires.\n *\n * **Requires hydrated context.** If any matched id is in the `\"unhydrated\"` state,\n * `getContext` will throw. Call `niceErrorDefined.hydrate(error)` beforehand when\n * working with errors deserialized from a JSON payload.\n *\n * @example\n * ```ts\n * const result = matchFirst(error, {\n * invalid_credentials: ({ username }) => `Wrong password for ${username}`,\n * account_locked: () => \"Account is locked\",\n * _: () => \"Unknown auth error\",\n * });\n * ```\n */\nexport function matchFirst<\n ERR_DEF extends INiceErrorDomainProps,\n ACTIVE_IDS extends keyof ERR_DEF[\"schema\"] & string,\n RESULT,\n>(\n error: NiceError<ERR_DEF, ACTIVE_IDS>,\n handlers: TMatchFirstHandlers<ERR_DEF, ACTIVE_IDS, RESULT>,\n): RESULT | undefined {\n for (const id of error.getIds()) {\n const handler = (handlers as Record<string, unknown>)[id as string];\n if (typeof handler === \"function\") {\n const context = error.getContext(id);\n return (handler as (ctx: unknown) => RESULT)(context);\n }\n }\n\n if (typeof handlers._ === \"function\") {\n return handlers._();\n }\n\n return undefined;\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -2,13 +2,13 @@
2
2
  "name": "@nice-code/error",
3
3
  "main": "build/index.js",
4
4
  "module": "build/index.js",
5
- "types": "build/types/index.d.ts",
5
+ "types": "build/index.d.ts",
6
6
  "type": "module",
7
- "version": "0.8.0",
7
+ "version": "0.9.0",
8
8
  "exports": {
9
9
  ".": {
10
10
  "source": "./src/index.ts",
11
- "types": "./build/types/index.d.ts",
11
+ "types": "./build/index.d.ts",
12
12
  "import": "./build/index.js"
13
13
  }
14
14
  },
@@ -26,7 +26,8 @@
26
26
  "vitest": "vitest --typecheck",
27
27
  "vitest-agent": "vitest --typecheck --reporter=agent",
28
28
  "clean-build": "bunx rimraf build",
29
- "build": "bun run clean-build && bun run build.ts && bun run build-types",
29
+ "build-bun": "bun run clean-build && bun run build.ts && bun run build-types",
30
+ "build": "bun run clean-build && tsdown",
30
31
  "build-types": "tsc --project tsconfig.build.json",
31
32
  "example": "bun run ./src/example/error_usage_example.ts"
32
33
  },
@@ -1,148 +0,0 @@
1
- import type { NiceErrorDomain } from "../NiceErrorDefined/NiceErrorDefined";
2
- import type { NiceErrorHandler } from "../NiceErrorHandler/NiceErrorHandler";
3
- import type { IHandleErrorOptions } from "../NiceErrorHandler/NiceErrorHandler.types";
4
- import { EErrorPackType } from "../utils/packError/packError.enums";
5
- import { type INiceErrorDomainProps, type INiceErrorJsonObject, type IRegularErrorJsonObject, type TDomainNiceErrorId, type TErrorDataForIdMap, type TErrorReconciledData, type TExtractContextType, type TNiceErrorSchema, type TUnknownNiceErrorDef } from "./NiceError.types";
6
- import type { NiceErrorHydrated } from "./NiceErrorHydrated";
7
- type ContextOf<S extends TNiceErrorSchema, K extends keyof S> = TExtractContextType<S[K]>;
8
- /** Full-featured construction from NiceErrorDefined.fromId / fromContext. */
9
- export interface INiceErrorOptions<ERR_DEF extends INiceErrorDomainProps, ID extends TDomainNiceErrorId<ERR_DEF> = TDomainNiceErrorId<ERR_DEF>> {
10
- def: Omit<ERR_DEF, "schema">;
11
- /** Primary id is first entry in ids. */
12
- ids: ID[];
13
- /** All active ids with their messages, http status codes, and context state. */
14
- errorData: TErrorDataForIdMap<ERR_DEF["schema"]>;
15
- message: string;
16
- wasntNice?: boolean;
17
- httpStatusCode?: number;
18
- originError?: IRegularErrorJsonObject | undefined;
19
- timeCreated?: number;
20
- }
21
- export declare class NiceError<ERR_DEF extends INiceErrorDomainProps = TUnknownNiceErrorDef,
22
- /**
23
- * Union of active error-id keys.
24
- * - After `fromId(id)`: exactly one key.
25
- * - After `fromContext({...})`: a union of all supplied keys.
26
- * - After `hasOneOfIds([a,b])`: narrows to that subset.
27
- * - Default (bare construction / castNiceError): `TUnknownNiceErrorId`.
28
- */
29
- ACTIVE_IDS extends TDomainNiceErrorId<ERR_DEF> = TDomainNiceErrorId<ERR_DEF>> extends Error {
30
- readonly name: "NiceError";
31
- readonly def: Omit<ERR_DEF, "schema">;
32
- /** Primary id is first entry in ids. */
33
- readonly ids: ACTIVE_IDS[];
34
- readonly wasntNice: boolean;
35
- readonly httpStatusCode: number;
36
- readonly timeCreated: number;
37
- readonly cleanMessage: string;
38
- originError?: IRegularErrorJsonObject;
39
- _packedState?: {
40
- packedAs: EErrorPackType.cause_pack;
41
- cause: unknown;
42
- } | {
43
- packedAs: EErrorPackType.msg_pack;
44
- message: string;
45
- } | undefined;
46
- /** Internal: all active id → reconciled data pairs. */
47
- protected readonly _errorDataMap: TErrorDataForIdMap<ERR_DEF["schema"]>;
48
- constructor(options: INiceErrorOptions<ERR_DEF, ACTIVE_IDS>);
49
- /**
50
- * Type guard: returns `true` if this error was created with (or contains) the
51
- * given `id`. After the guard, `getContext(id)` will be strongly typed.
52
- */
53
- hasId<ID extends keyof ERR_DEF["schema"] & string>(id: ID): this is NiceError<ERR_DEF, ID>;
54
- /**
55
- * Returns `true` if this error contains **at least one** of the supplied ids.
56
- * Narrows `ACTIVE_IDS` to the matching subset of `IDS`.
57
- */
58
- hasOneOfIds<IDS extends ReadonlyArray<keyof ERR_DEF["schema"] & string>>(ids: IDS): this is NiceError<ERR_DEF, IDS[number]>;
59
- /** `true` when this error was created with more than one id (via `fromContext`). */
60
- get hasMultiple(): boolean;
61
- /** Returns all active error ids on this instance. */
62
- getIds(): Array<ACTIVE_IDS>;
63
- /**
64
- * Returns the typed context value for the given error id.
65
- *
66
- * TypeScript will only allow you to call this with an id that is part of
67
- * `ACTIVE_IDS` (i.e. an id confirmed via `hasId` / `hasOneOfIds`, or passed
68
- * to `fromId` / `fromContext`).
69
- *
70
- * @throws If the context is in the `"unhydrated"` state — the error was
71
- * reconstructed from a JSON payload and its context has a custom serializer
72
- * that hasn't been run yet. Call `niceErrorDefined.hydrate(error)` first.
73
- */
74
- getContext<ID extends ACTIVE_IDS>(id: ID): ContextOf<ERR_DEF["schema"], ID>;
75
- getErrorDataForId<ID extends ACTIVE_IDS>(id: ID): TErrorReconciledData<ERR_DEF["schema"], ID> | undefined;
76
- withOriginError(error: unknown): this;
77
- /**
78
- * Returns `true` if `other` has the same domain and the exact same set of
79
- * active error ids as this error (order-independent).
80
- *
81
- * Useful for deduplication, retry logic, and asserting that two errors
82
- * represent the same "kind" of problem without comparing context values.
83
- *
84
- * ```ts
85
- * const a = err_auth.fromId("invalid_credentials", { username: "alice" });
86
- * const b = err_auth.fromId("invalid_credentials", { username: "bob" });
87
- * a.matches(b); // true — same domain + same id set
88
- *
89
- * const c = err_auth.fromId("account_locked");
90
- * a.matches(c); // false — same domain, different id
91
- * ```
92
- */
93
- matches(other: NiceError<any, any>): boolean;
94
- toJsonObject(): INiceErrorJsonObject<ERR_DEF>;
95
- toJSON(): INiceErrorJsonObject<ERR_DEF>;
96
- toJsonString(): string;
97
- toHttpResponse(): Response;
98
- hydrate(definedNiceError: NiceErrorDomain<ERR_DEF>): NiceErrorHydrated<ERR_DEF, ACTIVE_IDS>;
99
- /**
100
- * Iterates `cases` in order, finds the first whose domain matches this error
101
- * (via `is()`), optionally further filters by active ids, hydrates the error,
102
- * calls the handler, and returns `true`. Returns `false` if no case matched.
103
- *
104
- * Build cases with `forDomain` (any id in the domain) or `forIds` (specific
105
- * id subset). Handlers are invoked synchronously — any returned Promise is
106
- * not awaited. Use `handleWithAsync` when handlers are async.
107
- *
108
- * @example
109
- * ```ts
110
- * const handled = error.handleWith([
111
- * forIds(err_feature, ["not_found"], (h) => {
112
- * res.status(404).json({ missing: h.getContext("not_found").resource });
113
- * }),
114
- * forDomain(err_feature, (h) => {
115
- * matchFirst(h, {
116
- * forbidden: ({ userId }) => res.status(403).json({ userId }),
117
- * _: () => res.status(500).end(),
118
- * });
119
- * }),
120
- * forDomain(err_service, (h) => {
121
- * res.status(h.httpStatusCode).json({ error: h.message });
122
- * }),
123
- * ]);
124
- * if (!handled) next(error);
125
- * ```
126
- */
127
- handleWithSync<RD, R>(handlerInput: NiceErrorHandler<RD, R> | ReadonlyArray<NiceErrorHandler<RD, R>>, handlerOptions?: IHandleErrorOptions): R | RD | undefined;
128
- /**
129
- * Same matching logic as `handleWith`, but `await`s the handler's returned
130
- * Promise before resolving. Use this when your handlers perform async work
131
- * (database writes, HTTP calls, etc.).
132
- *
133
- * @example
134
- * ```ts
135
- * const handled = await error.handleWithAsync([
136
- * forDomain(err_payments, async (h) => {
137
- * await db.logFailedPayment(h);
138
- * await notifyOps(h.message);
139
- * }),
140
- * ]);
141
- * ```
142
- */
143
- handleWithAsync<RD, R>(handlerInput: NiceErrorHandler<RD, R> | ReadonlyArray<NiceErrorHandler<RD, R>>, handlerOptions?: IHandleErrorOptions): Promise<R | RD | undefined>;
144
- get isPacked(): boolean;
145
- pack(packType?: EErrorPackType): this;
146
- unpack(): this;
147
- }
148
- export {};
@@ -1,5 +0,0 @@
1
- export declare enum EContextSerializedState {
2
- serde_unset = "serde_unset",
3
- unhydrated = "unhydrated",
4
- hydrated = "hydrated"
5
- }
@@ -1,204 +0,0 @@
1
- import type { EErrorPackType } from "../utils/packError/packError.enums";
2
- import type { EContextSerializedState } from "./NiceError.enums";
3
- export interface IRegularErrorJsonObject extends Omit<Error, "stack"> {
4
- name: string;
5
- message: string;
6
- stack?: string | undefined;
7
- cause?: unknown;
8
- }
9
- export type JSONSerializableValue = string | number | boolean | null | {
10
- [key: string]: JSONSerializableValue;
11
- } | JSONSerializableValue[];
12
- interface ISerializationDefinition<C, D extends JSONSerializableValue> {
13
- toJsonSerializable: (context: C) => D;
14
- fromJsonSerializable: (obj: D) => C;
15
- }
16
- /** Describes the context attached to a single error id. */
17
- export interface INiceErrorContextDefinition<C, D extends JSONSerializableValue = JSONSerializableValue> {
18
- required?: boolean;
19
- serialization?: ISerializationDefinition<C, D>;
20
- }
21
- /**
22
- * A single entry in a NiceErrorDefined schema.
23
- * `C` is the context value type (defaults to `never` = no context).
24
- */
25
- export interface INiceErrorIdMetadata<C = never, D extends JSONSerializableValue = JSONSerializableValue> {
26
- context?: [C] extends [never] ? never : INiceErrorContextDefinition<C, D>;
27
- /** Static message string OR a function that receives the context value and returns a string. */
28
- message?: [C] extends [never] ? string : string | ((context: C) => string);
29
- httpStatusCode?: [C] extends [never] ? number : number | ((context: C) => number);
30
- }
31
- /** A record mapping error-id string keys to their metadata. */
32
- export type TNiceErrorSchema = Record<string, INiceErrorIdMetadata<any>>;
33
- /** Extracts the raw context value type `C` from a single schema entry. */
34
- export type TExtractContextType<M> = M extends INiceErrorIdMetadata<infer C> ? C : never;
35
- /**
36
- * Given a schema entry M, returns the context argument type expected by `fromId`:
37
- *
38
- * - `C = never` → `undefined` (no context field on this id)
39
- * - `C` defined, `required: true` → `C` (context is a required argument)
40
- * - `C` defined, `required` absent/false → `C | undefined` (context is optional)
41
- *
42
- * Note: `required: true` must be a literal `true` for TypeScript to narrow correctly.
43
- * Use the `err()` helper (which preserves literal types) rather than writing schema
44
- * entries inline without `as const`.
45
- */
46
- export type ExtractFromIdContextArg<M> = M extends INiceErrorIdMetadata<infer C> ? [C] extends [never] ? undefined : M extends {
47
- context: {
48
- required: true;
49
- };
50
- } ? C : C | undefined : undefined;
51
- /**
52
- * No custom serializer is defined for this error id's context.
53
- * `value` holds the typed context directly (plain JSON-safe value, or `undefined`
54
- * if the context was optional and not provided).
55
- *
56
- * This state is safe across a JSON round-trip because no type information is lost.
57
- */
58
- export type TContextStateNoSerialization<C> = {
59
- kind: EContextSerializedState.serde_unset;
60
- /** The typed context value (or `undefined` if optional and not provided). */
61
- value: C | undefined;
62
- };
63
- /**
64
- * A custom serializer is defined, but the context has **not** been deserialized
65
- * from its JSON-wire form yet.
66
- *
67
- * This state occurs after `castNiceError` reconstructs an error from a serialized
68
- * payload. `value` is absent — the raw serialized representation is in `serialized`.
69
- *
70
- * Call `niceErrorDefined.hydrate(error)` to reconstruct the typed context via
71
- * `fromJsonSerializable` and advance to the `"hydrated"` state.
72
- */
73
- export type TContextStateUnhydrated = {
74
- kind: EContextSerializedState.unhydrated;
75
- /** The JSON-serializable representation of the original context. */
76
- serialized: JSONSerializableValue;
77
- };
78
- /**
79
- * A custom serializer is defined, and the context is fully deserialized to its
80
- * original typed value.
81
- *
82
- * This state is set when the error is first created via `fromId`/`fromContext`,
83
- * or after `niceErrorDefined.hydrate(error)` reconstructs it.
84
- *
85
- * Note: `toJsonObject()` intentionally downgrades this to `"unhydrated"` on
86
- * output so the flag cannot survive a JSON round-trip as a false positive.
87
- */
88
- export type TContextStateHydrated<C> = {
89
- kind: EContextSerializedState.hydrated;
90
- /** The typed context value — the original value as provided at error creation. */
91
- value: C;
92
- /** The JSON-serializable representation (produced by `toJsonSerializable`). */
93
- serialized: JSONSerializableValue;
94
- };
95
- /**
96
- * Runtime context state — union of all three lifecycle states.
97
- * Stored in `_errorDataMap` on a live `NiceError` instance.
98
- */
99
- export type TContextState<C> = TContextStateNoSerialization<C> | TContextStateUnhydrated | TContextStateHydrated<C>;
100
- /**
101
- * Wire-safe context state — excludes `"hydrated"` because `toJsonObject()` downgrades
102
- * it to `"unhydrated"` before serialization. This is the only state that appears in
103
- * `INiceErrorJsonObject` and on errors reconstructed via `castNiceError`.
104
- */
105
- export type TSerializedContextState<C> = TContextStateNoSerialization<C> | TContextStateUnhydrated;
106
- /**
107
- * Runtime reconciled data for a single error id, stored in `_errorDataMap`.
108
- * Uses the full `TContextState` union (including `"hydrated"`).
109
- */
110
- export type TErrorReconciledData<SCHEMA extends TNiceErrorSchema, K extends keyof SCHEMA> = {
111
- contextState: TContextState<TExtractContextType<SCHEMA[K]>>;
112
- message: string;
113
- httpStatusCode: number;
114
- timeAdded: number;
115
- };
116
- /**
117
- * Wire-safe reconciled data — uses `TSerializedContextState` (no `"hydrated"`).
118
- * This is the shape stored in `INiceErrorJsonObject.errorData` and transmitted
119
- * over the wire. `"hydrated"` is excluded so that the serialization state can
120
- * never be trusted after a JSON round-trip.
121
- */
122
- export type TSerializedErrorReconciledData<SCHEMA extends TNiceErrorSchema, K extends TSchemaNiceErrorId<SCHEMA>> = {
123
- contextState: TSerializedContextState<TExtractContextType<SCHEMA[K]>>;
124
- message: string;
125
- httpStatusCode: number;
126
- timeAdded: number;
127
- };
128
- export type TErrorDataForIdMap<SCHEMA extends TNiceErrorSchema, K extends TSchemaNiceErrorId<SCHEMA> = TSchemaNiceErrorId<SCHEMA>> = {
129
- [key in K]?: TErrorReconciledData<SCHEMA, K>;
130
- };
131
- /** Wire-safe version of `TErrorDataForIdMap`. Used in `INiceErrorJsonObject`. */
132
- export type TSerializedErrorDataMap<SCHEMA extends TNiceErrorSchema> = {
133
- [K in TSchemaNiceErrorId<SCHEMA>]?: TSerializedErrorReconciledData<SCHEMA, K>;
134
- };
135
- /**
136
- * The Partial record that `fromContext` accepts: callers supply one or more
137
- * { [errorId]: contextValue } entries and NiceError stores them all.
138
- */
139
- export type TFromContextInput<SCHEMA extends TNiceErrorSchema> = {
140
- [K in TSchemaNiceErrorId<SCHEMA>]?: TExtractContextType<SCHEMA[K]> | undefined;
141
- };
142
- /**
143
- * Resolves the args tuple for `fromId` / `addId`:
144
- *
145
- * - No context on this id → `[id]`
146
- * - Context defined, `required: true` → `[id, context]`
147
- * - Context defined, `required` absent/false → `[id] | [id, context]`
148
- */
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]>];
150
- export interface IPackErrorAs_Base {
151
- packAs: EErrorPackType;
152
- }
153
- export interface IPackErrorAs_MatchEnvVar extends IPackErrorAs_Base {
154
- matchEnvVar: string;
155
- }
156
- export interface IDefineNewNiceErrorDomainOptions<ERR_DOMAIN extends string = string, SCHEMA extends TNiceErrorSchema = TNiceErrorSchema> {
157
- defaultHttpStatusCode?: number;
158
- defaultMessage?: string;
159
- packAs?: () => EErrorPackType | void;
160
- domain: ERR_DOMAIN;
161
- schema: SCHEMA;
162
- }
163
- export interface INiceErrorDomainProps<ERR_DOMAINS extends string[] = string[], SCHEMA extends TNiceErrorSchema = TNiceErrorSchema> {
164
- packAs?: () => EErrorPackType | void;
165
- defaultHttpStatusCode?: number;
166
- defaultMessage?: string;
167
- domain: ERR_DOMAINS[number];
168
- allDomains: ERR_DOMAINS;
169
- schema: SCHEMA;
170
- }
171
- export interface INiceErrorJsonObject<ERR_DEF extends INiceErrorDomainProps = INiceErrorDomainProps, ID extends TDomainNiceErrorId<ERR_DEF> = TDomainNiceErrorId<ERR_DEF>> {
172
- name: "NiceError";
173
- def: Omit<ERR_DEF, "schema">;
174
- ids: ID[];
175
- /** Wire-safe error data — context is in `"raw_unset"` or `"unhydrated"` state only. */
176
- errorData: TSerializedErrorDataMap<ERR_DEF["schema"]>;
177
- wasntNice: boolean;
178
- message: string;
179
- httpStatusCode: number;
180
- /** The stack trace of the NiceError at the point it was created. */
181
- stack?: string;
182
- cause?: unknown;
183
- originError?: IRegularErrorJsonObject | undefined;
184
- timeCreated: number;
185
- }
186
- export type TSchemaNiceErrorId<SCHEMA extends TNiceErrorSchema> = keyof SCHEMA & string;
187
- export type TDomainNiceErrorId<ERR_DEF extends INiceErrorDomainProps> = TSchemaNiceErrorId<ERR_DEF["schema"]>;
188
- /**
189
- * The widest ERR_DEF used when creating a NiceError without a definition
190
- * (bare construction, castNiceError, etc.).
191
- *
192
- * Uses the base `INiceErrorDefinedProps` defaults (`string[]` domains,
193
- * `TNiceErrorSchema` schema) so that type-guard narrowing via `is()` works
194
- * correctly — `string & "specific_domain"` narrows to `"specific_domain"`
195
- * instead of collapsing the intersection to `never`.
196
- */
197
- export type TUnknownNiceErrorDef = INiceErrorDomainProps;
198
- /**
199
- * Wide id type for bare / cast NiceErrors that have no schema.
200
- * Using `string` (rather than a literal `"unknown"`) ensures that
201
- * `is()` type-guard intersections narrow cleanly: `string & K` = `K`.
202
- */
203
- export type TUnknownNiceErrorId = string;
204
- export {};