happy-rusty 1.10.0 → 1.10.1

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/CHANGELOG.md CHANGED
@@ -5,55 +5,83 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.10.1] - 2026-09-06
9
+
10
+ ### Fixed
11
+
12
+ - **Channel**: `for await` leaving early (a `break`, an error thrown in the loop body, or an explicit `iterator.return()`) now cancels the pending `next()`. An abandoned iterator no longer holds its spot in the receive queue, so it cannot swallow a message intended for another consumer
13
+ - **Channel**: a timeout callback firing after its waiter was already served no longer removes an unrelated waiter (`splice(-1, 1)` on a `-1` index)
14
+ - **OnceAsync**: `set()` and `tryInsert()` return `Err` while a `getOrInit`/`getOrTryInit` attempt is in flight, instead of reporting `Ok` and then being overwritten by the attempt's result — matching Rust's `OnceLock::set` racing an in-progress `get_or_init`
15
+ - **OnceAsync**: `wait()` no longer rejects when an initialization attempt fails. It keeps waiting until the cell is actually initialized, matching Rust's `OnceLock::wait`
16
+ - **OnceAsync**: a caller joining a failed attempt retries with its own initializer, matching Rust's `get_or_try_init`. The in-flight slot is claimed synchronously, so a synchronously-executing initializer that re-enters joins the attempt instead of starting a second one
17
+
18
+ ### Chores
19
+
20
+ - Migrated to the Vite+ unified toolchain (`vp check` for fmt + lint + type checking, `vp pack` for JS and `.d.ts` bundling), replacing ESLint and the previous build setup
21
+ - Merged all CI gates into a single `ci.yml` job and added attw + publint verification of the tarball that is actually published
22
+ - Upgraded devDependencies: `vite-plus` 0.3.0, `@vitest/coverage-v8` 4.1.11, `publint` 0.3.24
23
+
8
24
  ## [1.10.0] - 2026-06-30
9
25
 
10
26
  ### Added
27
+
11
28
  - **New Sync Primitive**: `Semaphore` - Counting semaphore for limiting async concurrency, with `acquire`/`tryAcquire`/`withPermit`/`availablePermits`. Inspired by tokio's `Semaphore` (Rust std does not include one). Useful for fetch rate limiting, connection pools, and task queues.
12
29
  - **New Method**: `RwLockWriteGuard.downgrade()` - Atomically converts a write guard to a read guard, releasing waiting readers while keeping pending writers waiting. Equivalent to Rust 1.92's `RwLockWriteGuard::downgrade`
13
30
 
14
31
  ### Chores
32
+
15
33
  - Upgraded devDependencies: vite, vitest, @vitest/coverage-v8, @vitest/ui, eslint, rollup, typescript-eslint
16
34
 
17
35
  ## [1.9.2] - 2026-04-12
18
36
 
19
37
  ### Changed
38
+
20
39
  - **Performance**: Added `/*#__PURE__*/` annotations to all top-level function call expressions for better tree-shaking support in consumer bundlers
21
40
 
22
41
  ### Fixed
42
+
23
43
  - **Build**: Migrated `treeshake` config from deprecated `'smallest'` string to object form for Vite 8 (Rolldown) compatibility
24
44
  - **Build**: Added `topLevelVar: false` to output options to preserve `const` declarations in bundled output
25
45
 
26
46
  ### Chores
47
+
27
48
  - Upgraded devDependencies: vite, vitest, eslint, typedoc, typescript-eslint
28
49
 
29
50
  ## [1.9.1] - 2026-01-16
30
51
 
31
52
  ### Changed
53
+
32
54
  - **Performance**: `Channel` buffer replaced `Array` with `Queue` for O(1) shift operations
33
55
 
34
56
  ### Documentation
57
+
35
58
  - Added `@since` tags to all public APIs
36
59
  - Improved JSDoc consistency and formatting
37
60
 
38
61
  ### CI
62
+
39
63
  - Changed JSR publish to trigger on release instead of push to main
40
64
 
41
65
  ## [1.9.0] - 2026-01-04
42
66
 
43
67
  ### Added
68
+
44
69
  - **Try Extensions for Result**:
45
70
  - `andTryAsync<U>` - Like `andThenAsync`, but auto-catches exceptions/Promise rejections and converts them to `Err`
