first commit
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
# codes
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
## Purpose
|
||||
|
||||
Defines the stable, namespaced error-code registry for `@suaveplan/crypto-utils`. Every error thrown by this package carries a code from this registry, which lets callers type-narrow on `error.code` rather than relying on string matching against message text.
|
||||
|
||||
## Features
|
||||
|
||||
- Single `defineCodes` call produces a frozen, read-only map of codes under the `CRYPTO.UTILS` namespace
|
||||
- Codes are plain string literals (`"CRYPTO.UTILS.PRIMITIVE_NOT_IMPLEMENTED"`, etc.) — safe to log, serialize, and compare across process boundaries
|
||||
- `CryptoUtilsCode` union type keeps downstream `catch` blocks fully typed without any runtime cost
|
||||
- Covers the full error surface of the package: encoding validation, byte-length mismatches, integer-range checks, Merkle-tree errors, RNG limits, and the primitive-not-implemented sentinel
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { CRYPTO_UTILS_CODES, type CryptoUtilsCode } from "@suaveplan/crypto-utils/errors/codes";
|
||||
|
||||
function handleError(code: CryptoUtilsCode): string {
|
||||
switch (code) {
|
||||
case CRYPTO_UTILS_CODES.ENCODING_INVALID_INPUT:
|
||||
return "The supplied string is not valid for the chosen encoding.";
|
||||
case CRYPTO_UTILS_CODES.PRIMITIVE_NOT_IMPLEMENTED:
|
||||
return "This cryptographic primitive has no native implementation yet.";
|
||||
default:
|
||||
return "Unknown crypto-utils error.";
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
Type-narrowing in a catch block using the `CryptoUtilsCode` union:
|
||||
|
||||
```ts
|
||||
import { CRYPTO_UTILS_CODES, type CryptoUtilsCode } from "@suaveplan/crypto-utils/errors/codes";
|
||||
import { CryptoUtilsError } from "@suaveplan/crypto-utils/errors/crypto-utils-error";
|
||||
|
||||
async function safeHex(input: string): Promise<Uint8Array | null> {
|
||||
try {
|
||||
const { hexToBytes } = await import("@suaveplan/crypto-utils/encoding/hex/hex");
|
||||
return hexToBytes(input);
|
||||
} catch (err) {
|
||||
if (err instanceof CryptoUtilsError) {
|
||||
const code: CryptoUtilsCode = err.code;
|
||||
if (code === CRYPTO_UTILS_CODES.ENCODING_INVALID_INPUT) {
|
||||
console.warn("Bad hex input, returning null:", err.message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `CRYPTO_UTILS_CODES`
|
||||
|
||||
```ts
|
||||
const CRYPTO_UTILS_CODES: {
|
||||
readonly PRIMITIVE_NOT_IMPLEMENTED: "CRYPTO.UTILS.PRIMITIVE_NOT_IMPLEMENTED";
|
||||
readonly ENCODING_INVALID_INPUT: "CRYPTO.UTILS.ENCODING.INVALID_INPUT";
|
||||
readonly BYTES_LENGTH_MISMATCH: "CRYPTO.UTILS.BYTES.LENGTH_MISMATCH";
|
||||
readonly BYTES_INVALID_LENGTH: "CRYPTO.UTILS.BYTES.INVALID_LENGTH";
|
||||
readonly INTEGER_OUT_OF_RANGE: "CRYPTO.UTILS.INTEGER.OUT_OF_RANGE";
|
||||
readonly MERKLE_EMPTY_LEAVES: "CRYPTO.UTILS.MERKLE.EMPTY_LEAVES";
|
||||
readonly MERKLE_INVALID_PROOF: "CRYPTO.UTILS.MERKLE.INVALID_PROOF";
|
||||
readonly RNG_INVALID_LENGTH: "CRYPTO.UTILS.RNG.INVALID_LENGTH";
|
||||
};
|
||||
```
|
||||
|
||||
Frozen registry produced by `defineCodes("CRYPTO.UTILS", [...])`. Dot-separated sub-namespaces (`ENCODING.INVALID_INPUT`, `BYTES.LENGTH_MISMATCH`, etc.) become underscore-keyed properties on the returned object.
|
||||
|
||||
**Returns** — A read-only record whose values are opaque string literals suitable for stable logging and wire serialization.
|
||||
|
||||
---
|
||||
|
||||
### `CryptoUtilsCode`
|
||||
|
||||
```ts
|
||||
type CryptoUtilsCode = (typeof CRYPTO_UTILS_CODES)[keyof typeof CRYPTO_UTILS_CODES];
|
||||
```
|
||||
|
||||
Union of every string literal in `CRYPTO_UTILS_CODES`. Use this as the `code` parameter type in `catch` blocks or error-handler signatures to stay fully typed without importing the entire error object.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
`defineCodes` (from `@suaveplan/error`) is the single source of truth for code formatting: it prepends the namespace, freezes the resulting object, and guarantees that each value is a unique string. This file owns no logic — it is a pure declaration layer.
|
||||
|
||||
The dot-notation in the raw array entries (`"ENCODING.INVALID_INPUT"`) is a human-readable convention for grouping related codes within the namespace; the resulting object key uses the underscore-separated form (`ENCODING_INVALID_INPUT`). Consumers should always reference `CRYPTO_UTILS_CODES.*` constants rather than the raw string literals so that renames are caught at compile time.
|
||||
|
||||
Adding a new code requires only appending a string to the `as const` array in this file and optionally adding a new subclass to the `errors/` directory. No numeric IDs, no registry migrations.
|
||||
Reference in New Issue
Block a user