@zipbul/result 0.1.6 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.ko.md CHANGED
@@ -112,12 +112,10 @@ import { err } from '@zipbul/result';
112
112
  // 데이터 없음 — 단순 신호
113
113
  const e1 = err();
114
114
  // e1.data → never (접근 불가)
115
- // e1.stack → 캡처된 스택 트레이스
116
115
 
117
116
  // 데이터 포함 — 에러 상세 정보 전달
118
117
  const e2 = err('not found');
119
118
  // e2.data → 'not found'
120
- // e2.stack → 캡처된 스택 트레이스
121
119
 
122
120
  // 풍부한 에러 객체
123
121
  const e3 = err({ code: 'TIMEOUT', retryAfter: 3000 });
@@ -129,7 +127,6 @@ const e3 = err({ code: 'TIMEOUT', retryAfter: 3000 });
129
127
  | 프로퍼티 | 타입 | 설명 |
130
128
  |:---------|:-----|:-----|
131
129
  | `data` | `E` | 첨부된 에러 데이터 |
132
- | `stack` | `string` | `err()` 호출 지점에서 캡처된 스택 트레이스 |
133
130
 
134
131
  > **불변성** — 모든 `Err`는 `Object.freeze()`됩니다. strict mode에서 프로퍼티를 수정하면 `TypeError`가 발생합니다.
135
132
 
@@ -198,7 +195,6 @@ type ApiResult = Result<User, { code: string; message: string }>;
198
195
 
199
196
  ```typescript
200
197
  type Err<E = never> = {
201
- stack: string;
202
198
  data: E;
203
199
  };
204
200
  ```
@@ -374,21 +370,6 @@ async function fetchUser(id: number): Promise<Result<User, ApiError>> {
374
370
  }
375
371
  ```
376
372
 
377
- ### 스택 트레이스
378
-
379
- 모든 `Err`는 생성 시점에 스택 트레이스를 캡처하여, `throw` 없이 디버깅이 가능합니다:
380
-
381
- ```typescript
382
- const e = err('something went wrong');
383
- console.log(e.stack);
384
- // Error
385
- // at err (/.../err.ts:22:18)
386
- // at validate (/.../validate.ts:15:12)
387
- // at handleRequest (/.../server.ts:8:20)
388
- ```
389
-
390
- <br>
391
-
392
373
  ## 🔌 프레임워크 연동 예시
393
374
 
394
375
  <details>
package/README.md CHANGED
@@ -112,12 +112,10 @@ import { err } from '@zipbul/result';
112
112
  // No data — simple signal
113
113
  const e1 = err();
114
114
  // e1.data → never (cannot access)
115
- // e1.stack → captured stack trace
116
115
 
117
116
  // With data — carry error details
118
117
  const e2 = err('not found');
119
118
  // e2.data → 'not found'
120
- // e2.stack → captured stack trace
121
119
 
122
120
  // Rich error objects
123
121
  const e3 = err({ code: 'TIMEOUT', retryAfter: 3000 });
@@ -129,7 +127,6 @@ Properties of the returned `Err`:
129
127
  | Property | Type | Description |
130
128
  |:---------|:-----|:------------|
131
129
  | `data` | `E` | The attached error data |
132
- | `stack` | `string` | Stack trace captured at `err()` call site |
133
130
 
134
131
  > **Immutability** — every `Err` is `Object.freeze()`d. Attempting to modify properties in strict mode throws a `TypeError`.
135
132
 
@@ -198,7 +195,6 @@ The error type returned by `err()`.
198
195
 
199
196
  ```typescript
200
197
  type Err<E = never> = {
201
- stack: string;
202
198
  data: E;
203
199
  };
204
200
  ```
@@ -374,21 +370,6 @@ async function fetchUser(id: number): Promise<Result<User, ApiError>> {
374
370
  }
375
371
  ```
376
372
 