46
71
  - `orTryAsync<F>` - Like `orElseAsync`, but auto-catches exceptions in recovery logic
47
72
 
48
73
  ### Changed
74
+
49
75
  - **Performance**: `map()` and `mapErr()` now return `this` when the Result variant doesn't match, avoiding unnecessary object creation
50
76
 
51
77
  ### Removed
78
+
52
79
  - `promiseToAsyncResult()` - Use `tryAsyncResult()` instead (deprecated since v1.7.0)
53
80
 
54
81
  ## [1.8.0] - 2025-12-31
55
82
 
56
83
  ### Added
84
+
57
85
  - **New Sync Primitives**:
58
86
  - `OnceAsync<T>` - Async-first one-time initialization with concurrent call handling
59
87
  - `RwLock<T>` - Async read-write lock (multiple concurrent readers or single writer)
@@ -78,18 +106,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
78
106
  - **Rust Documentation Links** - All Rust-equivalent interfaces now link to official Rust docs via `@see` tags
79
107
 
80
108
  ### Changed
109
+
81
110
  - **Module Reorganization** - Source code restructured into `core/` (Option, Result) and `std/` (sync, ops) directories, mirroring Rust's stdlib organization
82
111
  - **Async Callback Types** - All async methods now accept `PromiseLike<T> | T` instead of just `Promise<T>`, allowing mixed sync/async callbacks
83
112
  - **Async Return Types** - Use `Awaited<T>` to properly flatten nested Promises in async method return types
84
113
  - **Internal Optimizations** - Cached Promise constants (`ASYNC_NONE`, etc.) for better runtime performance
85
114
 
86
115
  ### Fixed
116
+
87
117
  - `this` binding issue in `Once.getOrTryInitAsync`
88
118
  - Nested Promise flattening in async methods
89
119
 
90
120
  ## [1.7.1] - 2025-12-26
91
121
 
92
122
  ### Added
123
+
93
124
  - **Argument passing** - All `try*` functions now support passing arguments like `Promise.try`:
94
125
  - `tryOption(JSON.parse, jsonString)` instead of `tryOption(() => JSON.parse(jsonString))`
95
126
  - `tryResult(decodeURIComponent, str)` instead of `tryResult(() => decodeURIComponent(str))`
@@ -98,35 +129,42 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
98
129
  ## [1.7.0] - 2025-12-26
99
130
 
100
131
  ### Added
132
+
101
133
  - `tryOption()` - Capture synchronous exceptions as Option (success → Some, exception → None)
102
134
  - `tryAsyncOption()` - Capture async/Promise exceptions as Option
103
135
  - `tryResult()` - Capture synchronous exceptions as Result (success → Ok, exception → Err)
104
136
  - `tryAsyncResult()` - Capture async/Promise exceptions as Result
105
137
 
106
138
  ### Deprecated
139
+
107
140
  - `promiseToAsyncResult()` - Use `tryAsyncResult()` instead (same functionality, more consistent naming)
108
141
 
109
142
  ## [1.6.2] - 2025-12-25
110
143
 
111
144
  ### Changed
145
+
112
146
  - `promiseToAsyncResult` now accepts `PromiseLike<T>` instead of `Promise<T>` for broader compatibility with thenable objects
113
147
  - Use `AsyncResult` type alias in function signatures for consistency
114
148
 
115
149
  ### Removed
150
+
116
151
  - Removed unused `source` field from package.json (Parcel legacy)
117
152
  - Removed redundant `@internal` tags from private (non-exported) functions
118
153
 
119
154
  ## [1.6.1] - 2025-12-19
120
155
 
121
156
  ### Changed
157
+
122
158
  - License changed from GPL-3.0 to MIT for broader adoption and easier integration
123
159
 
124
160
  ### Added
161
+
125
162
  - Navigation links (GitHub, npm, JSR) in TypeDoc documentation header
126
163
 
127
164
  ## [1.6.0] - 2025-12-18
128
165
 
129
166
  ### Added
167
+
130
168
  - **Sync Primitives**: `Once<T>`, `Lazy<T>`, `LazyAsync<T>`, `Mutex<T>` for Rust-style synchronization
131
169
  - **Control Flow**: `ControlFlow<B, C>` with `Break` and `Continue` variants
