slang-ts 0.0.2 → 0.0.4

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
@@ -2,7 +2,7 @@
2
2
 
3
3
  Functional programming library for TypeScript.
4
4
 
5
- My experiment to learn more functional programming and other cool programming stuff from other languages as I try to implement them in TypeScript.
5
+ A collection of functional programming utilities and other cool programming stuff from other languages such as rust implemented in TypeScript.
6
6
 
7
7
  ## Install
8
8
 
@@ -19,17 +19,16 @@ npm i slang-ts
19
19
  - [x] Expect
20
20
  - [x] Unwrap (on Option)
21
21
  - [x] Else (on unwrap)
22
- - [ ] Panic!
22
+ - [x] Panic
23
23
  - [x] Zip, Unzip, zipWith
24
- - [ ] Try
25
- - [ ] Catch
24
+ - [x] SafeTry
26
25
  - [x] Match
27
26
  - [x] MatchAll
28
- - [ ] Pipe
27
+ - [x] Pipe
29
28
  - [ ] Map
30
29
  - [x] To (converters, e.g. `userAtom.to('option')`)
31
30
  - [ ] Promises and async utilities
32
- - [ ] Curry
31
+ - [ ] Currys
33
32
 
34
33
  ## Others (Planned)
35
34
 
@@ -46,6 +45,11 @@ import { Ok, Err } from "slang-ts";
46
45
 
47
46
  // Or import multiple at once
48
47
  import { option, Ok, Err, atom, match } from "slang-ts";
48
+
49
+ // Or import under namespace (not so performant)
50
+ import * as slang from "slang-ts";
51
+
52
+ slang.println("Hello world!");
49
53
  ```
50
54
 
51
55
  ### println
@@ -296,6 +300,90 @@ println(unzip(zipped));
296
300
  // [[1, 2, 3], [4, 5, 6]]
297
301
  ```
298
302
 
303
+ ### Pipe
304
+
305
+ Sequential function composition where each function receives a `Result` and returns a `Result`. Accepts plain values, Option, Result, or Atom as initial input.
306
+
307
+ ```ts
308
+ import { pipe, Ok, Err, option, type Result } from "slang-ts";
309
+
310
+ // Create pipeline functions
311
+ const add = (x: number) => (res: Result<number, string>) =>
312
+ res.isOk ? Ok(res.value + x) : res;
313
+
314
+ const multiply = (x: number) => (res: Result<number, string>) =>
315
+ res.isOk ? Ok(res.value * x) : res;
316
+
317
+ // Basic usage
318
+ const result = await pipe(5, add(3), multiply(2)).run();
319
+ println("Result:", result.value); // 16
320
+
321
+ // With Options as initial value
322
+ const fromOption = await pipe(option(10), add(5)).run();
323
+ println("From option:", fromOption.value); // 15
324
+
325
+ // With callbacks and error handling
326
+ const result = await pipe(5, add(3), multiply(2)).run({
327
+ onEach: ({ currentFn, prevResult }) => {
328
+ println("Executed:", currentFn);
329
+ },
330
+ onSuccess: (value) => println("Done:", value),
331
+ onError: (err) => println("Failed:", err.message),
332
+ allowErrors: false, // stops pipeline on first Err
333
+ });
334
+ ```
335
+
336
+ ### SafeTry
337
+
338
+ Wraps potentially throwing functions in try-catch, returning a `Result<T, string>`. Always needs to be awaited as its async.
339
+
340
+ ```ts
341
+ import { safeTry } from "slang-ts";
342
+
343
+ const result = await safeTry(() => {
344
+ if (denom === 0) throw new Error("Cannot divide by zero");
345
+ return num / denom;
346
+ });
347
+
348
+ if (result.isOk) {
349
+ println("Result:", result.value);
350
+ } else {
351
+ println("Error:", result.error);
352
+ }
353
+
354
+ // Async functions work the same way
355
+ const data = await safeTry(async () => {
356
+ const res = await fetch("/api/user");
357
+ return res.json();
358
+ });
359
+
360
+ if (data.isOk) {
361
+ println("User:", data.value);
362
+ }
363
+
364
+ // Re-throw critical errors instead of capturing
365
+ await safeTry(() => {
366
+ throw new Error("Critical!");
367
+ }, { throw: true });
368
+ ```
369
+
370
+ ### Panic
371
+
372
+ Throws an error immediately. Use for unrecoverable failures.
373
+
374
+ ```ts
375
+ import { panic } from "slang-ts";
376
+
377
+ function processUser(user: User | null) {
378
+ if (!user) panic("User cannot be null");
379
+ return user.name;
380
+ }
381
+
382
+ // Guard clause pattern
383
+ const config = loadConfig();
384
+ if (!config.apiKey) panic("API key required");
385
+ ```
386
+
299
387
  And more are to be implemented in coming versions...
300
388
 
301
389
  ## Code Samples
package/dist/index.d.ts CHANGED
@@ -1,281 +1,5 @@
1
- export declare const println: (...args: unknown[]) => void;
2
1
  /**
3
- * Converts between Slang types.
4
- * - `option`: Wraps primitive or symbol description into `Option`
5
- * - `atom`: Converts `Some<string>` to `Atom` or returns symbol Atom
6
- * - `result`: Wraps values into `Ok`, `None` into `Err`
2
+ * Slang - Functional programming utilities for TypeScript
3
+ * Re-exports all types and functions from the modular src folder.
7
4
  */