377
- ### Stack traces
378
-
379
- Every `Err` captures a stack trace at creation time, enabling debugging without `throw`:
380
-
381
- ```typescript
382
- const e = err('something went wrong');
383
- console.log(e.stack);
384
- // Error
385
- // at err (/.../err.ts:22:18)
386
- // at validate (/.../validate.ts:15:12)
387
- // at handleRequest (/.../server.ts:8:20)
388
- ```
389
-
390
- <br>
391
-
392
373
  ## 🔌 Framework Integration Examples
393
374
 
394
375
  <details>
package/dist/index.js CHANGED
@@ -1,5 +1,2 @@
1
1
  // @bun
2
- var G="__$$e_9f4a1c7b__",B="__$$e_9f4a1c7b__";function q(){return B}function H(D){if(D.trim().length===0)throw TypeError("Marker key must be a non-empty string");B=D}function Y(D){let L;try{L=Error().stack??""}catch{L=""}let F={[q()]:!0,stack:L,data:D};return Object.freeze(F)}function J(D){try{return D!==null&&D!==void 0&&typeof D==="object"&&D[q()]===!0}catch{return!1}}function Q(D,L){if(D instanceof Promise)return D.then((F)=>F,(F)=>L?Y(L(F)):Y(F));try{return D()}catch(F){return L?Y(L(F)):Y(F)}}export{H as setMarkerKey,Q as safe,J as isErr,q as getMarkerKey,Y as err,G as DEFAULT_MARKER_KEY};
3
-
4
- //# debugId=37920203590E901064756E2164756E21
5
- //# sourceMappingURL=index.js.map
2
+ var G="__$$e_9f4a1c7b__",B="__$$e_9f4a1c7b__";function q(){return B}function H(D){if(D.trim().length===0)throw TypeError("Marker key must be a non-empty string");B=D}function Y(D){let L={[q()]:!0,data:D};return Object.freeze(L)}function J(D){try{return D!==null&&D!==void 0&&typeof D==="object"&&D[q()]===!0}catch{return!1}}function Q(D,L){if(D instanceof Promise)return D.then((F)=>F,(F)=>L?Y(L(F)):Y(F));try{return D()}catch(F){return L?Y(L(F)):Y(F)}}export{H as setMarkerKey,Q as safe,J as isErr,q as getMarkerKey,Y as err,G as DEFAULT_MARKER_KEY};
package/dist/src/err.d.ts CHANGED
@@ -2,23 +2,20 @@ import type { Err } from './types';
2
2
  /**
3
3
  * Creates an immutable {@link Err} value with no attached data.
4
4
  *
5
- * The returned object is `Object.freeze()`-d and includes a stack trace
6
- * captured at the call site. This function **never throws**.
5
+ * The returned object is `Object.freeze()`-d. This function **never throws**.
7
6
  *
8
7
  * @returns A frozen `Err` with `data` typed as `never`.
9
8
  *
10
9
  * @example
11
10
  * ```ts
12
11
  * const e = err();
13
- * console.log(e.stack); // stack trace
14
12
  * ```
15
13
  */
16
14
  export declare function err(): Err;
17
15
  /**
18
16
  * Creates an immutable {@link Err} value carrying the given data.
19
17
  *
20
- * The returned object is `Object.freeze()`-d and includes a stack trace
21
- * captured at the call site. This function **never throws**.
18
+ * The returned object is `Object.freeze()`-d. This function **never throws**.
22
19
  *
23
20
  * @param data - Any value describing the error (string, object, number, etc.).
24
21
  * @returns A frozen `Err<E>` with `data` set to the provided value.
@@ -1,10 +1,10 @@
1
1
  /**
2
2
  * The error type returned by {@link err}.
3
3
  *
4
- * Every `Err` carries a `stack` trace captured at creation and an optional
5
- * `data` payload describing what went wrong. The hidden marker property used
6
- * for detection is intentionally excluded from the type — it is managed
7
- * internally by `err()` and checked only through `isErr()`.
4
+ * Every `Err` carries an optional `data` payload describing what went wrong.
5
+ * The hidden marker property used for detection is intentionally excluded
6
+ * from the type — it is managed internally by `err()` and checked only
7
+ * through `isErr()`.
8
8
  *
9
9
  * @template E - The type of the attached error data. Defaults to `never`.
10
10
  *
@@ -12,11 +12,9 @@
12
12
  * ```ts
13
13
  * const e: Err<string> = err('not found');
14
14
  * console.log(e.data); // 'not found'
15
- * console.log(e.stack); // stack trace string
16
15
  * ```
17
16
  */
