slang-ts 0.0.8 → 0.0.9

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.md CHANGED
@@ -38,6 +38,12 @@ npm i slang-ts
38
38
 
39
39
  All utilities fully tested. See [tests](https://github.com/Hussseinkizz/slang/tree/main/tests)
40
40
 
41
+ ## New in v0.0.9
42
+
43
+ - **SafeTry**: unwraps nested Result, Option, and Atom values into one result; nested failures now become the outer `Err`, while plain object properties and array elements stay unchanged.
44
+ - **Package types**: bundled declarations work with strict NodeNext consumers, so importing the package no longer exposes invalid declaration paths.
45
+ - **Build tooling**: tsdown and TypeScript 7 build JavaScript and bundled types together.
46
+
41
47
  ## New in v0.0.8
42
48
 
43
49
  - **Signal**: a simple on/off trigger that fires once and stays fired; use it to make something start only after something else finishes.
@@ -283,36 +289,59 @@ Useful when values come from different functions with inconsistent return types
283
289
 
284
290
  ### SafeTry
285
291
 
286
- Wraps potentially throwing functions in try-catch, returning a `Result<T, string>`. Always needs to be awaited as its async.
292
+ Runs sync or async functions and captures failures as `Err<string>`. Always await it. Nested Result, Option, and Atom values resolve to one `Result`: `Ok` and `Some` unwrap until a plain value appears, `Err` stops with its error normalized through `String`, `None` becomes `Err("Option was None")`, and Atom becomes its description.
287
293
 
288
294
  ```ts
289
- import { safeTry } from "slang-ts";
295
+ import { safeTry, Ok, Err, option, atom, println, type Result } from "slang-ts";
290
296
 
291
- const result = await safeTry(() => {
292
- if (denom === 0) throw new Error("Cannot divide by zero");
293
- return num / denom;
294
- });
297
+ // Inferred type is Promise<Result<number, string>>, not nested Results.
298
+ const pending: Promise<Result<number, string>> = safeTry(() => Ok(Ok(42)));
299
+ const nested = await pending; // Ok(42)
300
+ if (nested.isOk) println(nested.value); // 42
295
301
 
296
- if (result.isOk) {
297
- println("Result:", result.value);
298
- } else {
299
- println("Error:", result.error);
300
- }
302
+ const failed = await safeTry(() => Ok(Ok(Err("Not found")))); // Err("Not found")
303
+ if (failed.isErr) println(failed.error); // "Not found"
301
304
 
302
- // Async functions work the same way
303
- const data = await safeTry(async () => {
304
- const res = await fetch("/api/user");
305
- return res.json();
306
- });
305
+ const mixed = await safeTry(() => Ok(option(Ok(atom("ready")))));
306
+ // Ok("ready"); inferred success value is the literal "ready".
307
+ if (mixed.isOk) println(mixed.value); // "ready"
307
308
 
308
- if (data.isOk) {
309
- println("User:", data.value);
310
- }
309
+ const missing = await safeTry(() => Ok(option(null))); // Err("Option was None")
310
+ if (missing.isErr) println(missing.error);
311
+
312
+ const caught = await safeTry(async () => {
313
+ throw new Error("Could not load profile");
314
+ }); // Err("Could not load profile")
315
+ if (caught.isErr) println(caught.error);
316
+ ```
317
+
318
+ Only the returned wrapper chain unwraps. Plain object properties and array elements stay as supplied. Only the callback's return is awaited; a Promise inside `Ok` or `Some` stays a Promise.
319
+
320
+ ```ts
321
+ import { safeTry, Ok, println } from "slang-ts";
322
+
323
+ const payload = { result: Ok(42), items: [Ok(7)] };
324
+ const plain = await safeTry(() => payload); // Ok(payload), same object
325
+ if (plain.isOk) println(plain.value === payload); // true
326
+
327
+ const innerPromise = Promise.resolve(42);
328
+ const wrapped = await safeTry(() => Ok(innerPromise));
329
+ // Ok(innerPromise), success value stays Promise<number>.
330
+ if (wrapped.isOk) println(wrapped.value === innerPromise); // true
331
+ ```
332
+
333
+ `{ throw: true }` rethrows errors caught while running the callback or reading its returned wrappers. Returned `Err` values still return normally. A circular wrapper chain returns `Err("Cannot resolve a circular value")`, including with `{ throw: true }`.
334
+
335
+ ```ts
336
+ import { safeTry, Ok, Err, println } from "slang-ts";
337
+
338
+ const returned = await safeTry(() => Ok(Err("Not found")), { throw: true });
339
+ if (returned.isErr) println(returned.error); // "Not found"
311
340
 
312
- // Re-throw critical errors instead of capturing
313
341
  await safeTry(() => {
314
- throw new Error("Critical!");
315
- }, { throw: true });
342
+ throw new Error("Critical failure");
343
+ }, { throw: true }).catch((error: Error) => println(error.message));
344
+ // "Critical failure": the call rejects instead of returning Err.
316
345
  ```
317
346
 
318
347
  ### Pipe
@@ -641,6 +670,21 @@ channel.when({
641
670
 
642
671
  See [example.ts](https://github.com/Hussseinkizz/slang/blob/main/example.ts) for usage of currently implemented methods.
643
672
 
673
+ ## Development
674
+
675
+ Install project dependencies with Bun, then build:
676
+
677
+ ```bash
678
+ bun install
679
+ bun run build
680
+ ```
681
+
682
+ The build runs tests, checks types with TypeScript 7.0.2, then uses tsdown 0.23.1 to produce minified ESM at `dist/index.js` and bundled types at `dist/index.d.ts`. Package imports keep the same entry points. tsdown currently marks its TypeScript 7 integration as experimental; the project build passes with this setup.
683
+
684
+ For building, tsdown requires Node.js `^22.18.0 || ^24.11.0 || >=26.0.0`. This is a build-tool requirement, not a new runtime requirement for Slang consumers.
685
+
686
+ Packaged output passes strict consumer checks with TypeScript 5.9.3 and 7.0.2 under both NodeNext and Bundler resolution, including declaration checking. See [migration context](context.md) for verification details.
687
+
644
688
  ## Contributing
645
689
 
646
690
  Contributions are welcome. I know there are a lot of cool things out there we can bring in.