{"_id":"@async-kit/workflowx","name":"@async-kit/workflowx","dist-tags":{"latest":"0.2.0"},"versions":{"0.2.0":{"name":"@async-kit/workflowx","version":"0.2.0","description":"Lightweight async workflow engine with sequential steps, parallel branches, conditional logic, per-step retry and timeout for JavaScript/TypeScript","keywords":["async","workflow","orchestration","steps","saga","pipeline","state-machine"],"license":"MIT","repository":{"type":"git","url":"git+https://github.com/NexaLeaf/async-kit.git","directory":"packages/workflowx"},"homepage":"https://github.com/NexaLeaf/async-kit/tree/main/packages/workflowx#readme","main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"publishConfig":{"access":"public"},"sideEffects":false,"scripts":{"build":"tsup","typecheck":"tsc -p tsconfig.lib.json --noEmit"},"devDependencies":{},"gitHead":"f589ca61f0ee8b4e74e94cb2019745f6b63fc39e","_id":"@async-kit/workflowx@0.2.0","bugs":{"url":"https://github.com/NexaLeaf/async-kit/issues"},"_nodeVersion":"24.14.0","_npmVersion":"11.9.0","dist":{"integrity":"sha512-SA3eODCBrVR//zkJI0idHik17R87Whpz/6aUNyL3PAdiTE0EPY6Q0VgZ4tt2Eq3kR2/KMgy5otAOw7IG8eknxw==","shasum":"2718bdaa4c7776075d87df5406d61cc805727d08","tarball":"https://registry.npmjs.org/@async-kit/workflowx/-/workflowx-0.2.0.tgz","fileCount":9,"unpackedSize":56144,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@async-kit%2fworkflowx@0.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIAh+87xeP1YU5SjM/MNI6s+7bv+ORFp8jPIJxYjcaVhDAiEA0Jl46hoAcPlotgOFAPCS/CsH6f0x3zYQHXwasD28+3Y="}]},"_npmUser":{"name":"palanisamym14","email":"palanisamym14@gmail.com"},"directories":{},"maintainers":[{"name":"palanisamym14","email":"palanisamym14@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/workflowx_0.2.0_1773298981572_0.46968303653854226"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-12T07:03:01.468Z","0.2.0":"2026-03-12T07:03:01.776Z","modified":"2026-03-12T07:03:02.221Z"},"maintainers":[{"name":"palanisamym14","email":"palanisamym14@gmail.com"}],"description":"Lightweight async workflow engine with sequential steps, parallel branches, conditional logic, per-step retry and timeout for JavaScript/TypeScript","homepage":"https://github.com/NexaLeaf/async-kit/tree/main/packages/workflowx#readme","keywords":["async","workflow","orchestration","steps","saga","pipeline","state-machine"],"repository":{"type":"git","url":"git+https://github.com/NexaLeaf/async-kit.git","directory":"packages/workflowx"},"bugs":{"url":"https://github.com/NexaLeaf/async-kit/issues"},"license":"MIT","readme":"# @async-kit/workflowx\n\nLightweight async workflow engine with **step sequencing**, **retry**, **timeout**, **parallel branches**, **conditional steps**, and **AbortSignal** support.\n\n## Install\n\n```bash\nnpm install @async-kit/workflowx\n```\n\n## Quick start\n\n```ts\nimport { createWorkflow } from '@async-kit/workflowx';\n\ninterface OrderCtx extends WorkflowContext {\n  orderId: string;\n  user?: User;\n  inventory?: Item[];\n}\n\nconst workflow = createWorkflow<OrderCtx>()\n  .step('validate',  validateOrder)\n  .parallel([fetchUser, fetchInventory])\n  .if((ctx) => ctx.user?.isPremium, applyDiscount)\n  .step('charge',    chargeCard)\n  .step('notify',    sendConfirmation);\n\nconst { ctx, durationMs } = await workflow.run({ orderId: 'ord_123' });\n```\n\n## Features\n\n| Feature | Description |\n|---|---|\n| **Step sequencing** | Steps run in declaration order, sharing a typed context |\n| **Parallel branches** | `.parallel([...])` — all steps run concurrently, then rejoin |\n| **Conditional steps** | `.if(predicate, step)` — skip steps based on context |\n| **Retry** | Per-step `retries` with automatic re-execution |\n| **Timeout** | Per-step `timeoutMs` — throws `WorkflowTimeoutError` |\n| **AbortSignal** | Cancels between steps via `WorkflowRunOptions.signal` |\n| **Hooks** | `onStepStart`, `onStepComplete`, `onStepError` |\n| **Context threading** | All steps mutate/return the same typed context |\n\n## API\n\n### `createWorkflow<TCtx>()`\n\nReturns a `Workflow<TCtx>` builder.\n\n### `.step(name?, fn, options?)`\n\n```ts\nwf.step('fetchUser', async (ctx) => {\n  ctx.user = await getUser(ctx.userId);\n}, { retries: 2, timeoutMs: 5_000 });\n```\n\n### `.parallel(steps)`\n\n```ts\nwf.parallel([\n  async (ctx) => { ctx.user = await getUser(ctx.id); },\n  async (ctx) => { ctx.items = await getCart(ctx.id); },\n]);\n```\n\n### `.if(predicate, step)`\n\n```ts\nwf.if(\n  (ctx) => ctx.total > 100,\n  (ctx) => { ctx.discount = 0.1; }\n);\n```\n\n### `workflow.run(initialCtx, options?)`\n\n```ts\nconst { ctx, durationMs, stepsExecuted } = await workflow.run(\n  { orderId: 'x', currentStep: 0 },\n  {\n    signal: abortController.signal,\n    onStepStart: (i, name) => console.log(`▶ ${i} ${name}`),\n    onStepComplete: (i, name, ms) => console.log(`✓ ${name} (${ms}ms)`),\n    onStepError: (i, name, err, attempt) => {\n      logger.warn({ name, attempt, err });\n      return attempt < 2; // true = swallow and continue\n    },\n  }\n);\n```\n\n## WorkflowContext\n\nEvery workflow context must extend `WorkflowContext`:\n\n```ts\ninterface WorkflowContext {\n  signal: AbortSignal;   // checked between steps\n  currentStep: number;   // 0-based node index\n  [key: string]: unknown;\n}\n```\n\nYou only need to provide your own fields — `signal` and `currentStep` are injected by `run()`.\n\n## Errors\n\n| Error | When |\n|---|---|\n| `WorkflowError` | Step fails after exhausting retries (`.cause` = original error) |\n| `WorkflowAbortError` | AbortSignal fires between steps |\n| `WorkflowTimeoutError` | Step exceeds `timeoutMs` |\n\n```ts\nimport { WorkflowError, WorkflowAbortError, WorkflowTimeoutError } from '@async-kit/workflowx';\n\ntry {\n  await wf.run(ctx);\n} catch (err) {\n  if (err instanceof WorkflowError) {\n    console.error(err.stepName, err.cause);\n  }\n}\n```\n\n## Examples\n\n### Retry + timeout\n\n```ts\nwf.step('callExternal', callThirdPartyApi, { retries: 3, timeoutMs: 2_000 });\n```\n\n### Aborting mid-workflow\n\n```ts\nconst ac = new AbortController();\nsetTimeout(() => ac.abort(), 5_000); // cancel after 5 s\n\nawait wf.run(ctx, { signal: ac.signal });\n```\n\n### Observability hooks\n\n```ts\nawait wf.run(ctx, {\n  onStepStart: (i, name) => metrics.startTimer(`step.${name}`),\n  onStepComplete: (i, name, ms) => metrics.recordDuration(`step.${name}`, ms),\n  onStepError: (i, name, err, attempt) => {\n    logger.warn('step failed', { name, attempt, err });\n  },\n});\n```\n\n## License\n\nMIT\n","readmeFilename":"README.md","_rev":"1-efa2c1f62d52cbba0fd08181e38d6291"}