18
17
  export type Err<E = never> = {
19
- stack: string;
20
18
  data: E;
21
19
  };
22
20
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zipbul/result",
3
- "version": "0.1.6",
3
+ "version": "1.0.0",
4
4
  "description": "Lightweight Result type for error handling without exceptions",
5
5
  "license": "MIT",
6
6
  "author": "Junhyung Park (https://github.com/parkrevil)",
@@ -43,7 +43,7 @@
43
43
  "provenance": true
44
44
  },
45
45
  "scripts": {
46
- "build": "bun build index.ts --outdir dist --target bun --format esm --production --sourcemap=linked && tsc -p tsconfig.build.json",
46
+ "build": "bun build index.ts --outdir dist --target bun --format esm --production && tsc -p tsconfig.build.json",
47
47
  "typecheck": "tsc --noEmit",
48
48
  "test": "bun test",
49
49
  "coverage": "bun test --coverage"
package/dist/index.js.map DELETED
@@ -1,13 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../src/constants.ts", "../src/err.ts", "../src/is-err.ts", "../src/safe.ts"],
4
- "sourcesContent": [
5
- "/**\n * The default marker key used to identify {@link Err} objects.\n *\n * This collision-resistant string is set as a hidden property on every `Err`\n * created by `err()`. You rarely need to reference it directly — it is\n * provided for advanced use cases like cross-module error domain isolation.\n *\n * @example\n * ```ts\n * import { DEFAULT_MARKER_KEY } from '@zipbul/result';\n * console.log(DEFAULT_MARKER_KEY); // '__$$e_9f4a1c7b__'\n * ```\n */\nexport const DEFAULT_MARKER_KEY = '__$$e_9f4a1c7b__';\n\nlet currentMarkerKey: string = DEFAULT_MARKER_KEY;\n\n/**\n * Returns the marker key currently in use.\n *\n * Both `err()` and `isErr()` rely on this key to tag and detect error objects.\n *\n * @returns The current marker key string.\n *\n * @example\n * ```ts\n * console.log(getMarkerKey()); // '__$$e_9f4a1c7b__'\n * ```\n */\nexport function getMarkerKey(): string {\n return currentMarkerKey;\n}\n\n/**\n * Replaces the marker key used by `err()` and `isErr()`.\n *\n * After calling this, newly-created `Err` objects will use the new key, and\n * `isErr()` will only recognise objects carrying the new key. Previously\n * created `Err` objects will **no longer** be detected.\n *\n * Only change this if you need to isolate error domains across independent\n * modules — in most applications the default key is perfectly fine.\n *\n * @param key - A non-empty, non-whitespace-only string to use as the new key.\n * @throws {TypeError} If `key` is empty or contains only whitespace.\n *\n * @example\n * ```ts\n * setMarkerKey('__my_app_err__');\n * console.log(getMarkerKey()); // '__my_app_err__'\n * ```\n */\nexport function setMarkerKey(key: string): void {\n if (key.trim().length === 0) {\n throw new TypeError('Marker key must be a non-empty string');\n }\n currentMarkerKey = key;\n}\n",
6
- "import type { Err } from './types';\nimport { getMarkerKey } from './constants';\n\n/**\n * Creates an immutable {@link Err} value with no attached data.\n *\n * The returned object is `Object.freeze()`-d and includes a stack trace\n * captured at the call site. This function **never throws**.\n *\n * @returns A frozen `Err` with `data` typed as `never`.\n *\n * @example\n * ```ts\n * const e = err();\n * console.log(e.stack); // stack trace\n * ```\n */\nexport function err(): Err;\n/**\n * Creates an immutable {@link Err} value carrying the given data.\n *\n * The returned object is `Object.freeze()`-d and includes a stack trace\n * captured at the call site. This function **never throws**.\n *\n * @param data - Any value describing the error (string, object, number, etc.).\n * @returns A frozen `Err<E>` with `data` set to the provided value.\n *\n * @example\n * ```ts\n * const e = err({ code: 'TIMEOUT', retryAfter: 3000 });\n * console.log(e.data.code); // 'TIMEOUT'\n * ```\n */\nexport function err<E>(data: E): Err<E>;\nexport function err<E = never>(data?: E): Err<E> {\n let stack: string;\n try {\n stack = new Error().stack ?? '';\n } catch {\n stack = '';\n }\n\n const result = {\n [getMarkerKey()]: true,\n stack,\n data: data as E,\n };\n\n return Object.freeze(result) as Err<E>;\n}\n",
7
- "import type { Err } from './types';\nimport { getMarkerKey } from './constants';\n\n/**\n * Type guard that checks whether a value is an {@link Err}.\n *\n * Returns `true` when `value` is a non-null object whose current marker\n * property is strictly `true`. This function **never throws** — it safely\n * handles `null`, `undefined`, primitives, and even hostile Proxy objects.\n *\n * **Note:** The generic `E` is a compile-time assertion only. It does **not**\n * validate the shape of `data` at runtime — callers must ensure `E` matches\n * the actual error type.\n *\n * @typeParam E - Expected error data type (default: `unknown`).\n * @param value - The value to check. Can be anything.\n * @returns `true` if `value` is an `Err`, allowing TypeScript to narrow the type.\n *\n * @example\n * ```ts\n * const result: Result<number, string> = doSomething();\n *\n * if (isErr(result)) {\n * console.error(result.data); // string\n * } else {\n * console.log(result + 1); // number\n * }\n * ```\n */\nexport function isErr<E = unknown>(\n value: unknown,\n): value is Err<E> {\n try {\n return (\n value !== null &&\n value !== undefined &&\n typeof value === 'object' &&\n (value as Record<string, unknown>)[getMarkerKey()] === true\n );\n } catch {\n return false;\n }\n}\n",
8
- "import type { Result, ResultAsync } from './types';\nimport { err } from './err';\n\n/**\n * Executes a synchronous function and catches any thrown value into an {@link Err}.\n *\n * If `fn` returns normally, its return value is passed through as the success\n * value. If `fn` throws, the thrown value is wrapped with `err()` and returned.\n *\n * @param fn - A synchronous function to execute safely.\n * @returns The function's return value on success, or `Err<unknown>` on throw.\n *\n * @example\n * ```ts\n * const result = safe(() => JSON.parse(raw));\n * if (isErr(result)) console.error(result.data);\n * ```\n */\nexport function safe<T>(fn: () => T): Result<T, unknown>;\n/**\n * Executes a synchronous function and maps any thrown value through `mapErr`\n * before wrapping it in an {@link Err}.\n *\n * This overload lets you convert the raw `unknown` throw into a well-typed\n * error value, keeping your error types precise.\n *\n * @param fn - A synchronous function to execute safely.\n * @param mapErr - Transforms the thrown value into a typed error `E`.\n * @returns The function's return value on success, or `Err<E>` on throw.\n *\n * @example\n * ```ts\n * const result = safe(\n * () => JSON.parse(raw),\n * (e) => ({ code: 'PARSE', message: String(e) }),\n * );\n * ```\n */\nexport function safe<T, E>(fn: () => T, mapErr: (thrown: unknown) => E): Result<T, E>;\n/**\n * Wraps a Promise so that rejections become {@link Err} values instead of\n * thrown exceptions.\n *\n * If the promise resolves, the resolved value is passed through. If it\n * rejects, the rejection reason is wrapped with `err()` and the returned\n * promise resolves (never rejects) to `Err<unknown>`.\n *\n * @param promise - The promise to wrap.\n * @returns A `ResultAsync` that always resolves — either to `T` or to `Err<unknown>`.\n *\n * @example\n * ```ts\n * const result = await safe(fetch('/api/data'));\n * ```\n */\nexport function safe<T>(promise: Promise<T>): ResultAsync<T, unknown>;\n/**\n * Wraps a Promise so that rejections are mapped through `mapErr` and returned\n * as typed {@link Err} values.\n *\n * Combines the safety of promise wrapping with precise error typing.\n *\n * @param promise - The promise to wrap.\n * @param mapErr - Transforms the rejection reason into a typed error `E`.\n * @returns A `ResultAsync` that always resolves — either to `T` or to `Err<E>`.\n *\n * @example\n * ```ts\n * const result = await safe(\n * fetch('/api/users/1'),\n * (e) => ({ code: 'NETWORK', message: String(e) }),\n * );\n * ```\n */\nexport function safe<T, E>(promise: Promise<T>, mapErr: (thrown: unknown) => E): ResultAsync<T, E>;\nexport function safe<T, E = unknown>(\n fnOrPromise: (() => T) | Promise<T>,\n mapErr?: (thrown: unknown) => E,\n): Result<T, E> | ResultAsync<T, E> {\n if (fnOrPromise instanceof Promise) {\n return fnOrPromise.then(\n (value) => value as Result<T, E>,\n (thrown: unknown) => (mapErr ? err(mapErr(thrown)) : err(thrown)) as Result<T, E>,\n );\n }\n\n try {\n return fnOrPromise();\n } catch (thrown: unknown) {\n return mapErr ? err(mapErr(thrown)) : err(thrown as E);\n }\n}\n"
9
- ],
10
- "mappings": ";AAaO,IAAM,EAAqB,mBAE9B,EAF8B,mBAgB3B,SAAS,CAAY,EAAW,CACrC,OAAO,EAsBF,SAAS,CAAY,CAAC,EAAmB,CAC9C,GAAI,EAAI,KAAK,EAAE,SAAW,EACxB,MAAU,UAAU,uCAAuC,EAE7D,EAAmB,ECtBd,SAAS,CAAc,CAAC,EAAkB,CAC/C,IAAI,EACJ,GAAI,CACF,EAAY,MAAM,EAAE,OAAS,GAC7B,KAAM,CACN,EAAQ,GAGV,IAAM,EAAS,EACZ,EAAa,GAAI,GAClB,QACA,KAAM,CACR,EAEA,OAAO,OAAO,OAAO,CAAM,ECnBtB,SAAS,CAAkB,CAChC,EACiB,CACjB,GAAI,CACF,OACE,IAAU,MACV,IAAU,QACV,OAAO,IAAU,UAChB,EAAkC,EAAa,KAAO,GAEzD,KAAM,CACN,MAAO,ICmCJ,SAAS,CAAoB,CAClC,EACA,EACkC,CAClC,GAAI,aAAuB,QACzB,OAAO,EAAY,KACjB,CAAC,IAAU,EACX,CAAC,IAAqB,EAAS,EAAI,EAAO,CAAM,CAAC,EAAI,EAAI,CAAM,CACjE,EAGF,GAAI,CACF,OAAO,EAAY,EACnB,MAAO,EAAiB,CACxB,OAAO,EAAS,EAAI,EAAO,CAAM,CAAC,EAAI,EAAI,CAAW",
11
- "debugId": "37920203590E901064756E2164756E21",
12
- "names": []
13
- }