132
170
  - `Symbol.toStringTag` property to all types for better type identification
@@ -140,28 +178,33 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
140
178
  - CHANGELOG.md with full version history
141
179
 
142
180
  ### Changed
181
+
143
182
  - All instances are now frozen with `Object.freeze()` for runtime immutability
144
183
  - TypeDoc output format from Markdown to HTML for GitHub Pages compatibility
145
184
  - Migrated from Deno test to Vitest
146
185
  - Build process split into Vite (JS) and Rollup (dts)
147
186
 
148
187
  ### Fixed
188
+
149
189
  - Symbol property syntax and duplicate declaration issues
150
190
  - Type inference improvements for `None` interface methods
151
191
 
152
192
  ## [1.5.0] - 2024-08-11
153
193
 
154
194
  ### Added
195
+
155
196
  - Async versions of methods: `isSomeAndAsync`, `isOkAndAsync`, `isErrAndAsync`, `unwrapOrElseAsync`, `andThenAsync`, `orElseAsync`
156
197
  - Async examples
157
198
 
158
199
  ### Changed
200
+
159
201
  - Updated pnpm to v9.7.0
160
202
  - Updated ESLint configuration
161
203
 
162
204
  ## [1.4.0] - 2024-08-05
163
205
 
164
206
  ### Added
