@qlever-llc/result 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@qlever-llc/result",
3
+ "version": "0.6.0",
4
+ "description": "Class-based Result and AsyncResult types for Trellis TypeScript applications.",
5
+ "homepage": "https://github.com/Qlever-LLC/trellis#readme",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/Qlever-LLC/trellis"
9
+ },
10
+ "license": "Apache-2.0",
11
+ "bugs": {
12
+ "url": "https://github.com/Qlever-LLC/trellis/issues"
13
+ },
14
+ "main": "./script/mod.js",
15
+ "module": "./esm/mod.js",
16
+ "exports": {
17
+ ".": {
18
+ "import": "./esm/mod.js",
19
+ "require": "./script/mod.js"
20
+ }
21
+ },
22
+ "publishConfig": {
23
+ "access": "public"
24
+ },
25
+ "dependencies": {
26
+ "typebox": "^1.0.15",
27
+ "ulid": "^3.0.1"
28
+ },
29
+ "devDependencies": {
30
+ "@types/node": "^20.9.0"
31
+ },
32
+ "_generatedBy": "dnt@dev"
33
+ }
@@ -0,0 +1,7 @@
1
+ declare global {
2
+ interface Error {
3
+ cause?: unknown;
4
+ }
5
+ }
6
+ export {};
7
+ //# sourceMappingURL=_dnt.polyfills.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_dnt.polyfills.d.ts","sourceRoot":"","sources":["../src/_dnt.polyfills.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,KAAK;QACb,KAAK,CAAC,EAAE,OAAO,CAAC;KACjB;CACF;AAED,OAAO,EAAE,CAAC"}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Base error types for use with Result<T, E>
3
+ * @module error
4
+ */
5
+ import Type, { type Static } from "typebox";
6
+ /**
7
+ * Base error serialization schema.
8
+ * All errors serialize to this structure with optional additional fields.
9
+ */
10
+ export declare const BaseErrorSchema: Type.TObject<{
11
+ id: Type.TString;
12
+ type: Type.TString;
13
+ message: Type.TString;
14
+ context: Type.TOptional<Type.TRecord<"^.*$", Type.TUnknown>>;
15
+ traceId: Type.TOptional<Type.TString>;
16
+ }>;
17
+ export type BaseErrorSchema = Static<typeof BaseErrorSchema>;
18
+ export type BaseErrorOptions = ErrorOptions & {
19
+ context?: Record<string, unknown>;
20
+ id?: string;
21
+ traceId?: string;
22
+ };
23
+ /**
24
+ * Base class for all errors used in Result<T, E>.
25
+ * @template TData - The serialized data type for this error
26
+ */
27
+ export declare abstract class BaseError<TData extends BaseErrorSchema = BaseErrorSchema> extends Error {
28
+ #private;
29
+ /**
30
+ * Optional callback to provide a trace ID from ambient context (e.g. OpenTelemetry).
31
+ *
32
+ * Trellis (or other consumers) can set this once at startup so all BaseError
33
+ * instances capture a traceId automatically unless explicitly provided.
34
+ */
35
+ static traceIdGetter: (() => string | undefined) | undefined;
36
+ /** Unique identifier for this error instance */
37
+ readonly id: string;
38
+ /** Error type name (used for discrimination) */
39
+ abstract readonly name: string;
40
+ constructor(message: string, options?: BaseErrorOptions);
41
+ /**
42
+ * Add contextual information to this error.
43
+ * Useful for adding runtime context like request IDs, user IDs, etc.
44
+ *
45
+ * @param context - Key-value pairs to add to the error context
46
+ * @returns This error instance for chaining
47
+ *
48
+ * @example
49
+ * ```typescript
50
+ * const error = new UnauthorizedError({ reason: "Invalid token" })
51
+ * .withContext({ userId: "123", requestId: "req-456" });
52
+ * ```
53
+ */
54
+ withContext(context?: Record<string, unknown>): this;
55
+ /**
56
+ * Get the current context object.
57
+ * @returns The context object
58
+ */
59
+ getContext(): Record<string, unknown>;
60
+ /**
61
+ * Get the trace ID for this error.
62
+ * Returns the trace ID captured at error creation time.
63
+ *
64
+ * @returns The trace ID string or undefined
65
+ */
66
+ protected getTraceId(): string | undefined;
67
+ /**
68
+ * Helper method to get base serializable fields.
69
+ * Subclasses should use this to build their complete serializable object.
70
+ *
71
+ * @returns Base error fields (id, type, message, context, traceId)
72
+ */
73
+ protected baseSerializable(): BaseErrorSchema;
74
+ /**
75
+ * Serializes error to a plain object.
76
+ * Subclasses must implement this to return their specific data type.
77
+ *
78
+ * @returns Plain object representation of the error
79
+ */
80
+ abstract toSerializable(): TData;
81
+ /**
82
+ * Serializes error to JSON string.
83
+ *
84
+ * @returns JSON string representation of the error
85
+ */
86
+ toJSON(): string;
87
+ }
88
+ /**
89
+ * Schema for UnexpectedError serialization.
90
+ */
91
+ export declare const UnexpectedErrorDataSchema: Type.TObject<{
92
+ id: Type.TString;
93
+ type: Type.TLiteral<"UnexpectedError">;
94
+ message: Type.TString;
95
+ context: Type.TOptional<Type.TRecord<"^.*$", Type.TUnknown>>;
96
+ traceId: Type.TOptional<Type.TString>;
97
+ }>;
98
+ export type UnexpectedErrorData = Static<typeof UnexpectedErrorDataSchema>;
99
+ /**
100
+ * Represents an unexpected error.
101
+ * Use this for wrapping unknown errors or for truly unexpected conditions.
102
+ */
103
+ export declare class UnexpectedError extends BaseError<UnexpectedErrorData> {
104
+ readonly name: "UnexpectedError";
105
+ constructor(options?: BaseErrorOptions);
106
+ /**
107
+ * Serializes error to a plain object.
108
+ *
109
+ * @returns Plain object representation of the error
110
+ */
111
+ toSerializable(): UnexpectedErrorData;
112
+ }
113
+ //# sourceMappingURL=error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,IAAI,EAAE,EAAE,KAAK,MAAM,EAAE,MAAM,SAAS,CAAC;AAE5C;;;GAGG;AACH,eAAO,MAAM,eAAe;;;;;;EAM1B,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,OAAO,eAAe,CAAC,CAAC;AAE7D,MAAM,MAAM,gBAAgB,GAAG,YAAY,GAAG;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,EAAE,CAAC,EAAE,MAAM,CAAC;IAKZ,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;GAGG;AACH,8BAAsB,SAAS,CAC7B,KAAK,SAAS,eAAe,GAAG,eAAe,CAC/C,SAAQ,KAAK;;IACb;;;;;OAKG;IACH,MAAM,CAAC,aAAa,EAAE,CAAC,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC;IAE7D,gDAAgD;IAChD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAEpB,gDAAgD;IAChD,kBAA2B,IAAI,EAAE,MAAM,CAAC;gBAQ5B,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB;IAcvD;;;;;;;;;;;;OAYG;IACH,WAAW,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAOpD;;;OAGG;IACH,UAAU,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAIrC;;;;;OAKG;IACH,SAAS,CAAC,UAAU,IAAI,MAAM,GAAG,SAAS;IAI1C;;;;;OAKG;IACH,SAAS,CAAC,gBAAgB,IAAI,eAAe;IAW7C;;;;;OAKG;IACH,QAAQ,CAAC,cAAc,IAAI,KAAK;IAEhC;;;;OAIG;IACH,MAAM,IAAI,MAAM;CAGjB;AAED;;GAEG;AACH,eAAO,MAAM,yBAAyB;;;;;;EAMpC,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,MAAM,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAE3E;;;GAGG;AACH,qBAAa,eAAgB,SAAQ,SAAS,CAAC,mBAAmB,CAAC;IACjE,SAAkB,IAAI,oBAA8B;gBAExC,OAAO,CAAC,EAAE,gBAAgB;IAiBtC;;;;OAIG;IACM,cAAc,IAAI,mBAAmB;CAG/C"}
@@ -0,0 +1,171 @@
1
+ "use strict";
2
+ /**
3
+ * Base error types for use with Result<T, E>
4
+ * @module error
5
+ */
6
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
7
+ if (kind === "m") throw new TypeError("Private method is not writable");
8
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
9
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
10
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
11
+ };
12
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
13
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
14
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
15
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
16
+ };
17
+ var __importDefault = (this && this.__importDefault) || function (mod) {
18
+ return (mod && mod.__esModule) ? mod : { "default": mod };
19
+ };
20
+ var _BaseError_context, _BaseError_traceId;
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.UnexpectedError = exports.UnexpectedErrorDataSchema = exports.BaseError = exports.BaseErrorSchema = void 0;
23
+ const ulid_1 = require("ulid");
24
+ const typebox_1 = __importDefault(require("typebox"));
25
+ /**
26
+ * Base error serialization schema.
27
+ * All errors serialize to this structure with optional additional fields.
28
+ */
29
+ exports.BaseErrorSchema = typebox_1.default.Object({
30
+ id: typebox_1.default.String(),
31
+ type: typebox_1.default.String(),
32
+ message: typebox_1.default.String(),
33
+ context: typebox_1.default.Optional(typebox_1.default.Record(typebox_1.default.String(), typebox_1.default.Unknown())),
34
+ traceId: typebox_1.default.Optional(typebox_1.default.String()),
35
+ });
36
+ /**
37
+ * Base class for all errors used in Result<T, E>.
38
+ * @template TData - The serialized data type for this error
39
+ */
40
+ class BaseError extends Error {
41
+ constructor(message, options) {
42
+ const { context, id, traceId, ...errorOptions } = options ?? {};
43
+ super(message, errorOptions);
44
+ /** Unique identifier for this error instance */
45
+ Object.defineProperty(this, "id", {
46
+ enumerable: true,
47
+ configurable: true,
48
+ writable: true,
49
+ value: void 0
50
+ });
51
+ /** Runtime contextual information */
52
+ _BaseError_context.set(this, void 0);
53
+ /** Trace ID captured at error creation time */
54
+ _BaseError_traceId.set(this, void 0);
55
+ this.id = id ?? (0, ulid_1.ulid)();
56
+ __classPrivateFieldSet(this, _BaseError_context, context ?? {}, "f");
57
+ __classPrivateFieldSet(this, _BaseError_traceId, traceId ?? BaseError.traceIdGetter?.(), "f");
58
+ Object.setPrototypeOf(this, new.target.prototype);
59
+ if (Error.captureStackTrace) {
60
+ Error.captureStackTrace(this, this.constructor);
61
+ }
62
+ }
63
+ /**
64
+ * Add contextual information to this error.
65
+ * Useful for adding runtime context like request IDs, user IDs, etc.
66
+ *
67
+ * @param context - Key-value pairs to add to the error context
68
+ * @returns This error instance for chaining
69
+ *
70
+ * @example
71
+ * ```typescript
72
+ * const error = new UnauthorizedError({ reason: "Invalid token" })
73
+ * .withContext({ userId: "123", requestId: "req-456" });
74
+ * ```
75
+ */
76
+ withContext(context) {
77
+ if (context) {
78
+ Object.assign(__classPrivateFieldGet(this, _BaseError_context, "f"), context);
79
+ }
80
+ return this;
81
+ }
82
+ /**
83
+ * Get the current context object.
84
+ * @returns The context object
85
+ */
86
+ getContext() {
87
+ return __classPrivateFieldGet(this, _BaseError_context, "f");
88
+ }
89
+ /**
90
+ * Get the trace ID for this error.
91
+ * Returns the trace ID captured at error creation time.
92
+ *
93
+ * @returns The trace ID string or undefined
94
+ */
95
+ getTraceId() {
96
+ return __classPrivateFieldGet(this, _BaseError_traceId, "f");
97
+ }
98
+ /**
99
+ * Helper method to get base serializable fields.
100
+ * Subclasses should use this to build their complete serializable object.
101
+ *
102
+ * @returns Base error fields (id, type, message, context, traceId)
103
+ */
104
+ baseSerializable() {
105
+ const traceId = this.getTraceId();
106
+ return {
107
+ id: this.id,
108
+ type: this.name,
109
+ message: this.message,
110
+ context: __classPrivateFieldGet(this, _BaseError_context, "f"),
111
+ ...(traceId !== undefined && { traceId }),
112
+ };
113
+ }
114
+ /**
115
+ * Serializes error to JSON string.
116
+ *
117
+ * @returns JSON string representation of the error
118
+ */
119
+ toJSON() {
120
+ return JSON.stringify(this.toSerializable());
121
+ }
122
+ }
123
+ exports.BaseError = BaseError;
124
+ _BaseError_context = new WeakMap(), _BaseError_traceId = new WeakMap();
125
+ /**
126
+ * Schema for UnexpectedError serialization.
127
+ */
128
+ exports.UnexpectedErrorDataSchema = typebox_1.default.Object({
129
+ id: typebox_1.default.String(),
130
+ type: typebox_1.default.Literal("UnexpectedError"),
131
+ message: typebox_1.default.String(),
132
+ context: typebox_1.default.Optional(typebox_1.default.Record(typebox_1.default.String(), typebox_1.default.Unknown())),
133
+ traceId: typebox_1.default.Optional(typebox_1.default.String()),
134
+ });
135
+ /**
136
+ * Represents an unexpected error.
137
+ * Use this for wrapping unknown errors or for truly unexpected conditions.
138
+ */
139
+ class UnexpectedError extends BaseError {
140
+ constructor(options) {
141
+ super("An unexpected error has occurred", options);
142
+ Object.defineProperty(this, "name", {
143
+ enumerable: true,
144
+ configurable: true,
145
+ writable: true,
146
+ value: "UnexpectedError"
147
+ });
148
+ if (options?.cause) {
149
+ let root = options.cause;
150
+ while (root instanceof Error && root.cause) {
151
+ root = root.cause;
152
+ }
153
+ const causeMessage = root instanceof Error
154
+ ? root.message
155
+ : typeof root === "object"
156
+ ? JSON.stringify(root)
157
+ : String(root);
158
+ const causeStack = root instanceof Error ? root.stack : undefined;
159
+ this.withContext({ causeMessage, causeStack });
160
+ }
161
+ }
162
+ /**
163
+ * Serializes error to a plain object.
164
+ *
165
+ * @returns Plain object representation of the error
166
+ */
167
+ toSerializable() {
168
+ return this.baseSerializable();
169
+ }
170
+ }
171
+ exports.UnexpectedError = UnexpectedError;
@@ -0,0 +1,62 @@
1
+ /**
2
+ * @qlever-llc/result - Class-based Result type for TypeScript/Deno
3
+ *
4
+ * A class-based Result<T, E> system inspired by Rust's Result type,
5
+ * providing elegant error handling with method chaining and the `take()`
6
+ * pattern for early returns.
7
+ *
8
+ * This library provides two main classes:
9
+ * - `Result<T, E>`: Synchronous result type with method chaining
10
+ * - `AsyncResult<T, E>`: Asynchronous result type that implements PromiseLike
11
+ *
12
+ * @example Basic usage with static methods
13
+ * ```typescript
14
+ * import { Result } from "@qlever-llc/result";
15
+ *
16
+ * function divide(a: number, b: number): Result<number, ValidationError> {
17
+ * if (b === 0) {
18
+ * return Result.err(new ValidationError("Division by zero"));
19
+ * }
20
+ * return Result.ok(a / b);
21
+ * }
22
+ *
23
+ * const result = divide(10, 2)
24
+ * .map(x => x * 2)
25
+ * .map(x => x + 1);
26
+ *
27
+ * const value = result.take();
28
+ * if (Result.isErr(value)) return value;
29
+ * console.log(value); // 11
30
+ * ```
31
+ *
32
+ * @example Async operations
33
+ * ```typescript
34
+ * import { AsyncResult, Result } from "@qlever-llc/result";
35
+ *
36
+ * const user = AsyncResult.try(async () => {
37
+ * const response = await fetch(`/api/users/123`);
38
+ * return await response.json();
39
+ * });
40
+ *
41
+ * const result = user
42
+ * .map(user => user.name)
43
+ * .map(name => name.toUpperCase());
44
+ *
45
+ * const value = await result.take();
46
+ * if (Result.isErr(value)) return value;
47
+ * console.log(value); // "ALICE"
48
+ * ```
49
+ *
50
+ * @module
51
+ */
52
+ import "./_dnt.polyfills.js";
53
+ import { Result as ResultClass } from "./result.js";
54
+ export { Result, AsyncResult } from "./result.js";
55
+ export type { OkValue, ErrValue, Infer, InferErr, MaybeAsync } from "./result.js";
56
+ export declare const ok: typeof ResultClass.ok;
57
+ export declare const err: typeof ResultClass.err;
58
+ export declare const isOk: typeof ResultClass.isOk;
59
+ export declare const isErr: typeof ResultClass.isErr;
60
+ export { BaseError, UnexpectedError, UnexpectedErrorDataSchema, } from "./error.js";
61
+ export type { BaseErrorSchema, BaseErrorOptions } from "./error.js";
62
+ //# sourceMappingURL=mod.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../src/mod.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AACH,OAAO,qBAAqB,CAAC;AAG7B,OAAO,EAAE,MAAM,IAAI,WAAW,EAAE,MAAM,aAAa,CAAC;AAEpD,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAClD,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAElF,eAAO,MAAM,EAAE,uBAAiB,CAAC;AACjC,eAAO,MAAM,GAAG,wBAAkB,CAAC;AACnC,eAAO,MAAM,IAAI,yBAAmB,CAAC;AACrC,eAAO,MAAM,KAAK,0BAAoB,CAAC;AAEvC,OAAO,EACL,SAAS,EACT,eAAe,EACf,yBAAyB,GAC1B,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC"}
package/script/mod.js ADDED
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UnexpectedErrorDataSchema = exports.UnexpectedError = exports.BaseError = exports.isErr = exports.isOk = exports.err = exports.ok = exports.AsyncResult = exports.Result = void 0;
4
+ /**
5
+ * @qlever-llc/result - Class-based Result type for TypeScript/Deno
6
+ *
7
+ * A class-based Result<T, E> system inspired by Rust's Result type,
8
+ * providing elegant error handling with method chaining and the `take()`
9
+ * pattern for early returns.
10
+ *
11
+ * This library provides two main classes:
12
+ * - `Result<T, E>`: Synchronous result type with method chaining
13
+ * - `AsyncResult<T, E>`: Asynchronous result type that implements PromiseLike
14
+ *
15
+ * @example Basic usage with static methods
16
+ * ```typescript
17
+ * import { Result } from "@qlever-llc/result";
18
+ *
19
+ * function divide(a: number, b: number): Result<number, ValidationError> {
20
+ * if (b === 0) {
21
+ * return Result.err(new ValidationError("Division by zero"));
22
+ * }
23
+ * return Result.ok(a / b);
24
+ * }
25
+ *
26
+ * const result = divide(10, 2)
27
+ * .map(x => x * 2)
28
+ * .map(x => x + 1);
29
+ *
30
+ * const value = result.take();
31
+ * if (Result.isErr(value)) return value;
32
+ * console.log(value); // 11
33
+ * ```
34
+ *
35
+ * @example Async operations
36
+ * ```typescript
37
+ * import { AsyncResult, Result } from "@qlever-llc/result";
38
+ *
39
+ * const user = AsyncResult.try(async () => {
40
+ * const response = await fetch(`/api/users/123`);
41
+ * return await response.json();
42
+ * });
43
+ *
44
+ * const result = user
45
+ * .map(user => user.name)
46
+ * .map(name => name.toUpperCase());
47
+ *
48
+ * const value = await result.take();
49
+ * if (Result.isErr(value)) return value;
50
+ * console.log(value); // "ALICE"
51
+ * ```
52
+ *
53
+ * @module
54
+ */
55
+ require("./_dnt.polyfills.js");
56
+ const result_js_1 = require("./result.js");
57
+ var result_js_2 = require("./result.js");
58
+ Object.defineProperty(exports, "Result", { enumerable: true, get: function () { return result_js_2.Result; } });
59
+ Object.defineProperty(exports, "AsyncResult", { enumerable: true, get: function () { return result_js_2.AsyncResult; } });
60
+ exports.ok = result_js_1.Result.ok;
61
+ exports.err = result_js_1.Result.err;
62
+ exports.isOk = result_js_1.Result.isOk;
63
+ exports.isErr = result_js_1.Result.isErr;
64
+ var error_js_1 = require("./error.js");
65
+ Object.defineProperty(exports, "BaseError", { enumerable: true, get: function () { return error_js_1.BaseError; } });
66
+ Object.defineProperty(exports, "UnexpectedError", { enumerable: true, get: function () { return error_js_1.UnexpectedError; } });
67
+ Object.defineProperty(exports, "UnexpectedErrorDataSchema", { enumerable: true, get: function () { return error_js_1.UnexpectedErrorDataSchema; } });
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "commonjs"
3
+ }