happy-rusty 1.9.1 → 1.10.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/CHANGELOG.md CHANGED
@@ -5,6 +5,27 @@ 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.0] - 2026-06-30
9
+
10
+ ### Added
11
+ - **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
+ - **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
+
14
+ ### Chores
15
+ - Upgraded devDependencies: vite, vitest, @vitest/coverage-v8, @vitest/ui, eslint, rollup, typescript-eslint
16
+
17
+ ## [1.9.2] - 2026-04-12
18
+
19
+ ### Changed
20
+ - **Performance**: Added `/*#__PURE__*/` annotations to all top-level function call expressions for better tree-shaking support in consumer bundlers
21
+
22
+ ### Fixed
23
+ - **Build**: Migrated `treeshake` config from deprecated `'smallest'` string to object form for Vite 8 (Rolldown) compatibility
24
+ - **Build**: Added `topLevelVar: false` to output options to preserve `const` declarations in bundled output
25
+
26
+ ### Chores
27
+ - Upgraded devDependencies: vite, vitest, eslint, typedoc, typescript-eslint
28
+
8
29
  ## [1.9.1] - 2026-01-16
9
30
 
10
31
  ### Changed
@@ -282,6 +303,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
282
303
  - Full TypeScript support
283
304
  - Comprehensive API matching Rust's Option and Result
284
305
 
306
+ [1.10.0]: https://github.com/JiangJie/happy-rusty/compare/v1.9.2...v1.10.0
307
+ [1.9.2]: https://github.com/JiangJie/happy-rusty/compare/v1.9.1...v1.9.2
285
308
  [1.9.1]: https://github.com/JiangJie/happy-rusty/compare/v1.9.0...v1.9.1
286
309
  [1.9.0]: https://github.com/JiangJie/happy-rusty/compare/v1.8.0...v1.9.0
287
310
  [1.8.0]: https://github.com/JiangJie/happy-rusty/compare/v1.7.1...v1.8.0
package/README.md CHANGED
@@ -20,7 +20,7 @@ Rust's `Option`, `Result`, and sync primitives for JavaScript/TypeScript - Bette
20
20
 
21
21
  - **Option<T>** - Represents an optional value: every `Option` is either `Some(T)` or `None`
22
22
  - **Result<T, E>** - Represents either success (`Ok(T)`) or failure (`Err(E)`)
23
- - **Sync Primitives** - Rust-inspired `Once<T>`, `OnceAsync<T>`, `Lazy<T>`, `LazyAsync<T>`, `Mutex<T>`, `RwLock<T>`, and `Channel<T>`
23
+ - **Sync Primitives** - Rust-inspired `Once<T>`, `OnceAsync<T>`, `Lazy<T>`, `LazyAsync<T>`, `Mutex<T>`, `RwLock<T>`, `Semaphore`, and `Channel<T>`
24
24
  - **Control Flow** - `ControlFlow<B, C>` with `Break` and `Continue` for short-circuiting operations
25
25
  - **FnOnce** - One-time callable function wrappers (`FnOnce` and `FnOnceAsync`)
26
26
  - **Full TypeScript support** with strict type inference
@@ -137,7 +137,7 @@ const response = await tryAsyncResult(fetch, '/api/data');
137
137
  ### Sync Primitives
138
138
 
139
139
  ```ts
140
- import { Lazy, LazyAsync, Mutex, Channel } from 'happy-rusty';
140
+ import { Lazy, LazyAsync, Mutex, Semaphore, Channel } from 'happy-rusty';
141
141
 
142
142
  // Lazy - compute once on first access
143
143
  const expensive = Lazy(() => computeExpensiveValue());
@@ -151,6 +151,10 @@ await db.force(); // Only one connection, concurrent calls wait
151
151
  const state = Mutex({ count: 0 });
152
152
  await state.withLock(async (s) => { s.count += 1; });
153
153
 
154
+ // Semaphore - limit async concurrency (e.g. fetch rate limiting)
155
+ const sem = Semaphore(10);
156
+ await sem.withPermit(() => fetch(url));
157
+
154
158
  // Channel - MPMC async message passing
155
159
  const ch = Channel<string>(10); // bounded capacity
156
160
  await ch.send('hello');
@@ -165,6 +169,7 @@ for await (const msg of ch) { console.log(msg); }
165
169
  - [Lazy](examples/std/sync/lazy.ts) / [LazyAsync](examples/std/sync/lazy_async.ts)
166
170
  - [Mutex](examples/std/sync/mutex.ts)
167
171
  - [RwLock](examples/std/sync/rwlock.ts)
172
+ - [Semaphore](examples/std/sync/semaphore.ts)
168
173
  - [Channel](examples/std/sync/channel.ts)
169
174
  - [ControlFlow](examples/std/ops/control_flow.ts)
170
175
  - [FnOnce](examples/std/ops/fn_once.ts) / [FnOnceAsync](examples/std/ops/fn_once_async.ts)
@@ -173,7 +178,7 @@ for await (const msg of ch) { console.log(msg); }
173
178
 
174
179
  ### Immutability
175
180
 
176
- All types (`Option`, `Result`, `ControlFlow`, `Lazy`, `LazyAsync`, `Once`, `OnceAsync`, `Mutex`, `MutexGuard`, `RwLock`, `Channel`, `Sender`, `Receiver`, `FnOnce`, `FnOnceAsync`) are **immutable at runtime** via `Object.freeze()`. This prevents accidental modification of methods or properties:
181
+ All types (`Option`, `Result`, `ControlFlow`, `Lazy`, `LazyAsync`, `Once`, `OnceAsync`, `Mutex`, `MutexGuard`, `RwLock`, `Semaphore`, `SemaphorePermit`, `Channel`, `Sender`, `Receiver`, `FnOnce`, `FnOnceAsync`) are **immutable at runtime** via `Object.freeze()`. This prevents accidental modification of methods or properties:
177
182
 
178
183
  ```ts
179
184
  const some = Some(42);