rsult 1.4.0 → 2.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/package.json CHANGED
@@ -1,18 +1,19 @@
1
1
  {
2
2
  "name": "rsult",
3
- "version": "1.4.0",
3
+ "version": "2.0.0",
4
4
  "description": "",
5
5
  "main": "dist/lib.js",
6
6
  "types": "dist/lib.d.ts",
7
- "repository": "https://github.com/indicium-ag/rsult",
7
+ "repository": "https://github.com/19h/rsult",
8
8
  "keywords": [],
9
9
  "author": "Kenan Sulayman <kenan@sly.mn>",
10
10
  "license": "MIT",
11
11
  "devDependencies": {
12
- "@swc/core": "^1.4.12",
13
- "@swc/jest": "^0.2.36",
14
- "@types/jest": "^29.5.12",
15
- "jest": "^29.7.0"
12
+ "@swc/core": "^1.15.7",
13
+ "@swc/jest": "^0.2.39",
14
+ "@types/jest": "^30.0.0",
15
+ "jest": "^30.2.0",
16
+ "typescript": "^5.9.3"
16
17
  },
17
18
  "scripts": {
18
19
  "test": "echo \"Error: no test specified\" && exit 1"
package/readme.md CHANGED
@@ -24,6 +24,9 @@ $ pnpm add rsult
24
24
 
25
25
  ```typescript
26
26
  import { Option, Result, Some, None, Ok, Err } from 'rsult';
27
+
28
+ // Async variants for Promise-based workflows
29
+ import { ResultAsync, OptionAsync } from 'rsult';
27
30
  ```
28
31
 
29
32
  ### tl;dr
@@ -31,11 +34,8 @@ import { Option, Result, Some, None, Ok, Err } from 'rsult';
31
34
  - rsult is inspired by Rust's `Option` and `Result` types.
32
35
  - It helps you handle optional values and results, eliminating `null` and `undefined` checks.
33
36
  - You can wrap values in `Some`, `None`, `Ok`, or `Err`, and use handy functions to transform, combine, and handle errors expressively.
34
- - It's a friendly sidekick that makes your code safer and more predictable.
35
-
36
- ### tl;dr
37
-
38
- rsult makes your code safer and more predictable.
37
+ - Includes **async variants** (`ResultAsync`, `OptionAsync`) for seamless Promise-based workflows.
38
+ - Uses **branded types** for nominal typing and proper TypeScript type safety.
39
39
 
40
40
  ## Usage
41
41
 
@@ -109,6 +109,64 @@ const transformedResult = okResult.map(x => x * 2); // Ok(10)
109
109
  const valueWithDefault = errResult.unwrap_or(0); // 0
110
110
  ```
111
111
 
112
+ ### Async Variants
113
+
114
+ rsult provides `ResultAsync` and `OptionAsync` for working with Promises in a type-safe, composable way.
115
+
116
+ #### ResultAsync
117
+
118
+ ```typescript
119
+ import { ResultAsync } from 'rsult';
120
+
121
+ // Create from various sources
122
+ const fromPromise = ResultAsync.fromPromise(fetch('/api/data'));
123
+ const fromTry = ResultAsync.try(async () => {
124
+ const response = await fetch('/api/data');
125
+ return response.json();
126
+ });
127
+
128
+ // Chain async operations
129
+ const result = await ResultAsync.ok(userId)
130
+ .andThen(id => fetchUser(id))
131
+ .map(user => user.name)
132
+ .mapErr(err => `Failed: ${err.message}`);
133
+
134
+ // Combine multiple async results
135
+ const combined = await ResultAsync.all([
136
+ fetchUser(1),
137
+ fetchUser(2),
138
+ fetchUser(3),
139
+ ]);
140
+ ```
141
+
142
+ #### OptionAsync
143
+
144
+ ```typescript
145
+ import { OptionAsync } from 'rsult';
146
+
147
+ // Create from various sources
148
+ const fromNullable = OptionAsync.fromNullable(maybeValue);
149
+ const fromPromise = OptionAsync.fromPromise(fetchOptionalData());
150
+
151
+ // Chain async operations
152
+ const result = await OptionAsync.some(userId)
153
+ .andThen(id => findUser(id))
154
+ .map(user => user.email)
155
+ .filter(email => email.endsWith('@example.com'));
156
+ ```
157
+
158
+ #### Converting Between Sync and Async
159
+
160
+ ```typescript
161
+ // Sync to Async
162
+ const asyncResult = Ok(42).toAsync();
163
+ const asyncOption = Some('hello').toAsync();
164
+
165
+ // Async resolves to sync types
166
+ const syncResult: Result<number, Error> = await asyncResult;
167
+ const syncOption: Option<string> = await asyncOption;
168
+ ```
169
+
112
170
  ## Advanced Usage
113
171
 
114
172
  ### Advanced Usage: Option
@@ -225,6 +283,7 @@ console.log(result); // "Parsed content: {"parsed":"Resource content"}"
225
283
  - `is_some()`: Checks if the Option is Some.
226
284
  - `is_none()`: Checks if the Option is None.
227
285
  - `is_some_and(f: (arg: T) => boolean)`: Determines if the Option is Some and the contained value meets a condition.
286
+ - `is_none_or(f: (arg: T) => boolean)`: Returns `true` if the Option is None, or if Some and the value satisfies the predicate.
228
287
 
229
288
  #### Transform Methods
230
289
  - `map(fn: (arg: T) => U)`: Transforms the contained value of a Some with a provided function. Returns None if this Option is None.
@@ -259,6 +318,16 @@ console.log(result); // "Parsed content: {"parsed":"Resource content"}"
259
318
  #### Flatten Method
260
319
  - `flatten()`: Flattens a nested Option, if the Option contains another Option, returning the inner Option if it's Some.
261
320
 
321
+ #### Inspection Method
322
+ - `inspect(f: (arg: T) => void)`: Calls the provided function with the contained value if Some, returns the Option unchanged.
323
+
324
+ #### Conversion Methods
325
+ - `ok_or<E>(err: E)`: Transforms `Some(v)` to `Ok(v)` and `None` to `Err(err)`.
326
+ - `ok_or_else<E>(f: () => E)`: Transforms `Some(v)` to `Ok(v)` and `None` to `Err(f())`.
327
+ - `transpose()`: Transposes an `Option<Result<T, E>>` into a `Result<Option<T>, E>`.
328
+ - `unzip()`: Unzips an `Option<[A, B]>` into `[Option<A>, Option<B>]`.
329
+ - `toAsync()`: Converts the Option to an OptionAsync for async chaining.
330
+
262
331
  ### Result
263
332
 
264
333
  #### Basic Methods
@@ -304,6 +373,93 @@ console.log(result); // "Parsed content: {"parsed":"Resource content"}"
304
373
  - `iter()`: Returns an iterator over the potentially contained value.
305
374
  - `flatten()`: Flattens a nested `Result` if the contained value is itself a `Result`.
306
375
 
376
+ #### Transpose and Conversion Methods
377
+ - `transpose()`: Transposes a `Result<Option<T>, E>` into an `Option<Result<T, E>>`.
378
+ - `toAsync()`: Converts the Result to a ResultAsync for async chaining.
379
+
380
+ ### ResultAsync
381
+
382
+ A wrapper around `Promise<Result<T, E>>` that enables fluent async/await chains.
383
+
384
+ #### Constructors
385
+ - `ResultAsync.ok<T, E>(value: T)`: Creates a successful ResultAsync.
386
+ - `ResultAsync.err<T, E>(error: E)`: Creates a failed ResultAsync.
387
+ - `ResultAsync.fromResult(result: Result<T, E> | Promise<Result<T, E>>)`: Wraps a sync or async Result.
388
+ - `ResultAsync.fromPromise<T, E>(promise: Promise<T>, mapErr?: (e: unknown) => E)`: Converts a Promise to ResultAsync.
389
+ - `ResultAsync.try<T>(fn: () => T | Promise<T>)`: Executes a function and catches any errors.
390
+
391
+ #### Transformation Methods
392
+ - `map<U>(fn: (value: T) => U | Promise<U>)`: Transforms the Ok value.
393
+ - `mapErr<U>(fn: (error: E) => U | Promise<U>)`: Transforms the Err value.
394
+ - `mapOr<U>(defaultValue: U, fn: (value: T) => U | Promise<U>)`: Maps or returns default.
395
+ - `mapOrElse<U>(defaultFn: (error: E) => U, fn: (value: T) => U)`: Maps or computes default.
396
+
397
+ #### Chaining Methods
398
+ - `andThen<U>(fn: (value: T) => Result<U, E> | ResultAsync<U, E>)`: Chains on success.
399
+ - `orElse<U>(fn: (error: E) => Result<T, U> | ResultAsync<T, U>)`: Recovers from error.
400
+ - `and<U>(other: ResultAsync<U, E>)`: Returns other if Ok.
401
+ - `or<U>(other: ResultAsync<T, U>)`: Returns other if Err.
402
+
403
+ #### Unwrapping Methods
404
+ - `unwrap()`: Returns value or throws.
405
+ - `unwrapOr(defaultValue: T)`: Returns value or default.
406
+ - `unwrapOrElse(fn: (error: E) => T)`: Returns value or computes from error.
407
+ - `expect(message: string)`: Returns value or throws with message.
408
+
409
+ #### Inspection Methods
410
+ - `inspect(fn: (value: T) => void)`: Inspects Ok value.
411
+ - `inspectErr(fn: (error: E) => void)`: Inspects Err value.
412
+ - `isOk()`: Async check if Ok.
413
+ - `isErr()`: Async check if Err.
414
+
415
+ #### Static Combinators
416
+ - `ResultAsync.all<T, E>(results: ResultAsync<T, E>[])`: Combines all, short-circuits on first error.
417
+ - `ResultAsync.allSettled<T, E>(results: ResultAsync<T, E>[])`: Collects all errors.
418
+
419
+ #### Pattern Matching
420
+ - `match<U>({ Ok, Err })`: Pattern match with handlers.
421
+
422
+ ### OptionAsync
423
+
424
+ A wrapper around `Promise<Option<T>>` that enables fluent async/await chains.
425
+
426
+ #### Constructors
427
+ - `OptionAsync.some<T>(value: T)`: Creates an OptionAsync with a value.
428
+ - `OptionAsync.none<T>()`: Creates an empty OptionAsync.
429
+ - `OptionAsync.fromOption(option: Option<T> | Promise<Option<T>>)`: Wraps a sync or async Option.
430
+ - `OptionAsync.fromPromise<T>(promise: Promise<T>)`: Converts resolved to Some, rejected to None.
431
+ - `OptionAsync.fromNullable<T>(value: T | null | undefined)`: Creates from nullable value.
432
+ - `OptionAsync.try<T>(fn: () => T | Promise<T>)`: Executes and returns Some on success, None on error.
433
+
434
+ #### Transformation Methods
435
+ - `map<U>(fn: (value: T) => U | Promise<U>)`: Transforms the Some value.
436
+ - `mapOr<U>(defaultValue: U, fn: (value: T) => U | Promise<U>)`: Maps or returns default.
437
+ - `mapOrElse<U>(defaultFn: () => U, fn: (value: T) => U)`: Maps or computes default.
438
+ - `filter(predicate: (value: T) => boolean | Promise<boolean>)`: Filters the Option.
439
+
440
+ #### Chaining Methods
441
+ - `andThen<U>(fn: (value: T) => Option<U> | OptionAsync<U>)`: Chains on Some.
442
+ - `orElse<U>(fn: () => Option<T> | OptionAsync<T>)`: Provides fallback on None.
443
+ - `and<U>(other: OptionAsync<U>)`: Returns other if Some.
444
+ - `or(other: OptionAsync<T>)`: Returns other if None.
445
+
446
+ #### Unwrapping Methods
447
+ - `unwrap()`: Returns value or throws.
448
+ - `unwrapOr(defaultValue: T)`: Returns value or default.
449
+ - `unwrapOrElse(fn: () => T)`: Returns value or computes default.
450
+ - `expect(message: string)`: Returns value or throws with message.
451
+
452
+ #### Conversion Methods
453
+ - `flatten()`: Flattens nested Option.
454
+ - `zip<U>(other: OptionAsync<U>)`: Combines two Options into tuple.
455
+ - `zipWith<U, R>(other: OptionAsync<U>, fn: (a: T, b: U) => R)`: Combines with function.
456
+
457
+ #### Static Combinators
458
+ - `OptionAsync.all<T>(options: OptionAsync<T>[])`: Combines all, returns None if any is None.
459
+
460
+ #### Pattern Matching
461
+ - `match<U>({ Some, None })`: Pattern match with handlers.
462
+
307
463
  ## Contributing
308
464
 
309
465
  Contributions are welcome! Please open an issue or submit a pull request.