8
- export declare function _to<T>(value: Option<T>, target: "option"): Option<T>;
9
- export declare function _to<T extends string>(value: Option<T>, target: "atom"): Atom<T>;
10
- export declare function _to<T extends string>(value: Atom<T>, target: "option"): Option<string>;
11
- export declare function _to<T extends string>(value: Atom<T>, target: "atom"): Atom<T>;
12
- export declare function _to<T, E = string>(value: Option<T>, target: "result"): Result<T, E>;
13
- export declare function _to<E = string>(value: Atom<any>, target: "result"): Result<string, E>;
14
- /** Unique symbol to brand atoms */
15
- declare const __atom__: unique symbol;
16
- /** Atom type carrying the original name for hover/type info */
17
- export type Atom<T extends string = string> = symbol & {
18
- readonly [__atom__]: T;
19
- };
20
- /**
21
- * Creates a new, unique atom (non-interned)
22
- * @param name Name of the atom (used for hover/description)
23
- * @example
24
- * const a = atom("loading");
25
- * typeof a; // Atom<"loading">
26
- */
27
- /**
28
- * Creates a new, unique atom (non-interned)
29
- * @param name Name of the atom (used for hover/description)
30
- * @returns `Atom<T>` with chainable `to()`
31
- * @example
32
- * const ready = atom("ready");
33
- * ready.to("option"); // Some("ready")
34
- * ready.to("result"); // Ok("ready")
35
- */
36
- /** Methods available on an Atom */
37
- export interface AtomMethods<T extends string> {
38
- /** Returns the same atom */
39
- to(target: "atom"): Atom<T>;
40
- /** Returns `Option<string>` using the atom description
41
- * @example atom("ready").to("option") // Some("ready")
42
- */
43
- to(target: "option"): Option<string>;
44
- /** Returns `Ok<string>` using the atom description
45
- * @example atom("ready").to("result") // Ok("ready")
46
- */
47
- to(target: "result"): Result<string, string>;
48
- }
49
- export declare function atom<const T extends string>(name: T): Atom<T> & AtomMethods<T>;
50
- declare const __result__: unique symbol;
51
- export type Ok<T> = {
52
- type: "Ok";
53
- value: T;
54
- readonly isOk: true;
55
- readonly isErr: false;
56
- readonly [__result__]: true;
57
- };
58
- export type Err<E> = {
59
- type: "Err";
60
- error: E;
61
- readonly isOk: false;
62
- readonly isErr: true;
63
- readonly [__result__]: true;
64
- };
65
- export type Result<T, E> = (Ok<T> | Err<E>) & ResultMethods<T>;
66
- /**
67
- * Creates a new, successful result
68
- * @param value Value of the result
69
- * @example
70
- * const a = Ok("hello");
71
- * typeof a; // Ok<"hello">
72
- */
73
- /** Methods available on a Result */
74
- export interface ResultMethods<T> {
75
- /** Unwraps the value, throwing for Err
76
- * @example maybeFail().expect("must succeed")
77
- */
78
- expect(msg?: string): T;
79
- /** Returns an unwrap chain that throws if no else is provided
80
- * Use `.else(valueOrFn)` to supply a fallback for Err.
81
- * - If `Ok`, `.else(...)` returns the inner value and ignores fallback.
82
- * - If `Err`, `.else(...)` returns the fallback; if a function, it receives the error.
83
- */
84
- unwrap(): {
85
- /** Fallback value or function to recover from Err
86
- * If a function is provided, it is called with the Err's error.
87
- * Returns the unwrapped value (Ok) or the provided fallback (Err).
88
- */ else(fallback: T | ((error: any) => T)): T;
89
- };
90
- }
91
- /** Creates a new, successful result */
92
- export declare function Ok<T>(value: T): Ok<T> & ResultMethods<T>;
93
- /**
94
- * Creates a new, failed result
95
- * @param error Error of the result
96
- * @example
97
- * const a = Err("error");
98
- * typeof a; // Err<"error">
99
- */
100
- /** Creates a new, failed result */
101
- export declare function Err<E>(error: E): Err<E> & ResultMethods<never>;
102
- declare const __option__: unique symbol;
103
- export type Some<T> = {
104
- type: "Some";
105
- value: T;
106
- readonly isSome: true;
107
- readonly isNone: false;
108
- readonly [__option__]: true;
109
- };
110
- export type None = {
111
- type: "None";
112
- readonly isSome: false;
113
- readonly isNone: true;
114
- readonly [__option__]: true;
115
- };
116
- export type Option<T> = (Some<T> | None) & OptionMethods<T>;
117
- export type NonTruthy = null | undefined | "";
118
- /**
119
- * Creates a new option type from a value
120
- * @param value - the value to be made an option
121
- * @tutorial The returned option will be Some if the value is truthy, and None if it is not (null,undefined,Nan,'')
122
- * @example
123
- * const b = option("hello");
124
- * typeof b; // Some<"hello">
125
- * const c = option(null);
126
- * typeof c; // None
127
- * const d = option(undefined);
128
- * typeof d; // None
129
- * const e = option(0);
130
- * typeof e; // Some<number>
131
- * const f = option("");
132
- * typeof f; // None
133
- * const g = option(false);
134
- * typeof g; // Some<boolean>
135
- */
136
- /** Methods available on an Option */
137
- export interface OptionMethods<T> {
138
- /** Returns the same option */
139
- to(target: "option"): Option<T>;
140
- /** Converts `Some<string>` to `Atom<string>`; throws for `None` or non-string */
141
- to(target: "atom"): Atom<T & string>;
142
- /** Converts to `Result<T, string>`; `None` becomes `Err("Value is None")` */
143
- to(target: "result"): Result<T | (T extends string ? never : Atom<string>), string>;
144
- /**
145
- * Unwraps the option, throwing if `None`.
146
- * @throws Error with provided message or default.
147
- * @example
148
- * option(42).expect(); // 42
149
- * option("").expect("must be present"); // throws
150
- */
151
- expect(msg?: string): T;
152
- /** Returns an unwrap chain that MUST be completed with `.else(...)`.
153
- * If `.else(...)` is not chained, an error is thrown ("Expected else").
154
- * - If `Some`, `.else(...)` is required but ignored for outcome; returns the inner value.
155
- * - If `None`, `.else(...)` provides fallback; if a function, it is called with `undefined`.
156
- * - Fallback result must be truthy; otherwise, throws ("Fallback must be truthy").
157
- */
158
- unwrap(): {
159
- /** Fallback value or transformer to recover from `None`.
160
- * - Function form receives `undefined` and must return a truthy value.
161
- * - Direct value must be truthy.
162
- * Returns the inner value for `Some`, or the validated fallback for `None`.
163
- */ else(fallback: T | ((value: T | undefined) => T)): T;
164
- };
165
- }
166
- /**
167
- * Creates a new option type from a value.
168
- * - Truthy values become `Some<T>`; `null|undefined|""` become `None`.
169
- * - Provides chainable `.to()` and `.expect()` helpers.
170
- * @example
171
- * option("hi").expect(); // "hi"
172
- * option("").expect("cannot be empty"); // throws Error("cannot be empty")
173
- * option("state").to("atom"); // Atom<"state">
174
- * option(null).to("result"); // Err("Value is None")
175
- */
176
- export declare function option<T>(value: T | NonTruthy): Option<T> & OptionMethods<T>;
177
- /**
178
- * Pattern matching for `Result` and `Option` — exhaustiveness enforced.
179
- *
180
- * Returns the value returned by the selected handler. If all handlers return
181
- * `Result` or `Option`, TypeScript will infer that automatically.
182
- */
183
- export declare function match<T, E, R>(value: Result<T, E> | (Result<any, any> & ResultMethods<any>), patterns: {
184
- Ok: ((v: Ok<T>) => R) | (() => R);
185
- Err: ((e: Err<E>) => R) | (() => R);
186
- }): R;
187
- export declare function match<T, R>(value: Some<T> | None, patterns: {
188
- Some: ((v: Some<T>) => R) | (() => R);
189
- None: ((v: None) => R) | (() => R);
190
- }): R;
191
- /**
192
- * Allowed keys in matchAll patterns.
193
- * - Strings, numbers, and Atom descriptions.
194
- * - Booleans are represented as "true" | "false" strings
195
- */
196
- type MatchKey = string | number | symbol;
197
- /**
198
- * Type-safe pattern object: must always have `_` fallback.
199
- */
200
- type MatchPatterns<V, R> = {
201
- [K in MatchKey]?: (v: V) => R;
202
- } & {
203
- _: () => R;
204
- };
205
- /**
206
- * Matches a value against literal or Atom cases by *semantic name*.
207
- * - Supports string, number, booleans and Atom (symbol) values.
208
- * - Unsupported will throw an error. (objects, arrays, functions, etc)
209
- * - For Atoms, uses their description as a key (e.g. atom("ready") → "ready").
210
- * - Requires a `_` default handler.
211
- *
212
- * @example
213
- * matchAll(ready, {
214
- * 1: () => println("One"),
215
- * 2: () => println("Two"),
216
- * 0: () => println("Zero"),
217
- * true: () => println("True"),
218
- * false: () => println("False"),
219
- * ready: () => println("Ready!"),
220
- * failed: () => println("Failed!"),
221
- * _: () => println("Unknown!"),
222
- * });
223
- */
224
- export declare function matchAll<T extends MatchKey | boolean, R>(value: T, patterns: MatchPatterns<T, R>): R;
225
- /**
226
- * Combines multiple collections element-wise into tuples.
227
- * - All inputs must be the same type (all arrays, all Sets, or all objects).
228
- * - By default, only arrays are allowed; set `includeValues: true` to extract values from Sets/Objects.
229
- * - Stops at shortest collection by default; use `fillValue` to extend to longest.
230
- * - Transforms columns into rows for parallel iteration.
231
- * @param inputs Collections of the same type to combine
232
- * @param options Configuration: `fillValue` extends to longest, `includeValues` extracts values from Sets/Objects (default: false)
233
- * @returns Array of tuples, one per index position
234
- * @example
235
- * zip([[1, 2], ['a', 'b']]); // [[1, 'a'], [2, 'b']]
236
- * zip([[1, 2], ['a']], { fillValue: 'x' }); // [[1, 'a'], [2, 'x']]
237
- * const s1 = new Set([1, 2]); const s2 = new Set([3, 4]);
238
- * zip([s1, s2], { includeValues: true }); // [[1, 3], [2, 4]]
239
- */
240
- export declare function zip<T extends readonly any[]>(inputs: {
241
- [K in keyof T]: Iterable<T[K]> | {
242
- [key: string]: T[K];
243
- };
244
- }, options?: {
245
- fillValue?: T[number];
246
- includeValues?: boolean;
247
- }): T[number][][];
248
- /**
249
- * Combines multiple collections element-wise and transforms each tuple.
250
- * - All inputs must be the same type (all arrays, all Sets, or all objects).
251
- * - By default, only arrays are allowed; set `includeValues: true` to extract values from Sets/Objects.
252
- * - Applies a function to each set of corresponding elements.
253
- * - Useful for aggregating, computing, or transforming aligned data.
254
- * @param inputs Collections of the same type to combine
255
- * @param fn Transform function applied to each tuple
256
- * @param options Configuration: `fillValue` extends to longest, `includeValues` extracts values from Sets/Objects (default: false)
257
- * @returns Array of transformed results
258
- * @example
259
- * zipWith([[1, 2], [3, 4]], (t) => t[0] + t[1]); // [4, 6]
260
- * zipWith([[1, 2], [10]], (t) => t.reduce((a, b) => a + b, 0), { fillValue: 0 }); // [11, 2]
261
- */
262
- export declare function zipWith<T extends readonly any[], R>(inputs: {
263
- [K in keyof T]: Iterable<T[K]> | {
264
- [key: string]: T[K];
265
- };
266
- }, fn: (tuple: T[number][]) => R, options?: {
267
- fillValue?: T[number];
268
- includeValues?: boolean;
269
- }): R[];
270
- /**
271
- * Unzips an array of tuples back into separate arrays.
272
- * - Reverses the zip operation: transforms rows to columns.
273
- * - Useful for separating previously combined collections.
274
- * @param zipped Array of tuples (rows) to transpose
275
- * @returns Array of arrays (columns), one per tuple position
276
- * @example
277
- * const zipped = [[1, 'a'], [2, 'b'], [3, 'c']];
278
- * unzip(zipped); // [[1, 2, 3], ['a', 'b', 'c']]
279
- */
280
- export declare function unzip<T>(zipped: T[][]): T[][];
281
- export {};
5
+ export * from "./src";
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- var _=(...j)=>{globalThis?.console?.log?.(...j)},Z=(j)=>{let B=globalThis?.queueMicrotask;if(typeof B==="function")B(j);else Promise.resolve().then(j)};function $(j,B){let G=(H)=>H!=null&&typeof H==="object"&&("isSome"in H)&&("isNone"in H);if(j&&(j.type==="Ok"||j.type==="Err"))throw Error("Cannot convert a Result to any other type");switch(B){case"option":{if(G(j))return j;if(typeof j==="symbol")return Y(j.description);return Y(j)}case"atom":{if(G(j)){if(j.isNone)throw Error("Cannot convert None to Atom");if(typeof j.value!=="string")throw Error("Only string values can be converted to Atom");return N(j.value)}if(typeof j==="symbol")return j;throw Error(`Cannot convert type ${typeof j} to Atom`)}case"result":{if(G(j))return j.isSome?X(j.value):R("Value is None");if(typeof j==="symbol")return X(j.description);return X(j)}default:throw Error(`Invalid target: ${B}`)}}function N(j){let B=Symbol(j),G=Object(B),H=(D)=>$(B,D);return G.to=H,G}function X(j){let B=Object.freeze({type:"Ok",value:j,isOk:!0,isErr:!1});return{...B,expect:(H)=>B.value,unwrap:()=>{let H=!1;return Z(()=>{}),{else(D){return H=!0,B.value}}}}}function R(j){let B=Object.freeze({type:"Err",error:j,isOk:!1,isErr:!0}),G=(D,I)=>{if(typeof D==="string")return D;if(D&&typeof D==="object"&&"message"in D)return String(D.message);return I??String(D)};return{...B,expect:(D)=>{throw Error(D??G(B.error,"Expected Ok, got Err"))},unwrap:()=>{let D=!1;return Z(()=>{if(!D){let I=G(B.error,"Expected Ok, got Err");throw Error(I)}}),{else(I){if(D=!0,typeof I==="function")return I(B.error);return I}}}}}var C=(j)=>{return j===null||j===void 0||j===""||Number.isNaN(j)||j===1/0||j===-1/0};function q(j){if(C(j))throw Error("Cannot wrap null, undefined, NaN, or empty string in Some");return Object.freeze({type:"Some",value:j,isSome:!0,isNone:!1})}var F=Object.freeze({type:"None",isSome:!1,isNone:!0});function Y(j){let B=C(j)?F:q(j);return{...B,to:(P)=>$(B,P),expect:(P)=>{if(B.isSome)return B.value;throw Error(P??"Expected Some, got None")},unwrap:()=>{let P=!1,Q=B;return Z(()=>{if(!P)throw Error("Expected else")}),{else(T){if(P=!0,Q.isSome)return Q.value;let J=typeof T==="function"?T(void 0):T;if(Y(J).isNone)throw Error("Fallback must be truthy");return J}}}}}function A(j,B){let G=B[j.type];if(!G)throw Error(`Non-exhaustive match — missing handler for '${j.type}'`);return G(j)}var L=(j)=>{return typeof j==="string"||typeof j==="number"||typeof j==="boolean"||typeof j==="symbol"};function E(j,B){let G=(Q)=>typeof Q?.valueOf==="function"?Q.valueOf():Q,H=(Q)=>typeof Q==="symbol"?Q.description:void 0,D=G(j);if(!L(D))throw Error(`Unsupported match all value type: ${typeof D}`);let I=H(D)??D,P=typeof I==="boolean"||typeof I==="number"?String(I):I;if(P!=null&&P in B)return B[P](j);return B._()}function S(j,B=!1){if(!B&&!Array.isArray(j))throw Error("Only arrays allowed when includeValues=false");if(Array.isArray(j))return j;if(j instanceof Set)return Array.from(j);return Object.values(j)}function U(j,B){let{fillValue:G,includeValues:H=!1}=B||{};if(j.length===0)return[];let D=j.map((J)=>S(J,H)),I=Math.max(...D.map((J)=>J.length)),P=Math.min(...D.map((J)=>J.length)),Q=G===void 0?P:I,T=[];for(let J=0;J<Q;J++)T.push(D.map((W)=>J<W.length?W[J]:G));return T}function K(j,B,G){return U(j,G).map(B)}function M(j){if(j.length===0)return[];let B=j[0]?.length??0,G=Array.from({length:B},()=>[]);for(let H of j)H.forEach((D,I)=>G[I]?.push(D));return G}export{K as zipWith,U as zip,M as unzip,_ as println,Y as option,E as matchAll,A as match,N as atom,$ as _to,X as Ok,R as Err};
1
+ var W=(G)=>{let B=globalThis?.queueMicrotask;if(typeof B==="function")B(G);else Promise.resolve().then(G)},C=(G)=>G!=null&&typeof G==="object"&&("type"in G)&&(G.type==="Ok"||G.type==="Err"),F=(G)=>G!=null&&typeof G==="object"&&("isSome"in G)&&("isNone"in G),z=(G)=>G!=null&&typeof G==="object"&&typeof G.valueOf?.()==="symbol";function q(G){if(z(G))return{ok:!0,value:G.valueOf().description};if(C(G)){if(G.isOk)return{ok:!0,value:G.value};return{ok:!1,error:typeof G.error==="string"?G.error:String(G.error)}}if(F(G)){if(G.isSome)return{ok:!0,value:G.value};return{ok:!1,error:"Option was None"}}return{ok:!0,value:G}}var O=(...G)=>{globalThis?.console?.log?.(...G)};function E(G){throw Error(G)}function L(G){let B=Object.freeze({type:"Ok",value:G,isOk:!0,isErr:!1});return{...B,expect:(J)=>B.value,unwrap:()=>{let J=!1;return W(()=>{}),{else(Q){return J=!0,B.value}}}}}function I(G){return{...Object.freeze({type:"Err",error:G,isOk:!1,isErr:!0}),expect:(J)=>{throw Error(J??G)},unwrap:()=>{let J=!1;return W(()=>{if(!J)throw Error(G)}),{else(Q){if(J=!0,typeof Q==="function")return Q(G);return Q}}}}}var K=(G)=>{return G===null||G===void 0||G===""||Number.isNaN(G)||G===1/0||G===-1/0};function R(G){if(K(G))throw Error("Cannot wrap null, undefined, NaN, or empty string in Some");return Object.freeze({type:"Some",value:G,isSome:!0,isNone:!1})}var g=Object.freeze({type:"None",isSome:!1,isNone:!0}),N=null;function M(G){N=G}function U(G){let B=K(G)?g:R(G);return{...B,to:($)=>{if(!N)throw Error("Converter not initialized");return N(B,$)},expect:($)=>{if(B.isSome)return B.value;throw Error($??"Expected Some, got None")},unwrap:()=>{let $=!1,X=B;return W(()=>{if(!$)throw Error("Expected else")}),{else(j){if($=!0,X.isSome)return X.value;let Y=typeof j==="function"?j(void 0):j;if(K(Y))throw Error("Fallback must be truthy");return Y}}}}}var P=null;function _(G){P=G}function S(G){let B=Symbol(G),D=Object(B),J=(Q)=>{if(!P)throw Error("Converter not initialized");return P(B,Q)};return D.to=J,D}var T=(G)=>G!=null&&typeof G==="object"&&("isSome"in G)&&("isNone"in G);function V(G,B){if(G&&(G.type==="Ok"||G.type==="Err"))throw Error("Cannot convert a Result to any other type");switch(B){case"option":{if(T(G))return G;if(typeof G==="symbol")return U(G.description);return U(G)}case"atom":{if(T(G)){if(G.isNone)throw Error("Cannot convert None to Atom");if(typeof G.value!=="string")throw Error("Only string values can be converted to Atom");return S(G.value)}if(typeof G==="symbol")return G;throw Error(`Cannot convert type ${typeof G} to Atom`)}case"result":{if(T(G))return G.isSome?L(G.value):I("Value is None");if(typeof G==="symbol")return L(G.description);return L(G)}default:throw Error(`Invalid target: ${B}`)}}M(V);_(V);function w(G,B){let D=B[G.type];if(!D)throw Error(`Non-exhaustive match — missing handler for '${G.type}'`);return D(G)}var b=(G)=>{return typeof G==="string"||typeof G==="number"||typeof G==="boolean"||typeof G==="symbol"};function k(G,B){let D=(X)=>typeof X?.valueOf==="function"?X.valueOf():X,J=(X)=>typeof X==="symbol"?X.description:void 0,Q=D(G);if(!b(Q))throw Error(`Unsupported match all value type: ${typeof Q}`);let H=J(Q)??Q,$=typeof H==="boolean"||typeof H==="number"?String(H):H;if($!=null&&$ in B)return B[$](G);return B._()}function h(G,B=!1){if(!B&&!Array.isArray(G))throw Error("Only arrays allowed when includeValues=false");if(Array.isArray(G))return G;if(G instanceof Set)return Array.from(G);return Object.values(G)}function A(G,B){let{fillValue:D,includeValues:J=!1}=B||{};if(G.length===0)return[];let Q=G.map((Y)=>h(Y,J)),H=Math.max(...Q.map((Y)=>Y.length)),$=Math.min(...Q.map((Y)=>Y.length)),X=D===void 0?$:H,j=[];for(let Y=0;Y<X;Y++)j.push(Q.map((Z)=>Y<Z.length?Z[Y]:D));return j}function y(G,B,D){return A(G,D).map(B)}function f(G){if(G.length===0)return[];let B=G[0]?.length??0,D=Array.from({length:B},()=>[]);for(let J of G)J.forEach((Q,H)=>D[H]?.push(Q));return D}async function m(G,B){let D=B?.throw??!1;try{let J=await G(),Q=q(J);if(Q.ok)return L(Q.value);return I(Q.error)}catch(J){let Q=J instanceof Error?J.message:String(J);if(D)throw J instanceof Error?J:Error(Q);return I(Q)}}function x(G){return G.error??"Unknown error"}function d(G){let B=q(G);if(B.ok)return L(B.value);return I(B.error)}async function c(G,B){try{let D=await G(B);if(!C(D))return I("Pipeline function must return a Result");return D}catch(D){let J=D instanceof Error?D.message:String(D);return I(J)}}function p(G,...B){return{async run(D){let{onEach:J,onSuccess:Q,onError:H,allowErrors:$=!1}=D??{},X=d(G);for(let j=0;j<B.length;j++){let Y=B[j],Z=B[j+1];if(X.isErr&&!$)return H?.(Error(x(X))),X;X=await c(Y,X),J?.({prevResult:X,currentFn:Y.name||`fn${j+1}`,nextFn:Z?Z.name||`fn${j+2}`:void 0})}if(X.isOk)Q?.(X.value);else H?.(Error(x(X)));return X}}}export{y as zipWith,A as zip,f as unzip,W as scheduleMicrotask,m as safeTry,O as println,p as pipe,E as panic,U as option,k as matchAll,w as match,K as isFalsy,S as atom,V as _to,L as Ok,I as Err};
@@ -0,0 +1,40 @@
1
+ import type { Option } from "./option";
2
+ import type { Result } from "./result";
3
+ /** Unique symbol to brand atoms */
4
+ declare const __atom__: unique symbol;
5
+ /** Atom type carrying the original name for hover/type info */
6
+ export type Atom<T extends string = string> = symbol & {
7
+ readonly [__atom__]: T;
8
+ };
9
+ /** Methods available on an Atom */
10
+ export interface AtomMethods<T extends string> {
11
+ /** Returns the same atom */
12
+ to(target: "atom"): Atom<T>;
13
+ /**
14
+ * Returns `Option<string>` using the atom description.
15
+ * @example atom("ready").to("option") // Some("ready")
16
+ */
17
+ to(target: "option"): Option<string>;
18
+ /**
19
+ * Returns `Ok<string>` using the atom description.
20
+ * @example atom("ready").to("result") // Ok("ready")
21
+ */
22
+ to(target: "result"): Result<string, string>;
23
+ }
24
+ /**
25
+ * Sets the _to converter function (called from to.ts to break circular dep).
26
+ * @internal
27
+ */
28
+ export declare function setToConverter(fn: (value: any, target: string) => any): void;
29
+ /**
30
+ * Creates a new, unique atom (non-interned).
31
+ * - Atoms are symbols with additional methods for type-safe conversions.
32
+ * @param name - Name of the atom (used for hover/description).
33
+ * @returns `Atom<T>` with chainable `to()` method for conversions.
34
+ * @example
35
+ * const ready = atom("ready");
36
+ * ready.to("option"); // Some("ready")
37
+ * ready.to("result"); // Ok("ready")
38
+ */
39
+ export declare function atom<const T extends string>(name: T): Atom<T> & AtomMethods<T>;
40
+ export {};
@@ -0,0 +1,16 @@
1
+ export { scheduleMicrotask } from "./internals";
2
+ export { println } from "./println";
3
+ export { panic } from "./panic";
4
+ export { Ok, Err } from "./result";
5
+ export type { Result, ResultMethods, Ok as OkType, Err as ErrType } from "./result";
6
+ export { option, isFalsy } from "./option";
7
+ export type { Option, OptionMethods, Some, None, NonTruthy } from "./option";
8
+ export { atom } from "./atom";
9
+ export type { Atom, AtomMethods } from "./atom";
10
+ import "./to";
11
+ export { _to } from "./to";
12
+ export { match, matchAll } from "./match";
13
+ export { zip, zipWith, unzip } from "./zip";
14
+ export { safeTry } from "./safe-try";
15
+ export { pipe } from "./pipe";
16
+ export type { PipeFn, PipeEachContext, PipeRunOptions, Pipeline } from "./pipe";
@@ -0,0 +1,26 @@
1
+ import type { Result } from "./result";
2
+ import type { Option } from "./option";
3
+ /**
4
+ * Schedules a microtask; falls back to Promise if unavailable.
5
+ * Used internally for deferred error handling in unwrap chains.
6
+ */
7
+ export declare const scheduleMicrotask: (fn: () => void) => void;
8
+ /** Type guard for Result */
9
+ export declare const isResult: (value: unknown) => value is Result<unknown, unknown>;
10
+ /** Type guard for Option */
11
+ export declare const isOption: (value: unknown) => value is Option<unknown>;
12
+ /** Type guard for Atom (boxed symbol) */
13
+ export declare const isAtom: (value: unknown) => boolean;
14
+ /** Evaluated value result type */
15
+ export type EvaluatedValue = {
16
+ ok: true;
17
+ value: unknown;
18
+ } | {
19
+ ok: false;
20
+ error: string;
21
+ };
22
+ /**
23
+ * Extracts inner value from Slang types (Atom, Result, Option) or plain values.
24
+ * Returns a discriminated union indicating success or failure.
25
+ */
26
+ export declare function evaluateValue<T>(value: T): EvaluatedValue;
@@ -0,0 +1,51 @@
1
+ import type { Ok, Err, Result, ResultMethods } from "./result";
2
+ import type { Some, None } from "./option";
3
+ /**
4
+ * Pattern matching for `Result` and `Option` — exhaustiveness enforced.
5
+ *
6
+ * Returns the value returned by the selected handler. If all handlers return
7
+ * `Result` or `Option`, TypeScript will infer that automatically.
8
+ */
9
+ export declare function match<T, E, R>(value: Result<T, E> | (Result<any, any> & ResultMethods<any>), patterns: {
10
+ Ok: ((v: Ok<T>) => R) | (() => R);
11
+ Err: ((e: Err<E>) => R) | (() => R);
12
+ }): R;
13
+ export declare function match<T, R>(value: Some<T> | None, patterns: {
14
+ Some: ((v: Some<T>) => R) | (() => R);
15
+ None: ((v: None) => R) | (() => R);
16
+ }): R;
17
+ /**
18
+ * Allowed keys in matchAll patterns.
19
+ * - Strings, numbers, and Atom descriptions.
20
+ * - Booleans are represented as "true" | "false" strings
21
+ */
22
+ type MatchKey = string | number | symbol;
23
+ /**
24
+ * Type-safe pattern object: must always have `_` fallback.
25
+ */
26
+ type MatchPatterns<V, R> = {
27
+ [K in MatchKey]?: (v: V) => R;
28
+ } & {
29
+ _: () => R;
30
+ };
31
+ /**
32
+ * Matches a value against literal or Atom cases by *semantic name*.
33
+ * - Supports string, number, booleans and Atom (symbol) values.
34
+ * - Unsupported will throw an error. (objects, arrays, functions, etc)
35
+ * - For Atoms, uses their description as a key (e.g. atom("ready") → "ready").
36
+ * - Requires a `_` default handler.
37
+ *
38
+ * @example
39
+ * matchAll(ready, {
40
+ * 1: () => println("One"),
41
+ * 2: () => println("Two"),
42
+ * 0: () => println("Zero"),
43
+ * true: () => println("True"),
44
+ * false: () => println("False"),
45
+ * ready: () => println("Ready!"),
46
+ * failed: () => println("Failed!"),
47
+ * _: () => println("Unknown!"),
48
+ * });
49
+ */
50
+ export declare function matchAll<T extends MatchKey | boolean, R>(value: T, patterns: MatchPatterns<T, R>): R;
51
+ export {};
@@ -0,0 +1,85 @@
1
+ import type { Atom } from "./atom";
2
+ import type { Result } from "./result";
3
+ declare const __option__: unique symbol;
4
+ export type Some<T> = {
5
+ type: "Some";
6
+ value: T;
7
+ readonly isSome: true;
8
+ readonly isNone: false;
9
+ readonly [__option__]: true;
10
+ };
11
+ export type None = {
12
+ type: "None";
13
+ readonly isSome: false;
14
+ readonly isNone: true;
15
+ readonly [__option__]: true;
16
+ };
17
+ export type Option<T> = (Some<T> | None) & OptionMethods<T>;
18
+ /** Values treated as falsy by Option */
19
+ export type NonTruthy = null | undefined | "";
20
+ /** Methods available on an Option */
21
+ export interface OptionMethods<T> {
22
+ /** Returns the same option */
23
+ to(target: "option"): Option<T>;
24
+ /** Converts `Some<string>` to `Atom<string>`; throws for `None` or non-string */
25
+ to(target: "atom"): Atom<T & string>;
26
+ /** Converts to `Result<T, string>`; `None` becomes `Err("Value is None")` */
27
+ to(target: "result"): Result<T | (T extends string ? never : Atom<string>), string>;
28
+ /**
29
+ * Unwraps the option, throwing if `None`.
30
+ * @throws Error with provided message or default.
31
+ * @example
32
+ * option(42).expect(); // 42
33
+ * option("").expect("must be present"); // throws
34
+ */
35
+ expect(msg?: string): T;
36
+ /**
37
+ * Returns an unwrap chain that MUST be completed with `.else(...)`.
38
+ * If `.else(...)` is not chained, an error is thrown ("Expected else").
39
+ * - If `Some`, `.else(...)` is required but ignored for outcome; returns the inner value.
40
+ * - If `None`, `.else(...)` provides fallback; if a function, it is called with `undefined`.
41
+ * - Fallback result must be truthy; otherwise, throws ("Fallback must be truthy").
42
+ */
43
+ unwrap(): {
44
+ /**
45
+ * Fallback value or transformer to recover from `None`.
46
+ * - Function form receives `undefined` and must return a truthy value.
47
+ * - Direct value must be truthy.
48
+ * Returns the inner value for `Some`, or the validated fallback for `None`.
49
+ */
50
+ else(fallback: T | ((value: T | undefined) => T)): T;
51
+ };
52
+ }
53
+ /**
54
+ * Checks if a value is falsy for Option purposes.
55
+ * Falsy: null, undefined, empty string, NaN, Infinity, -Infinity
56
+ */
57
+ export declare const isFalsy: (value: any) => boolean;
58
+ /**
59
+ * Creates a new truthy option.
60
+ * @param value - the value of the option
61
+ * @throws Error if value is falsy
62
+ * @example
63
+ * const a = Some("hello");
64
+ * typeof a; // Some<"hello">
65
+ */
66
+ declare function Some<T>(value: T): Some<T>;
67
+ /** Singleton None value */
68
+ declare const None: None;
69
+ /**
70
+ * Sets the _to converter function (called from to.ts to break circular dep).
71
+ * @internal
72
+ */
73
+ export declare function setToConverter(fn: (value: any, target: string) => any): void;
74
+ /**
75
+ * Creates a new option type from a value.
76
+ * - Truthy values become `Some<T>`; `null|undefined|""` become `None`.
77
+ * - Provides chainable `.to()`, `.expect()`, and `.unwrap()` helpers.
78
+ * @example
79
+ * option("hi").expect(); // "hi"
80
+ * option("").expect("cannot be empty"); // throws Error("cannot be empty")
81
+ * option("state").to("atom"); // Atom<"state">
82
+ * option(null).to("result"); // Err("Value is None")
83
+ */
84
+ export declare function option<T>(value: T | NonTruthy): Option<T> & OptionMethods<T>;
85
+ export { Some, None };
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Throws an error immediately.
3
+ * Use for unrecoverable failures or guard clauses.
4
+ * @param message - Error message
5
+ * @example
6
+ * panic("Critical!");
7
+ *
8
+ * // Guard clause pattern
9
+ * if (!config.apiKey) panic("API key required");
10
+ */
11
+ export declare function panic(message: string): never;
@@ -0,0 +1,47 @@
1
+ import type { Result } from "./result";
2
+ /** Function that transforms one Result into another */
3
+ export type PipeFn<T = any, E = any> = (input: Result<T, E>) => Result<any, any> | Promise<Result<any, any>>;
4
+ /** Context passed to onEach callback */
5
+ export type PipeEachContext = {
6
+ prevResult: Result<any, any>;
7
+ currentFn: string;
8
+ nextFn: string | undefined;
9
+ };
10
+ /** Options for pipeline execution */
11
+ export type PipeRunOptions = {
12
+ /** Called after each function executes */
13
+ onEach?: (ctx: PipeEachContext) => void;
14
+ /** Called when pipeline completes successfully */
15
+ onSuccess?: (value: any) => void;
16
+ /** Called when pipeline encounters an error (only when allowErrors is false) */
17
+ onError?: (error: Error) => void;
18
+ /** If true, continues pipeline even when a function returns Err */
19
+ allowErrors?: boolean;
20
+ };
21
+ /** Pipeline object returned by pipe() */
22
+ export type Pipeline<T, E> = {
23
+ run: (options?: PipeRunOptions) => Promise<Result<T, E>>;
24
+ };
25
+ /**
26
+ * Creates a pipeline for sequential function composition.
27
+ * Each function receives the previous Result and returns a new Result.
28
+ *
29
+ * @param initial - Starting value (plain value, Option, Result, or Atom)
30
+ * @param fns - Pipeline functions that transform Results
31
+ * @returns Pipeline object with `.run()` method
32
+ *
33
+ * @example
34
+ * const add = (x: number) => (res: Result<number, string>) =>
35
+ * res.isOk ? Ok(res.value + x) : res;
36
+ *
37
+ * const result = await pipe(5, add(3), add(2)).run();
38
+ * // result.value === 10
39
+ *
40
+ * @example
41
+ * const result = await pipe(option(5), add(3)).run({
42
+ * onEach: ({ currentFn, prevResult }) => console.log(currentFn, prevResult),
43
+ * onSuccess: (value) => console.log("Done:", value),
44
+ * allowErrors: false,
45
+ * });
46
+ */
47
+ export declare function pipe<T, E = string>(initial: T, ...fns: PipeFn[]): Pipeline<any, E>;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Logs the provided arguments to the console.
3
+ * - Uses `globalThis.console.log` if available.
4
+ * - Supports variadic arguments.
5
+ * @param args - The arguments to log. Can be of any type.
6
+ */
7
+ export declare const println: (...args: unknown[]) => void;
@@ -0,0 +1,56 @@
1
+ declare const __result__: unique symbol;
2
+ export type Ok<T> = {
3
+ type: "Ok";
4
+ value: T;
5
+ readonly isOk: true;
6
+ readonly isErr: false;
7
+ readonly [__result__]: true;
8
+ };
9
+ export type Err<E> = {
10
+ type: "Err";
11
+ error: E;
12
+ readonly isOk: false;
13
+ readonly isErr: true;
14
+ readonly [__result__]: true;
15
+ };
16
+ /** Discriminated union: mutually exclusive Ok or Err */
17
+ export type Result<T, E> = (Ok<T> | Err<E>) & ResultMethods<T>;
18
+ /** Methods available on a Result */
19
+ export interface ResultMethods<T> {
20
+ /**
21
+ * Unwraps the value, throwing for Err.
22
+ * @example maybeFail().expect("must succeed")
23
+ */
24
+ expect(msg?: string): T;
25
+ /**
26
+ * Returns an unwrap chain that throws if no else is provided.
27
+ * Use `.else(valueOrFn)` to supply a fallback for Err.
28
+ * - If `Ok`, `.else(...)` returns the inner value and ignores fallback.
29
+ * - If `Err`, `.else(...)` returns the fallback; if a function, it receives the error.
30
+ */
31
+ unwrap(): {
32
+ /**
33
+ * Fallback value or function to recover from Err.
34
+ * If a function is provided, it is called with the Err's error.
35
+ * Returns the unwrapped value (Ok) or the provided fallback (Err).
36
+ */
37
+ else(fallback: T | ((error: any) => T)): T;
38
+ };
39
+ }
40
+ /**
41
+ * Creates a new, successful result.
42
+ * @param value Value of the result
43
+ * @example
44
+ * const a = Ok("hello");
45
+ * typeof a; // Ok<"hello">
46
+ */
47
+ export declare function Ok<T>(value: T): Ok<T> & ResultMethods<T>;
48
+ /**
49
+ * Creates a new, failed result with a string error message.
50
+ * @param error Error message (must be a string)
51
+ * @example
52
+ * const a = Err("something went wrong");
53
+ * typeof a; // Err<string>
54
+ */
55
+ export declare function Err(error: string): Err<string> & ResultMethods<never>;
56
+ export {};
@@ -0,0 +1,28 @@
1
+ import type { Result } from "./result";
2
+ /** Options for safeTry behavior */
3
+ type SafeTryOptions = {
4
+ /** If true, re-throws the error instead of capturing it */
5
+ throw?: boolean;
6
+ };
7
+ /**
8
+ * Wraps a function in try-catch, returns `Result<T, string>`.
9
+ * - Always returns a Promise resolving to Ok or Err.
10
+ * - Internally evaluates return values from Atom, Result, or Option types.
11
+ * - Use `{ throw: true }` to re-throw errors instead of capturing.
12
+ *
13
+ * @param fn - Function to execute (sync or async)
14
+ * @param options - `{ throw?: boolean }`
15
+ * @returns Promise of `Result<T, string>`
16
+ *
17
+ * @example
18
+ * const result = await safeTry(() => "Hello");
19
+ * if (result.isOk) println(result.value);
20
+ *
21
+ * @example
22
+ * const result = await safeTry(() => {
23
+ * throw new Error("Oops!");
24
+ * });
25
+ * if (result.isErr) println(result.error);
26
+ */
27
+ export declare function safeTry<T>(fn: () => T | Promise<T>, options?: SafeTryOptions): Promise<Result<T, string>>;
28
+ export {};
@@ -0,0 +1,15 @@
1
+ import type { Atom } from "./atom";
2
+ import type { Option } from "./option";
3
+ import type { Result } from "./result";
4
+ /**
5
+ * Converts between Slang types.
6
+ * - `option`: Wraps primitive or symbol description into `Option`
7
+ * - `atom`: Converts `Some<string>` to `Atom` or returns symbol Atom
8
+ * - `result`: Wraps values into `Ok`, `None` into `Err`
9
+ */
10
+ export declare function _to<T>(value: Option<T>, target: "option"): Option<T>;
11
+ export declare function _to<T extends string>(value: Option<T>, target: "atom"): Atom<T>;
12
+ export declare function _to<T extends string>(value: Atom<T>, target: "option"): Option<string>;
13
+ export declare function _to<T extends string>(value: Atom<T>, target: "atom"): Atom<T>;
14
+ export declare function _to<T, E = string>(value: Option<T>, target: "result"): Result<T, E>;
15
+ export declare function _to<E = string>(value: Atom<any>, target: "result"): Result<string, E>;
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Combines multiple collections element-wise into tuples.
3
+ * - All inputs must be the same type (all arrays, all Sets, or all objects).
4
+ * - By default, only arrays are allowed; set `includeValues: true` to extract values from Sets/Objects.
5
+ * - Stops at shortest collection by default; use `fillValue` to extend to longest.
6
+ * - Transforms columns into rows for parallel iteration.
7
+ * @param inputs Collections of the same type to combine
8
+ * @param options Configuration: `fillValue` extends to longest, `includeValues` extracts values from Sets/Objects (default: false)
9
+ * @returns Array of tuples, one per index position
10
+ * @example
11
+ * zip([[1, 2], ['a', 'b']]); // [[1, 'a'], [2, 'b']]
12
+ * zip([[1, 2], ['a']], { fillValue: 'x' }); // [[1, 'a'], [2, 'x']]
13
+ * const s1 = new Set([1, 2]); const s2 = new Set([3, 4]);
14
+ * zip([s1, s2], { includeValues: true }); // [[1, 3], [2, 4]]
15
+ */
16
+ export declare function zip<T extends readonly any[]>(inputs: {
17
+ [K in keyof T]: Iterable<T[K]> | {
18
+ [key: string]: T[K];
19
+ };
20
+ }, options?: {
21
+ fillValue?: T[number];
22
+ includeValues?: boolean;
23
+ }): T[number][][];
24
+ /**
25
+ * Combines multiple collections element-wise and transforms each tuple.
26
+ * - All inputs must be the same type (all arrays, all Sets, or all objects).
27
+ * - By default, only arrays are allowed; set `includeValues: true` to extract values from Sets/Objects.
28
+ * - Applies a function to each set of corresponding elements.
29
+ * - Useful for aggregating, computing, or transforming aligned data.
30
+ * @param inputs Collections of the same type to combine
31
+ * @param fn Transform function applied to each tuple
32
+ * @param options Configuration: `fillValue` extends to longest, `includeValues` extracts values from Sets/Objects (default: false)
33
+ * @returns Array of transformed results
34
+ * @example
35
+ * zipWith([[1, 2], [3, 4]], (t) => t[0] + t[1]); // [4, 6]
36
+ * zipWith([[1, 2], [10]], (t) => t.reduce((a, b) => a + b, 0), { fillValue: 0 }); // [11, 2]
37
+ */
38
+ export declare function zipWith<T extends readonly any[], R>(inputs: {
39
+ [K in keyof T]: Iterable<T[K]> | {
40
+ [key: string]: T[K];
41
+ };
42
+ }, fn: (tuple: T[number][]) => R, options?: {
43
+ fillValue?: T[number];
44
+ includeValues?: boolean;
45
+ }): R[];
46
+ /**
47
+ * Unzips an array of tuples back into separate arrays.
48
+ * - Reverses the zip operation: transforms rows to columns.
49
+ * - Useful for separating previously combined collections.
50
+ * @param zipped Array of tuples (rows) to transpose
51
+ * @returns Array of arrays (columns), one per tuple position
52
+ * @example
53
+ * const zipped = [[1, 'a'], [2, 'b'], [3, 'c']];
54
+ * unzip(zipped); // [[1, 2, 3], ['a', 'b', 'c']]
55
+ */
56
+ export declare function unzip<T>(zipped: T[][]): T[][];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "slang-ts",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "description": "Functional programming library for TypeScript",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",