slang-ts 0.2.0 → 0.2.2
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 +2 -3
- package/README.md +4 -3
- package/package.json +2 -1
- package/skill/SKILL.md +190 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
Everything notable in `slang-ts`, grouped by area. No release diary
|
|
3
|
+
Everything notable in `slang-ts`, grouped by area. No release diary: just what's here.
|
|
4
4
|
|
|
5
5
|
## Results and flow
|
|
6
6
|
|
|
7
|
-
- `Ok(value, message?)` keeps an optional success message on the result
|
|
8
|
-
the user. Results without one have no `message` property.
|
|
7
|
+
- `Ok(value, message?)` keeps an optional success message on the result. Results without one have no `message` property.
|
|
9
8
|
- `SafeTry` unwraps Option and Atom values into one result. A Result never nests inside another
|
|
10
9
|
Result, and plain object properties and array elements stay unchanged.
|
|
11
10
|
|
package/README.md
CHANGED
|
@@ -39,7 +39,7 @@ if (result.isOk) {
|
|
|
39
39
|
}
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
-
`println` is optional
|
|
42
|
+
`println` is optional: it's a small development logger.
|
|
43
43
|
|
|
44
44
|
## Imports
|
|
45
45
|
|
|
@@ -107,7 +107,7 @@ import { option, Ok, Err, atom, match } from "slang-ts";
|
|
|
107
107
|
- [println][logging] (with `setEnvironment`)
|
|
108
108
|
- [createStepper][stepper]
|
|
109
109
|
|
|
110
|
-
Full reference: [docs index][docs-index]. Feature list: [CHANGELOG.md][changelog].
|
|
110
|
+
Full reference: [docs index][docs-index]. Feature list: [CHANGELOG.md][changelog]. Agent guide: [skill/SKILL.md](skill/SKILL.md).
|
|
111
111
|
|
|
112
112
|
## Real-world examples
|
|
113
113
|
|
|
@@ -168,7 +168,7 @@ Full detail: [SafeTry][safe-try] and [Result][result].
|
|
|
168
168
|
### Call an API with a timeout and retries: SuperPromise
|
|
169
169
|
|
|
170
170
|
Your function gets an `AbortSignal`. `timeout` aborts an attempt, `retry` runs it again after an
|
|
171
|
-
ordinary failure, and you get back `Ok` or `Err
|
|
171
|
+
ordinary failure, and you get back `Ok` or `Err`: so no `try`/`catch` around the await.
|
|
172
172
|
|
|
173
173
|
```ts
|
|
174
174
|
import { superPromise, println } from "slang-ts";
|
|
@@ -287,3 +287,4 @@ MIT License. See [LICENSE][license].
|
|
|
287
287
|
[docs-index]: https://github.com/Hussseinkizz/slang/blob/main/docs/README.md
|
|
288
288
|
[changelog]: https://github.com/Hussseinkizz/slang/blob/main/CHANGELOG.md
|
|
289
289
|
[license]: https://github.com/Hussseinkizz/slang/blob/main/LICENSE
|
|
290
|
+
[skill]: https://github.com/Hussseinkizz/slang/blob/main/skill/SKILL.md
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "slang-ts",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Functional programming utilities for TypeScript: Option, Result, SafeTry, pattern matching, async control, and data helpers",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"types": "dist/index.d.ts",
|
|
16
16
|
"files": [
|
|
17
17
|
"dist",
|
|
18
|
+
"skill",
|
|
18
19
|
"CHANGELOG.md"
|
|
19
20
|
],
|
|
20
21
|
"engines": {
|
package/skill/SKILL.md
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# slang-ts agent skill
|
|
2
|
+
|
|
3
|
+
This skill tells AI agents how to work with slang-ts: its APIs, patterns, and conventions so agents can write correct TypeScript against it.
|
|
4
|
+
|
|
5
|
+
## What slang-ts is
|
|
6
|
+
|
|
7
|
+
slang-ts is a zero-dependency functional programming library for TypeScript. It brings Rust- and Erlang-style utilities: `Option`, `Result`, `SafeTry`, pattern matching (`match`/`matchAll`), async control (`SuperPromise`, `SuperRunner`, `taskGroup`, `Signal`, `Channel`), and data helpers (`list`, `struct`, `sets`, `Ok.iterate`, `memoized`, `zip`, `pipe`, `atom`, `to`).
|
|
8
|
+
|
|
9
|
+
Import only what you use:
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import { option, Ok, Err, match, superPromise, list } from "slang-ts";
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Core wrappers
|
|
16
|
+
|
|
17
|
+
### Option
|
|
18
|
+
|
|
19
|
+
`option<T>(value): Option<T>` — wraps a value that may or may not be there.
|
|
20
|
+
|
|
21
|
+
`0` and `false` count as present; `null`, `undefined`, `""`, `NaN`, and `Infinity` are `None`.
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
const port = option(process.env.PORT).unwrap().else(3000);
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Never read `.value` on `None`. Check `.isSome` / `.isNone` first, or use `.unwrap().else(fallback)`.
|
|
28
|
+
|
|
29
|
+
### Result
|
|
30
|
+
|
|
31
|
+
`Result<T, E>` is `Ok<T>` or `Err<E>`.
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
Ok<T>(value, message?); // success, optional message
|
|
35
|
+
Err<E>(error, raw?); // failure, optional diagnostic cause
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
`Err(error, raw?)` keeps the original cause on the non-enumerable `.raw` for logs; `.error` stays human-readable.
|
|
39
|
+
|
|
40
|
+
Branch with `if (result.isOk) { ... } else { ... }`. Finish chains with `.unwrap().else(fallback)` or `.unwrap().panic(message?)`.
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
function divide(a: number, b: number): Result<number, string> {
|
|
44
|
+
return b === 0 ? Err("Cannot divide by zero") : Ok(a / b);
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
`Result` never nests inside another `Result` — `Ok(Ok(x))` and `Ok(Err(x))` won't compile.
|
|
49
|
+
|
|
50
|
+
### match / matchAll
|
|
51
|
+
|
|
52
|
+
`match(value, patterns)` — exhaustive pattern matching for `Option` and `Result`. TypeScript requires both cases.
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
match(result, { Ok: (v) => ..., Err: (e) => ... });
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
`matchAll(value, patterns)` — matching for strings, numbers, booleans, symbols, and `Atom`s. Always needs a `_` fallback.
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
const message = matchAll(failed.category, {
|
|
62
|
+
OUT_OF_BOUNDS: () => "That page is out of range.",
|
|
63
|
+
_: (category) => `Unexpected failure: ${category}`,
|
|
64
|
+
});
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Collection chains (list, struct, sets, Ok.iterate)
|
|
68
|
+
|
|
69
|
+
These return a `Fallible<T>`, not a plain `Result`. Finish with `.else(fallback)` or `.panic(message?)`. On failure, `.category` holds a string like `"OUT_OF_BOUNDS"` or `"INVALID_INPUT"`.
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
const failed = list([1, 2, 3]).range(1, 99).take(1);
|
|
73
|
+
if (failed.category === "OUT_OF_BOUNDS") {
|
|
74
|
+
println(failed.else([])); // []
|
|
75
|
+
} else {
|
|
76
|
+
failed.panic(failed.category);
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
- `get` already takes a fallback: `get(key, fallback)`. Do not pair `get(x, fallback)` with `.else(fallback)` — that's redundant.
|
|
81
|
+
- `.panic()` throws; once you panic, no custom message is read afterward.
|
|
82
|
+
|
|
83
|
+
### list
|
|
84
|
+
|
|
85
|
+
`list<T>(input): ListChain<T>` — strict indexed arrays with explicit bounds. Out-of-range fails instead of clamping.
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
const page = list(users).range(start, end).else([]);
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Methods: `get`, `take`, `skip`, `range`, `chunk`, `count`, `prune`.
|
|
92
|
+
|
|
93
|
+
### struct
|
|
94
|
+
|
|
95
|
+
`struct<T>(input): StructChain<T>` — safe record access and shaping.
|
|
96
|
+
|
|
97
|
+
Methods: `get`, `pick`, `omit`, `merge`, `countBy`, `keyBy`, `prune`.
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
const port = struct(config).get(["server", "port"], 3000);
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
- `prune` drops Slang-falsy values (`null`, `undefined`, `""`, `NaN`, `Infinity`, `-Infinity`) but keeps `0` and `false`. Its predicate receives `(value, key)` and returns `true` to keep a value. It needs a plain object.
|
|
104
|
+
- Wrong shape for the operation fails with `INVALID_INPUT`. A missing `get` path fails with `OUT_OF_BOUNDS`. Once a chain fails, later steps don't run, and the category survives so you can check `.category`.
|
|
105
|
+
|
|
106
|
+
### sets
|
|
107
|
+
|
|
108
|
+
`sets<T>(input): SetsChain<T>` — membership and set operations.
|
|
109
|
+
|
|
110
|
+
Methods: `has`, `unique`, `union`, `intersection`, `difference`. Objects compare by identity; primitives by value.
|
|
111
|
+
|
|
112
|
+
### Ok.iterate
|
|
113
|
+
|
|
114
|
+
`Ok<T>(value).iterate(): IterateChain<T>` — lazy pipelines over a successful `Ok`.
|
|
115
|
+
|
|
116
|
+
Methods: `map`, `filter`, `flatMap`, `take`, `drop`, `chunk`, `reduce`, `count`, `toArray`.
|
|
117
|
+
|
|
118
|
+
```ts
|
|
119
|
+
const names = Ok(users)
|
|
120
|
+
.iterate()
|
|
121
|
+
.filter((u) => u.active)
|
|
122
|
+
.map((u) => u.name)
|
|
123
|
+
.toArray()
|
|
124
|
+
.else([]);
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Async
|
|
128
|
+
|
|
129
|
+
### SuperPromise
|
|
130
|
+
|
|
131
|
+
`superPromise<T>(fn, options?): SuperPromise<T>` — one async operation with start, retry, timeout, and cancel controls. Your function gets an `AbortSignal`. Tasks end as `Ok` or `Err`.
|
|
132
|
+
|
|
133
|
+
Options: `defer`, `delay`, `timeout`, `retry`, `retryUntil`, `group`.
|
|
134
|
+
|
|
135
|
+
```ts
|
|
136
|
+
const user = await superPromise(
|
|
137
|
+
async (signal) => {
|
|
138
|
+
const response = await fetch(`/api/users/${id}`, { signal });
|
|
139
|
+
return response.json();
|
|
140
|
+
},
|
|
141
|
+
{ timeout: 5000, retry: 2 },
|
|
142
|
+
);
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### SuperRunner
|
|
146
|
+
|
|
147
|
+
`superRunner(config): SuperRunner<Value>` — manages several already-created `SuperPromise`s: sequence, parallel, or race. `start()` runs once.
|
|
148
|
+
|
|
149
|
+
```ts
|
|
150
|
+
const all = superRunner({ type: "all", runners: { a, b } });
|
|
151
|
+
const result = await all.start();
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### taskGroup
|
|
155
|
+
|
|
156
|
+
`taskGroup(name, options?): TaskGroup` — shared concurrency limit and start spacing across tasks and runners. Retries wait for a new slot.
|
|
157
|
+
|
|
158
|
+
```ts
|
|
159
|
+
const api = taskGroup("user-api", { concurrency: 3, throttle: 200 });
|
|
160
|
+
const task = superPromise(fetchUsers, { group: api });
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### Signal / Channel
|
|
164
|
+
|
|
165
|
+
`createSignal(): Signal` — a trigger that fires once (`fire()`), AbortSignal-compatible.
|
|
166
|
+
|
|
167
|
+
`createChannel(): Channel` — in-process publish/subscribe. `subscribe(topic, handler)` returns an unsubscribe function.
|
|
168
|
+
|
|
169
|
+
## Other utilities
|
|
170
|
+
|
|
171
|
+
- `atom<T>(name): Atom<T>` — unique symbol with a readable description; matches in `matchAll` by description.
|
|
172
|
+
- `to(target)` — convert between `Option`, `Atom`, `Result` (e.g. `option("ready").to("atom")`).
|
|
173
|
+
- `pipe(value, ...fns)` — run `Result`-returning steps in order, stopping at the first failure.
|
|
174
|
+
- `zip` / `zipWith` / `unzip` — combine parallel collections.
|
|
175
|
+
- `memoized(fn)` — cache a function by argument identity.
|
|
176
|
+
- `panic(message)` — throw immediately for unrecoverable states.
|
|
177
|
+
- `println` — dev logging, silent in production unless `setEnvironment` routes it.
|
|
178
|
+
|
|
179
|
+
## Conventions agents should follow
|
|
180
|
+
|
|
181
|
+
- Named params in an object for multi-arg functions, not positional.
|
|
182
|
+
- No classes: use functions and plain objects.
|
|
183
|
+
- Error categories are strings (`.category`), not numeric codes. Never call them "error codes."
|
|
184
|
+
- `get` accepts a fallback; don't chain `.else()` after a `get` that already has one.
|
|
185
|
+
- `.panic()` throws: only for unrecoverable states. Use `Result` / `.else()` for expected failures.
|
|
186
|
+
- Zero runtime dependencies; ESM only.
|
|
187
|
+
|
|
188
|
+
## Package contents
|
|
189
|
+
|
|
190
|
+
The published package ships `dist/` (JS + bundled declarations), `CHANGELOG.md`, and `skill/SKILL.md` (this file, for agents working with slang-ts).
|