@pencroff-lab/kore 0.1.0 → 0.1.1

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.
Files changed (2) hide show
  1. package/README.md +220 -0
  2. package/package.json +1 -1
package/README.md ADDED
@@ -0,0 +1,220 @@
1
+ # @pencroff-lab/kore
2
+
3
+ TypeScript core utilities library providing value-based error handling types inspired by Go-style error handling. Published as a dual ESM/CJS package.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @pencroff-lab/kore
9
+ # or
10
+ bun add @pencroff-lab/kore
11
+ ```
12
+
13
+ Requires TypeScript 5.9+ as a peer dependency.
14
+
15
+ ## API
16
+
17
+ ### Err
18
+
19
+ Immutable, value-based error type. Supports wrapping (cause chains), aggregation (multiple errors), hierarchical error codes, JSON serialization, and conversion to native `Error`.
20
+
21
+ ```typescript
22
+ import { Err } from "@pencroff-lab/kore";
23
+
24
+ // Create an error with a code
25
+ const err = Err.from("User not found", "NOT_FOUND");
26
+
27
+ // Wrap with context (returns a new instance)
28
+ const wrapped = err.wrap("Failed to load profile");
29
+
30
+ // Aggregate multiple errors
31
+ let errors = Err.aggregate("Validation failed");
32
+ errors = errors.add("Name is required");
33
+ errors = errors.add(Err.from("Invalid email", "INVALID_EMAIL"));
34
+
35
+ if (errors.count > 0) {
36
+ console.log(errors.toString());
37
+ }
38
+ ```
39
+
40
+ #### Creating errors
41
+
42
+ ```typescript
43
+ // From string with code
44
+ Err.from("Timeout", "TIMEOUT");
45
+
46
+ // From string with options
47
+ Err.from("Connection failed", {
48
+ code: "DB_ERROR",
49
+ metadata: { host: "localhost" },
50
+ });
51
+
52
+ // From native Error (preserves stack and cause chain)
53
+ try {
54
+ riskyOperation();
55
+ } catch (e) {
56
+ Err.from(e as Error, { code: "OPERATION_FAILED" });
57
+ }
58
+
59
+ // Static wrap for catch blocks
60
+ try {
61
+ await db.query(sql);
62
+ } catch (e) {
63
+ Err.wrap("Database query failed", e as Error);
64
+ }
65
+ ```
66
+
67
+ #### Error inspection
68
+
69
+ ```typescript
70
+ const err = Err.from("DB error", "DB:CONNECTION:TIMEOUT")
71
+ .wrap("Repository failed")
72
+ .wrap("Service unavailable");
73
+
74
+ err.hasCode("DB:CONNECTION:TIMEOUT"); // true - exact match in chain
75
+ err.hasCodePrefix("DB"); // true - hierarchical prefix match
76
+ err.root.message; // "DB error" - original error
77
+ err.chain(); // array from root to current
78
+ err.find((e) => e.code === "DB:CONNECTION:TIMEOUT"); // find in tree
79
+ ```
80
+
81
+ #### Serialization
82
+
83
+ ```typescript
84
+ // Serialize for API responses
85
+ const json = err.toJSON({ stack: false }); // omit stack for public APIs
86
+
87
+ // Deserialize
88
+ const restored = Err.fromJSON(json);
89
+
90
+ // Convert to native Error
91
+ throw err.toError();
92
+ ```
93
+
94
+ ### Outcome\<T\>
95
+
96
+ Monadic container wrapping `ResultTuple<T>` (`[T, null] | [null, Err]`). Supports `map`/`mapErr`/`pipe`/`pipeAsync` chains, combinators (`all`, `any`), side effects (`effect`), and terminal operations (`toTuple`, `defaultTo`, `either`).
97
+
98
+ ```typescript
99
+ import { Outcome, Err } from "@pencroff-lab/kore";
100
+
101
+ // Create from callback
102
+ const outcome = Outcome.from(() => {
103
+ if (!isValid(input)) return Err.from("Invalid input", "VALIDATION");
104
+ return [processedValue, null];
105
+ });
106
+
107
+ // Extract with tuple destructuring
108
+ const [value, err] = outcome.toTuple();
109
+ if (err) {
110
+ console.error(err.message);
111
+ return;
112
+ }
113
+ console.log(value);
114
+ ```
115
+
116
+ #### Construction
117
+
118
+ ```typescript
119
+ Outcome.ok(42); // success
120
+ Outcome.err("Failed", "ERROR_CODE"); // error
121
+ Outcome.unit(); // void success (null value)
122
+
123
+ // From sync callback (catches throws)
124
+ Outcome.from(() => {
125
+ const data = JSON.parse(input); // may throw
126
+ return [data, null];
127
+ });
128
+
129
+ // From async callback
130
+ await Outcome.fromAsync(async () => {
131
+ const res = await fetch("/api/data");
132
+ if (!res.ok) return Err.from("Request failed", "HTTP_ERROR");
133
+ return [await res.json(), null];
134
+ });
135
+ ```
136
+
137
+ #### Transformations
138
+
139
+ ```typescript
140
+ const result = Outcome.ok(5)
141
+ .map((n) => [n * 2, null]) // transform success
142
+ .mapErr((err) => err.wrap("Added context")) // transform error
143
+ .toTuple();
144
+
145
+ // Pipe for sequential transformations with access to both value and error
146
+ const piped = Outcome.ok(rawInput).pipe(
147
+ ([val, err]) => {
148
+ if (err) return err;
149
+ return [validate(val), null];
150
+ },
151
+ ([val, err]) => {
152
+ if (err) return err;
153
+ return [transform(val), null];
154
+ },
155
+ );
156
+ ```
157
+
158
+ #### Combinators
159
+
160
+ ```typescript
161
+ // All must succeed (collects all errors)
162
+ const all = Outcome.all([Outcome.ok(1), Outcome.ok(2), Outcome.ok(3)]);
163
+ // all.value === [1, 2, 3]
164
+
165
+ // First success wins
166
+ const any = Outcome.any([
167
+ Outcome.err("Failed"),
168
+ Outcome.ok(42),
169
+ Outcome.ok(100),
170
+ ]);
171
+ // any.value === 42
172
+ ```
173
+
174
+ #### Terminal operations
175
+
176
+ ```typescript
177
+ // Default value on error
178
+ const count = parseNumber(input).defaultTo(0);
179
+
180
+ // Computed fallback
181
+ const name = fetchUser(id).defaultTo((err) =>
182
+ err.hasCode("NOT_FOUND") ? "Guest" : "Unknown",
183
+ );
184
+
185
+ // Transform both cases
186
+ const response = processOrder(orderId).either(
187
+ (order) => ({ status: 200, body: order }),
188
+ (err) => ({ status: err.hasCode("NOT_FOUND") ? 404 : 500, body: { error: err.message } }),
189
+ );
190
+ ```
191
+
192
+ ### Utilities
193
+
194
+ #### dtStamp
195
+
196
+ Formats a `Date` into a compact timestamp string. Useful for filenames, logs, and identifiers.
197
+
198
+ ```typescript
199
+ import { dtStamp } from "@pencroff-lab/kore";
200
+
201
+ dtStamp(); // "20260218_153045"
202
+ dtStamp(new Date(), { parts: "date" }); // "20260218"
203
+ dtStamp(new Date(), { parts: "time", ms: true }); // "153045_123"
204
+ dtStamp(new Date(), { compact: true }); // "20260218153045"
205
+ dtStamp(new Date(), { tz: "local" }); // uses local timezone
206
+ ```
207
+
208
+ ## Development
209
+
210
+ ```bash
211
+ bun install # install dependencies
212
+ bun test # run tests
213
+ bun run test:coverage # run tests with coverage (>= 83%)
214
+ bun run lint # lint + type check (auto-fix)
215
+ bun run build # build ESM + CJS to dist/
216
+ ```
217
+
218
+ ## License
219
+
220
+ [Apache-2.0](LICENSE)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pencroff-lab/kore",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Core utilities library",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Pencroff",