go-go-try 7.1.0 → 7.2.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/AGENTS.md +182 -0
- package/README.md +211 -1
- package/dist/index.cjs +29 -12
- package/dist/index.d.cts +94 -2
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +94 -2
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +29 -13
- package/package.json +1 -1
- package/src/index.test.ts +419 -0
- package/src/index.ts +124 -15
package/AGENTS.md
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
# go-go-try - Agent Guide
|
|
2
|
+
|
|
3
|
+
## Project Overview
|
|
4
|
+
|
|
5
|
+
**go-go-try** is a TypeScript utility library for error handling inspired by Go's error handling pattern. It provides a functional approach to try/catch operations by returning a tuple `[error, value]` instead of throwing exceptions.
|
|
6
|
+
|
|
7
|
+
- **Name**: go-go-try
|
|
8
|
+
- **Version**: 6.2.0
|
|
9
|
+
- **License**: MIT
|
|
10
|
+
- **Repository**: thelinuxlich/go-go-try
|
|
11
|
+
- **Node.js Requirements**: >= 16
|
|
12
|
+
|
|
13
|
+
## Technology Stack
|
|
14
|
+
|
|
15
|
+
- **Language**: TypeScript 5.8.3
|
|
16
|
+
- **Build Tool**: [pkgroll](https://github.com/privatenumber/pkgroll) - A zero-config TypeScript package bundler
|
|
17
|
+
- **Linter**: [Biome](https://biomejs.dev/) - Fast linter and formatter
|
|
18
|
+
- **Test Framework**: [Vitest](https://vitest.dev/) - Vite-native unit test framework
|
|
19
|
+
- **Type Testing**: [@ark/attest](https://github.com/arktypeio/arktype) - Runtime type assertions for TypeScript
|
|
20
|
+
|
|
21
|
+
## Project Structure
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
.
|
|
25
|
+
├── src/
|
|
26
|
+
│ ├── index.ts # Main source file - exports goTry, goTryRaw, and utility types
|
|
27
|
+
│ └── index.test.ts # Comprehensive test suite with runtime and type tests
|
|
28
|
+
├── dist/ # Build output (generated by pkgroll)
|
|
29
|
+
│ ├── index.cjs # CommonJS build
|
|
30
|
+
│ ├── index.mjs # ES Module build
|
|
31
|
+
│ ├── index.d.cts # CommonJS type definitions
|
|
32
|
+
│ └── index.d.mts # ES Module type definitions
|
|
33
|
+
├── .github/workflows/
|
|
34
|
+
│ └── main.yml # CI configuration for GitHub Actions
|
|
35
|
+
├── .attest/ # Ark attest cache directory
|
|
36
|
+
├── package.json # Package configuration with dual CJS/ESM exports
|
|
37
|
+
├── tsconfig.json # TypeScript strict configuration
|
|
38
|
+
├── vitest.config.ts # Vitest configuration with type checking enabled
|
|
39
|
+
├── setupVitest.ts # Vitest global setup for @ark/attest
|
|
40
|
+
└── README.md # User-facing documentation
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Build and Test Commands
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# Build the project (generates dist/ with CJS, ESM, and type definitions)
|
|
47
|
+
npm run build
|
|
48
|
+
|
|
49
|
+
# Run linting with auto-fix
|
|
50
|
+
npm run lint
|
|
51
|
+
|
|
52
|
+
# Run the full test suite (build + lint + vitest)
|
|
53
|
+
npm test
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
The test script is a composite that:
|
|
57
|
+
1. Builds the project
|
|
58
|
+
2. Runs the linter
|
|
59
|
+
3. Executes Vitest tests
|
|
60
|
+
|
|
61
|
+
## Code Style Guidelines
|
|
62
|
+
|
|
63
|
+
- **Linter**: Biome is used for linting and formatting
|
|
64
|
+
- **Configuration**: Uses Biome's default configuration (no biome.json present)
|
|
65
|
+
- **Strict TypeScript**: The `tsconfig.json` enforces strict mode with additional checks:
|
|
66
|
+
- `noUnusedLocals`: true
|
|
67
|
+
- `noUnusedParameters`: true
|
|
68
|
+
- `allowUnreachableCode`: false
|
|
69
|
+
- `noUncheckedIndexedAccess`: true
|
|
70
|
+
- `noFallthroughCasesInSwitch`: true
|
|
71
|
+
- `forceConsistentCasingInFileNames`: true
|
|
72
|
+
|
|
73
|
+
## Testing Instructions
|
|
74
|
+
|
|
75
|
+
### Test Structure
|
|
76
|
+
|
|
77
|
+
Tests are co-located with source code in `src/index.test.ts` using Vitest.
|
|
78
|
+
|
|
79
|
+
### Test Types
|
|
80
|
+
|
|
81
|
+
1. **Runtime Tests**: Standard unit tests verifying behavior
|
|
82
|
+
2. **Type Tests**: Using `@ark/attest` to verify TypeScript type inference at runtime
|
|
83
|
+
|
|
84
|
+
### Key Testing Patterns
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
// Runtime test
|
|
88
|
+
import { assert, test } from 'vitest'
|
|
89
|
+
test('description', () => {
|
|
90
|
+
const result = goTry(() => 'value')
|
|
91
|
+
assert.equal(result[1], 'value')
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
// Type test
|
|
95
|
+
import { attest } from '@ark/attest'
|
|
96
|
+
test('types are correct', () => {
|
|
97
|
+
const result = goTry('value')
|
|
98
|
+
attest<Result<string, string>>(result)
|
|
99
|
+
})
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Running Tests
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
# Run all tests with type checking
|
|
106
|
+
npx vitest run
|
|
107
|
+
|
|
108
|
+
# Run tests in watch mode (during development)
|
|
109
|
+
npx vitest
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Global Setup
|
|
113
|
+
|
|
114
|
+
The `setupVitest.ts` file configures `@ark/attest` for type assertions in tests.
|
|
115
|
+
|
|
116
|
+
## API Design
|
|
117
|
+
|
|
118
|
+
### Core Functions
|
|
119
|
+
|
|
120
|
+
- **`goTry<T>(value)`**: Returns `[string | undefined, T | undefined]` - error is the message string
|
|
121
|
+
- **`goTryRaw<T, E>(value)`**: Returns `[E | undefined, T | undefined]` - error is the raw Error object
|
|
122
|
+
|
|
123
|
+
### Type Helpers
|
|
124
|
+
|
|
125
|
+
- **`Result<E, T>`**: The tuple type `[E | undefined, T | undefined]`
|
|
126
|
+
- **`Success<T>`**: `[undefined, T]`
|
|
127
|
+
- **`Failure<E>`**: `[E, undefined]`
|
|
128
|
+
- **`isSuccess(result)`**: Type guard to check if result is success
|
|
129
|
+
- **`isFailure(result)`**: Type guard to check if result is failure
|
|
130
|
+
|
|
131
|
+
### Input Handling
|
|
132
|
+
|
|
133
|
+
Both functions accept:
|
|
134
|
+
- Direct values
|
|
135
|
+
- Functions (sync or async)
|
|
136
|
+
- Promises
|
|
137
|
+
|
|
138
|
+
## Dual Package Support
|
|
139
|
+
|
|
140
|
+
The package supports both CommonJS and ESM consumers:
|
|
141
|
+
|
|
142
|
+
```json
|
|
143
|
+
{
|
|
144
|
+
"main": "./dist/index.cjs",
|
|
145
|
+
"module": "./dist/index.mjs",
|
|
146
|
+
"types": "./dist/index.d.mts",
|
|
147
|
+
"exports": {
|
|
148
|
+
"require": { "types": "./dist/index.d.cts", "default": "./dist/index.cjs" },
|
|
149
|
+
"import": { "types": "./dist/index.d.mts", "default": "./dist/index.mjs" }
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## CI/CD
|
|
155
|
+
|
|
156
|
+
GitHub Actions workflow (`.github/workflows/main.yml`) runs on every push and PR:
|
|
157
|
+
|
|
158
|
+
- Tests against Node.js versions: 12, 14, 16, 18
|
|
159
|
+
- Uses `yarn install` and `yarn test`
|
|
160
|
+
- `fail-fast: false` to see results for all Node versions
|
|
161
|
+
|
|
162
|
+
## Security Considerations
|
|
163
|
+
|
|
164
|
+
- Zero runtime dependencies - reduces supply chain attack surface
|
|
165
|
+
- Dev dependencies are locked via `package-lock.json`
|
|
166
|
+
- Uses `type: "module"` for native ESM support
|
|
167
|
+
|
|
168
|
+
## Development Workflow
|
|
169
|
+
|
|
170
|
+
1. Make changes to `src/index.ts`
|
|
171
|
+
2. Add/update tests in `src/index.test.ts`
|
|
172
|
+
3. Run `npm test` to verify build, lint, and tests pass
|
|
173
|
+
4. The CI will test against multiple Node.js versions on push
|
|
174
|
+
|
|
175
|
+
## Notes for AI Agents
|
|
176
|
+
|
|
177
|
+
- Always run `npm test` after making changes to ensure build, lint, and tests pass
|
|
178
|
+
- Type tests with `@ark/attest` are as important as runtime tests
|
|
179
|
+
- The library has zero dependencies - avoid adding any
|
|
180
|
+
- Maintain dual CJS/ESM compatibility when making changes
|
|
181
|
+
- Follow the existing function overload patterns for type inference
|
|
182
|
+
- Error handling should preserve the Go-style tuple return pattern
|
package/README.md
CHANGED
|
@@ -202,6 +202,88 @@ if (err === undefined) {
|
|
|
202
202
|
}
|
|
203
203
|
```
|
|
204
204
|
|
|
205
|
+
### Tagged Errors for Discriminated Unions
|
|
206
|
+
|
|
207
|
+
Create typed errors with a `_tag` property for pattern matching and discriminated unions:
|
|
208
|
+
|
|
209
|
+
```ts
|
|
210
|
+
import { taggedError, goTryRaw, failure, type Result } from 'go-go-try'
|
|
211
|
+
|
|
212
|
+
// Define error types
|
|
213
|
+
const DatabaseError = taggedError('DatabaseError')
|
|
214
|
+
const NetworkError = taggedError('NetworkError')
|
|
215
|
+
const ValidationError = taggedError('ValidationError')
|
|
216
|
+
|
|
217
|
+
// Create a union type
|
|
218
|
+
import type { TaggedUnion } from 'go-go-try'
|
|
219
|
+
|
|
220
|
+
// Option 1: Using TaggedUnion helper (cleaner)
|
|
221
|
+
const DatabaseError = taggedError('DatabaseError')
|
|
222
|
+
const NetworkError = taggedError('NetworkError')
|
|
223
|
+
const ValidationError = taggedError('ValidationError')
|
|
224
|
+
|
|
225
|
+
type AppError = TaggedUnion<[typeof DatabaseError, typeof NetworkError, typeof ValidationError]>
|
|
226
|
+
// Equivalent to: DatabaseError | NetworkError | ValidationError
|
|
227
|
+
|
|
228
|
+
// Option 2: Using InstanceType (standard TypeScript)
|
|
229
|
+
type AppErrorVerbose =
|
|
230
|
+
| InstanceType<typeof DatabaseError>
|
|
231
|
+
| InstanceType<typeof NetworkError>
|
|
232
|
+
| InstanceType<typeof ValidationError>
|
|
233
|
+
|
|
234
|
+
// Use in functions with typed error returns
|
|
235
|
+
async function fetchUser(id: string): Promise<Result<AppError, User>> {
|
|
236
|
+
const [dbErr, user] = await goTryRaw(queryDatabase(id), DatabaseError)
|
|
237
|
+
if (dbErr) return failure(dbErr)
|
|
238
|
+
|
|
239
|
+
const [netErr, enriched] = await goTryRaw(enrichUserData(user!), NetworkError)
|
|
240
|
+
if (netErr) return failure(netErr)
|
|
241
|
+
|
|
242
|
+
return [undefined, enriched] as const
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Pattern matching on errors
|
|
246
|
+
const [err, user] = await fetchUser('123')
|
|
247
|
+
if (err) {
|
|
248
|
+
switch (err._tag) {
|
|
249
|
+
case 'DatabaseError':
|
|
250
|
+
console.error('Database failed:', err.message)
|
|
251
|
+
break
|
|
252
|
+
case 'NetworkError':
|
|
253
|
+
console.error('Network issue:', err.message)
|
|
254
|
+
break
|
|
255
|
+
case 'ValidationError':
|
|
256
|
+
console.error('Invalid data:', err.message)
|
|
257
|
+
break
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Exhaustive switch with compile-time safety
|
|
262
|
+
function assertNever(value: never): never {
|
|
263
|
+
throw new Error(`Unhandled case: ${String(value)}`)
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
function handleError(err: AppError): string {
|
|
267
|
+
switch (err._tag) {
|
|
268
|
+
case 'DatabaseError':
|
|
269
|
+
return `DB: ${err.message}`
|
|
270
|
+
case 'NetworkError':
|
|
271
|
+
return `NET: ${err.message}`
|
|
272
|
+
case 'ValidationError':
|
|
273
|
+
return `VAL: ${err.message}`
|
|
274
|
+
default:
|
|
275
|
+
// TypeScript will error here if any case is missing above
|
|
276
|
+
return assertNever(err)
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
The `taggedError` function creates an error class with:
|
|
282
|
+
- `_tag`: A readonly string literal for discriminated unions
|
|
283
|
+
- `message`: The error message
|
|
284
|
+
- `cause`: Optional cause for error chaining
|
|
285
|
+
- `name`: Set to the tag value
|
|
286
|
+
|
|
205
287
|
### Helper Functions
|
|
206
288
|
|
|
207
289
|
Build custom utilities on top of the primitives:
|
|
@@ -236,12 +318,32 @@ Executes a function, promise, or value and returns a Result type with error mess
|
|
|
236
318
|
function goTry<T>(value: T | Promise<T> | (() => T | Promise<T>)): Result<string, T> | Promise<Result<string, T>>
|
|
237
319
|
```
|
|
238
320
|
|
|
239
|
-
### `goTryRaw<T, E>(value)`
|
|
321
|
+
### `goTryRaw<T, E>(value, ErrorClass?)`
|
|
240
322
|
|
|
241
323
|
Like `goTry` but returns the raw Error object instead of just the message.
|
|
242
324
|
|
|
325
|
+
Optionally accepts an error constructor to wrap caught errors - useful with `taggedError` for discriminated unions.
|
|
326
|
+
|
|
243
327
|
```ts
|
|
328
|
+
// Without ErrorClass - err is Error | undefined
|
|
244
329
|
function goTryRaw<T, E = Error>(value: T | Promise<T> | (() => T | Promise<T>)): Result<E, T> | Promise<Result<E, T>>
|
|
330
|
+
|
|
331
|
+
// With ErrorClass - err is E | undefined (e.g., DatabaseError | undefined)
|
|
332
|
+
function goTryRaw<T, E>(value: T | Promise<T> | (() => T | Promise<T>), ErrorClass: ErrorConstructor<E>): Result<E, T> | Promise<Result<E, T>>
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
**Example:**
|
|
336
|
+
```ts
|
|
337
|
+
const DatabaseError = taggedError('DatabaseError')
|
|
338
|
+
|
|
339
|
+
// Raw error (default)
|
|
340
|
+
const [err1, data1] = await goTryRaw(fetchData())
|
|
341
|
+
// err1 is Error | undefined
|
|
342
|
+
|
|
343
|
+
// Tagged error
|
|
344
|
+
const [err2, data2] = await goTryRaw(fetchData(), DatabaseError)
|
|
345
|
+
// err2 is DatabaseError | undefined
|
|
346
|
+
// err2._tag is 'DatabaseError' - enables discriminated unions
|
|
245
347
|
```
|
|
246
348
|
|
|
247
349
|
### `goTryAll<T>(items, options?)`
|
|
@@ -325,12 +427,120 @@ function success<T>(value: T): Success<T>
|
|
|
325
427
|
function failure<E>(error: E): Failure<E>
|
|
326
428
|
```
|
|
327
429
|
|
|
430
|
+
### `taggedError<T>(tag)`
|
|
431
|
+
|
|
432
|
+
Creates a tagged error class for discriminated error handling. Returns a class constructor that extends `Error` and includes a readonly `_tag` property.
|
|
433
|
+
|
|
434
|
+
```ts
|
|
435
|
+
function taggedError<T extends string>(tag: T): TaggedErrorClass<T>
|
|
436
|
+
|
|
437
|
+
// Returned class interface:
|
|
438
|
+
class TaggedErrorClass<T> extends Error implements TaggedError<T> {
|
|
439
|
+
readonly _tag: T
|
|
440
|
+
readonly cause?: unknown
|
|
441
|
+
constructor(message: string, options?: { cause?: unknown })
|
|
442
|
+
}
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
**Example:**
|
|
446
|
+
```ts
|
|
447
|
+
const DatabaseError = taggedError('DatabaseError')
|
|
448
|
+
const err = new DatabaseError('connection failed', { cause: originalError })
|
|
449
|
+
|
|
450
|
+
console.log(err._tag) // 'DatabaseError'
|
|
451
|
+
console.log(err.message) // 'connection failed'
|
|
452
|
+
console.log(err.name) // 'DatabaseError'
|
|
453
|
+
console.log(err.cause) // originalError
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
### `TaggedInstance<T>`
|
|
457
|
+
|
|
458
|
+
Extracts the instance type from a tagged error class. Cleaner alternative to `InstanceType<typeof ErrorClass>`.
|
|
459
|
+
|
|
460
|
+
```ts
|
|
461
|
+
type TaggedInstance<T extends ErrorConstructor<unknown>> =
|
|
462
|
+
T extends ErrorConstructor<infer E> ? E : never
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
**Example:**
|
|
466
|
+
```ts
|
|
467
|
+
const DatabaseError = taggedError('DatabaseError')
|
|
468
|
+
type DbError = TaggedInstance<typeof DatabaseError>
|
|
469
|
+
// Equivalent to: InstanceType<typeof DatabaseError>
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
### `TaggedUnion<T>`
|
|
473
|
+
|
|
474
|
+
Creates a union type from multiple tagged error classes.
|
|
475
|
+
|
|
476
|
+
```ts
|
|
477
|
+
type TaggedUnion<T extends readonly ErrorConstructor<unknown>[]> =
|
|
478
|
+
{ [K in keyof T]: T[K] extends ErrorConstructor<infer E> ? E : never }[number]
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
**Example:**
|
|
482
|
+
```ts
|
|
483
|
+
const DatabaseError = taggedError('DatabaseError')
|
|
484
|
+
const NetworkError = taggedError('NetworkError')
|
|
485
|
+
const ValidationError = taggedError('ValidationError')
|
|
486
|
+
|
|
487
|
+
// Before (verbose):
|
|
488
|
+
type AppErrorVerbose =
|
|
489
|
+
| InstanceType<typeof DatabaseError>
|
|
490
|
+
| InstanceType<typeof NetworkError>
|
|
491
|
+
| InstanceType<typeof ValidationError>
|
|
492
|
+
|
|
493
|
+
// After (clean):
|
|
494
|
+
type AppError = TaggedUnion<[typeof DatabaseError, typeof NetworkError, typeof ValidationError]>
|
|
495
|
+
// Results in: DatabaseError | NetworkError | ValidationError
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
#### Automatic Union Inference
|
|
499
|
+
|
|
500
|
+
When using `goTryRaw` with different error classes in the same function, TypeScript **automatically infers** the union type without needing explicit type annotations:
|
|
501
|
+
|
|
502
|
+
```ts
|
|
503
|
+
// No explicit return type needed!
|
|
504
|
+
async function fetchUserData(id: string) {
|
|
505
|
+
// First operation might fail with DatabaseError
|
|
506
|
+
const [dbErr, user] = await goTryRaw(queryDb(id), DatabaseError)
|
|
507
|
+
if (dbErr) return failure(dbErr) // returns Failure<DatabaseError>
|
|
508
|
+
|
|
509
|
+
// Second operation might fail with NetworkError
|
|
510
|
+
const [netErr, enriched] = await goTryRaw(enrichUser(user!), NetworkError)
|
|
511
|
+
if (netErr) return failure(netErr) // returns Failure<NetworkError>
|
|
512
|
+
|
|
513
|
+
return success(enriched) // returns Success<User>
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
// TypeScript infers: Promise<Result<DatabaseError | NetworkError, User>>
|
|
517
|
+
// No TaggedUnion or explicit types needed!
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
The inferred union enables exhaustive pattern matching:
|
|
521
|
+
|
|
522
|
+
```ts
|
|
523
|
+
const [err, user] = await fetchUserData('123')
|
|
524
|
+
if (err) {
|
|
525
|
+
switch (err._tag) {
|
|
526
|
+
case 'DatabaseError': /* handle db error */ break
|
|
527
|
+
case 'NetworkError': /* handle network error */ break
|
|
528
|
+
default: assertNever(err) // compile-time safety
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
```
|
|
532
|
+
|
|
328
533
|
## Types
|
|
329
534
|
|
|
330
535
|
```ts
|
|
331
536
|
type Success<T> = readonly [undefined, T]
|
|
332
537
|
type Failure<E> = readonly [E, undefined]
|
|
333
538
|
type Result<E, T> = Success<T> | Failure<E>
|
|
539
|
+
|
|
540
|
+
// Error type helpers
|
|
541
|
+
type TaggedInstance<T> = T extends ErrorConstructor<infer E> ? E : never
|
|
542
|
+
type TaggedUnion<T extends readonly ErrorConstructor<unknown>[]> =
|
|
543
|
+
{ [K in keyof T]: T[K] extends ErrorConstructor<infer E> ? E : never }[number]
|
|
334
544
|
```
|
|
335
545
|
|
|
336
546
|
## License
|
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
function taggedError(tag) {
|
|
4
|
+
return class TaggedErrorClass extends Error {
|
|
5
|
+
constructor(message, options) {
|
|
6
|
+
super(message);
|
|
7
|
+
this._tag = tag;
|
|
8
|
+
this.name = tag;
|
|
9
|
+
this.cause = options?.cause;
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
}
|
|
3
13
|
function isSuccess(result) {
|
|
4
14
|
return result[0] === void 0;
|
|
5
15
|
}
|
|
@@ -118,24 +128,30 @@ function goTry(value) {
|
|
|
118
128
|
return failure(getErrorMessage(err));
|
|
119
129
|
}
|
|
120
130
|
}
|
|
121
|
-
function goTryRaw(value) {
|
|
131
|
+
function goTryRaw(value, ErrorClass) {
|
|
132
|
+
const wrapError = (err) => {
|
|
133
|
+
if (ErrorClass) {
|
|
134
|
+
if (err === void 0) {
|
|
135
|
+
return new ErrorClass("undefined");
|
|
136
|
+
}
|
|
137
|
+
if (isError(err)) {
|
|
138
|
+
return new ErrorClass(err.message, { cause: err });
|
|
139
|
+
}
|
|
140
|
+
return new ErrorClass(String(err));
|
|
141
|
+
}
|
|
142
|
+
if (err === void 0) {
|
|
143
|
+
return new Error("undefined");
|
|
144
|
+
}
|
|
145
|
+
return isError(err) ? err : new Error(String(err));
|
|
146
|
+
};
|
|
122
147
|
try {
|
|
123
148
|
const result = typeof value === "function" ? value() : value;
|
|
124
149
|
if (isPromise(result)) {
|
|
125
|
-
return result.then((resolvedValue) => success(resolvedValue)).catch((err) =>
|
|
126
|
-
if (err === void 0) {
|
|
127
|
-
return failure(new Error("undefined"));
|
|
128
|
-
}
|
|
129
|
-
return failure(
|
|
130
|
-
isError(err) ? err : new Error(String(err))
|
|
131
|
-
);
|
|
132
|
-
});
|
|
150
|
+
return result.then((resolvedValue) => success(resolvedValue)).catch((err) => failure(wrapError(err)));
|
|
133
151
|
}
|
|
134
152
|
return success(result);
|
|
135
153
|
} catch (err) {
|
|
136
|
-
return failure(
|
|
137
|
-
isError(err) ? err : new Error(String(err))
|
|
138
|
-
);
|
|
154
|
+
return failure(wrapError(err));
|
|
139
155
|
}
|
|
140
156
|
}
|
|
141
157
|
|
|
@@ -148,3 +164,4 @@ exports.goTryRaw = goTryRaw;
|
|
|
148
164
|
exports.isFailure = isFailure;
|
|
149
165
|
exports.isSuccess = isSuccess;
|
|
150
166
|
exports.success = success;
|
|
167
|
+
exports.taggedError = taggedError;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,51 @@
|
|
|
1
1
|
type Success<T> = readonly [undefined, T];
|
|
2
2
|
type Failure<E> = readonly [E, undefined];
|
|
3
3
|
type Result<E, T> = Success<T> | Failure<E>;
|
|
4
|
+
/**
|
|
5
|
+
* Base interface for tagged errors.
|
|
6
|
+
* The `_tag` property enables discriminated union narrowing.
|
|
7
|
+
*/
|
|
8
|
+
interface TaggedError<T extends string> {
|
|
9
|
+
readonly _tag: T;
|
|
10
|
+
readonly message: string;
|
|
11
|
+
readonly cause?: unknown;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Creates a tagged error class for discriminated error handling.
|
|
15
|
+
*
|
|
16
|
+
* @template T The literal type of the tag
|
|
17
|
+
* @param tag The string tag to identify this error type (e.g., 'DatabaseError')
|
|
18
|
+
* @returns A class constructor for creating tagged errors
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* const DatabaseError = taggedError('DatabaseError')
|
|
22
|
+
* const NetworkError = taggedError('NetworkError')
|
|
23
|
+
*
|
|
24
|
+
* type MyError = InstanceType<typeof DatabaseError> | InstanceType<typeof NetworkError>
|
|
25
|
+
*
|
|
26
|
+
* function fetchUser(id: string): Result<MyError, User> {
|
|
27
|
+
* const [err, user] = goTryRaw(fetch(`/users/${id}`), DatabaseError)
|
|
28
|
+
* if (err) return failure(err)
|
|
29
|
+
* // ...
|
|
30
|
+
* }
|
|
31
|
+
*
|
|
32
|
+
* // Pattern matching on errors
|
|
33
|
+
* if (err._tag === 'DatabaseError') {
|
|
34
|
+
* // TypeScript knows this is DatabaseError
|
|
35
|
+
* }
|
|
36
|
+
*/
|
|
37
|
+
declare function taggedError<T extends string>(tag: T): {
|
|
38
|
+
new (message: string, options?: {
|
|
39
|
+
cause?: unknown;
|
|
40
|
+
}): {
|
|
41
|
+
readonly _tag: T;
|
|
42
|
+
readonly cause?: unknown;
|
|
43
|
+
name: string;
|
|
44
|
+
message: string;
|
|
45
|
+
stack?: string;
|
|
46
|
+
};
|
|
47
|
+
isError(error: unknown): error is Error;
|
|
48
|
+
};
|
|
4
49
|
type ResultWithDefault<E, T> = readonly [E | undefined, T];
|
|
5
50
|
type MaybePromise<T> = T | Promise<T>;
|
|
6
51
|
interface GoTryAllOptions {
|
|
@@ -121,6 +166,41 @@ declare function goTry<T>(fn: () => Promise<T>): Promise<Result<string, T>>;
|
|
|
121
166
|
declare function goTry<T>(promise: Promise<T>): Promise<Result<string, T>>;
|
|
122
167
|
declare function goTry<T>(fn: () => T): Result<string, T>;
|
|
123
168
|
declare function goTry<T>(value: T): Result<string, T>;
|
|
169
|
+
/**
|
|
170
|
+
* Type for error constructors that can be used with goTryRaw.
|
|
171
|
+
*/
|
|
172
|
+
type ErrorConstructor<E> = new (message: string, options?: {
|
|
173
|
+
cause?: unknown;
|
|
174
|
+
}) => E;
|
|
175
|
+
/**
|
|
176
|
+
* Extracts the instance type from a tagged error class.
|
|
177
|
+
* Useful for creating cleaner error type definitions.
|
|
178
|
+
*
|
|
179
|
+
* @template T The tagged error class type
|
|
180
|
+
* @returns The instance type of the error class
|
|
181
|
+
*
|
|
182
|
+
* @example
|
|
183
|
+
* const DatabaseError = taggedError('DatabaseError')
|
|
184
|
+
* type DbError = TaggedInstance<typeof DatabaseError>
|
|
185
|
+
* // Equivalent to: InstanceType<typeof DatabaseError>
|
|
186
|
+
*/
|
|
187
|
+
type TaggedInstance<T extends ErrorConstructor<unknown>> = T extends ErrorConstructor<infer E> ? E : never;
|
|
188
|
+
/**
|
|
189
|
+
* Creates a union type from multiple tagged error classes.
|
|
190
|
+
*
|
|
191
|
+
* @template T A tuple of tagged error class types
|
|
192
|
+
* @returns A union of all instance types
|
|
193
|
+
*
|
|
194
|
+
* @example
|
|
195
|
+
* const DatabaseError = taggedError('DatabaseError')
|
|
196
|
+
* const NetworkError = taggedError('NetworkError')
|
|
197
|
+
*
|
|
198
|
+
* type AppError = TaggedUnion<[typeof DatabaseError, typeof NetworkError]>
|
|
199
|
+
* // Equivalent to: DatabaseError | NetworkError
|
|
200
|
+
*/
|
|
201
|
+
type TaggedUnion<T extends readonly ErrorConstructor<unknown>[]> = {
|
|
202
|
+
[K in keyof T]: T[K] extends ErrorConstructor<infer E> ? E : never;
|
|
203
|
+
}[number];
|
|
124
204
|
/**
|
|
125
205
|
* Executes a function, promise, or value and returns a Result type.
|
|
126
206
|
* If an error occurs, it returns a Failure with the raw error object.
|
|
@@ -128,6 +208,7 @@ declare function goTry<T>(value: T): Result<string, T>;
|
|
|
128
208
|
* @template T The type of the successful result
|
|
129
209
|
* @template E The type of the error, defaults to Error
|
|
130
210
|
* @param {T | Promise<T> | (() => T | Promise<T>)} value - The value, promise, or function to execute
|
|
211
|
+
* @param {ErrorConstructor<E>} [ErrorClass] - Optional error constructor to wrap caught errors
|
|
131
212
|
* @returns {Result<E, T> | Promise<Result<E, T>>} A Result type or a Promise of a Result type
|
|
132
213
|
*
|
|
133
214
|
* @example
|
|
@@ -141,13 +222,24 @@ declare function goTry<T>(value: T): Result<string, T>;
|
|
|
141
222
|
* @example
|
|
142
223
|
* // With a promise
|
|
143
224
|
* const [err, result] = await goTryRaw(fetch('https://api.example.com/data'));
|
|
225
|
+
*
|
|
226
|
+
* @example
|
|
227
|
+
* // With tagged error for discriminated unions
|
|
228
|
+
* const DatabaseError = taggedError('DatabaseError');
|
|
229
|
+
* const [err, result] = await goTryRaw(fetchData(), DatabaseError);
|
|
230
|
+
* // err is InstanceType<typeof DatabaseError> | undefined
|
|
144
231
|
*/
|
|
145
232
|
declare function goTryRaw<T, E = Error>(fn: () => never): Result<E, never>;
|
|
233
|
+
declare function goTryRaw<T, E = Error>(fn: () => never, ErrorClass: ErrorConstructor<E>): Result<E, never>;
|
|
146
234
|
declare function goTryRaw<T, E = Error>(fn: () => Promise<T>): Promise<Result<E, T>>;
|
|
235
|
+
declare function goTryRaw<T, E = Error>(fn: () => Promise<T>, ErrorClass: ErrorConstructor<E>): Promise<Result<E, T>>;
|
|
147
236
|
declare function goTryRaw<T, E = Error>(promise: Promise<T>): Promise<Result<E, T>>;
|
|
237
|
+
declare function goTryRaw<T, E = Error>(promise: Promise<T>, ErrorClass: ErrorConstructor<E>): Promise<Result<E, T>>;
|
|
148
238
|
declare function goTryRaw<T, E = Error>(fn: () => T): Result<E, T>;
|
|
239
|
+
declare function goTryRaw<T, E = Error>(fn: () => T, ErrorClass: ErrorConstructor<E>): Result<E, T>;
|
|
149
240
|
declare function goTryRaw<T, E = Error>(value: T): Result<E, T>;
|
|
241
|
+
declare function goTryRaw<T, E = Error>(value: T, ErrorClass: ErrorConstructor<E>): Result<E, T>;
|
|
150
242
|
|
|
151
|
-
export { failure, goTry, goTryAll, goTryAllRaw, goTryOr, goTryRaw, isFailure, isSuccess, success };
|
|
152
|
-
export type { Failure, GoTryAllOptions, MaybePromise, Result, ResultWithDefault, Success };
|
|
243
|
+
export { failure, goTry, goTryAll, goTryAllRaw, goTryOr, goTryRaw, isFailure, isSuccess, success, taggedError };
|
|
244
|
+
export type { ErrorConstructor, Failure, GoTryAllOptions, MaybePromise, Result, ResultWithDefault, Success, TaggedError, TaggedInstance, TaggedUnion };
|
|
153
245
|
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","sources":["../src/index.ts"],"mappings":"KAAY,OAAO,CAAC,CAAC,IAAI,SAAS,CAAC,SAAS,EAAE,CAAC,CAAC,CAAA;KACpC,OAAO,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC,EAAE,SAAS,CAAC,CAAA;KACpC,MAAM,CAAC,CAAC,EAAE,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.cts","sources":["../src/index.ts"],"mappings":"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","names":[]}
|