@nice-code/error 0.0.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/build/index.js +2747 -0
- package/build/types/NiceError/NiceError.d.ts +141 -0
- package/build/types/NiceError/NiceError.enums.d.ts +5 -0
- package/build/types/NiceError/NiceError.types.d.ts +199 -0
- package/build/types/NiceError/NiceErrorHydrated.d.ts +49 -0
- package/build/types/NiceError/nice_error.static.d.ts +2 -0
- package/build/types/NiceErrorDefined/NiceErrorDefined.d.ts +135 -0
- package/build/types/NiceErrorDefined/defineNiceError.d.ts +7 -0
- package/build/types/NiceErrorDefined/err.d.ts +59 -0
- package/build/types/example/error_usage_example.d.ts +41 -0
- package/build/types/index.d.ts +16 -0
- package/build/types/internal/index.d.ts +1 -0
- package/build/types/internal/nice_core_errors.d.ts +44 -0
- package/build/types/test/helpers/nice_error_testing.static.d.ts +3 -0
- package/build/types/test/helpers/test_utils.d.ts +1 -0
- package/build/types/utils/castAndHydrate.d.ts +35 -0
- package/build/types/utils/castNiceError.d.ts +15 -0
- package/build/types/utils/handleWith.d.ts +49 -0
- package/build/types/utils/inspectPotentialError/inspectPotentialError.d.ts +2 -0
- package/build/types/utils/inspectPotentialError/inspectPotentialError.enums.d.ts +9 -0
- package/build/types/utils/inspectPotentialError/inspectPotentialError.types.d.ts +51 -0
- package/build/types/utils/isNiceErrorObject.d.ts +12 -0
- package/build/types/utils/isRegularErrorObject.d.ts +2 -0
- package/build/types/utils/jsErrorOrCastJsError.d.ts +1 -0
- package/build/types/utils/logger.d.ts +3 -0
- package/build/types/utils/matchFirst.d.ts +35 -0
- package/build/types/utils/packError/causePack.d.ts +2 -0
- package/build/types/utils/packError/msgPack.d.ts +2 -0
- package/build/types/utils/packError/packError.d.ts +3 -0
- package/build/types/utils/packError/packError.enums.d.ts +5 -0
- package/package.json +37 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { IInspectErrorResult_JsError, IInspectErrorResult_JsErrorObject, IInspectErrorResult_JsOther, IInspectErrorResult_Nullish, TInspectErrorResult_JsDataType } from "../utils/inspectPotentialError/inspectPotentialError.types";
|
|
2
|
+
export declare const err_nice: import("..").NiceErrorDefined<{
|
|
3
|
+
domain: "err_nice";
|
|
4
|
+
allDomains: ["err_nice"];
|
|
5
|
+
schema: {};
|
|
6
|
+
}>;
|
|
7
|
+
export declare enum EErrId_CastNotNice {
|
|
8
|
+
js_error = "native_error",
|
|
9
|
+
js_error_like_object = "js_error_like_object",
|
|
10
|
+
nullish_value = "nullish_value",
|
|
11
|
+
js_data_type = "js_data_type",
|
|
12
|
+
js_other = "js_other"
|
|
13
|
+
}
|
|
14
|
+
export declare const err_cast_not_nice: import("..").NiceErrorDefined<{
|
|
15
|
+
domain: string;
|
|
16
|
+
allDomains: [string, "err_nice"];
|
|
17
|
+
schema: {
|
|
18
|
+
native_error: import("..").INiceErrorIdMetadata<IInspectErrorResult_JsError, import("..").JSONSerializableValue> & {
|
|
19
|
+
context: {
|
|
20
|
+
required: true;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
js_error_like_object: import("..").INiceErrorIdMetadata<IInspectErrorResult_JsErrorObject, import("..").JSONSerializableValue> & {
|
|
24
|
+
context: {
|
|
25
|
+
required: true;
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
nullish_value: import("..").INiceErrorIdMetadata<IInspectErrorResult_Nullish, import("..").JSONSerializableValue> & {
|
|
29
|
+
context: {
|
|
30
|
+
required: true;
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
js_data_type: import("..").INiceErrorIdMetadata<TInspectErrorResult_JsDataType, import("..").JSONSerializableValue> & {
|
|
34
|
+
context: {
|
|
35
|
+
required: true;
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
js_other: import("..").INiceErrorIdMetadata<IInspectErrorResult_JsOther, import("..").JSONSerializableValue> & {
|
|
39
|
+
context: {
|
|
40
|
+
required: true;
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
}>;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { INiceErrorOptions } from "../../NiceError/NiceError";
|
|
2
|
+
import type { INiceErrorDefinedProps } from "../../NiceError/NiceError.types";
|
|
3
|
+
export declare const nice_error_test_options: INiceErrorOptions<INiceErrorDefinedProps, keyof INiceErrorDefinedProps["schema"]>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const isVal: <T>(input: unknown, val: T) => input is T;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { NiceError } from "../NiceError/NiceError";
|
|
2
|
+
import type { INiceErrorDefinedProps } from "../NiceError/NiceError.types";
|
|
3
|
+
import { NiceErrorHydrated } from "../NiceError/NiceErrorHydrated";
|
|
4
|
+
import type { NiceErrorDefined } from "../NiceErrorDefined/NiceErrorDefined";
|
|
5
|
+
/**
|
|
6
|
+
* Combines `castNiceError`, `is()`, and `hydrate()` in a single call — the
|
|
7
|
+
* idiomatic way to handle an unknown value arriving from a remote boundary
|
|
8
|
+
* (API response, message queue, IPC, etc.) when you have a specific domain in mind.
|
|
9
|
+
*
|
|
10
|
+
* - Casts `value` to a `NiceError` using `castNiceError`.
|
|
11
|
+
* - If the result belongs to `niceErrorDefined`'s domain (`is()` returns `true`),
|
|
12
|
+
* hydrates it and returns a fully-typed `NiceErrorHydrated`.
|
|
13
|
+
* - Otherwise returns the raw cast `NiceError` (which may be a `wasntNice` error
|
|
14
|
+
* if `value` was not a NiceError at all).
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* // In an Express error handler:
|
|
19
|
+
* app.use((err, req, res, next) => {
|
|
20
|
+
* const error = castAndHydrate(err, err_user_auth);
|
|
21
|
+
*
|
|
22
|
+
* if (err_user_auth.is(error)) {
|
|
23
|
+
* // error is NiceErrorHydrated — getContext / addId available
|
|
24
|
+
* const result = matchFirst(error, {
|
|
25
|
+
* invalid_credentials: ({ username }) => res.status(401).json({ username }),
|
|
26
|
+
* account_locked: () => res.status(403).json({ locked: true }),
|
|
27
|
+
* });
|
|
28
|
+
* if (result) return;
|
|
29
|
+
* }
|
|
30
|
+
*
|
|
31
|
+
* next(err);
|
|
32
|
+
* });
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export declare function castAndHydrate<ERR_DEF extends INiceErrorDefinedProps>(value: unknown, niceErrorDefined: NiceErrorDefined<ERR_DEF>): NiceErrorHydrated<ERR_DEF, keyof ERR_DEF["schema"] & string> | NiceError;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { NiceError } from "../NiceError/NiceError";
|
|
2
|
+
/**
|
|
3
|
+
* Casts any unknown value into a `NiceError`.
|
|
4
|
+
*
|
|
5
|
+
* - If the value is already a `NiceError` instance, it is returned as-is.
|
|
6
|
+
* - If the value is a plain `Error`, it is wrapped with the original as `originError`.
|
|
7
|
+
* - If the value is a JSON-serialised `NiceError` object (e.g. from an API
|
|
8
|
+
* response), a best-effort `NiceError` is re-created from it.
|
|
9
|
+
* - For all other values, a generic `NiceError` is created with a descriptive
|
|
10
|
+
* message.
|
|
11
|
+
*
|
|
12
|
+
* After casting, use `NiceErrorDefined.is(error)` to narrow the error to a
|
|
13
|
+
* specific domain and access its strongly-typed ids and context.
|
|
14
|
+
*/
|
|
15
|
+
export declare const castNiceError: (error: unknown) => NiceError;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { INiceErrorDefinedProps } from "../NiceError/NiceError.types";
|
|
2
|
+
import type { NiceErrorHydrated } from "../NiceError/NiceErrorHydrated";
|
|
3
|
+
import type { NiceErrorDefined } from "../NiceErrorDefined/NiceErrorDefined";
|
|
4
|
+
/**
|
|
5
|
+
* A single case in a `handleWith` / `handleWithAsync` call.
|
|
6
|
+
*
|
|
7
|
+
* Construct via `forDomain` or `forIds` — do not build this object directly.
|
|
8
|
+
*/
|
|
9
|
+
export interface IErrorCase<DEF extends INiceErrorDefinedProps, IDS extends keyof DEF["schema"] & string> {
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Builds a case that fires for any error whose domain exactly matches `domain`.
|
|
13
|
+
* The handler receives the fully-hydrated error, narrowed to all schema ids.
|
|
14
|
+
*
|
|
15
|
+
* Use with `error.handleWith([...])` (sync) or `error.handleWithAsync([...])` (async).
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* error.handleWith([
|
|
20
|
+
* forDomain(err_payments, (h) => {
|
|
21
|
+
* matchFirst(h, {
|
|
22
|
+
* payment_failed: ({ reason }) => res.status(402).json({ reason }),
|
|
23
|
+
* card_expired: () => res.status(402).json({ expired: true }),
|
|
24
|
+
* });
|
|
25
|
+
* }),
|
|
26
|
+
* ]);
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export declare function forDomain<DEF extends INiceErrorDefinedProps>(domain: NiceErrorDefined<DEF>, handler: (error: NiceErrorHydrated<DEF, keyof DEF["schema"] & string>) => void | Promise<void>): IErrorCase<DEF, keyof DEF["schema"] & string>;
|
|
30
|
+
/**
|
|
31
|
+
* Builds a case that fires only if the error's domain matches `domain` **and**
|
|
32
|
+
* at least one of `ids` is active on the error.
|
|
33
|
+
* The handler receives the fully-hydrated error, narrowed to `IDS[number]`.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```ts
|
|
37
|
+
* error.handleWith([
|
|
38
|
+
* forIds(err_feature, ["not_found", "forbidden"], (h) => {
|
|
39
|
+
* // h.getContext("not_found") and h.getContext("forbidden") are both available
|
|
40
|
+
* if (h.hasId("not_found")) res.status(404).json({ missing: h.getContext("not_found").resource });
|
|
41
|
+
* if (h.hasId("forbidden")) res.status(403).json({ denied: true });
|
|
42
|
+
* }),
|
|
43
|
+
*
|
|
44
|
+
* // Fallback: any other err_feature error
|
|
45
|
+
* forDomain(err_feature, (h) => res.status(500).json({ error: h.message })),
|
|
46
|
+
* ]);
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export declare function forIds<DEF extends INiceErrorDefinedProps, IDS extends ReadonlyArray<keyof DEF["schema"] & string>>(domain: NiceErrorDefined<DEF>, ids: IDS, handler: (error: NiceErrorHydrated<DEF, IDS[number]>) => void | Promise<void>): IErrorCase<DEF, IDS[number]>;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { NiceError } from "../../NiceError/NiceError";
|
|
2
|
+
import type { INiceErrorJsonObject, IRegularErrorJsonObject } from "../../NiceError/NiceError.types";
|
|
3
|
+
import type { EInspectErrorResultType } from "./inspectPotentialError.enums";
|
|
4
|
+
export interface IInspectErrorResult_Base<T extends EInspectErrorResultType> {
|
|
5
|
+
type: T;
|
|
6
|
+
}
|
|
7
|
+
export interface IInspectErrorResult_Nullish extends IInspectErrorResult_Base<EInspectErrorResultType.nullish> {
|
|
8
|
+
value: null | undefined;
|
|
9
|
+
}
|
|
10
|
+
export interface IInspectErrorResult_NiceErrorObject extends IInspectErrorResult_Base<EInspectErrorResultType.niceErrorObject> {
|
|
11
|
+
niceErrorObject: INiceErrorJsonObject;
|
|
12
|
+
}
|
|
13
|
+
export interface IInspectErrorResult_NiceError extends IInspectErrorResult_Base<EInspectErrorResultType.niceError> {
|
|
14
|
+
niceError: NiceError;
|
|
15
|
+
}
|
|
16
|
+
export interface IInspectErrorResult_JsError extends IInspectErrorResult_Base<EInspectErrorResultType.jsError> {
|
|
17
|
+
jsError: Error;
|
|
18
|
+
}
|
|
19
|
+
export interface IInspectErrorResult_JsErrorObject extends IInspectErrorResult_Base<EInspectErrorResultType.jsErrorObject> {
|
|
20
|
+
jsErrorObject: IRegularErrorJsonObject;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* JS DATA TYPES
|
|
24
|
+
*/
|
|
25
|
+
export interface IInspectErrorResult_JsDataType_String extends IInspectErrorResult_Base<EInspectErrorResultType.jsDataType> {
|
|
26
|
+
jsDataType: "string";
|
|
27
|
+
jsDataValue: string;
|
|
28
|
+
}
|
|
29
|
+
export interface IInspectErrorResult_JsDataType_Number extends IInspectErrorResult_Base<EInspectErrorResultType.jsDataType> {
|
|
30
|
+
jsDataType: "number";
|
|
31
|
+
jsDataValue: number;
|
|
32
|
+
}
|
|
33
|
+
export interface IInspectErrorResult_JsDataType_Boolean extends IInspectErrorResult_Base<EInspectErrorResultType.jsDataType> {
|
|
34
|
+
jsDataType: "boolean";
|
|
35
|
+
jsDataValue: boolean;
|
|
36
|
+
}
|
|
37
|
+
export interface IInspectErrorResult_JsDataType_Object extends IInspectErrorResult_Base<EInspectErrorResultType.jsDataType> {
|
|
38
|
+
jsDataType: "object";
|
|
39
|
+
jsDataValue: object;
|
|
40
|
+
}
|
|
41
|
+
export type TInspectErrorResult_JsDataType = IInspectErrorResult_JsDataType_String | IInspectErrorResult_JsDataType_Number | IInspectErrorResult_JsDataType_Boolean | IInspectErrorResult_JsDataType_Object;
|
|
42
|
+
/**
|
|
43
|
+
* Catch-all for any other JS data type that doesn't fit the above categories (e.g. symbol, bigint, function, etc.)
|
|
44
|
+
*/
|
|
45
|
+
export interface IInspectErrorResult_JsOther extends IInspectErrorResult_Base<EInspectErrorResultType.jsOther> {
|
|
46
|
+
jsDataValue: unknown;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Union of all possible results from inspectPotentialError
|
|
50
|
+
*/
|
|
51
|
+
export type TInspectErrorResult = IInspectErrorResult_Nullish | IInspectErrorResult_NiceErrorObject | IInspectErrorResult_NiceError | IInspectErrorResult_JsError | IInspectErrorResult_JsErrorObject | TInspectErrorResult_JsDataType | IInspectErrorResult_JsOther;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type INiceErrorJsonObject } from "../NiceError/NiceError.types";
|
|
2
|
+
/**
|
|
3
|
+
* Returns `true` if `obj` is a JSON-serialised `NiceError` object matching the
|
|
4
|
+
* current wire format (contextState-based errorData entries).
|
|
5
|
+
*
|
|
6
|
+
* Validates:
|
|
7
|
+
* - Top-level shape (`name`, `message`, `wasntNice`, `httpStatusCode`, `def`)
|
|
8
|
+
* - Each `errorData` entry has a `contextState` with a valid `kind` discriminant
|
|
9
|
+
* (`"no_serialization"` or `"unhydrated"`) — rejecting payloads in the old
|
|
10
|
+
* format (`context` / `serialized` fields) to prevent silent data corruption.
|
|
11
|
+
*/
|
|
12
|
+
export declare function isNiceErrorObject(obj: unknown): obj is INiceErrorJsonObject;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function jsErrorOrCastJsError(error: unknown, logMessage?: boolean): Error;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { NiceError } from "../NiceError/NiceError";
|
|
2
|
+
import type { INiceErrorDefinedProps, TExtractContextType } from "../NiceError/NiceError.types";
|
|
3
|
+
/**
|
|
4
|
+
* Handler map for `matchFirst`. Each key is an error id (from `ACTIVE_IDS`) and
|
|
5
|
+
* the value is a function that receives the typed context for that id.
|
|
6
|
+
*
|
|
7
|
+
* The `_` key is an optional fallback that runs when no id-specific handler matched.
|
|
8
|
+
*/
|
|
9
|
+
export type TMatchFirstHandlers<ERR_DEF extends INiceErrorDefinedProps, ACTIVE_IDS extends keyof ERR_DEF["schema"] & string, RESULT> = {
|
|
10
|
+
[K in ACTIVE_IDS]?: (context: TExtractContextType<ERR_DEF["schema"][K]>) => RESULT;
|
|
11
|
+
} & {
|
|
12
|
+
_?: () => RESULT;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Pattern-matches an error against a map of id → handler functions, returning the
|
|
16
|
+
* result of the first handler whose id is active on the error.
|
|
17
|
+
*
|
|
18
|
+
* - Ids are tested in the order returned by `error.getIds()`.
|
|
19
|
+
* - If no id-specific handler matched and `_` is provided, the fallback is called.
|
|
20
|
+
* - Returns `undefined` when neither any id handler nor the fallback fires.
|
|
21
|
+
*
|
|
22
|
+
* **Requires hydrated context.** If any matched id is in the `"unhydrated"` state,
|
|
23
|
+
* `getContext` will throw. Call `niceErrorDefined.hydrate(error)` beforehand when
|
|
24
|
+
* working with errors deserialized from a JSON payload.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```ts
|
|
28
|
+
* const result = matchFirst(error, {
|
|
29
|
+
* invalid_credentials: ({ username }) => `Wrong password for ${username}`,
|
|
30
|
+
* account_locked: () => "Account is locked",
|
|
31
|
+
* _: () => "Unknown auth error",
|
|
32
|
+
* });
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export declare function matchFirst<ERR_DEF extends INiceErrorDefinedProps, ACTIVE_IDS extends keyof ERR_DEF["schema"] & string, RESULT>(error: NiceError<ERR_DEF, ACTIVE_IDS>, handlers: TMatchFirstHandlers<ERR_DEF, ACTIVE_IDS, RESULT>): RESULT | undefined;
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nice-code/error",
|
|
3
|
+
"main": "build/index.js",
|
|
4
|
+
"module": "build/index.js",
|
|
5
|
+
"types": "build/types/index.d.ts",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"version": "0.0.15",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./build/types/index.d.ts",
|
|
11
|
+
"import": "./build/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"build",
|
|
16
|
+
"package.json",
|
|
17
|
+
"README.md"
|
|
18
|
+
],
|
|
19
|
+
"publishConfig": {
|
|
20
|
+
"access": "public"
|
|
21
|
+
},
|
|
22
|
+
"scripts": {
|
|
23
|
+
"type-check": "bunx tsc --noEmit",
|
|
24
|
+
"type-check-watch": "bunx tsc --noEmit --watch",
|
|
25
|
+
"vitest": "vitest --typecheck",
|
|
26
|
+
"vitest-agent": "vitest --typecheck --reporter=agent",
|
|
27
|
+
"clean-build": "bunx rimraf build",
|
|
28
|
+
"build": "bun run clean-build && bun run build.ts && bun run build-types",
|
|
29
|
+
"build-types": "tsc --project tsconfig.build.json",
|
|
30
|
+
"example": "bun run ./src/example/error_usage_example.ts"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"http-status-codes": "^2.3.0",
|
|
34
|
+
"valibot": "1.3.1",
|
|
35
|
+
"tslog": "^4.10.2"
|
|
36
|
+
}
|
|
37
|
+
}
|