@jagreehal/workflow 1.0.0 → 1.1.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/README.md +61 -0
- package/dist/core.cjs +1 -1
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +70 -0
- package/dist/core.d.ts +70 -0
- package/dist/core.js +1 -1
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/workflow.cjs +1 -1
- package/dist/workflow.cjs.map +1 -1
- package/dist/workflow.js +1 -1
- package/dist/workflow.js.map +1 -1
- package/package.json +15 -17
- package/docs/___advanced.test.ts +0 -565
- package/docs/___advanced_VERIFICATION.md +0 -64
package/README.md
CHANGED
|
@@ -131,6 +131,33 @@ const result = await workflow(async (step) => {
|
|
|
131
131
|
// result.error: 'NOT_FOUND' | 'FETCH_FAILED' | 'PARSE_FAILED' | UnexpectedError
|
|
132
132
|
```
|
|
133
133
|
|
|
134
|
+
### Wrapping Result-returning functions with step.fromResult
|
|
135
|
+
|
|
136
|
+
When calling functions that return `Result<T, E>`, use `step.fromResult()` to map their typed errors:
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
// callProvider returns Result<Response, ProviderError>
|
|
140
|
+
const callProvider = async (input: string): AsyncResult<Response, ProviderError> => { ... };
|
|
141
|
+
|
|
142
|
+
const result = await workflow(async (step) => {
|
|
143
|
+
// step.fromResult gives you typed errors in onError (not unknown like step.try)
|
|
144
|
+
const response = await step.fromResult(
|
|
145
|
+
() => callProvider(input),
|
|
146
|
+
{
|
|
147
|
+
onError: (e) => ({
|
|
148
|
+
type: 'PROVIDER_FAILED' as const,
|
|
149
|
+
provider: e.provider, // TypeScript knows e is ProviderError
|
|
150
|
+
code: e.code,
|
|
151
|
+
})
|
|
152
|
+
}
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
return response;
|
|
156
|
+
});
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Unlike `step.try()` where `onError` receives `unknown`, `step.fromResult()` preserves the error type.
|
|
160
|
+
|
|
134
161
|
### Parallel operations
|
|
135
162
|
|
|
136
163
|
```typescript
|
|
@@ -163,12 +190,46 @@ if (result.ok) {
|
|
|
163
190
|
| Function | What it does |
|
|
164
191
|
|----------|--------------|
|
|
165
192
|
| `createWorkflow(deps)` | Create workflow with auto-inferred error types |
|
|
193
|
+
| `run(callback, options)` | Execute workflow with manual error types |
|
|
166
194
|
| `step(op())` | Unwrap Result or exit early |
|
|
167
195
|
| `step.try(fn, { error })` | Catch throws/rejects → typed error |
|
|
196
|
+
| `step.fromResult(fn, { onError })` | Map Result errors with typed onError |
|
|
168
197
|
| `ok(value)` / `err(error)` | Create Results |
|
|
169
198
|
| `map`, `andThen`, `match` | Transform Results |
|
|
170
199
|
| `allAsync`, `partition` | Batch operations |
|
|
171
200
|
|
|
201
|
+
### Choosing Between run() and createWorkflow()
|
|
202
|
+
|
|
203
|
+
| Use Case | Recommendation |
|
|
204
|
+
|----------|----------------|
|
|
205
|
+
| Dependencies known at compile time | `createWorkflow()` |
|
|
206
|
+
| Dependencies passed as parameters | `run()` |
|
|
207
|
+
| Need step caching or resume | `createWorkflow()` |
|
|
208
|
+
| One-off workflow invocation | `run()` |
|
|
209
|
+
| Want automatic error inference | `createWorkflow()` |
|
|
210
|
+
| Error types known upfront | `run()` |
|
|
211
|
+
|
|
212
|
+
**`run()`** - Best for dynamic dependencies, testing, or lightweight workflows where you know the error types:
|
|
213
|
+
|
|
214
|
+
```typescript
|
|
215
|
+
import { run } from '@jagreehal/workflow';
|
|
216
|
+
|
|
217
|
+
const result = await run<Output, 'NOT_FOUND' | 'FETCH_ERROR'>(
|
|
218
|
+
async (step) => {
|
|
219
|
+
const user = await step(fetchUser(userId)); // userId from parameter
|
|
220
|
+
return user;
|
|
221
|
+
},
|
|
222
|
+
{ onError: (e) => console.log('Failed:', e) }
|
|
223
|
+
);
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
**`createWorkflow()`** - Best for reusable workflows with static dependencies. Provides automatic error type inference:
|
|
227
|
+
|
|
228
|
+
```typescript
|
|
229
|
+
const loadUser = createWorkflow({ fetchUser, fetchPosts });
|
|
230
|
+
// Error type computed automatically from deps
|
|
231
|
+
```
|
|
232
|
+
|
|
172
233
|
### Import paths
|
|
173
234
|
|
|
174
235
|
```typescript
|
package/dist/core.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var U=Object.defineProperty;var L=Object.getOwnPropertyDescriptor;var X=Object.getOwnPropertyNames;var W=Object.prototype.hasOwnProperty;var Y=(e,n)=>{for(var r in n)U(e,r,{get:n[r],enumerable:!0})},J=(e,n,r,t)=>{if(n&&typeof n=="object"||typeof n=="function")for(let u of X(n))!W.call(e,u)&&u!==r&&U(e,u,{get:()=>n[u],enumerable:!(t=L(n,u))||t.enumerable});return e};var G=e=>J(U({},"__esModule",{value:!0}),e);var me={};Y(me,{EARLY_EXIT_SYMBOL:()=>b,UnwrapError:()=>h,all:()=>we,allAsync:()=>ye,allSettled:()=>ke,allSettledAsync:()=>fe,andThen:()=>ie,any:()=>Re,anyAsync:()=>de,createEarlyExit:()=>M,err:()=>i,from:()=>ne,fromNullable:()=>oe,fromPromise:()=>re,isEarlyExit:()=>K,isErr:()=>B,isOk:()=>q,isUnexpectedError:()=>O,map:()=>se,mapError:()=>ue,mapErrorTry:()=>pe,mapTry:()=>ce,match:()=>ae,ok:()=>k,partition:()=>Te,run:()=>_,tap:()=>le,tapError:()=>Ee,tryAsync:()=>te,unwrap:()=>Q,unwrapOr:()=>Z,unwrapOrElse:()=>ee});module.exports=G(me);var k=e=>({ok:!0,value:e}),i=(e,n)=>({ok:!1,error:e,...n?.cause!==void 0?{cause:n.cause}:{}}),q=e=>e.ok,B=e=>!e.ok,O=e=>typeof e=="object"&&e!==null&&e.type==="UNEXPECTED_ERROR",b=Symbol("early-exit");function M(e,n){return{[b]:!0,error:e,meta:n}}function K(e){return typeof e=="object"&&e!==null&&e[b]===!0}var F=Symbol("mapper-exception");function H(e){return{[F]:!0,thrown:e}}function $(e){return typeof e=="object"&&e!==null&&e[F]===!0}function z(e){return typeof e=="string"?{name:e}:e??{}}async function _(e,n){let{onError:r,onEvent:t,catchUnexpected:u,workflowId:R,context:d}=n&&typeof n=="object"?n:{},a=R??crypto.randomUUID(),D=!r&&!u,c=o=>{t?.(o,d)},P=M,I=o=>K(o),S=(o,f)=>D?f?.origin==="result"?{type:"UNEXPECTED_ERROR",cause:{type:"STEP_FAILURE",origin:"result",error:o,...f.resultCause!==void 0?{cause:f.resultCause}:{}}}:f?.origin==="throw"?{type:"UNEXPECTED_ERROR",cause:{type:"STEP_FAILURE",origin:"throw",error:o,thrown:f.thrown}}:{type:"UNEXPECTED_ERROR",cause:{type:"STEP_FAILURE",origin:"result",error:o}}:o,N=o=>o.origin==="result"?o.resultCause:o.thrown,V=o=>({type:"UNEXPECTED_ERROR",cause:o.meta.origin==="result"?{type:"STEP_FAILURE",origin:"result",error:o.error,...o.meta.resultCause!==void 0?{cause:o.meta.resultCause}:{}}:{type:"STEP_FAILURE",origin:"throw",error:o.error,thrown:o.meta.thrown}});try{let o=(m,T)=>(async()=>{let{name:l,key:s}=z(T),v=t?performance.now():0;t&&c({type:"step_start",workflowId:a,stepKey:s,name:l,ts:Date.now()});let p;try{p=await(typeof m=="function"?m():m)}catch(y){let C=performance.now()-v;if(I(y))throw c({type:"step_aborted",workflowId:a,stepKey:s,name:l,ts:Date.now(),durationMs:C}),y;if(u){let A;try{A=u(y)}catch(j){throw H(j)}throw c({type:"step_error",workflowId:a,stepKey:s,name:l,ts:Date.now(),durationMs:C,error:A}),s&&c({type:"step_complete",workflowId:a,stepKey:s,name:l,ts:Date.now(),durationMs:C,result:i(A,{cause:y}),meta:{origin:"throw",thrown:y}}),r?.(A,l),P(A,{origin:"throw",thrown:y})}else{let A={type:"UNEXPECTED_ERROR",cause:{type:"UNCAUGHT_EXCEPTION",thrown:y}};throw c({type:"step_error",workflowId:a,stepKey:s,name:l,ts:Date.now(),durationMs:C,error:A}),s&&c({type:"step_complete",workflowId:a,stepKey:s,name:l,ts:Date.now(),durationMs:C,result:i(A,{cause:y}),meta:{origin:"throw",thrown:y}}),y}}let E=performance.now()-v;if(p.ok)return c({type:"step_success",workflowId:a,stepKey:s,name:l,ts:Date.now(),durationMs:E}),s&&c({type:"step_complete",workflowId:a,stepKey:s,name:l,ts:Date.now(),durationMs:E,result:p}),p.value;let w=S(p.error,{origin:"result",resultCause:p.cause});throw c({type:"step_error",workflowId:a,stepKey:s,name:l,ts:Date.now(),durationMs:E,error:w}),s&&c({type:"step_complete",workflowId:a,stepKey:s,name:l,ts:Date.now(),durationMs:E,result:p,meta:{origin:"result",resultCause:p.cause}}),r?.(p.error,l),P(p.error,{origin:"result",resultCause:p.cause})})();o.try=(m,T)=>{let l=T.name,s=T.key,g="error"in T?()=>T.error:T.onError,v=t;return(async()=>{let p=v?performance.now():0;t&&c({type:"step_start",workflowId:a,stepKey:s,name:l,ts:Date.now()});try{let E=await m(),w=performance.now()-p;return c({type:"step_success",workflowId:a,stepKey:s,name:l,ts:Date.now(),durationMs:w}),s&&c({type:"step_complete",workflowId:a,stepKey:s,name:l,ts:Date.now(),durationMs:w,result:k(E)}),E}catch(E){let w=g(E),y=performance.now()-p,C=S(w,{origin:"throw",thrown:E});throw c({type:"step_error",workflowId:a,stepKey:s,name:l,ts:Date.now(),durationMs:y,error:C}),s&&c({type:"step_complete",workflowId:a,stepKey:s,name:l,ts:Date.now(),durationMs:y,result:i(w,{cause:E}),meta:{origin:"throw",thrown:E}}),r?.(w,l),P(w,{origin:"throw",thrown:E})}})()},o.fromResult=(m,T)=>{let l=T.name,s=T.key,g="error"in T?()=>T.error:T.onError,v=t;return(async()=>{let p=v?performance.now():0;t&&c({type:"step_start",workflowId:a,stepKey:s,name:l,ts:Date.now()});let E=await m();if(E.ok){let w=performance.now()-p;return c({type:"step_success",workflowId:a,stepKey:s,name:l,ts:Date.now(),durationMs:w}),s&&c({type:"step_complete",workflowId:a,stepKey:s,name:l,ts:Date.now(),durationMs:w,result:k(E.value)}),E.value}else{let w=g(E.error),y=performance.now()-p,C=S(w,{origin:"result",resultCause:E.error});throw c({type:"step_error",workflowId:a,stepKey:s,name:l,ts:Date.now(),durationMs:y,error:C}),s&&c({type:"step_complete",workflowId:a,stepKey:s,name:l,ts:Date.now(),durationMs:y,result:i(w,{cause:E.error}),meta:{origin:"result",resultCause:E.error}}),r?.(w,l),P(w,{origin:"result",resultCause:E.error})}})()};let x=await e(o);return k(x)}catch(o){if($(o))throw o.thrown;if(I(o)){let x=N(o.meta);if(u||r)return i(o.error,{cause:x});if(O(o.error))return i(o.error,{cause:x});let m=V(o);return i(m,{cause:x})}if(u){let x=u(o);return r?.(x,"unexpected"),i(x,{cause:o})}let f={type:"UNEXPECTED_ERROR",cause:{type:"UNCAUGHT_EXCEPTION",thrown:o}};return r?.(f,"unexpected"),i(f,{cause:o})}}_.strict=(e,n)=>_(e,n);var h=class extends Error{constructor(r,t){super(`Unwrap called on an error result: ${String(r)}`);this.error=r;this.cause=t;this.name="UnwrapError"}},Q=e=>{if(e.ok)return e.value;throw new h(e.error,e.cause)},Z=(e,n)=>e.ok?e.value:n,ee=(e,n)=>e.ok?e.value:n(e.error,e.cause);function ne(e,n){try{return k(e())}catch(r){return n?i(n(r),{cause:r}):i(r)}}async function re(e,n){try{return k(await e)}catch(r){return n?i(n(r),{cause:r}):i(r)}}async function te(e,n){try{return k(await e())}catch(r){return n?i(n(r),{cause:r}):i(r)}}function oe(e,n){return e!=null?k(e):i(n())}function se(e,n){return e.ok?k(n(e.value)):e}function ue(e,n){return e.ok?e:i(n(e.error),{cause:e.cause})}function ae(e,n){return e.ok?n.ok(e.value):n.err(e.error,e.cause)}function ie(e,n){return e.ok?n(e.value):e}function le(e,n){return e.ok&&n(e.value),e}function Ee(e,n){return e.ok||n(e.error,e.cause),e}function ce(e,n,r){if(!e.ok)return e;try{return k(n(e.value))}catch(t){return i(r(t),{cause:t})}}function pe(e,n,r){if(e.ok)return e;try{return i(n(e.error),{cause:e.cause})}catch(t){return i(r(t),{cause:t})}}function we(e){let n=[];for(let r of e){if(!r.ok)return r;n.push(r.value)}return k(n)}async function ye(e){return e.length===0?k([]):new Promise(n=>{let r=!1,t=e.length,u=new Array(e.length);for(let R=0;R<e.length;R++){let d=R;Promise.resolve(e[d]).catch(a=>i({type:"PROMISE_REJECTED",cause:a},{cause:{type:"PROMISE_REJECTION",reason:a}})).then(a=>{if(!r){if(!a.ok){r=!0,n(a);return}u[d]=a.value,t--,t===0&&n(k(u))}})}})}function ke(e){let n=[],r=[];for(let t of e)t.ok?n.push(t.value):r.push({error:t.error,cause:t.cause});return r.length>0?i(r):k(n)}function Te(e){let n=[],r=[];for(let t of e)t.ok?n.push(t.value):r.push(t.error);return{values:n,errors:r}}function Re(e){if(e.length===0)return i({type:"EMPTY_INPUT",message:"any() requires at least one Result"});let n=null;for(let r of e){if(r.ok)return r;n||(n=r)}return n}async function de(e){return e.length===0?i({type:"EMPTY_INPUT",message:"anyAsync() requires at least one Result"}):new Promise(n=>{let r=!1,t=e.length,u=null;for(let R of e)Promise.resolve(R).catch(d=>i({type:"PROMISE_REJECTED",cause:d},{cause:{type:"PROMISE_REJECTION",reason:d}})).then(d=>{if(!r){if(d.ok){r=!0,n(d);return}u||(u=d),t--,t===0&&n(u)}})})}async function fe(e){let n=await Promise.all(e.map(u=>Promise.resolve(u).then(R=>({status:"result",result:R})).catch(R=>({status:"rejected",error:{type:"PROMISE_REJECTED",cause:R},cause:{type:"PROMISE_REJECTION",reason:R}})))),r=[],t=[];for(let u of n)u.status==="rejected"?t.push({error:u.error,cause:u.cause}):u.result.ok?r.push(u.result.value):t.push({error:u.result.error,cause:u.result.cause});return t.length>0?i(t):k(r)}0&&(module.exports={EARLY_EXIT_SYMBOL,UnwrapError,all,allAsync,allSettled,allSettledAsync,andThen,any,anyAsync,createEarlyExit,err,from,fromNullable,fromPromise,isEarlyExit,isErr,isOk,isUnexpectedError,map,mapError,mapErrorTry,mapTry,match,ok,partition,run,tap,tapError,tryAsync,unwrap,unwrapOr,unwrapOrElse});
|
|
2
2
|
//# sourceMappingURL=core.cjs.map
|