207
+
165
208
  - `Ok()` constructor without arguments (similar to Rust's `Ok(())`)
166
209
  - `RESULT_VOID` constant for void Result returns
167
210
  - `VoidResult<E>`, `VoidIOResult`, `AsyncVoidResult<E>`, `AsyncVoidIOResult` type aliases
@@ -169,94 +212,114 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
169
212
  ## [1.3.2] - 2024-08-04
170
213
 
171
214
  ### Changed
215
+
172
216
  - Renamed `helpers` to `utils`
173
217
  - Improved `@example` annotations in JSDoc
174
218
 
175
219
  ## [1.3.1] - 2024-08-03
176
220
 
177
221
  ### Fixed
222
+
178
223
  - `map` methods now correctly return new objects instead of mutating
179
224
 
180
225
  ### Changed
226
+
181
227
  - Updated Rollup to v4.20.0
182
228
 
183
229
  ## [1.3.0] - 2024-08-01
184
230
 
185
231
  ### Added
232
+
186
233
  - `RESULT_TRUE`, `RESULT_FALSE`, `RESULT_ZERO` constants
187
234
 
188
235
  ### Fixed
236
+
189
237
  - Circular dependency issues
190
238
 
191
239
  ### Changed
240
+
192
241
  - Reorganized code structure
193
242
 
194
243
  ## [1.2.0] - 2024-08-01
195
244
 
196
245
  ### Added
246
+
197
247
  - `isOption()` and `isResult()` type guard utilities
198
248
  - Custom string conversion for Option and Result
199
249
 
200
250
  ### Changed
251
+
201
252
  - Replaced arrow functions with normal functions for better debug experience
202
253
  - Updated ESLint to v9
203
254
 
204
255
  ## [1.1.2] - 2024-07-17
205
256
 
206
257
  ### Added
258
+
207
259
  - `asOk<F>()` and `asErr<U>()` methods for type casting
208
260
 
209
261
  ## [1.1.1] - 2024-07-13
210
262
 
211
263
  ### Fixed
264
+
212
265
  - TypeDoc configuration issues
213
266
 
214
267
  ### Changed
268
+
215
269
  - Updated dependencies
216
270
 
217
271
  ## [1.1.0] - 2024-06-09
218
272
 
219
273
  ### Added
274
+
220
275
  - `Option.filter()` method
221
276
  - Many new Option and Result APIs
222
277
  - Comprehensive code comments and documentation
223
278
 
224
279
  ### Changed
280
+
225
281
  - Improved type inference
226
282
  - `Option.filter()` now returns `Option<T>` instead of boolean
227
283
 
228
284
  ## [1.0.9] - 2024-05-14
229
285
 
230
286
  ### Added
287
+
231
288
  - Documentation for exported symbols
232
289
  - README examples
233
290
 
234
291
  ## [1.0.8] - 2024-05-13
235
292
 
236
293
  ### Changed
294
+
237
295
  - Switched from npm to pnpm
238
296
  - Added GitHub Actions test workflow with Codecov
239
297
 
240
298
  ## [1.0.7] - 2024-05-08
241
299
 
242
300
  ### Changed
301
+
243
302
  - `Some` value type changed to `NonNullable<T>`
244
303
 
245
304
  ### Fixed
305
+
246
306
  - Can now invoke `err()` from `Ok` variant
247
307
 
248
308
  ## [1.0.6] - 2024-05-08
249
309
 
250
310
  ### Added
311
+
251
312
  - Commonly used type exports
252
313
 
253
314
  ### Changed
315
+
254
316
  - Set `type: "module"` in package.json
255
317
  - Build target set to ESNext
256
318
 
257
319
  ## [1.0.5] - 2024-05-05
258
320
 
259
321
  ### Changed
322
+
260
323
  - Throw `TypeError` instead of generic `Error`
261
324
  - Switched to Rollup for building
262
325
  - Added Bun support in CI
@@ -264,45 +327,54 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
264
327
  ## [1.0.4] - 2024-05-04
265
328
 
266
329
  ### Added
330
+
267
331
  - Chinese README (`README.cn.md`)
268
332
  - JSR publishing workflow
269
333
  - npm publishing workflows
270
334
 
271
335
  ### Changed
336
+
272
337
  - Replaced Parcel with Rollup for building
273
338
  - Replaced Jest with Bun test
274
339
 
275
340
  ## [1.0.3] - 2024-04-27
276
341
 
277
342
  ### Added
343
+
278
344
  - Installation and Examples sections in README
279
345
 
280
346
  ### Changed
347
+
281
348
  - Force return const for better type inference
282
349
 
283
350
  ## [1.0.2] - 2024-04-26
284
351
 
285
352
  ### Added
353
+
286
354
  - JSR publishing support
287
355
 
288
356
  ### Changed
357
+
289
358
  - Improved code comments
290
359
 
291
360
  ## [1.0.1] - 2024-04-26
292
361
 
293
362
  ### Changed
363
+
294
364
  - Replaced enum with const for better tree-shaking
295
365
  - Marked package as side-effect free
296
366
 
297
367
  ## [1.0.0] - 2024-04-24
298
368
 
299
369
  ### Added
370
+
300
371
  - Initial release
301
372
  - `Option<T>` type with `Some` and `None` variants
302
373
  - `Result<T, E>` type with `Ok` and `Err` variants
303
374
  - Full TypeScript support
304
375
  - Comprehensive API matching Rust's Option and Result
305
376
 
377
+ [1.10.1]: https://github.com/JiangJie/happy-rusty/compare/v1.10.0...v1.10.1
306
378
  [1.10.0]: https://github.com/JiangJie/happy-rusty/compare/v1.9.2...v1.10.0
307
379
  [1.9.2]: https://github.com/JiangJie/happy-rusty/compare/v1.9.1...v1.9.2
308
380
  [1.9.1]: https://github.com/JiangJie/happy-rusty/compare/v1.9.0...v1.9.1
package/README.cn.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # happy-rusty
2
2
 
3
3
  [![License](https://img.shields.io/npm/l/happy-rusty.svg)](LICENSE)
4
- [![Build Status](https://github.com/JiangJie/happy-rusty/actions/workflows/test.yml/badge.svg)](https://github.com/JiangJie/happy-rusty/actions/workflows/test.yml)
4
+ [![Build Status](https://github.com/JiangJie/happy-rusty/actions/workflows/ci.yml/badge.svg)](https://github.com/JiangJie/happy-rusty/actions/workflows/ci.yml)
5
5
  [![codecov](https://codecov.io/gh/JiangJie/happy-rusty/graph/badge.svg)](https://codecov.io/gh/JiangJie/happy-rusty)
6
6
  [![NPM version](https://img.shields.io/npm/v/happy-rusty.svg)](https://npmjs.org/package/happy-rusty)
7
7
  [![NPM downloads](https://badgen.net/npm/dm/happy-rusty)](https://npmjs.org/package/happy-rusty)
@@ -84,37 +84,39 @@ const config = parseJSON<Config>(jsonStr)
84
84
 
85
85
  ### Option&lt;T&gt;
86
86
 
87
- | 分类 | 方法 |
88
- |------|------|
89
- | **构造器** | `Some(value)`, `None` |
90
- | **查询** | `isSome()`, `isNone()`, `isSomeAnd(fn)` |
91
- | **提取** | `expect(msg)`, `unwrap()`, `unwrapOr(default)`, `unwrapOrElse(fn)` |
92
- | **转换** | `map(fn)`, `mapOr(default, fn)`, `mapOrElse(defaultFn, fn)`, `filter(fn)`, `flatten()` |
93
- | **布尔操作** | `and(other)`, `andThen(fn)`, `or(other)`, `orElse(fn)`, `xor(other)` |
94
- | **类型转换** | `okOr(err)`, `okOrElse(fn)`, `transpose()` |
95
- | **组合** | `zip(other)`, `zipWith(other, fn)`, `unzip()` |
96
- | **副作用** | `inspect(fn)` |
97
- | **比较** | `eq(other)` |
87
+ | 分类 | 方法 |
88
+ | ------------ | -------------------------------------------------------------------------------------- |
89
+ | **构造器** | `Some(value)`, `None` |
90
+ | **查询** | `isSome()`, `isNone()`, `isSomeAnd(fn)` |
91
+ | **提取** | `expect(msg)`, `unwrap()`, `unwrapOr(default)`, `unwrapOrElse(fn)` |
92
+ | **转换** | `map(fn)`, `mapOr(default, fn)`, `mapOrElse(defaultFn, fn)`, `filter(fn)`, `flatten()` |
93
+ | **布尔操作** | `and(other)`, `andThen(fn)`, `or(other)`, `orElse(fn)`, `xor(other)` |
94
+ | **类型转换** | `okOr(err)`, `okOrElse(fn)`, `transpose()` |
95
+ | **组合** | `zip(other)`, `zipWith(other, fn)`, `unzip()` |
96
+ | **副作用** | `inspect(fn)` |
97
+ | **比较** | `eq(other)` |
98
98
 
99
99
  ### Result&lt;T, E&gt;
100
100
 
101
- | 分类 | 方法 |
102
- |------|------|
103
- | **构造器** | `Ok(value)`, `Ok()` (void), `Err(error)` |
104
- | **查询** | `isOk()`, `isErr()`, `isOkAnd(fn)`, `isErrAnd(fn)` |
105
- | **提取 Ok** | `expect(msg)`, `unwrap()`, `unwrapOr(default)`, `unwrapOrElse(fn)` |
106
- | **提取 Err** | `expectErr(msg)`, `unwrapErr()` |
107
- | **转换** | `map(fn)`, `mapErr(fn)`, `mapOr(default, fn)`, `mapOrElse(defaultFn, fn)`, `flatten()` |
108
- | **布尔操作** | `and(other)`, `andThen(fn)`, `or(other)`, `orElse(fn)` |
109
- | **类型转换** | `ok()`, `err()`, `transpose()` |
110
- | **类型断言** | `asOk<F>()`, `asErr<U>()` |
111
- | **副作用** | `inspect(fn)`, `inspectErr(fn)` |
112
- | **比较** | `eq(other)` |
101
+ | 分类 | 方法 |
102
+ | ------------ | -------------------------------------------------------------------------------------- |
103
+ | **构造器** | `Ok(value)`, `Ok()` (void), `Err(error)` |
104
+ | **查询** | `isOk()`, `isErr()`, `isOkAnd(fn)`, `isErrAnd(fn)` |
105
+ | **提取 Ok** | `expect(msg)`, `unwrap()`, `unwrapOr(default)`, `unwrapOrElse(fn)` |
106
+ | **提取 Err** | `expectErr(msg)`, `unwrapErr()` |
107
+ | **转换** | `map(fn)`, `mapErr(fn)`, `mapOr(default, fn)`, `mapOrElse(defaultFn, fn)`, `flatten()` |
108
+ | **布尔操作** | `and(other)`, `andThen(fn)`, `or(other)`, `orElse(fn)` |
109
+ | **类型转换** | `ok()`, `err()`, `transpose()` |
110
+ | **类型断言** | `asOk<F>()`, `asErr<U>()` |
111
+ | **副作用** | `inspect(fn)`, `inspectErr(fn)` |
112
+ | **比较** | `eq(other)` |
113
113
 
114
114
  ### 异步方法
115
115
 
116
116
  所有转换方法都有带 `Async` 后缀的异步变体(如 `andThenAsync`、`mapAsync`、`unwrapOrElseAsync`)。
117
117
 
118
+ 异步变体遵循库的错误约定:回调被实际调用时,若其同步抛错,错误会在调用点同步抛出——与同步方法一致;只有回调返回 rejected Promise 时,错误才以 rejection 形式呈现。如需把抛出的异常转为 `Err`/`None` 值,请使用 `try*` 辅助函数(`tryResult`/`tryAsyncResult`/`tryOption`/`tryAsyncOption`),或在 `Result` 上使用 `andTryAsync`/`orTryAsync` 方法。
119
+
118
120
  ### 类型别名
119
121
 
120
122
  ```ts
@@ -195,12 +197,14 @@ some.unwrap = () => 0; // TypeError: Cannot assign to read only property
195
197
  ## 为什么选择 happy-rusty?
196
198
 
197
199
  JavaScript 的 `null`/`undefined` 和 try-catch 模式会导致:
200
+
198
201
  - 未捕获的空引用错误
199
202
  - 遗忘的错误处理
200
203
  - 冗长的 try-catch 代码块
201
204
  - 不清晰的函数契约
202
205
 
203
206
  `happy-rusty` 提供了 Rust 久经考验的模式:
207
+
204
208
  - **显式可选性** - `Option<T>` 在类型中明确表示值的缺失
205
209
  - **显式错误** - `Result<T, E>` 强制考虑错误处理
206
210
  - **链式调用** - 无需嵌套 if-else 或 try-catch 即可转换值
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # happy-rusty
2
2
 
3
3
  [![License](https://img.shields.io/npm/l/happy-rusty.svg)](LICENSE)
4
- [![Build Status](https://github.com/JiangJie/happy-rusty/actions/workflows/test.yml/badge.svg)](https://github.com/JiangJie/happy-rusty/actions/workflows/test.yml)
4
+ [![Build Status](https://github.com/JiangJie/happy-rusty/actions/workflows/ci.yml/badge.svg)](https://github.com/JiangJie/happy-rusty/actions/workflows/ci.yml)
5
5
  [![codecov](https://codecov.io/gh/JiangJie/happy-rusty/graph/badge.svg)](https://codecov.io/gh/JiangJie/happy-rusty)
6
6
  [![NPM version](https://img.shields.io/npm/v/happy-rusty.svg)](https://npmjs.org/package/happy-rusty)
7
7
  [![NPM downloads](https://badgen.net/npm/dm/happy-rusty)](https://npmjs.org/package/happy-rusty)
@@ -84,37 +84,39 @@ const config = parseJSON<Config>(jsonStr)
84
84
 
85
85
  ### Option&lt;T&gt;
86
86
 
87
- | Category | Methods |
88
- |----------|---------|
89
- | **Constructors** | `Some(value)`, `None` |
90
- | **Querying** | `isSome()`, `isNone()`, `isSomeAnd(fn)` |
91
- | **Extracting** | `expect(msg)`, `unwrap()`, `unwrapOr(default)`, `unwrapOrElse(fn)` |
87
+ | Category | Methods |
88
+ | ---------------- | -------------------------------------------------------------------------------------- |
89
+ | **Constructors** | `Some(value)`, `None` |
90
+ | **Querying** | `isSome()`, `isNone()`, `isSomeAnd(fn)` |
91
+ | **Extracting** | `expect(msg)`, `unwrap()`, `unwrapOr(default)`, `unwrapOrElse(fn)` |
92
92
  | **Transforming** | `map(fn)`, `mapOr(default, fn)`, `mapOrElse(defaultFn, fn)`, `filter(fn)`, `flatten()` |
93
- | **Boolean ops** | `and(other)`, `andThen(fn)`, `or(other)`, `orElse(fn)`, `xor(other)` |
94
- | **Converting** | `okOr(err)`, `okOrElse(fn)`, `transpose()` |
95
- | **Combining** | `zip(other)`, `zipWith(other, fn)`, `unzip()` |
96
- | **Side effects** | `inspect(fn)` |
97
- | **Comparison** | `eq(other)` |
93
+ | **Boolean ops** | `and(other)`, `andThen(fn)`, `or(other)`, `orElse(fn)`, `xor(other)` |
94
+ | **Converting** | `okOr(err)`, `okOrElse(fn)`, `transpose()` |
95
+ | **Combining** | `zip(other)`, `zipWith(other, fn)`, `unzip()` |
96
+ | **Side effects** | `inspect(fn)` |
97
+ | **Comparison** | `eq(other)` |
98
98
 
99
99
  ### Result&lt;T, E&gt;
100
100
 
101
- | Category | Methods |
102
- |----------|---------|
103
- | **Constructors** | `Ok(value)`, `Ok()` (void), `Err(error)` |
104
- | **Querying** | `isOk()`, `isErr()`, `isOkAnd(fn)`, `isErrAnd(fn)` |
105
- | **Extracting Ok** | `expect(msg)`, `unwrap()`, `unwrapOr(default)`, `unwrapOrElse(fn)` |
106
- | **Extracting Err** | `expectErr(msg)`, `unwrapErr()` |
107
- | **Transforming** | `map(fn)`, `mapErr(fn)`, `mapOr(default, fn)`, `mapOrElse(defaultFn, fn)`, `flatten()` |
108
- | **Boolean ops** | `and(other)`, `andThen(fn)`, `or(other)`, `orElse(fn)` |
109
- | **Converting** | `ok()`, `err()`, `transpose()` |
110
- | **Type casting** | `asOk<F>()`, `asErr<U>()` |
111
- | **Side effects** | `inspect(fn)`, `inspectErr(fn)` |
112
- | **Comparison** | `eq(other)` |
101
+ | Category | Methods |
102
+ | ------------------ | -------------------------------------------------------------------------------------- |
103
+ | **Constructors** | `Ok(value)`, `Ok()` (void), `Err(error)` |
104
+ | **Querying** | `isOk()`, `isErr()`, `isOkAnd(fn)`, `isErrAnd(fn)` |
105
+ | **Extracting Ok** | `expect(msg)`, `unwrap()`, `unwrapOr(default)`, `unwrapOrElse(fn)` |
106
+ | **Extracting Err** | `expectErr(msg)`, `unwrapErr()` |
107
+ | **Transforming** | `map(fn)`, `mapErr(fn)`, `mapOr(default, fn)`, `mapOrElse(defaultFn, fn)`, `flatten()` |
108
+ | **Boolean ops** | `and(other)`, `andThen(fn)`, `or(other)`, `orElse(fn)` |
109
+ | **Converting** | `ok()`, `err()`, `transpose()` |
110
+ | **Type casting** | `asOk<F>()`, `asErr<U>()` |
111
+ | **Side effects** | `inspect(fn)`, `inspectErr(fn)` |
112
+ | **Comparison** | `eq(other)` |
113
113
 
114
114
  ### Async Methods
115
115
 
116
116
  All transformation methods have async variants with `Async` suffix (e.g., `andThenAsync`, `mapAsync`, `unwrapOrElseAsync`).
117
117
 
118
+ Async variants follow the library's error convention: when the callback is invoked, a synchronous throw propagates synchronously at the call site — just like the sync methods — and only a callback that returns a rejected promise surfaces as a promise rejection. To capture thrown exceptions as `Err`/`None` values instead, use the `try*` helpers (`tryResult`/`tryAsyncResult`/`tryOption`/`tryAsyncOption`) or, on `Result`, the `andTryAsync`/`orTryAsync` methods.
119
+
118
120
  ### Type Aliases
119
121
 
120
122
  ```ts
@@ -200,12 +202,14 @@ We intentionally omit `readonly` modifiers from method signatures in interfaces.
200
202
  ## Why happy-rusty?
201
203
 
202
204
  JavaScript's `null`/`undefined` and try-catch patterns lead to:
205
+
203
206
  - Uncaught null reference errors
204
207
  - Forgotten error handling
205
208
  - Verbose try-catch blocks
206
209
  - Unclear function contracts
207
210
 
208
211
  `happy-rusty` provides Rust's battle-tested patterns:
212
+
209
213
  - **Explicit optionality** - `Option<T>` makes absence visible in types
210
214
  - **Explicit errors** - `Result<T, E>` forces error handling consideration
211
215
  - **Method chaining** - Transform values without nested if-else or try-catch