@jagreehal/workflow 1.0.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/LICENSE +21 -0
- package/README.md +295 -0
- package/dist/core.cjs +2 -0
- package/dist/core.cjs.map +1 -0
- package/dist/core.d.cts +1606 -0
- package/dist/core.d.ts +1606 -0
- package/dist/core.js +2 -0
- package/dist/core.js.map +1 -0
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/workflow.cjs +2 -0
- package/dist/workflow.cjs.map +1 -0
- package/dist/workflow.d.cts +775 -0
- package/dist/workflow.d.ts +775 -0
- package/dist/workflow.js +2 -0
- package/dist/workflow.js.map +1 -0
- package/docs/___advanced.test.ts +565 -0
- package/docs/___advanced_VERIFICATION.md +64 -0
- package/docs/advanced.md +234 -0
- package/docs/api.md +195 -0
- package/package.json +119 -0
package/docs/advanced.md
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
# Advanced Usage
|
|
2
|
+
|
|
3
|
+
For core concepts (`createWorkflow`, `step`, `step.try`), see the [README](../README.md).
|
|
4
|
+
|
|
5
|
+
## Batch operations
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
import { all, allSettled, any, partition } from '@jagreehal/workflow';
|
|
9
|
+
|
|
10
|
+
// All must succeed (short-circuits on first error)
|
|
11
|
+
const combined = all([ok(1), ok(2), ok(3)]); // ok([1, 2, 3])
|
|
12
|
+
|
|
13
|
+
// Collect ALL errors (great for form validation)
|
|
14
|
+
const validated = allSettled([
|
|
15
|
+
validateEmail(email),
|
|
16
|
+
validatePassword(password),
|
|
17
|
+
]);
|
|
18
|
+
// If any fail: err(['INVALID_EMAIL', 'WEAK_PASSWORD'])
|
|
19
|
+
|
|
20
|
+
// First success wins
|
|
21
|
+
const first = any([err('A'), ok('success'), err('B')]); // ok('success')
|
|
22
|
+
|
|
23
|
+
// Split successes and failures
|
|
24
|
+
const { values, errors } = partition(results);
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Async versions: `allAsync`, `allSettledAsync`, `anyAsync`.
|
|
28
|
+
|
|
29
|
+
## Dynamic error mapping
|
|
30
|
+
|
|
31
|
+
Use `{ onError }` instead of `{ error }` to create errors from the caught value:
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
const result = await workflow(async (step) => {
|
|
35
|
+
const data = await step.try(
|
|
36
|
+
() => fetchExternalApi(),
|
|
37
|
+
{ onError: (e) => ({ type: 'API_ERROR' as const, message: String(e) }) }
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
// Or extract specific error info
|
|
41
|
+
const parsed = await step.try(
|
|
42
|
+
() => schema.parse(data),
|
|
43
|
+
{ onError: (e) => ({ type: 'VALIDATION_ERROR' as const, issues: e.issues }) }
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
return parsed;
|
|
47
|
+
});
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Type utilities
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
import { type ErrorOf, type Errors, type ErrorsOfDeps } from '@jagreehal/workflow';
|
|
54
|
+
|
|
55
|
+
// Extract error type from a function
|
|
56
|
+
type UserError = ErrorOf<typeof fetchUser>; // 'NOT_FOUND'
|
|
57
|
+
|
|
58
|
+
// Combine errors from multiple functions
|
|
59
|
+
type AppError = Errors<[typeof fetchUser, typeof fetchPosts]>;
|
|
60
|
+
// 'NOT_FOUND' | 'FETCH_ERROR'
|
|
61
|
+
|
|
62
|
+
// Extract from a deps object (same as createWorkflow uses)
|
|
63
|
+
type WorkflowErrors = ErrorsOfDeps<{ fetchUser: typeof fetchUser }>;
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Wrapping existing code
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
import { from, fromPromise, tryAsync, fromNullable } from '@jagreehal/workflow';
|
|
70
|
+
|
|
71
|
+
// Sync throwing function
|
|
72
|
+
const parsed = from(
|
|
73
|
+
() => JSON.parse(input),
|
|
74
|
+
(cause) => ({ type: 'PARSE_ERROR' as const, cause })
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
// Existing promise (remember: fetch needs r.ok check!)
|
|
78
|
+
const result = await fromPromise(
|
|
79
|
+
fetch('/api').then(r => {
|
|
80
|
+
if (!r.ok) throw new Error(`HTTP ${r.status}`);
|
|
81
|
+
return r.json();
|
|
82
|
+
}),
|
|
83
|
+
() => 'FETCH_FAILED' as const
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
// Nullable → Result
|
|
87
|
+
const element = fromNullable(
|
|
88
|
+
document.getElementById('app'),
|
|
89
|
+
() => 'NOT_FOUND' as const
|
|
90
|
+
);
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Transformers
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
import { map, mapError, match, andThen, tap } from '@jagreehal/workflow';
|
|
97
|
+
|
|
98
|
+
const doubled = map(ok(21), n => n * 2); // ok(42)
|
|
99
|
+
|
|
100
|
+
const mapped = mapError(err('not_found'), e => e.toUpperCase()); // err('NOT_FOUND')
|
|
101
|
+
|
|
102
|
+
const message = match(result, {
|
|
103
|
+
ok: (user) => `Hello ${user.name}`,
|
|
104
|
+
err: (error) => `Error: ${error}`,
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// Chain results (flatMap)
|
|
108
|
+
const userPosts = andThen(fetchUser('1'), user => fetchPosts(user.id));
|
|
109
|
+
|
|
110
|
+
// Side effects without changing result
|
|
111
|
+
const logged = tap(result, user => console.log('Got user:', user.name));
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Human-in-the-loop (HITL)
|
|
115
|
+
|
|
116
|
+
Build workflows that pause for human approval:
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
import {
|
|
120
|
+
createWorkflow,
|
|
121
|
+
createApprovalStep,
|
|
122
|
+
createHITLCollector,
|
|
123
|
+
isPendingApproval,
|
|
124
|
+
injectApproval,
|
|
125
|
+
} from '@jagreehal/workflow';
|
|
126
|
+
|
|
127
|
+
// 1. Create an approval step
|
|
128
|
+
const requireManagerApproval = createApprovalStep<{ approvedBy: string }>({
|
|
129
|
+
key: 'manager-approval',
|
|
130
|
+
checkApproval: async () => {
|
|
131
|
+
const approval = await db.getApproval('manager-approval');
|
|
132
|
+
if (!approval) return { status: 'pending' };
|
|
133
|
+
if (approval.rejected) return { status: 'rejected', reason: approval.reason };
|
|
134
|
+
return { status: 'approved', value: { approvedBy: approval.manager } };
|
|
135
|
+
},
|
|
136
|
+
pendingReason: 'Waiting for manager approval',
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// 2. Use in workflow with collector
|
|
140
|
+
const collector = createHITLCollector();
|
|
141
|
+
const workflow = createWorkflow(
|
|
142
|
+
{ fetchData, requireManagerApproval },
|
|
143
|
+
{ onEvent: collector.handleEvent }
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
const result = await workflow(async (step) => {
|
|
147
|
+
const data = await step(() => fetchData('123'), { key: 'data' });
|
|
148
|
+
const approval = await step(requireManagerApproval, { key: 'manager-approval' });
|
|
149
|
+
return { data, approvedBy: approval.approvedBy };
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
// 3. Handle pending state
|
|
153
|
+
if (!result.ok && isPendingApproval(result.error)) {
|
|
154
|
+
// Save state for later resume
|
|
155
|
+
await saveToDatabase(collector.getState());
|
|
156
|
+
console.log(`Workflow paused: ${result.error.reason}`);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// 4. Resume after approval granted
|
|
160
|
+
const savedState = await loadFromDatabase();
|
|
161
|
+
const resumeState = injectApproval(savedState, {
|
|
162
|
+
stepKey: 'manager-approval',
|
|
163
|
+
value: { approvedBy: 'alice@example.com' }
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
const workflow2 = createWorkflow(
|
|
167
|
+
{ fetchData, requireManagerApproval },
|
|
168
|
+
{ resumeState }
|
|
169
|
+
);
|
|
170
|
+
// Re-run same workflow body — cached steps skip, approval injected
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### HITL utilities
|
|
174
|
+
|
|
175
|
+
```typescript
|
|
176
|
+
// Check approval state
|
|
177
|
+
hasPendingApproval(state, 'approval-key') // boolean
|
|
178
|
+
getPendingApprovals(state) // string[]
|
|
179
|
+
|
|
180
|
+
// Modify state
|
|
181
|
+
clearStep(state, 'step-key') // Remove step from state
|
|
182
|
+
injectApproval(state, { stepKey, value }) // Add approval result
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Interop with neverthrow
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
import { Result as NTResult } from 'neverthrow';
|
|
189
|
+
import { ok, err, type Result } from '@jagreehal/workflow';
|
|
190
|
+
|
|
191
|
+
function fromNeverthrow<T, E>(ntResult: NTResult<T, E>): Result<T, E> {
|
|
192
|
+
return ntResult.isOk() ? ok(ntResult.value) : err(ntResult.error);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Use in workflow
|
|
196
|
+
const result = await workflow(async (step) => {
|
|
197
|
+
const validated = await step(fromNeverthrow(validateInput(data)));
|
|
198
|
+
return validated;
|
|
199
|
+
});
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## Low-level: run()
|
|
203
|
+
|
|
204
|
+
`createWorkflow` is built on `run()`. Use it for one-off workflows:
|
|
205
|
+
|
|
206
|
+
```typescript
|
|
207
|
+
import { run } from '@jagreehal/workflow';
|
|
208
|
+
|
|
209
|
+
const result = await run(async (step) => {
|
|
210
|
+
const user = await step(fetchUser(id));
|
|
211
|
+
return user;
|
|
212
|
+
});
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### run.strict()
|
|
216
|
+
|
|
217
|
+
For closed error unions without `UnexpectedError`:
|
|
218
|
+
|
|
219
|
+
```typescript
|
|
220
|
+
import { run } from '@jagreehal/workflow';
|
|
221
|
+
|
|
222
|
+
type AppError = 'NOT_FOUND' | 'UNAUTHORIZED' | 'UNEXPECTED';
|
|
223
|
+
|
|
224
|
+
const result = await run.strict<User, AppError>(
|
|
225
|
+
async (step) => {
|
|
226
|
+
return await step(fetchUser(id));
|
|
227
|
+
},
|
|
228
|
+
{ catchUnexpected: () => 'UNEXPECTED' as const }
|
|
229
|
+
);
|
|
230
|
+
|
|
231
|
+
// result.error: 'NOT_FOUND' | 'UNAUTHORIZED' | 'UNEXPECTED' (exactly)
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Prefer `createWorkflow` for automatic error type inference.
|
package/docs/api.md
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# API Reference
|
|
2
|
+
|
|
3
|
+
## Workflows
|
|
4
|
+
|
|
5
|
+
### createWorkflow
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
createWorkflow(deps) // Auto-inferred error types
|
|
9
|
+
createWorkflow(deps, { strict: true, catchUnexpected }) // Closed error union
|
|
10
|
+
createWorkflow(deps, { onEvent, createContext }) // Event stream + context
|
|
11
|
+
createWorkflow(deps, { cache }) // Step caching
|
|
12
|
+
createWorkflow(deps, { resumeState }) // Resume from saved state
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
### step
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
step(result) // Unwrap Result or exit early
|
|
19
|
+
step(result, { name, key }) // With tracing/caching options
|
|
20
|
+
step(() => result) // Lazy form (for caching/resume)
|
|
21
|
+
step(() => result, { name, key }) // Lazy with options
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### step.try
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
step.try(fn, { error }) // Static error type
|
|
28
|
+
step.try(fn, { onError }) // Dynamic error from caught value
|
|
29
|
+
step.try(fn, { error, name, key }) // With tracing options
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Low-level run
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
run(fn) // One-off workflow
|
|
36
|
+
run(fn, { onError }) // With error callback
|
|
37
|
+
run.strict(fn, { catchUnexpected }) // Closed error union
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Event helpers
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
isStepComplete(event) // Type guard for step_complete events
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Results
|
|
47
|
+
|
|
48
|
+
### Constructors
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
ok(value) // Create success
|
|
52
|
+
err(error) // Create error
|
|
53
|
+
err(error, { cause }) // Create error with cause
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Type guards
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
isOk(result) // result is { ok: true, value }
|
|
60
|
+
isErr(result) // result is { ok: false, error }
|
|
61
|
+
isUnexpectedError(error) // error is UnexpectedError
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Unwrap
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
unwrap(result) // Value or throw UnwrapError
|
|
68
|
+
unwrapOr(result, defaultValue) // Value or default
|
|
69
|
+
unwrapOrElse(result, fn) // Value or compute from error
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Wrap
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
from(fn) // Sync throwing → Result
|
|
76
|
+
from(fn, onError) // With error mapper
|
|
77
|
+
fromPromise(promise) // Promise → Result
|
|
78
|
+
fromPromise(promise, onError) // With error mapper
|
|
79
|
+
tryAsync(fn) // Async fn → Result
|
|
80
|
+
tryAsync(fn, onError) // With error mapper
|
|
81
|
+
fromNullable(value, onNull) // Nullable → Result
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Transform
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
map(result, fn) // Transform value
|
|
88
|
+
mapError(result, fn) // Transform error
|
|
89
|
+
mapTry(result, fn, onError) // Transform value, catch throws
|
|
90
|
+
mapErrorTry(result, fn, onError) // Transform error, catch throws
|
|
91
|
+
andThen(result, fn) // Chain (flatMap)
|
|
92
|
+
match(result, { ok, err }) // Pattern match
|
|
93
|
+
tap(result, fn) // Side effect on success
|
|
94
|
+
tapError(result, fn) // Side effect on error
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Batch
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
all(results) // All succeed (sync, short-circuits)
|
|
101
|
+
allAsync(results) // All succeed (async, short-circuits)
|
|
102
|
+
any(results) // First success (sync)
|
|
103
|
+
anyAsync(results) // First success (async)
|
|
104
|
+
allSettled(results) // Collect all; error array if any fail (sync)
|
|
105
|
+
allSettledAsync(results) // Collect all; error array if any fail (async)
|
|
106
|
+
partition(results) // Split into { values, errors }
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Human-in-the-Loop (HITL)
|
|
110
|
+
|
|
111
|
+
### Creating approval steps
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
createApprovalStep<T>(options) // Create approval-gated step function
|
|
115
|
+
// options: { key, checkApproval, pendingReason?, rejectedReason? }
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Checking approval status
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
isPendingApproval(error) // error is PendingApproval
|
|
122
|
+
isApprovalRejected(error) // error is ApprovalRejected
|
|
123
|
+
pendingApproval(stepKey, options?) // Create PendingApproval error
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Managing approval state
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
createHITLCollector() // Collect step events for resume
|
|
130
|
+
injectApproval(state, { stepKey, value }) // Add approval to resume state
|
|
131
|
+
clearStep(state, stepKey) // Remove step from resume state
|
|
132
|
+
hasPendingApproval(state, stepKey) // Check if step is pending
|
|
133
|
+
getPendingApprovals(state) // Get all pending step keys
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Types
|
|
137
|
+
|
|
138
|
+
### Core Result types
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
Result<T, E, C> // { ok: true, value: T } | { ok: false, error: E, cause?: C }
|
|
142
|
+
AsyncResult<T, E, C> // Promise<Result<T, E, C>>
|
|
143
|
+
UnexpectedError // { type: 'UNEXPECTED_ERROR', cause: unknown }
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Workflow types
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
Workflow<E, Deps> // Non-strict workflow return type
|
|
150
|
+
WorkflowStrict<E, U, Deps> // Strict workflow return type
|
|
151
|
+
WorkflowOptions<E, C> // Options for createWorkflow
|
|
152
|
+
WorkflowOptionsStrict<E, U, C> // Options for strict createWorkflow
|
|
153
|
+
AnyResultFn // Constraint for Result-returning functions
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Event types
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
WorkflowEvent<E> // Union of all event types
|
|
160
|
+
StepOptions // { name?: string, key?: string }
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### Cache & Resume types
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
StepCache // Cache interface (get/set/has/delete/clear)
|
|
167
|
+
ResumeState // { steps: Map<string, ResumeStateEntry> }
|
|
168
|
+
ResumeStateEntry // { result: Result, meta?: StepFailureMeta }
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### HITL types
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
PendingApproval // { type: 'PENDING_APPROVAL', stepKey, reason? }
|
|
175
|
+
ApprovalRejected // { type: 'APPROVAL_REJECTED', stepKey, reason? }
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Type extraction utilities
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
ErrorOf<Fn> // Extract error type from function
|
|
182
|
+
CauseOf<Fn> // Extract cause type from function
|
|
183
|
+
Errors<[Fn1, Fn2, ...]> // Union of error types from functions
|
|
184
|
+
ErrorsOfDeps<Deps> // Extract errors from deps object
|
|
185
|
+
CausesOfDeps<Deps> // Extract causes from deps object
|
|
186
|
+
ExtractValue<Result> // Extract value type from Result
|
|
187
|
+
ExtractError<Result> // Extract error type from Result
|
|
188
|
+
ExtractCause<Result> // Extract cause type from Result
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Error types
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
UnwrapError<E, C> // Error thrown by unwrap()
|
|
195
|
+
```
|
package/package.json
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@jagreehal/workflow",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Typed async workflows with automatic error inference. Build type-safe workflows with Result types, step caching, resume state, and human-in-the-loop support.",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"require": "./dist/index.cjs"
|
|
14
|
+
},
|
|
15
|
+
"./core": {
|
|
16
|
+
"types": "./dist/core.d.ts",
|
|
17
|
+
"import": "./dist/core.js",
|
|
18
|
+
"require": "./dist/core.cjs"
|
|
19
|
+
},
|
|
20
|
+
"./workflow": {
|
|
21
|
+
"types": "./dist/workflow.d.ts",
|
|
22
|
+
"import": "./dist/workflow.js",
|
|
23
|
+
"require": "./dist/workflow.cjs"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"files": [
|
|
27
|
+
"dist",
|
|
28
|
+
"README.md",
|
|
29
|
+
"docs"
|
|
30
|
+
],
|
|
31
|
+
"scripts": {
|
|
32
|
+
"build": "tsup",
|
|
33
|
+
"build:tsc": "tsc --noEmit",
|
|
34
|
+
"test": "vitest run",
|
|
35
|
+
"test:watch": "vitest watch",
|
|
36
|
+
"test:coverage": "vitest run --coverage",
|
|
37
|
+
"lint": "eslint .",
|
|
38
|
+
"clean": "rm -rf dist lib",
|
|
39
|
+
"prebuild": "pnpm clean",
|
|
40
|
+
"prepare": "pnpm build",
|
|
41
|
+
"prepublishOnly": "pnpm build:tsc && pnpm run test && pnpm run lint",
|
|
42
|
+
"changeset": "changeset",
|
|
43
|
+
"version-packages": "changeset version",
|
|
44
|
+
"release": "pnpm build && changeset publish"
|
|
45
|
+
},
|
|
46
|
+
"keywords": [
|
|
47
|
+
"workflow",
|
|
48
|
+
"workflows",
|
|
49
|
+
"result",
|
|
50
|
+
"result-type",
|
|
51
|
+
"error-handling",
|
|
52
|
+
"typescript",
|
|
53
|
+
"async",
|
|
54
|
+
"async-await",
|
|
55
|
+
"type-safe",
|
|
56
|
+
"type-inference",
|
|
57
|
+
"railway-oriented-programming",
|
|
58
|
+
"functional-programming",
|
|
59
|
+
"either",
|
|
60
|
+
"monad",
|
|
61
|
+
"step",
|
|
62
|
+
"orchestration",
|
|
63
|
+
"pipeline",
|
|
64
|
+
"early-exit",
|
|
65
|
+
"resume",
|
|
66
|
+
"caching",
|
|
67
|
+
"hitl",
|
|
68
|
+
"human-in-the-loop"
|
|
69
|
+
],
|
|
70
|
+
"author": "Jag Reehal <jag@jagreehal.com>",
|
|
71
|
+
"homepage": "https://github.com/jagreehal/workflow#readme",
|
|
72
|
+
"bugs": {
|
|
73
|
+
"url": "https://github.com/jagreehal/workflow/issues"
|
|
74
|
+
},
|
|
75
|
+
"repository": {
|
|
76
|
+
"type": "git",
|
|
77
|
+
"url": "git+https://github.com/jagreehal/workflow.git"
|
|
78
|
+
},
|
|
79
|
+
"license": "MIT",
|
|
80
|
+
"devDependencies": {
|
|
81
|
+
"@changesets/cli": "^2.29.8",
|
|
82
|
+
"@eslint/js": "^9.39.2",
|
|
83
|
+
"@ianvs/prettier-plugin-sort-imports": "^4.7.0",
|
|
84
|
+
"@total-typescript/ts-reset": "^0.6.1",
|
|
85
|
+
"@total-typescript/tsconfig": "^1.0.4",
|
|
86
|
+
"@types/node": "^25.0.3",
|
|
87
|
+
"@types/picomatch": "^4.0.2",
|
|
88
|
+
"@typescript-eslint/eslint-plugin": "^8.50.0",
|
|
89
|
+
"@typescript-eslint/parser": "^8.50.0",
|
|
90
|
+
"@typescript-eslint/rule-tester": "^8.50.0",
|
|
91
|
+
"@typescript-eslint/utils": "^8.50.0",
|
|
92
|
+
"@vitest/coverage-v8": "^4.0.16",
|
|
93
|
+
"eslint": "9.39.2",
|
|
94
|
+
"eslint-config-prettier": "^10.1.8",
|
|
95
|
+
"eslint-plugin-unicorn": "^62.0.0",
|
|
96
|
+
"tsd": "^0.33.0",
|
|
97
|
+
"tsup": "^8.5.1",
|
|
98
|
+
"typescript": "^5.9.3",
|
|
99
|
+
"typescript-eslint": "^8.50.0",
|
|
100
|
+
"vitest": "^4.0.16"
|
|
101
|
+
},
|
|
102
|
+
"engines": {
|
|
103
|
+
"node": ">=18.0.0"
|
|
104
|
+
},
|
|
105
|
+
"tsd": {
|
|
106
|
+
"directory": "src",
|
|
107
|
+
"testFilePattern": "**/index.test-d.ts",
|
|
108
|
+
"compilerOptions": {
|
|
109
|
+
"strict": true,
|
|
110
|
+
"noUnusedLocals": false,
|
|
111
|
+
"noUnusedParameters": false,
|
|
112
|
+
"skipLibCheck": true
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
"publishConfig": {
|
|
116
|
+
"access": "public",
|
|
117
|
+
"registry": "https://registry.npmjs.org/"
|
|
118
|
+
}
|
|
119
|
+
}
|