awaitly 1.35.0 → 2.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/dist/{duration.d.ts → di-BDlT7InM.d.cts} +15 -1
- package/dist/{duration.d.cts → di-BbFFfO8y.d.ts} +15 -1
- package/dist/errors-DtXvrCiO.d.cts +708 -0
- package/dist/errors-DtXvrCiO.d.ts +708 -0
- package/dist/index.cjs +4594 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1970 -141
- package/dist/index.d.ts +1970 -141
- package/dist/index.js +4398 -1
- package/dist/index.js.map +1 -1
- package/dist/result.cjs +641 -1
- package/dist/result.cjs.map +1 -1
- package/dist/result.d.cts +29 -4
- package/dist/result.d.ts +29 -4
- package/dist/result.js +561 -1
- package/dist/result.js.map +1 -1
- package/dist/testing.cjs +4202 -8
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +2 -6
- package/dist/testing.d.ts +2 -6
- package/dist/testing.js +4154 -8
- package/dist/testing.js.map +1 -1
- package/dist/{run-entry-DGs0tySr.d.cts → types-B8NfNRGX.d.ts} +1078 -1502
- package/dist/{run-entry-BOuNyVoO.d.ts → types-BZ2f4MRR.d.cts} +1078 -1502
- package/dist/workflow.cjs +7096 -6
- package/dist/workflow.cjs.map +1 -1
- package/dist/workflow.d.cts +3346 -22
- package/dist/workflow.d.ts +3346 -22
- package/dist/workflow.js +6929 -6
- package/dist/workflow.js.map +1 -1
- package/package.json +3 -168
- package/dist/adapters.cjs +0 -7
- package/dist/adapters.cjs.map +0 -1
- package/dist/adapters.d.cts +0 -179
- package/dist/adapters.d.ts +0 -179
- package/dist/adapters.js +0 -7
- package/dist/adapters.js.map +0 -1
- package/dist/batch.cjs +0 -7
- package/dist/batch.cjs.map +0 -1
- package/dist/batch.d.cts +0 -200
- package/dist/batch.d.ts +0 -200
- package/dist/batch.js +0 -7
- package/dist/batch.js.map +0 -1
- package/dist/bind-deps.cjs +0 -2
- package/dist/bind-deps.cjs.map +0 -1
- package/dist/bind-deps.d.cts +0 -28
- package/dist/bind-deps.d.ts +0 -28
- package/dist/bind-deps.js +0 -2
- package/dist/bind-deps.js.map +0 -1
- package/dist/cache.cjs +0 -2
- package/dist/cache.cjs.map +0 -1
- package/dist/cache.d.cts +0 -269
- package/dist/cache.d.ts +0 -269
- package/dist/cache.js +0 -2
- package/dist/cache.js.map +0 -1
- package/dist/circuit-breaker.cjs +0 -7
- package/dist/circuit-breaker.cjs.map +0 -1
- package/dist/circuit-breaker.d.cts +0 -211
- package/dist/circuit-breaker.d.ts +0 -211
- package/dist/circuit-breaker.js +0 -7
- package/dist/circuit-breaker.js.map +0 -1
- package/dist/conditional.cjs +0 -2
- package/dist/conditional.cjs.map +0 -1
- package/dist/conditional.d.cts +0 -252
- package/dist/conditional.d.ts +0 -252
- package/dist/conditional.js +0 -2
- package/dist/conditional.js.map +0 -1
- package/dist/core.cjs +0 -7
- package/dist/core.cjs.map +0 -1
- package/dist/core.d.cts +0 -5
- package/dist/core.d.ts +0 -5
- package/dist/core.js +0 -7
- package/dist/core.js.map +0 -1
- package/dist/di-By77n4Fa.d.ts +0 -15
- package/dist/di-OJfsohf-.d.cts +0 -15
- package/dist/diagnostics.cjs +0 -8
- package/dist/diagnostics.cjs.map +0 -1
- package/dist/diagnostics.d.cts +0 -68
- package/dist/diagnostics.d.ts +0 -68
- package/dist/diagnostics.js +0 -8
- package/dist/diagnostics.js.map +0 -1
- package/dist/durable.cjs +0 -11
- package/dist/durable.cjs.map +0 -1
- package/dist/durable.d.cts +0 -9
- package/dist/durable.d.ts +0 -9
- package/dist/durable.js +0 -11
- package/dist/durable.js.map +0 -1
- package/dist/duration.cjs +0 -2
- package/dist/duration.cjs.map +0 -1
- package/dist/duration.js +0 -2
- package/dist/duration.js.map +0 -1
- package/dist/engine.cjs +0 -11
- package/dist/engine.cjs.map +0 -1
- package/dist/engine.d.cts +0 -115
- package/dist/engine.d.ts +0 -115
- package/dist/engine.js +0 -11
- package/dist/engine.js.map +0 -1
- package/dist/errors.cjs +0 -2
- package/dist/errors.cjs.map +0 -1
- package/dist/errors.d.cts +0 -361
- package/dist/errors.d.ts +0 -361
- package/dist/errors.js +0 -2
- package/dist/errors.js.map +0 -1
- package/dist/fetch.cjs +0 -7
- package/dist/fetch.cjs.map +0 -1
- package/dist/fetch.d.cts +0 -86
- package/dist/fetch.d.ts +0 -86
- package/dist/fetch.js +0 -7
- package/dist/fetch.js.map +0 -1
- package/dist/flow.cjs +0 -7
- package/dist/flow.cjs.map +0 -1
- package/dist/flow.d.cts +0 -163
- package/dist/flow.d.ts +0 -163
- package/dist/flow.js +0 -7
- package/dist/flow.js.map +0 -1
- package/dist/functional.cjs +0 -2
- package/dist/functional.cjs.map +0 -1
- package/dist/functional.d.cts +0 -444
- package/dist/functional.d.ts +0 -444
- package/dist/functional.js +0 -2
- package/dist/functional.js.map +0 -1
- package/dist/guards-4sV7mTqj.d.cts +0 -72
- package/dist/guards-BIX05ALH.d.ts +0 -72
- package/dist/hitl-DFn4Xa_l.d.cts +0 -468
- package/dist/hitl-DU5VpKq7.d.ts +0 -468
- package/dist/hitl.cjs +0 -7
- package/dist/hitl.cjs.map +0 -1
- package/dist/hitl.d.cts +0 -442
- package/dist/hitl.d.ts +0 -442
- package/dist/hitl.js +0 -7
- package/dist/hitl.js.map +0 -1
- package/dist/index-CnvBryQB.d.ts +0 -417
- package/dist/index-DEZEf8Fs.d.cts +0 -417
- package/dist/match-entry-DjI2bLpD.d.cts +0 -209
- package/dist/match-entry-DjI2bLpD.d.ts +0 -209
- package/dist/match.cjs +0 -2
- package/dist/match.cjs.map +0 -1
- package/dist/match.d.cts +0 -1
- package/dist/match.d.ts +0 -1
- package/dist/match.js +0 -2
- package/dist/match.js.map +0 -1
- package/dist/otel.cjs +0 -2
- package/dist/otel.cjs.map +0 -1
- package/dist/otel.d.cts +0 -188
- package/dist/otel.d.ts +0 -188
- package/dist/otel.js +0 -2
- package/dist/otel.js.map +0 -1
- package/dist/persistence-entry-B-8PjnSR.d.cts +0 -831
- package/dist/persistence-entry-D8zRkLiT.d.ts +0 -831
- package/dist/persistence.cjs +0 -2
- package/dist/persistence.cjs.map +0 -1
- package/dist/persistence.d.cts +0 -7
- package/dist/persistence.d.ts +0 -7
- package/dist/persistence.js +0 -2
- package/dist/persistence.js.map +0 -1
- package/dist/policies.cjs +0 -2
- package/dist/policies.cjs.map +0 -1
- package/dist/policies.d.cts +0 -379
- package/dist/policies.d.ts +0 -379
- package/dist/policies.js +0 -2
- package/dist/policies.js.map +0 -1
- package/dist/ratelimit.cjs +0 -7
- package/dist/ratelimit.cjs.map +0 -1
- package/dist/ratelimit.d.cts +0 -458
- package/dist/ratelimit.d.ts +0 -458
- package/dist/ratelimit.js +0 -7
- package/dist/ratelimit.js.map +0 -1
- package/dist/reliability.cjs +0 -11
- package/dist/reliability.cjs.map +0 -1
- package/dist/reliability.d.cts +0 -11
- package/dist/reliability.d.ts +0 -11
- package/dist/reliability.js +0 -11
- package/dist/reliability.js.map +0 -1
- package/dist/resolver.cjs +0 -7
- package/dist/resolver.cjs.map +0 -1
- package/dist/resolver.d.cts +0 -68
- package/dist/resolver.d.ts +0 -68
- package/dist/resolver.js +0 -7
- package/dist/resolver.js.map +0 -1
- package/dist/resource.cjs +0 -7
- package/dist/resource.cjs.map +0 -1
- package/dist/resource.d.cts +0 -174
- package/dist/resource.d.ts +0 -174
- package/dist/resource.js +0 -7
- package/dist/resource.js.map +0 -1
- package/dist/result/retry.cjs +0 -2
- package/dist/result/retry.cjs.map +0 -1
- package/dist/result/retry.d.cts +0 -70
- package/dist/result/retry.d.ts +0 -70
- package/dist/result/retry.js +0 -2
- package/dist/result/retry.js.map +0 -1
- package/dist/retry.cjs +0 -2
- package/dist/retry.cjs.map +0 -1
- package/dist/retry.d.cts +0 -388
- package/dist/retry.d.ts +0 -388
- package/dist/retry.js +0 -2
- package/dist/retry.js.map +0 -1
- package/dist/run.cjs +0 -7
- package/dist/run.cjs.map +0 -1
- package/dist/run.d.cts +0 -4
- package/dist/run.d.ts +0 -4
- package/dist/run.js +0 -7
- package/dist/run.js.map +0 -1
- package/dist/saga.cjs +0 -11
- package/dist/saga.cjs.map +0 -1
- package/dist/saga.d.cts +0 -164
- package/dist/saga.d.ts +0 -164
- package/dist/saga.js +0 -11
- package/dist/saga.js.map +0 -1
- package/dist/singleflight.cjs +0 -2
- package/dist/singleflight.cjs.map +0 -1
- package/dist/singleflight.d.cts +0 -145
- package/dist/singleflight.d.ts +0 -145
- package/dist/singleflight.js +0 -2
- package/dist/singleflight.js.map +0 -1
- package/dist/slugs.cjs +0 -2
- package/dist/slugs.cjs.map +0 -1
- package/dist/slugs.d.cts +0 -67
- package/dist/slugs.d.ts +0 -67
- package/dist/slugs.js +0 -2
- package/dist/slugs.js.map +0 -1
- package/dist/streaming.cjs +0 -9
- package/dist/streaming.cjs.map +0 -1
- package/dist/streaming.d.cts +0 -596
- package/dist/streaming.d.ts +0 -596
- package/dist/streaming.js +0 -9
- package/dist/streaming.js.map +0 -1
- package/dist/tagged-error.cjs +0 -2
- package/dist/tagged-error.cjs.map +0 -1
- package/dist/tagged-error.d.cts +0 -275
- package/dist/tagged-error.d.ts +0 -275
- package/dist/tagged-error.js +0 -2
- package/dist/tagged-error.js.map +0 -1
- package/dist/types-BziYHFkD.d.ts +0 -323
- package/dist/types-C5jLEUqY.d.cts +0 -323
- package/dist/webhook.cjs +0 -7
- package/dist/webhook.cjs.map +0 -1
- package/dist/webhook.d.cts +0 -499
- package/dist/webhook.d.ts +0 -499
- package/dist/webhook.js +0 -7
- package/dist/webhook.js.map +0 -1
package/dist/persistence.cjs
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
"use strict";var d=Object.defineProperty;var v=Object.getOwnPropertyDescriptor;var V=Object.getOwnPropertyNames;var W=Object.prototype.hasOwnProperty;var N=(t,e)=>{for(var n in e)d(t,n,{get:e[n],enumerable:!0})},R=(t,e,n,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of V(e))!W.call(t,r)&&r!==n&&d(t,r,{get:()=>e[r],enumerable:!(s=v(e,r))||s.enumerable});return t};var E=t=>R(d({},"__esModule",{value:!0}),t);var C={};N(C,{SnapshotDecodeError:()=>c,SnapshotFormatError:()=>l,SnapshotMismatchError:()=>p,assertValidSnapshot:()=>x,createMemoryCache:()=>O,deserializeCauseNew:()=>w,looksLikeWorkflowSnapshot:()=>y,mergeSnapshots:()=>b,serializeError:()=>g,serializeThrown:()=>h,validateSnapshot:()=>m});module.exports=E(C);var l=class extends Error{constructor(n,s=[]){super(n);this.errors=s;this.name="SnapshotFormatError"}errors},p=class extends Error{constructor(n,s,r){super(n);this.mismatchType=s;this.details=r;this.name="SnapshotMismatchError"}mismatchType;details},c=class extends Error{constructor(n,s,r){super(n);this.stepId=s;this.originalError=r;this.name="SnapshotDecodeError"}stepId;originalError};function y(t){return typeof t=="object"&&t!==null&&"formatVersion"in t&&t.formatVersion===1&&"steps"in t&&typeof t.steps=="object"&&t.steps!==null&&"execution"in t&&typeof t.execution=="object"}function m(t){let e=[];if(typeof t!="object"||t===null)return{valid:!1,errors:["Snapshot must be an object"]};let n=t;if("formatVersion"in n?n.formatVersion!==1&&e.push(`Invalid formatVersion: expected 1, got ${n.formatVersion}`):e.push("Missing required field: formatVersion"),!("steps"in n))e.push("Missing required field: steps");else if(typeof n.steps!="object"||n.steps===null)e.push("steps must be an object");else{let s=n.steps;for(let[r,u]of Object.entries(s)){if(typeof u!="object"||u===null){e.push(`steps["${r}"] must be an object`);continue}let i=u;"ok"in i?typeof i.ok!="boolean"?e.push(`steps["${r}"].ok must be a boolean`):i.ok===!1&&("error"in i||e.push(`steps["${r}"] is error result but missing error field`),"cause"in i||e.push(`steps["${r}"] is error result but missing cause field`)):e.push(`steps["${r}"] missing required field: ok`)}}if(!("execution"in n))e.push("Missing required field: execution");else if(typeof n.execution!="object"||n.execution===null)e.push("execution must be an object");else{let s=n.execution;"status"in s?["running","completed","failed"].includes(s.status)||e.push("execution.status must be one of: running, completed, failed"):e.push("execution missing required field: status"),"lastUpdated"in s?typeof s.lastUpdated!="string"&&e.push("execution.lastUpdated must be a string (ISO timestamp)"):e.push("execution missing required field: lastUpdated")}return e.length>0?{valid:!1,errors:e}:{valid:!0,snapshot:t}}function x(t){let e=m(t);if(!e.valid)throw new l(`Invalid snapshot format: ${e.errors[0]}`,e.errors);return e.snapshot}function b(t,e){let n=Object.create(null);for(let[i,o]of Object.entries(t.steps))Object.prototype.hasOwnProperty.call(t.steps,i)&&(n[i]=o);for(let[i,o]of Object.entries(e.steps))Object.prototype.hasOwnProperty.call(e.steps,i)&&(n[i]=o);let s=t.metadata||e.metadata?{...t.metadata,...e.metadata}:void 0,u=[...(t.warnings||[]).filter(i=>!Object.prototype.hasOwnProperty.call(e.steps,i.stepId)),...e.warnings||[]];return{formatVersion:1,steps:n,execution:{...e.execution},metadata:s,warnings:u.length>0?u:void 0}}var S=1e3;function g(t){let e={type:"error",name:t.name,message:t.message};t.stack&&(e.stack=t.stack);let n=t;return n.cause!==void 0&&(n.cause instanceof Error?e.cause=g(n.cause):e.cause=h(n.cause)),e}function h(t){let e,n=!1;try{e=String(t),e.length>S&&(e=e.slice(0,S),n=!0)}catch{e="[unable to convert to string]"}let s=t===null?"null":typeof t=="object"?t.constructor?.name??"Object":typeof t,r;try{let i=JSON.stringify(t);i!==void 0&&(r=JSON.parse(i))}catch{}let u={type:"thrown",originalType:s,stringRepresentation:e};return r!==void 0&&(u.value=r),n&&(u.truncated=!0),u}function w(t){if(t.type==="error"){let e=new Error(t.message);return e.name=t.name,t.stack&&(e.stack=t.stack),t.cause&&(e.cause=w(t.cause)),e}return t.value!==void 0?t.value:t.stringRepresentation}function O(t={}){let{maxSize:e,ttl:n}=t,s=new Map,r=o=>{let a=o.entryTtl??n;return a?Date.now()-o.timestamp>a:!1},u=()=>{for(let[o,a]of s)r(a)&&s.delete(o)},i=()=>{if(!e||s.size<e)return;let o,a=1/0;for(let[f,k]of s)k.timestamp<a&&(a=k.timestamp,o=f);o&&s.delete(o)};return{get(o){u();let a=s.get(o);if(a){if(r(a)){s.delete(o);return}return a.result}},set(o,a,f){u(),i(),s.set(o,{result:a,timestamp:Date.now(),entryTtl:f?.ttl})},has(o){u();let a=s.get(o);return a?r(a)?(s.delete(o),!1):!0:!1},delete(o){return s.delete(o)},clear(){s.clear()}}}0&&(module.exports={SnapshotDecodeError,SnapshotFormatError,SnapshotMismatchError,assertValidSnapshot,createMemoryCache,deserializeCauseNew,looksLikeWorkflowSnapshot,mergeSnapshots,serializeError,serializeThrown,validateSnapshot});
|
|
2
|
-
//# sourceMappingURL=persistence.cjs.map
|
package/dist/persistence.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/persistence-entry.ts","../src/persistence.ts"],"sourcesContent":["/**\n * awaitly/persistence\n *\n * Simplified Persistence API for workflow snapshots.\n */\n\n// =============================================================================\n// Snapshot API (JSON-serializable workflow state)\n// =============================================================================\nexport {\n // Types\n type JSONValue,\n type WorkflowSnapshot,\n type StepResult,\n type SerializedCause,\n type SnapshotWarning,\n\n // Store interface\n type SnapshotStore,\n\n // Validation\n looksLikeWorkflowSnapshot,\n validateSnapshot,\n assertValidSnapshot,\n mergeSnapshots,\n\n // Error classes\n SnapshotFormatError,\n SnapshotMismatchError,\n SnapshotDecodeError,\n\n // Serialization helpers (for custom implementations)\n serializeError,\n serializeThrown,\n deserializeCauseNew,\n\n // Cache adapter\n type MemoryCacheOptions,\n createMemoryCache,\n} from \"./persistence\";\n","/**\n * awaitly/persistence\n *\n * Simplified Persistence API for workflow snapshots.\n * Provides JSON-serializable snapshot format and store adapters.\n */\n\nimport type { Result } from \"./core\";\nimport type { StepCache } from \"./workflow\";\n\n// =============================================================================\n// JSON-Safe Type Enforcement\n// =============================================================================\n\n/**\n * Enforce JSON-safety at type level.\n * Only allows values that can be safely serialized with JSON.stringify.\n */\nexport type JSONValue =\n | null\n | boolean\n | number\n | string\n | JSONValue[]\n | { [k: string]: JSONValue };\n\n// =============================================================================\n// WorkflowSnapshot Types (Simplified API)\n// =============================================================================\n\n/**\n * Canonical error wire format - handles both Error instances and thrown non-Errors.\n * This is the single source of truth for serialized errors in snapshots.\n */\nexport type SerializedCause =\n | { type: \"error\"; name: string; message: string; stack?: string; cause?: SerializedCause }\n | { type: \"thrown\"; originalType?: string; value?: JSONValue; stringRepresentation: string; truncated?: true };\n\n/**\n * Single source of truth for step outcome (no error/cause confusion).\n * Uses discriminated union with `ok` field.\n */\nexport type StepResult =\n | { ok: true; value: JSONValue }\n | { ok: false; error: JSONValue; cause: SerializedCause; meta?: { origin: \"result\" | \"throw\" } };\n\n/**\n * JSON-serializable workflow snapshot.\n * Designed to be passed directly to JSON.stringify without special handling.\n *\n * @example\n * ```typescript\n * // Persist\n * localStorage.setItem('wf-123', JSON.stringify(wf.getSnapshot()));\n *\n * // Restore (safe pattern - storage can be empty/corrupt)\n * const raw = localStorage.getItem('wf-123');\n * const snapshot = raw ? JSON.parse(raw) : null;\n * createWorkflow(deps, { snapshot }); // null = fresh start\n * ```\n */\nexport interface WorkflowSnapshot {\n /** Snapshot format version (literal type - bump when shape changes) */\n formatVersion: 1;\n /** Workflow name (from createWorkflow first argument). */\n workflowName?: string;\n /** Step results keyed by step ID. Uses Object.create(null) internally. */\n steps: Record<string, StepResult>;\n /** Execution state metadata */\n execution: {\n status: \"running\" | \"completed\" | \"failed\";\n /** ISO timestamp (UTC toISOString()) */\n lastUpdated: string;\n /** ISO timestamp if finished */\n completedAt?: string;\n /**\n * For paused/running workflows: the step key of the current step.\n * Aligns with Workflow Diagram DSL step state ids (see awaitly/workflow diagram-dsl)\n * so visualizers can highlight the current node.\n */\n currentStepId?: string;\n };\n /** Optional metadata for workflow identification and replay */\n metadata?: {\n /** Detect wrong snapshot for wrong workflow */\n workflowId?: string;\n /** Optional: detect definition changes (user-supplied, advisory only) */\n definitionHash?: string;\n /** Original input for replay */\n input?: JSONValue;\n [key: string]: JSONValue | undefined;\n };\n /** Warnings for lossy serialization (keeps step results pure) */\n warnings?: Array<{\n type: \"lossy_value\";\n stepId: string;\n path: string;\n reason: \"non-json\" | \"circular\" | \"encode-failed\";\n }>;\n}\n\n/**\n * Warning entry for lossy value serialization.\n */\nexport type SnapshotWarning = NonNullable<WorkflowSnapshot[\"warnings\"]>[number];\n\n// =============================================================================\n// Snapshot Validation\n// =============================================================================\n\n/**\n * Error thrown when snapshot structure is invalid.\n */\nexport class SnapshotFormatError extends Error {\n constructor(\n message: string,\n public readonly errors: string[] = []\n ) {\n super(message);\n this.name = \"SnapshotFormatError\";\n }\n}\n\n/**\n * Error thrown when snapshot doesn't match workflow (unknown steps, workflowId mismatch).\n */\nexport class SnapshotMismatchError extends Error {\n constructor(\n message: string,\n public readonly mismatchType: \"unknown_steps\" | \"workflow_id\" | \"definition_hash\",\n public readonly details?: {\n unknownSteps?: string[];\n snapshotWorkflowId?: string;\n expectedWorkflowId?: string;\n snapshotHash?: string;\n expectedHash?: string;\n }\n ) {\n super(message);\n this.name = \"SnapshotMismatchError\";\n }\n}\n\n/**\n * Error thrown when decode fails during restore.\n */\nexport class SnapshotDecodeError extends Error {\n constructor(\n message: string,\n public readonly stepId: string,\n public readonly originalError?: unknown\n ) {\n super(message);\n this.name = \"SnapshotDecodeError\";\n }\n}\n\n/**\n * Light check to see if an object looks like a WorkflowSnapshot.\n * Cheap check for basic structure - use validateSnapshot() for full validation.\n *\n * @example\n * ```typescript\n * const raw = JSON.parse(localStorage.getItem('wf-123') || 'null');\n * if (looksLikeWorkflowSnapshot(raw)) {\n * createWorkflow(deps, { snapshot: raw });\n * }\n * ```\n */\nexport function looksLikeWorkflowSnapshot(obj: unknown): obj is WorkflowSnapshot {\n return (\n typeof obj === \"object\" &&\n obj !== null &&\n \"formatVersion\" in obj &&\n (obj as { formatVersion: unknown }).formatVersion === 1 &&\n \"steps\" in obj &&\n typeof (obj as { steps: unknown }).steps === \"object\" &&\n (obj as { steps: unknown }).steps !== null &&\n \"execution\" in obj &&\n typeof (obj as { execution: unknown }).execution === \"object\"\n );\n}\n\n/**\n * Type guard for WorkflowSnapshot. Same as looksLikeWorkflowSnapshot; use for consistent naming with isResumeState / isSerializedResumeState.\n */\nexport const isWorkflowSnapshot = looksLikeWorkflowSnapshot;\n\n/**\n * Full validation with detailed errors.\n * Returns either a validated snapshot or an array of validation errors.\n */\nexport function validateSnapshot(obj: unknown): { valid: true; snapshot: WorkflowSnapshot } | { valid: false; errors: string[] } {\n const errors: string[] = [];\n\n if (typeof obj !== \"object\" || obj === null) {\n return { valid: false, errors: [\"Snapshot must be an object\"] };\n }\n\n const snapshot = obj as Record<string, unknown>;\n\n // Check formatVersion\n if (!(\"formatVersion\" in snapshot)) {\n errors.push(\"Missing required field: formatVersion\");\n } else if (snapshot.formatVersion !== 1) {\n errors.push(`Invalid formatVersion: expected 1, got ${snapshot.formatVersion}`);\n }\n\n // Check steps\n if (!(\"steps\" in snapshot)) {\n errors.push(\"Missing required field: steps\");\n } else if (typeof snapshot.steps !== \"object\" || snapshot.steps === null) {\n errors.push(\"steps must be an object\");\n } else {\n // Validate each step result\n const steps = snapshot.steps as Record<string, unknown>;\n for (const [stepId, stepResult] of Object.entries(steps)) {\n if (typeof stepResult !== \"object\" || stepResult === null) {\n errors.push(`steps[\"${stepId}\"] must be an object`);\n continue;\n }\n\n const step = stepResult as Record<string, unknown>;\n if (!(\"ok\" in step)) {\n errors.push(`steps[\"${stepId}\"] missing required field: ok`);\n } else if (typeof step.ok !== \"boolean\") {\n errors.push(`steps[\"${stepId}\"].ok must be a boolean`);\n } else if (step.ok === false) {\n if (!(\"error\" in step)) {\n errors.push(`steps[\"${stepId}\"] is error result but missing error field`);\n }\n if (!(\"cause\" in step)) {\n errors.push(`steps[\"${stepId}\"] is error result but missing cause field`);\n }\n }\n }\n }\n\n // Check execution\n if (!(\"execution\" in snapshot)) {\n errors.push(\"Missing required field: execution\");\n } else if (typeof snapshot.execution !== \"object\" || snapshot.execution === null) {\n errors.push(\"execution must be an object\");\n } else {\n const execution = snapshot.execution as Record<string, unknown>;\n if (!(\"status\" in execution)) {\n errors.push(\"execution missing required field: status\");\n } else if (![\"running\", \"completed\", \"failed\"].includes(execution.status as string)) {\n errors.push(`execution.status must be one of: running, completed, failed`);\n }\n if (!(\"lastUpdated\" in execution)) {\n errors.push(\"execution missing required field: lastUpdated\");\n } else if (typeof execution.lastUpdated !== \"string\") {\n errors.push(\"execution.lastUpdated must be a string (ISO timestamp)\");\n }\n }\n\n if (errors.length > 0) {\n return { valid: false, errors };\n }\n\n return { valid: true, snapshot: obj as WorkflowSnapshot };\n}\n\n/**\n * Throwing helper for cleaner code.\n * Validates a snapshot and throws SnapshotFormatError if invalid.\n *\n * @throws {SnapshotFormatError} If snapshot is invalid\n */\nexport function assertValidSnapshot(obj: unknown): WorkflowSnapshot {\n const result = validateSnapshot(obj);\n if (!result.valid) {\n throw new SnapshotFormatError(`Invalid snapshot format: ${result.errors[0]}`, result.errors);\n }\n return result.snapshot;\n}\n\n// =============================================================================\n// Snapshot Merge Helper\n// =============================================================================\n\n/**\n * Merge two snapshots (for incremental updates).\n * Delta steps overwrite base steps; execution from delta; metadata shallow merge.\n */\nexport function mergeSnapshots(base: WorkflowSnapshot, delta: WorkflowSnapshot): WorkflowSnapshot {\n // Create new steps object using Object.create(null) for prototype safety\n const mergedSteps = Object.create(null) as Record<string, StepResult>;\n\n // Copy base steps (use Object.prototype.hasOwnProperty for ES2020 compat)\n for (const [key, value] of Object.entries(base.steps)) {\n if (Object.prototype.hasOwnProperty.call(base.steps, key)) {\n mergedSteps[key] = value;\n }\n }\n\n // Overlay delta steps\n for (const [key, value] of Object.entries(delta.steps)) {\n if (Object.prototype.hasOwnProperty.call(delta.steps, key)) {\n mergedSteps[key] = value;\n }\n }\n\n // Merge metadata (delta wins for conflicts)\n const mergedMetadata = base.metadata || delta.metadata\n ? { ...base.metadata, ...delta.metadata }\n : undefined;\n\n // Merge warnings: only keep base warnings for steps not re-executed in delta.\n // If a step was re-executed and serialized cleanly, its old warning should disappear.\n const baseWarnings = (base.warnings || []).filter(\n (w) => !Object.prototype.hasOwnProperty.call(delta.steps, w.stepId)\n );\n const mergedWarnings = [...baseWarnings, ...(delta.warnings || [])];\n\n return {\n formatVersion: 1,\n steps: mergedSteps,\n execution: { ...delta.execution },\n metadata: mergedMetadata,\n warnings: mergedWarnings.length > 0 ? mergedWarnings : undefined,\n };\n}\n\n// =============================================================================\n// Serialization Helpers\n// =============================================================================\n\n/**\n * Maximum length for string representation in thrown non-Error values.\n */\nconst MAX_STRING_REPRESENTATION_LENGTH = 1000;\n\n/**\n * Serialize an Error object to SerializedCause format.\n * Preserves Error.cause recursively.\n */\nexport function serializeError(error: Error): SerializedCause {\n const serialized: SerializedCause = {\n type: \"error\",\n name: error.name,\n message: error.message,\n };\n\n if (error.stack) {\n serialized.stack = error.stack;\n }\n\n // Recursively serialize Error.cause if present (ES2022 feature, but commonly available)\n const errorWithCause = error as Error & { cause?: unknown };\n if (errorWithCause.cause !== undefined) {\n if (errorWithCause.cause instanceof Error) {\n serialized.cause = serializeError(errorWithCause.cause);\n } else {\n // cause is not an Error, serialize as thrown value\n serialized.cause = serializeThrown(errorWithCause.cause);\n }\n }\n\n return serialized;\n}\n\n/**\n * Serialize a non-Error thrown value to SerializedCause format.\n */\nexport function serializeThrown(value: unknown): SerializedCause {\n // Get string representation\n let stringRepresentation: string;\n let truncated = false;\n\n try {\n stringRepresentation = String(value);\n if (stringRepresentation.length > MAX_STRING_REPRESENTATION_LENGTH) {\n stringRepresentation = stringRepresentation.slice(0, MAX_STRING_REPRESENTATION_LENGTH);\n truncated = true;\n }\n } catch {\n stringRepresentation = \"[unable to convert to string]\";\n }\n\n // Try to get the original type\n const originalType = value === null\n ? \"null\"\n : typeof value === \"object\"\n ? (value.constructor?.name ?? \"Object\")\n : typeof value;\n\n // Try to serialize the value as JSON\n let jsonValue: JSONValue | undefined;\n try {\n const serialized = JSON.stringify(value);\n if (serialized !== undefined) {\n jsonValue = JSON.parse(serialized) as JSONValue;\n }\n } catch {\n // Non-JSON-serializable, will only use stringRepresentation\n }\n\n const result: SerializedCause = {\n type: \"thrown\",\n originalType,\n stringRepresentation,\n };\n\n if (jsonValue !== undefined) {\n result.value = jsonValue;\n }\n\n if (truncated) {\n result.truncated = true;\n }\n\n return result;\n}\n\n/**\n * Deserialize a SerializedCause back to its original form.\n */\nexport function deserializeCauseNew(serialized: SerializedCause): unknown {\n if (serialized.type === \"error\") {\n const error = new Error(serialized.message);\n error.name = serialized.name;\n if (serialized.stack) {\n error.stack = serialized.stack;\n }\n if (serialized.cause) {\n (error as Error & { cause: unknown }).cause = deserializeCauseNew(serialized.cause);\n }\n return error;\n }\n\n // type === \"thrown\"\n // Return the JSON value if available, otherwise the string representation\n return serialized.value !== undefined ? serialized.value : serialized.stringRepresentation;\n}\n\n// =============================================================================\n// SnapshotStore Interface (New Simplified API)\n// =============================================================================\n\n/**\n * Simplified store interface for workflow snapshot persistence.\n * Works directly with WorkflowSnapshot objects.\n *\n * Adapters may implement an extended contract (see awaitly/workflow): save can accept\n * WorkflowSnapshot | ResumeState; load can return WorkflowSnapshot | ResumeState | null.\n * Use isWorkflowSnapshot / isSerializedResumeState and serializeResumeState / deserializeResumeState\n * when branching. For type-safe restore, use store.loadResumeState(id) or toResumeState(await store.load(id)).\n *\n * @example\n * ```typescript\n * import { postgres } from 'awaitly-postgres';\n * import { createWorkflow } from 'awaitly/workflow';\n *\n * const store = postgres('postgresql://localhost/mydb');\n * const workflow = createWorkflow(deps);\n *\n * // Run and persist resume state\n * const { result, resumeState } = await workflow.runWithState(fn);\n * await store.save('wf-123', resumeState);\n *\n * // Restore\n * const loaded = await store.load('wf-123');\n * const resumeState = toResumeState(loaded);\n * if (resumeState) await workflow.run(fn, { resumeState });\n * ```\n */\nexport interface SnapshotStore {\n /** Save a workflow snapshot (upsert - insert or update). Adapters may also accept ResumeState. */\n save(id: string, snapshot: WorkflowSnapshot): Promise<void>;\n /** Load a workflow snapshot. Returns null if not found. Adapters may return ResumeState when stored as such. */\n load(id: string): Promise<WorkflowSnapshot | null>;\n /** Delete a workflow snapshot. */\n delete(id: string): Promise<void>;\n /** List workflow IDs with their last update time. */\n list(options?: { prefix?: string; limit?: number }): Promise<Array<{ id: string; updatedAt: string }>>;\n /** Clean shutdown for tests/graceful exit. */\n close(): Promise<void>;\n}\n\n// =============================================================================\n// In-Memory Cache Adapter\n// =============================================================================\n\n/**\n * Options for the in-memory cache adapter.\n */\nexport interface MemoryCacheOptions {\n /**\n * Maximum number of entries to store.\n * Oldest entries are evicted when limit is reached.\n */\n maxSize?: number;\n\n /**\n * Time-to-live in milliseconds.\n * Entries are automatically removed after this duration.\n */\n ttl?: number;\n}\n\n/**\n * Create an in-memory StepCache with optional LRU eviction and TTL.\n *\n * @param options - Cache options\n * @returns StepCache implementation\n *\n * @example\n * ```typescript\n * const cache = createMemoryCache({ maxSize: 1000, ttl: 60000 });\n * const workflow = createWorkflow(deps, { cache });\n * ```\n */\nexport function createMemoryCache(options: MemoryCacheOptions = {}): StepCache {\n const { maxSize, ttl } = options;\n const cache = new Map<string, {\n result: Result<unknown, unknown, unknown>;\n timestamp: number;\n entryTtl?: number;\n }>();\n\n const isExpired = (entry: { timestamp: number; entryTtl?: number }): boolean => {\n const effectiveTtl = entry.entryTtl ?? ttl;\n if (!effectiveTtl) return false;\n return Date.now() - entry.timestamp > effectiveTtl;\n };\n\n const evictExpired = (): void => {\n for (const [key, entry] of cache) {\n if (isExpired(entry)) {\n cache.delete(key);\n }\n }\n };\n\n const evictOldest = (): void => {\n if (!maxSize || cache.size < maxSize) return;\n\n // Find oldest entry\n let oldestKey: string | undefined;\n let oldestTime = Infinity;\n\n for (const [key, entry] of cache) {\n if (entry.timestamp < oldestTime) {\n oldestTime = entry.timestamp;\n oldestKey = key;\n }\n }\n\n if (oldestKey) {\n cache.delete(oldestKey);\n }\n };\n\n return {\n get(key: string): Result<unknown, unknown, unknown> | undefined {\n evictExpired();\n const entry = cache.get(key);\n if (!entry) return undefined;\n if (isExpired(entry)) {\n cache.delete(key);\n return undefined;\n }\n return entry.result;\n },\n\n set(key: string, result: Result<unknown, unknown, unknown>, options?: { ttl?: number }): void {\n evictExpired();\n evictOldest();\n cache.set(key, { result, timestamp: Date.now(), entryTtl: options?.ttl });\n },\n\n has(key: string): boolean {\n evictExpired();\n const entry = cache.get(key);\n if (!entry) return false;\n if (isExpired(entry)) {\n cache.delete(key);\n return false;\n }\n return true;\n },\n\n delete(key: string): boolean {\n return cache.delete(key);\n },\n\n clear(): void {\n cache.clear();\n },\n };\n}\n"],"mappings":"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","names":["persistence_entry_exports","__export","SnapshotDecodeError","SnapshotFormatError","SnapshotMismatchError","assertValidSnapshot","createMemoryCache","deserializeCauseNew","looksLikeWorkflowSnapshot","mergeSnapshots","serializeError","serializeThrown","validateSnapshot","__toCommonJS","SnapshotFormatError","message","errors","SnapshotMismatchError","mismatchType","details","SnapshotDecodeError","stepId","originalError","looksLikeWorkflowSnapshot","obj","validateSnapshot","obj","errors","snapshot","steps","stepId","stepResult","step","execution","assertValidSnapshot","result","SnapshotFormatError","mergeSnapshots","base","delta","mergedSteps","key","value","mergedMetadata","mergedWarnings","w","MAX_STRING_REPRESENTATION_LENGTH","serializeError","error","serialized","errorWithCause","serializeThrown","stringRepresentation","truncated","originalType","jsonValue","deserializeCauseNew","createMemoryCache","options","maxSize","ttl","cache","isExpired","entry","effectiveTtl","evictExpired","evictOldest","oldestKey","oldestTime"]}
|
package/dist/persistence.d.cts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export { J as JSONValue, M as MemoryCacheOptions, m as SerializedCause, n as SnapshotDecodeError, o as SnapshotFormatError, p as SnapshotMismatchError, S as SnapshotStore, q as SnapshotWarning, g as StepResult, a as WorkflowSnapshot, u as assertValidSnapshot, z as createMemoryCache, B as deserializeCauseNew, w as looksLikeWorkflowSnapshot, x as mergeSnapshots, D as serializeError, F as serializeThrown, y as validateSnapshot } from './persistence-entry-B-8PjnSR.cjs';
|
|
2
|
-
import './run-entry-DGs0tySr.cjs';
|
|
3
|
-
import './errors.cjs';
|
|
4
|
-
import './tagged-error.cjs';
|
|
5
|
-
import './slugs.cjs';
|
|
6
|
-
import './types-C5jLEUqY.cjs';
|
|
7
|
-
import '@standard-schema/spec';
|
package/dist/persistence.d.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export { J as JSONValue, M as MemoryCacheOptions, m as SerializedCause, n as SnapshotDecodeError, o as SnapshotFormatError, p as SnapshotMismatchError, S as SnapshotStore, q as SnapshotWarning, g as StepResult, a as WorkflowSnapshot, u as assertValidSnapshot, z as createMemoryCache, B as deserializeCauseNew, w as looksLikeWorkflowSnapshot, x as mergeSnapshots, D as serializeError, F as serializeThrown, y as validateSnapshot } from './persistence-entry-D8zRkLiT.js';
|
|
2
|
-
import './run-entry-BOuNyVoO.js';
|
|
3
|
-
import './errors.js';
|
|
4
|
-
import './tagged-error.js';
|
|
5
|
-
import './slugs.js';
|
|
6
|
-
import './types-BziYHFkD.js';
|
|
7
|
-
import '@standard-schema/spec';
|
package/dist/persistence.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
var l=class extends Error{constructor(n,s=[]){super(n);this.errors=s;this.name="SnapshotFormatError"}errors},c=class extends Error{constructor(n,s,i){super(n);this.mismatchType=s;this.details=i;this.name="SnapshotMismatchError"}mismatchType;details},f=class extends Error{constructor(n,s,i){super(n);this.stepId=s;this.originalError=i;this.name="SnapshotDecodeError"}stepId;originalError};function S(t){return typeof t=="object"&&t!==null&&"formatVersion"in t&&t.formatVersion===1&&"steps"in t&&typeof t.steps=="object"&&t.steps!==null&&"execution"in t&&typeof t.execution=="object"}function g(t){let e=[];if(typeof t!="object"||t===null)return{valid:!1,errors:["Snapshot must be an object"]};let n=t;if("formatVersion"in n?n.formatVersion!==1&&e.push(`Invalid formatVersion: expected 1, got ${n.formatVersion}`):e.push("Missing required field: formatVersion"),!("steps"in n))e.push("Missing required field: steps");else if(typeof n.steps!="object"||n.steps===null)e.push("steps must be an object");else{let s=n.steps;for(let[i,u]of Object.entries(s)){if(typeof u!="object"||u===null){e.push(`steps["${i}"] must be an object`);continue}let o=u;"ok"in o?typeof o.ok!="boolean"?e.push(`steps["${i}"].ok must be a boolean`):o.ok===!1&&("error"in o||e.push(`steps["${i}"] is error result but missing error field`),"cause"in o||e.push(`steps["${i}"] is error result but missing cause field`)):e.push(`steps["${i}"] missing required field: ok`)}}if(!("execution"in n))e.push("Missing required field: execution");else if(typeof n.execution!="object"||n.execution===null)e.push("execution must be an object");else{let s=n.execution;"status"in s?["running","completed","failed"].includes(s.status)||e.push("execution.status must be one of: running, completed, failed"):e.push("execution missing required field: status"),"lastUpdated"in s?typeof s.lastUpdated!="string"&&e.push("execution.lastUpdated must be a string (ISO timestamp)"):e.push("execution missing required field: lastUpdated")}return e.length>0?{valid:!1,errors:e}:{valid:!0,snapshot:t}}function y(t){let e=g(t);if(!e.valid)throw new l(`Invalid snapshot format: ${e.errors[0]}`,e.errors);return e.snapshot}function x(t,e){let n=Object.create(null);for(let[o,r]of Object.entries(t.steps))Object.prototype.hasOwnProperty.call(t.steps,o)&&(n[o]=r);for(let[o,r]of Object.entries(e.steps))Object.prototype.hasOwnProperty.call(e.steps,o)&&(n[o]=r);let s=t.metadata||e.metadata?{...t.metadata,...e.metadata}:void 0,u=[...(t.warnings||[]).filter(o=>!Object.prototype.hasOwnProperty.call(e.steps,o.stepId)),...e.warnings||[]];return{formatVersion:1,steps:n,execution:{...e.execution},metadata:s,warnings:u.length>0?u:void 0}}var m=1e3;function h(t){let e={type:"error",name:t.name,message:t.message};t.stack&&(e.stack=t.stack);let n=t;return n.cause!==void 0&&(n.cause instanceof Error?e.cause=h(n.cause):e.cause=w(n.cause)),e}function w(t){let e,n=!1;try{e=String(t),e.length>m&&(e=e.slice(0,m),n=!0)}catch{e="[unable to convert to string]"}let s=t===null?"null":typeof t=="object"?t.constructor?.name??"Object":typeof t,i;try{let o=JSON.stringify(t);o!==void 0&&(i=JSON.parse(o))}catch{}let u={type:"thrown",originalType:s,stringRepresentation:e};return i!==void 0&&(u.value=i),n&&(u.truncated=!0),u}function k(t){if(t.type==="error"){let e=new Error(t.message);return e.name=t.name,t.stack&&(e.stack=t.stack),t.cause&&(e.cause=k(t.cause)),e}return t.value!==void 0?t.value:t.stringRepresentation}function b(t={}){let{maxSize:e,ttl:n}=t,s=new Map,i=r=>{let a=r.entryTtl??n;return a?Date.now()-r.timestamp>a:!1},u=()=>{for(let[r,a]of s)i(a)&&s.delete(r)},o=()=>{if(!e||s.size<e)return;let r,a=1/0;for(let[p,d]of s)d.timestamp<a&&(a=d.timestamp,r=p);r&&s.delete(r)};return{get(r){u();let a=s.get(r);if(a){if(i(a)){s.delete(r);return}return a.result}},set(r,a,p){u(),o(),s.set(r,{result:a,timestamp:Date.now(),entryTtl:p?.ttl})},has(r){u();let a=s.get(r);return a?i(a)?(s.delete(r),!1):!0:!1},delete(r){return s.delete(r)},clear(){s.clear()}}}export{f as SnapshotDecodeError,l as SnapshotFormatError,c as SnapshotMismatchError,y as assertValidSnapshot,b as createMemoryCache,k as deserializeCauseNew,S as looksLikeWorkflowSnapshot,x as mergeSnapshots,h as serializeError,w as serializeThrown,g as validateSnapshot};
|
|
2
|
-
//# sourceMappingURL=persistence.js.map
|
package/dist/persistence.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/persistence.ts"],"sourcesContent":["/**\n * awaitly/persistence\n *\n * Simplified Persistence API for workflow snapshots.\n * Provides JSON-serializable snapshot format and store adapters.\n */\n\nimport type { Result } from \"./core\";\nimport type { StepCache } from \"./workflow\";\n\n// =============================================================================\n// JSON-Safe Type Enforcement\n// =============================================================================\n\n/**\n * Enforce JSON-safety at type level.\n * Only allows values that can be safely serialized with JSON.stringify.\n */\nexport type JSONValue =\n | null\n | boolean\n | number\n | string\n | JSONValue[]\n | { [k: string]: JSONValue };\n\n// =============================================================================\n// WorkflowSnapshot Types (Simplified API)\n// =============================================================================\n\n/**\n * Canonical error wire format - handles both Error instances and thrown non-Errors.\n * This is the single source of truth for serialized errors in snapshots.\n */\nexport type SerializedCause =\n | { type: \"error\"; name: string; message: string; stack?: string; cause?: SerializedCause }\n | { type: \"thrown\"; originalType?: string; value?: JSONValue; stringRepresentation: string; truncated?: true };\n\n/**\n * Single source of truth for step outcome (no error/cause confusion).\n * Uses discriminated union with `ok` field.\n */\nexport type StepResult =\n | { ok: true; value: JSONValue }\n | { ok: false; error: JSONValue; cause: SerializedCause; meta?: { origin: \"result\" | \"throw\" } };\n\n/**\n * JSON-serializable workflow snapshot.\n * Designed to be passed directly to JSON.stringify without special handling.\n *\n * @example\n * ```typescript\n * // Persist\n * localStorage.setItem('wf-123', JSON.stringify(wf.getSnapshot()));\n *\n * // Restore (safe pattern - storage can be empty/corrupt)\n * const raw = localStorage.getItem('wf-123');\n * const snapshot = raw ? JSON.parse(raw) : null;\n * createWorkflow(deps, { snapshot }); // null = fresh start\n * ```\n */\nexport interface WorkflowSnapshot {\n /** Snapshot format version (literal type - bump when shape changes) */\n formatVersion: 1;\n /** Workflow name (from createWorkflow first argument). */\n workflowName?: string;\n /** Step results keyed by step ID. Uses Object.create(null) internally. */\n steps: Record<string, StepResult>;\n /** Execution state metadata */\n execution: {\n status: \"running\" | \"completed\" | \"failed\";\n /** ISO timestamp (UTC toISOString()) */\n lastUpdated: string;\n /** ISO timestamp if finished */\n completedAt?: string;\n /**\n * For paused/running workflows: the step key of the current step.\n * Aligns with Workflow Diagram DSL step state ids (see awaitly/workflow diagram-dsl)\n * so visualizers can highlight the current node.\n */\n currentStepId?: string;\n };\n /** Optional metadata for workflow identification and replay */\n metadata?: {\n /** Detect wrong snapshot for wrong workflow */\n workflowId?: string;\n /** Optional: detect definition changes (user-supplied, advisory only) */\n definitionHash?: string;\n /** Original input for replay */\n input?: JSONValue;\n [key: string]: JSONValue | undefined;\n };\n /** Warnings for lossy serialization (keeps step results pure) */\n warnings?: Array<{\n type: \"lossy_value\";\n stepId: string;\n path: string;\n reason: \"non-json\" | \"circular\" | \"encode-failed\";\n }>;\n}\n\n/**\n * Warning entry for lossy value serialization.\n */\nexport type SnapshotWarning = NonNullable<WorkflowSnapshot[\"warnings\"]>[number];\n\n// =============================================================================\n// Snapshot Validation\n// =============================================================================\n\n/**\n * Error thrown when snapshot structure is invalid.\n */\nexport class SnapshotFormatError extends Error {\n constructor(\n message: string,\n public readonly errors: string[] = []\n ) {\n super(message);\n this.name = \"SnapshotFormatError\";\n }\n}\n\n/**\n * Error thrown when snapshot doesn't match workflow (unknown steps, workflowId mismatch).\n */\nexport class SnapshotMismatchError extends Error {\n constructor(\n message: string,\n public readonly mismatchType: \"unknown_steps\" | \"workflow_id\" | \"definition_hash\",\n public readonly details?: {\n unknownSteps?: string[];\n snapshotWorkflowId?: string;\n expectedWorkflowId?: string;\n snapshotHash?: string;\n expectedHash?: string;\n }\n ) {\n super(message);\n this.name = \"SnapshotMismatchError\";\n }\n}\n\n/**\n * Error thrown when decode fails during restore.\n */\nexport class SnapshotDecodeError extends Error {\n constructor(\n message: string,\n public readonly stepId: string,\n public readonly originalError?: unknown\n ) {\n super(message);\n this.name = \"SnapshotDecodeError\";\n }\n}\n\n/**\n * Light check to see if an object looks like a WorkflowSnapshot.\n * Cheap check for basic structure - use validateSnapshot() for full validation.\n *\n * @example\n * ```typescript\n * const raw = JSON.parse(localStorage.getItem('wf-123') || 'null');\n * if (looksLikeWorkflowSnapshot(raw)) {\n * createWorkflow(deps, { snapshot: raw });\n * }\n * ```\n */\nexport function looksLikeWorkflowSnapshot(obj: unknown): obj is WorkflowSnapshot {\n return (\n typeof obj === \"object\" &&\n obj !== null &&\n \"formatVersion\" in obj &&\n (obj as { formatVersion: unknown }).formatVersion === 1 &&\n \"steps\" in obj &&\n typeof (obj as { steps: unknown }).steps === \"object\" &&\n (obj as { steps: unknown }).steps !== null &&\n \"execution\" in obj &&\n typeof (obj as { execution: unknown }).execution === \"object\"\n );\n}\n\n/**\n * Type guard for WorkflowSnapshot. Same as looksLikeWorkflowSnapshot; use for consistent naming with isResumeState / isSerializedResumeState.\n */\nexport const isWorkflowSnapshot = looksLikeWorkflowSnapshot;\n\n/**\n * Full validation with detailed errors.\n * Returns either a validated snapshot or an array of validation errors.\n */\nexport function validateSnapshot(obj: unknown): { valid: true; snapshot: WorkflowSnapshot } | { valid: false; errors: string[] } {\n const errors: string[] = [];\n\n if (typeof obj !== \"object\" || obj === null) {\n return { valid: false, errors: [\"Snapshot must be an object\"] };\n }\n\n const snapshot = obj as Record<string, unknown>;\n\n // Check formatVersion\n if (!(\"formatVersion\" in snapshot)) {\n errors.push(\"Missing required field: formatVersion\");\n } else if (snapshot.formatVersion !== 1) {\n errors.push(`Invalid formatVersion: expected 1, got ${snapshot.formatVersion}`);\n }\n\n // Check steps\n if (!(\"steps\" in snapshot)) {\n errors.push(\"Missing required field: steps\");\n } else if (typeof snapshot.steps !== \"object\" || snapshot.steps === null) {\n errors.push(\"steps must be an object\");\n } else {\n // Validate each step result\n const steps = snapshot.steps as Record<string, unknown>;\n for (const [stepId, stepResult] of Object.entries(steps)) {\n if (typeof stepResult !== \"object\" || stepResult === null) {\n errors.push(`steps[\"${stepId}\"] must be an object`);\n continue;\n }\n\n const step = stepResult as Record<string, unknown>;\n if (!(\"ok\" in step)) {\n errors.push(`steps[\"${stepId}\"] missing required field: ok`);\n } else if (typeof step.ok !== \"boolean\") {\n errors.push(`steps[\"${stepId}\"].ok must be a boolean`);\n } else if (step.ok === false) {\n if (!(\"error\" in step)) {\n errors.push(`steps[\"${stepId}\"] is error result but missing error field`);\n }\n if (!(\"cause\" in step)) {\n errors.push(`steps[\"${stepId}\"] is error result but missing cause field`);\n }\n }\n }\n }\n\n // Check execution\n if (!(\"execution\" in snapshot)) {\n errors.push(\"Missing required field: execution\");\n } else if (typeof snapshot.execution !== \"object\" || snapshot.execution === null) {\n errors.push(\"execution must be an object\");\n } else {\n const execution = snapshot.execution as Record<string, unknown>;\n if (!(\"status\" in execution)) {\n errors.push(\"execution missing required field: status\");\n } else if (![\"running\", \"completed\", \"failed\"].includes(execution.status as string)) {\n errors.push(`execution.status must be one of: running, completed, failed`);\n }\n if (!(\"lastUpdated\" in execution)) {\n errors.push(\"execution missing required field: lastUpdated\");\n } else if (typeof execution.lastUpdated !== \"string\") {\n errors.push(\"execution.lastUpdated must be a string (ISO timestamp)\");\n }\n }\n\n if (errors.length > 0) {\n return { valid: false, errors };\n }\n\n return { valid: true, snapshot: obj as WorkflowSnapshot };\n}\n\n/**\n * Throwing helper for cleaner code.\n * Validates a snapshot and throws SnapshotFormatError if invalid.\n *\n * @throws {SnapshotFormatError} If snapshot is invalid\n */\nexport function assertValidSnapshot(obj: unknown): WorkflowSnapshot {\n const result = validateSnapshot(obj);\n if (!result.valid) {\n throw new SnapshotFormatError(`Invalid snapshot format: ${result.errors[0]}`, result.errors);\n }\n return result.snapshot;\n}\n\n// =============================================================================\n// Snapshot Merge Helper\n// =============================================================================\n\n/**\n * Merge two snapshots (for incremental updates).\n * Delta steps overwrite base steps; execution from delta; metadata shallow merge.\n */\nexport function mergeSnapshots(base: WorkflowSnapshot, delta: WorkflowSnapshot): WorkflowSnapshot {\n // Create new steps object using Object.create(null) for prototype safety\n const mergedSteps = Object.create(null) as Record<string, StepResult>;\n\n // Copy base steps (use Object.prototype.hasOwnProperty for ES2020 compat)\n for (const [key, value] of Object.entries(base.steps)) {\n if (Object.prototype.hasOwnProperty.call(base.steps, key)) {\n mergedSteps[key] = value;\n }\n }\n\n // Overlay delta steps\n for (const [key, value] of Object.entries(delta.steps)) {\n if (Object.prototype.hasOwnProperty.call(delta.steps, key)) {\n mergedSteps[key] = value;\n }\n }\n\n // Merge metadata (delta wins for conflicts)\n const mergedMetadata = base.metadata || delta.metadata\n ? { ...base.metadata, ...delta.metadata }\n : undefined;\n\n // Merge warnings: only keep base warnings for steps not re-executed in delta.\n // If a step was re-executed and serialized cleanly, its old warning should disappear.\n const baseWarnings = (base.warnings || []).filter(\n (w) => !Object.prototype.hasOwnProperty.call(delta.steps, w.stepId)\n );\n const mergedWarnings = [...baseWarnings, ...(delta.warnings || [])];\n\n return {\n formatVersion: 1,\n steps: mergedSteps,\n execution: { ...delta.execution },\n metadata: mergedMetadata,\n warnings: mergedWarnings.length > 0 ? mergedWarnings : undefined,\n };\n}\n\n// =============================================================================\n// Serialization Helpers\n// =============================================================================\n\n/**\n * Maximum length for string representation in thrown non-Error values.\n */\nconst MAX_STRING_REPRESENTATION_LENGTH = 1000;\n\n/**\n * Serialize an Error object to SerializedCause format.\n * Preserves Error.cause recursively.\n */\nexport function serializeError(error: Error): SerializedCause {\n const serialized: SerializedCause = {\n type: \"error\",\n name: error.name,\n message: error.message,\n };\n\n if (error.stack) {\n serialized.stack = error.stack;\n }\n\n // Recursively serialize Error.cause if present (ES2022 feature, but commonly available)\n const errorWithCause = error as Error & { cause?: unknown };\n if (errorWithCause.cause !== undefined) {\n if (errorWithCause.cause instanceof Error) {\n serialized.cause = serializeError(errorWithCause.cause);\n } else {\n // cause is not an Error, serialize as thrown value\n serialized.cause = serializeThrown(errorWithCause.cause);\n }\n }\n\n return serialized;\n}\n\n/**\n * Serialize a non-Error thrown value to SerializedCause format.\n */\nexport function serializeThrown(value: unknown): SerializedCause {\n // Get string representation\n let stringRepresentation: string;\n let truncated = false;\n\n try {\n stringRepresentation = String(value);\n if (stringRepresentation.length > MAX_STRING_REPRESENTATION_LENGTH) {\n stringRepresentation = stringRepresentation.slice(0, MAX_STRING_REPRESENTATION_LENGTH);\n truncated = true;\n }\n } catch {\n stringRepresentation = \"[unable to convert to string]\";\n }\n\n // Try to get the original type\n const originalType = value === null\n ? \"null\"\n : typeof value === \"object\"\n ? (value.constructor?.name ?? \"Object\")\n : typeof value;\n\n // Try to serialize the value as JSON\n let jsonValue: JSONValue | undefined;\n try {\n const serialized = JSON.stringify(value);\n if (serialized !== undefined) {\n jsonValue = JSON.parse(serialized) as JSONValue;\n }\n } catch {\n // Non-JSON-serializable, will only use stringRepresentation\n }\n\n const result: SerializedCause = {\n type: \"thrown\",\n originalType,\n stringRepresentation,\n };\n\n if (jsonValue !== undefined) {\n result.value = jsonValue;\n }\n\n if (truncated) {\n result.truncated = true;\n }\n\n return result;\n}\n\n/**\n * Deserialize a SerializedCause back to its original form.\n */\nexport function deserializeCauseNew(serialized: SerializedCause): unknown {\n if (serialized.type === \"error\") {\n const error = new Error(serialized.message);\n error.name = serialized.name;\n if (serialized.stack) {\n error.stack = serialized.stack;\n }\n if (serialized.cause) {\n (error as Error & { cause: unknown }).cause = deserializeCauseNew(serialized.cause);\n }\n return error;\n }\n\n // type === \"thrown\"\n // Return the JSON value if available, otherwise the string representation\n return serialized.value !== undefined ? serialized.value : serialized.stringRepresentation;\n}\n\n// =============================================================================\n// SnapshotStore Interface (New Simplified API)\n// =============================================================================\n\n/**\n * Simplified store interface for workflow snapshot persistence.\n * Works directly with WorkflowSnapshot objects.\n *\n * Adapters may implement an extended contract (see awaitly/workflow): save can accept\n * WorkflowSnapshot | ResumeState; load can return WorkflowSnapshot | ResumeState | null.\n * Use isWorkflowSnapshot / isSerializedResumeState and serializeResumeState / deserializeResumeState\n * when branching. For type-safe restore, use store.loadResumeState(id) or toResumeState(await store.load(id)).\n *\n * @example\n * ```typescript\n * import { postgres } from 'awaitly-postgres';\n * import { createWorkflow } from 'awaitly/workflow';\n *\n * const store = postgres('postgresql://localhost/mydb');\n * const workflow = createWorkflow(deps);\n *\n * // Run and persist resume state\n * const { result, resumeState } = await workflow.runWithState(fn);\n * await store.save('wf-123', resumeState);\n *\n * // Restore\n * const loaded = await store.load('wf-123');\n * const resumeState = toResumeState(loaded);\n * if (resumeState) await workflow.run(fn, { resumeState });\n * ```\n */\nexport interface SnapshotStore {\n /** Save a workflow snapshot (upsert - insert or update). Adapters may also accept ResumeState. */\n save(id: string, snapshot: WorkflowSnapshot): Promise<void>;\n /** Load a workflow snapshot. Returns null if not found. Adapters may return ResumeState when stored as such. */\n load(id: string): Promise<WorkflowSnapshot | null>;\n /** Delete a workflow snapshot. */\n delete(id: string): Promise<void>;\n /** List workflow IDs with their last update time. */\n list(options?: { prefix?: string; limit?: number }): Promise<Array<{ id: string; updatedAt: string }>>;\n /** Clean shutdown for tests/graceful exit. */\n close(): Promise<void>;\n}\n\n// =============================================================================\n// In-Memory Cache Adapter\n// =============================================================================\n\n/**\n * Options for the in-memory cache adapter.\n */\nexport interface MemoryCacheOptions {\n /**\n * Maximum number of entries to store.\n * Oldest entries are evicted when limit is reached.\n */\n maxSize?: number;\n\n /**\n * Time-to-live in milliseconds.\n * Entries are automatically removed after this duration.\n */\n ttl?: number;\n}\n\n/**\n * Create an in-memory StepCache with optional LRU eviction and TTL.\n *\n * @param options - Cache options\n * @returns StepCache implementation\n *\n * @example\n * ```typescript\n * const cache = createMemoryCache({ maxSize: 1000, ttl: 60000 });\n * const workflow = createWorkflow(deps, { cache });\n * ```\n */\nexport function createMemoryCache(options: MemoryCacheOptions = {}): StepCache {\n const { maxSize, ttl } = options;\n const cache = new Map<string, {\n result: Result<unknown, unknown, unknown>;\n timestamp: number;\n entryTtl?: number;\n }>();\n\n const isExpired = (entry: { timestamp: number; entryTtl?: number }): boolean => {\n const effectiveTtl = entry.entryTtl ?? ttl;\n if (!effectiveTtl) return false;\n return Date.now() - entry.timestamp > effectiveTtl;\n };\n\n const evictExpired = (): void => {\n for (const [key, entry] of cache) {\n if (isExpired(entry)) {\n cache.delete(key);\n }\n }\n };\n\n const evictOldest = (): void => {\n if (!maxSize || cache.size < maxSize) return;\n\n // Find oldest entry\n let oldestKey: string | undefined;\n let oldestTime = Infinity;\n\n for (const [key, entry] of cache) {\n if (entry.timestamp < oldestTime) {\n oldestTime = entry.timestamp;\n oldestKey = key;\n }\n }\n\n if (oldestKey) {\n cache.delete(oldestKey);\n }\n };\n\n return {\n get(key: string): Result<unknown, unknown, unknown> | undefined {\n evictExpired();\n const entry = cache.get(key);\n if (!entry) return undefined;\n if (isExpired(entry)) {\n cache.delete(key);\n return undefined;\n }\n return entry.result;\n },\n\n set(key: string, result: Result<unknown, unknown, unknown>, options?: { ttl?: number }): void {\n evictExpired();\n evictOldest();\n cache.set(key, { result, timestamp: Date.now(), entryTtl: options?.ttl });\n },\n\n has(key: string): boolean {\n evictExpired();\n const entry = cache.get(key);\n if (!entry) return false;\n if (isExpired(entry)) {\n cache.delete(key);\n return false;\n }\n return true;\n },\n\n delete(key: string): boolean {\n return cache.delete(key);\n },\n\n clear(): void {\n cache.clear();\n },\n };\n}\n"],"mappings":"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","names":["SnapshotFormatError","message","errors","SnapshotMismatchError","mismatchType","details","SnapshotDecodeError","stepId","originalError","looksLikeWorkflowSnapshot","obj","validateSnapshot","obj","errors","snapshot","steps","stepId","stepResult","step","execution","assertValidSnapshot","result","SnapshotFormatError","mergeSnapshots","base","delta","mergedSteps","key","value","mergedMetadata","mergedWarnings","w","MAX_STRING_REPRESENTATION_LENGTH","serializeError","error","serialized","errorWithCause","serializeThrown","stringRepresentation","truncated","originalType","jsonValue","deserializeCauseNew","createMemoryCache","options","maxSize","ttl","cache","isExpired","entry","effectiveTtl","evictExpired","evictOldest","oldestKey","oldestTime"]}
|
package/dist/policies.cjs
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
"use strict";var y=Object.defineProperty;var b=Object.getOwnPropertyDescriptor;var S=Object.getOwnPropertyNames;var h=Object.prototype.hasOwnProperty;var k=(t,e)=>{for(var i in e)y(t,i,{get:e[i],enumerable:!0})},D=(t,e,i,c)=>{if(e&&typeof e=="object"||typeof e=="function")for(let l of S(e))!h.call(t,l)&&l!==i&&y(t,l,{get:()=>e[l],enumerable:!(c=b(e,l))||c.enumerable});return t};var v=t=>D(y({},"__esModule",{value:!0}),t);var R={};k(R,{conditionalPolicy:()=>f,createPolicyApplier:()=>u,createPolicyBundle:()=>P,createPolicyRegistry:()=>O,envPolicy:()=>g,mergePolicies:()=>o,retryPolicies:()=>p,retryPolicy:()=>n,servicePolicies:()=>m,stepOptions:()=>x,timeoutPolicies:()=>s,timeoutPolicy:()=>r,withPolicies:()=>d,withPolicy:()=>a});module.exports=v(R);function o(...t){let e={};for(let i of t)i.key!==void 0&&(e.key=i.key),i.retry!==void 0&&(e.retry=e.retry?{...e.retry,...i.retry}:{...i.retry}),i.timeout!==void 0&&(e.timeout=e.timeout?{...e.timeout,...i.timeout}:{...i.timeout});return e}function u(...t){let e=o(...t);return i=>o(e,i??{})}function P(t,...e){return{name:t,policy:o(...e)}}function n(t){return{retry:t}}var p={none:n({attempts:1}),transient:n({attempts:3,backoff:"exponential",initialDelay:100,maxDelay:1e3,jitter:!0}),standard:n({attempts:3,backoff:"exponential",initialDelay:200,maxDelay:5e3,jitter:!0}),aggressive:n({attempts:5,backoff:"exponential",initialDelay:500,maxDelay:3e4,jitter:!0}),fixed:(t,e)=>n({attempts:t,backoff:"fixed",initialDelay:e,jitter:!1}),linear:(t,e)=>n({attempts:t,backoff:"linear",initialDelay:e,jitter:!0}),custom:t=>n({backoff:"exponential",initialDelay:100,maxDelay:3e4,jitter:!0,...t})};function r(t){return{timeout:t}}var s={none:{},fast:r({ms:1e3}),api:r({ms:5e3}),extended:r({ms:3e4}),long:r({ms:12e4}),ms:t=>r({ms:t}),seconds:t=>r({ms:t*1e3}),withError:(t,e)=>r({ms:t,error:e}),withSignal:t=>r({ms:t,signal:!0})},m={httpApi:o(s.api,p.standard),database:o(s.extended,n({attempts:2,backoff:"exponential",initialDelay:100,maxDelay:2e3,jitter:!0})),cache:o(s.fast,p.none),messageQueue:o(s.extended,p.aggressive),fileSystem:o(s.long,p.standard),rateLimited:o(r({ms:1e4}),n({attempts:5,backoff:"linear",initialDelay:1e3,maxDelay:1e4,jitter:!0}))};function a(t,e){return o(t,e??{})}function d(t,e){let i=e??{};return o(...t,i)}function f(t,e,i={}){return t?e:i}function g(t,e=process.env.NODE_ENV??"development",i={}){return t[e]??i}function O(){let t=new Map;return{register(e,i){t.set(e,i)},get(e){return t.get(e)},has(e){return t.has(e)},names(){return Array.from(t.keys())},apply(e,i){let c=t.get(e);if(!c)throw new Error(`Policy not found: ${e}`);return a(c,i)}}}function x(){let t=[],e={key(i){return t.push({key:i}),e},policy(i){return t.push(i),e},timeout(i){return t.push(r({ms:i})),e},retry(i){return t.push(n(i)),e},retries(i){return t.push(p.custom({attempts:i})),e},build(){return o(...t)}};return e}0&&(module.exports={conditionalPolicy,createPolicyApplier,createPolicyBundle,createPolicyRegistry,envPolicy,mergePolicies,retryPolicies,retryPolicy,servicePolicies,stepOptions,timeoutPolicies,timeoutPolicy,withPolicies,withPolicy});
|
|
2
|
-
//# sourceMappingURL=policies.cjs.map
|
package/dist/policies.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/policies-entry.ts","../src/policies.ts"],"sourcesContent":["/**\n * awaitly/policies\n *\n * Retry and timeout policies: composable reliability configurations.\n *\n * @example\n * ```typescript\n * import { servicePolicies, withPolicy, mergePolicies } from 'awaitly/policies';\n *\n * // Pre-built policies for common services\n * const dbPolicy = servicePolicies.database();\n * const apiPolicy = servicePolicies.externalApi();\n *\n * // Apply to steps\n * const user = await withPolicy(dbPolicy, () => step(fetchUser(id)));\n *\n * // Compose policies\n * const strictPolicy = mergePolicies(dbPolicy, { timeout: { ms: 1000 } });\n * ```\n */\n\nexport {\n type Policy,\n type PolicyFactory,\n type NamedPolicy,\n type WithPoliciesOptions,\n type PolicyRegistry,\n type StepOptionsBuilder,\n mergePolicies,\n createPolicyApplier,\n createPolicyBundle,\n retryPolicy,\n retryPolicies,\n timeoutPolicy,\n timeoutPolicies,\n servicePolicies,\n withPolicy,\n withPolicies,\n conditionalPolicy,\n envPolicy,\n createPolicyRegistry,\n stepOptions,\n} from \"./policies\";\n","/**\n * awaitly/policies\n *\n * Policy-Driven Step Middleware - Reusable bundles of StepOptions\n * that can be composed and applied per-workflow or per-step.\n */\n\nimport type { StepOptions, RetryOptions, TimeoutOptions } from \"./core\";\n\n// =============================================================================\n// Policy Types\n// =============================================================================\n\n/**\n * A policy is a partial StepOptions that can be merged with other policies.\n */\nexport type Policy = Partial<StepOptions>;\n\n/**\n * A policy factory that creates policies based on context.\n */\nexport type PolicyFactory<T = void> = T extends void\n ? () => Policy\n : (context: T) => Policy;\n\n/**\n * Named policy with metadata.\n */\nexport interface NamedPolicy {\n name: string;\n policy: Policy;\n description?: string;\n}\n\n// =============================================================================\n// Policy Composition\n// =============================================================================\n\n/**\n * Merge multiple policies into a single StepOptions object.\n * Later policies override earlier ones for conflicting properties.\n * Retry and timeout options are deep-merged.\n *\n * @param policies - Policies to merge (in order of precedence)\n * @returns Merged StepOptions\n *\n * @example\n * ```typescript\n * const merged = mergePolicies(\n * timeoutPolicies.api, // timeout: 5000ms\n * retryPolicies.transient, // retry: 3 attempts\n * { name: 'fetch-user' } // name override\n * );\n * ```\n */\nexport function mergePolicies(...policies: Policy[]): StepOptions {\n const result: StepOptions = {};\n\n for (const policy of policies) {\n if (policy.key !== undefined) result.key = policy.key;\n\n // Deep merge retry options\n if (policy.retry !== undefined) {\n result.retry = result.retry\n ? { ...result.retry, ...policy.retry }\n : { ...policy.retry };\n }\n\n // Deep merge timeout options\n if (policy.timeout !== undefined) {\n result.timeout = result.timeout\n ? { ...result.timeout, ...policy.timeout }\n : { ...policy.timeout };\n }\n }\n\n return result;\n}\n\n/**\n * Create a policy applier that merges base policies with step-specific options.\n *\n * @param basePolicies - Base policies to apply to all steps\n * @returns A function that applies policies to step options\n *\n * @example\n * ```typescript\n * const applyPolicy = createPolicyApplier(\n * timeoutPolicies.api,\n * retryPolicies.transient\n * );\n *\n * // In workflow\n * const user = await step(\n * 'fetch-user',\n * () => fetchUser(id),\n * applyPolicy({ key: 'user:' + id })\n * );\n * ```\n */\nexport function createPolicyApplier(\n ...basePolicies: Policy[]\n): (stepOptions?: StepOptions) => StepOptions {\n const basePolicy = mergePolicies(...basePolicies);\n\n return (stepOptions?: StepOptions): StepOptions => {\n const opts = stepOptions ?? {};\n return mergePolicies(basePolicy, opts);\n };\n}\n\n/**\n * Create a named policy bundle for reuse across workflows.\n *\n * @param name - Policy bundle name\n * @param policies - Policies to include in the bundle\n * @returns Named policy object\n */\nexport function createPolicyBundle(\n name: string,\n ...policies: Policy[]\n): NamedPolicy {\n return {\n name,\n policy: mergePolicies(...policies),\n };\n}\n\n// =============================================================================\n// Retry Policies\n// =============================================================================\n\n/**\n * Create a retry policy with the given options.\n */\nexport function retryPolicy(options: RetryOptions): Policy {\n return { retry: options };\n}\n\n/**\n * Pre-built retry policies for common scenarios.\n */\nexport const retryPolicies = {\n /**\n * No retry - fail immediately on error.\n */\n none: retryPolicy({ attempts: 1 }),\n\n /**\n * Quick retry for transient errors (3 attempts, fast backoff).\n */\n transient: retryPolicy({\n attempts: 3,\n backoff: \"exponential\",\n initialDelay: 100,\n maxDelay: 1000,\n jitter: true,\n }),\n\n /**\n * Standard retry for API calls (3 attempts, moderate backoff).\n */\n standard: retryPolicy({\n attempts: 3,\n backoff: \"exponential\",\n initialDelay: 200,\n maxDelay: 5000,\n jitter: true,\n }),\n\n /**\n * Aggressive retry for critical operations (5 attempts, longer backoff).\n */\n aggressive: retryPolicy({\n attempts: 5,\n backoff: \"exponential\",\n initialDelay: 500,\n maxDelay: 30000,\n jitter: true,\n }),\n\n /**\n * Fixed interval retry (useful for polling).\n */\n fixed: (attempts: number, delayMs: number): Policy =>\n retryPolicy({\n attempts,\n backoff: \"fixed\",\n initialDelay: delayMs,\n jitter: false,\n }),\n\n /**\n * Linear backoff retry.\n */\n linear: (attempts: number, initialDelay: number): Policy =>\n retryPolicy({\n attempts,\n backoff: \"linear\",\n initialDelay,\n jitter: true,\n }),\n\n /**\n * Custom retry policy builder.\n */\n custom: (options: Partial<RetryOptions> & { attempts: number }): Policy =>\n retryPolicy({\n backoff: \"exponential\",\n initialDelay: 100,\n maxDelay: 30000,\n jitter: true,\n ...options,\n }),\n} as const;\n\n// =============================================================================\n// Timeout Policies\n// =============================================================================\n\n/**\n * Create a timeout policy with the given options.\n */\nexport function timeoutPolicy(options: TimeoutOptions): Policy {\n return { timeout: options };\n}\n\n/**\n * Pre-built timeout policies for common scenarios.\n */\nexport const timeoutPolicies = {\n /**\n * No timeout.\n */\n none: {} as Policy,\n\n /**\n * Fast timeout for quick operations (1 second).\n */\n fast: timeoutPolicy({ ms: 1000 }),\n\n /**\n * Standard API timeout (5 seconds).\n */\n api: timeoutPolicy({ ms: 5000 }),\n\n /**\n * Extended timeout for slower operations (30 seconds).\n */\n extended: timeoutPolicy({ ms: 30000 }),\n\n /**\n * Long timeout for batch operations (2 minutes).\n */\n long: timeoutPolicy({ ms: 120000 }),\n\n /**\n * Custom timeout in milliseconds.\n */\n ms: (ms: number): Policy => timeoutPolicy({ ms }),\n\n /**\n * Custom timeout in seconds.\n */\n seconds: (seconds: number): Policy => timeoutPolicy({ ms: seconds * 1000 }),\n\n /**\n * Timeout with custom error.\n */\n withError: <E>(ms: number, error: E): Policy =>\n timeoutPolicy({ ms, error }),\n\n /**\n * Timeout with AbortSignal support.\n */\n withSignal: (ms: number): Policy =>\n timeoutPolicy({ ms, signal: true }),\n} as const;\n\n// =============================================================================\n// Combined Policies\n// =============================================================================\n\n/**\n * Pre-built combined policies for common service patterns.\n */\nexport const servicePolicies = {\n /**\n * Policy for external HTTP APIs.\n * - 5 second timeout\n * - 3 retries with exponential backoff\n */\n httpApi: mergePolicies(\n timeoutPolicies.api,\n retryPolicies.standard\n ),\n\n /**\n * Policy for database operations.\n * - 30 second timeout\n * - 2 retries for transient errors\n */\n database: mergePolicies(\n timeoutPolicies.extended,\n retryPolicy({\n attempts: 2,\n backoff: \"exponential\",\n initialDelay: 100,\n maxDelay: 2000,\n jitter: true,\n })\n ),\n\n /**\n * Policy for cache operations.\n * - 1 second timeout\n * - No retry (cache misses are not errors)\n */\n cache: mergePolicies(\n timeoutPolicies.fast,\n retryPolicies.none\n ),\n\n /**\n * Policy for message queue operations.\n * - 30 second timeout\n * - 5 retries with longer backoff\n */\n messageQueue: mergePolicies(\n timeoutPolicies.extended,\n retryPolicies.aggressive\n ),\n\n /**\n * Policy for file operations.\n * - 2 minute timeout\n * - 3 retries\n */\n fileSystem: mergePolicies(\n timeoutPolicies.long,\n retryPolicies.standard\n ),\n\n /**\n * Policy for third-party services with rate limits.\n * - 10 second timeout\n * - 5 retries with linear backoff\n */\n rateLimited: mergePolicies(\n timeoutPolicy({ ms: 10000 }),\n retryPolicy({\n attempts: 5,\n backoff: \"linear\",\n initialDelay: 1000,\n maxDelay: 10000,\n jitter: true,\n })\n ),\n} as const;\n\n// =============================================================================\n// Policy Decorators\n// =============================================================================\n\n/**\n * Options for withPolicies workflow wrapper.\n */\nexport interface WithPoliciesOptions {\n /**\n * Base policies applied to all steps.\n */\n policies: Policy[];\n\n /**\n * Step-specific policy overrides by name or key pattern.\n */\n overrides?: Record<string, Policy>;\n}\n\n/**\n * Create step options with policies applied.\n * This is a helper for applying policies inline.\n *\n * @param policies - Policies to apply\n * @param stepOptions - Step-specific options\n * @returns Merged StepOptions\n *\n * @example\n * ```typescript\n * const user = await step(\n * () => fetchUser(id),\n * withPolicy(servicePolicies.httpApi, { name: 'fetch-user' })\n * );\n * ```\n */\nexport function withPolicy(\n policy: Policy,\n stepOptions?: StepOptions\n): StepOptions {\n const opts = stepOptions ?? {};\n return mergePolicies(policy, opts);\n}\n\n/**\n * Create step options with multiple policies applied.\n *\n * @param policies - Policies to apply (in order)\n * @param stepOptions - Step-specific options\n * @returns Merged StepOptions\n *\n * @example\n * ```typescript\n * const user = await step(\n * 'fetch-user',\n * () => fetchUser(id),\n * withPolicies([timeoutPolicies.api, retryPolicies.standard])\n * );\n * ```\n */\nexport function withPolicies(\n policies: Policy[],\n stepOptions?: StepOptions\n): StepOptions {\n const opts = stepOptions ?? {};\n return mergePolicies(...policies, opts);\n}\n\n// =============================================================================\n// Conditional Policies\n// =============================================================================\n\n/**\n * Create a policy that applies conditionally.\n *\n * @param condition - Condition to check\n * @param policy - Policy to apply if condition is true\n * @param elsePolicy - Policy to apply if condition is false (optional)\n * @returns The selected policy\n *\n * @example\n * ```typescript\n * const policy = conditionalPolicy(\n * isProduction,\n * servicePolicies.httpApi, // Use in production\n * retryPolicies.none // Skip in development\n * );\n * ```\n */\nexport function conditionalPolicy(\n condition: boolean,\n policy: Policy,\n elsePolicy: Policy = {}\n): Policy {\n return condition ? policy : elsePolicy;\n}\n\n/**\n * Create a policy based on environment.\n *\n * @param envPolicies - Map of environment names to policies\n * @param currentEnv - Current environment (defaults to NODE_ENV)\n * @param defaultPolicy - Default policy if environment not found\n * @returns The selected policy\n *\n * @example\n * ```typescript\n * const policy = envPolicy({\n * production: servicePolicies.httpApi,\n * development: retryPolicies.none,\n * test: retryPolicies.none,\n * });\n * ```\n */\nexport function envPolicy(\n envPolicies: Record<string, Policy>,\n currentEnv: string = process.env.NODE_ENV ?? \"development\",\n defaultPolicy: Policy = {}\n): Policy {\n return envPolicies[currentEnv] ?? defaultPolicy;\n}\n\n// =============================================================================\n// Policy Registry\n// =============================================================================\n\n/**\n * A registry for managing named policies.\n */\nexport interface PolicyRegistry {\n /**\n * Register a named policy.\n */\n register(name: string, policy: Policy): void;\n\n /**\n * Get a policy by name.\n */\n get(name: string): Policy | undefined;\n\n /**\n * Check if a policy exists.\n */\n has(name: string): boolean;\n\n /**\n * Get all registered policy names.\n */\n names(): string[];\n\n /**\n * Create step options using a registered policy.\n */\n apply(policyName: string, stepOptions?: StepOptions): StepOptions;\n}\n\n/**\n * Create a policy registry for managing named policies.\n *\n * @returns PolicyRegistry instance\n *\n * @example\n * ```typescript\n * const registry = createPolicyRegistry();\n *\n * // Register policies\n * registry.register('api', servicePolicies.httpApi);\n * registry.register('db', servicePolicies.database);\n *\n * // Use in workflow\n * const user = await step(\n * 'fetch-user',\n * () => fetchUser(id),\n * registry.apply('api')\n * );\n * ```\n */\nexport function createPolicyRegistry(): PolicyRegistry {\n const policies = new Map<string, Policy>();\n\n return {\n register(name: string, policy: Policy): void {\n policies.set(name, policy);\n },\n\n get(name: string): Policy | undefined {\n return policies.get(name);\n },\n\n has(name: string): boolean {\n return policies.has(name);\n },\n\n names(): string[] {\n return Array.from(policies.keys());\n },\n\n apply(policyName: string, stepOptions?: StepOptions): StepOptions {\n const policy = policies.get(policyName);\n if (!policy) {\n throw new Error(`Policy not found: ${policyName}`);\n }\n return withPolicy(policy, stepOptions);\n },\n };\n}\n\n// =============================================================================\n// Step Options Builder (Fluent API)\n// =============================================================================\n\n/**\n * Fluent builder for constructing step options.\n */\nexport interface StepOptionsBuilder {\n /**\n * Set step key for caching.\n */\n key(key: string): StepOptionsBuilder;\n\n /**\n * Apply a policy.\n */\n policy(policy: Policy): StepOptionsBuilder;\n\n /**\n * Set timeout in milliseconds.\n */\n timeout(ms: number): StepOptionsBuilder;\n\n /**\n * Set retry options.\n */\n retry(options: RetryOptions): StepOptionsBuilder;\n\n /**\n * Set retry attempts (with default exponential backoff).\n */\n retries(attempts: number): StepOptionsBuilder;\n\n /**\n * Build the final StepOptions.\n */\n build(): StepOptions;\n}\n\n/**\n * Create a fluent builder for step options.\n *\n * @returns StepOptionsBuilder instance\n *\n * @example\n * ```typescript\n * const options = stepOptions()\n * .key('user:123')\n * .timeout(5000)\n * .retries(3)\n * .build();\n *\n * const user = await step('fetch-user', () => fetchUser(id), options);\n * ```\n */\nexport function stepOptions(): StepOptionsBuilder {\n const policies: Policy[] = [];\n\n const builder: StepOptionsBuilder = {\n key(key: string) {\n policies.push({ key });\n return builder;\n },\n\n policy(policy: Policy) {\n policies.push(policy);\n return builder;\n },\n\n timeout(ms: number) {\n policies.push(timeoutPolicy({ ms }));\n return builder;\n },\n\n retry(options: RetryOptions) {\n policies.push(retryPolicy(options));\n return builder;\n },\n\n retries(attempts: number) {\n policies.push(retryPolicies.custom({ attempts }));\n return builder;\n },\n\n build(): StepOptions {\n return mergePolicies(...policies);\n },\n };\n\n return builder;\n}\n"],"mappings":"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","names":["policies_entry_exports","__export","conditionalPolicy","createPolicyApplier","createPolicyBundle","createPolicyRegistry","envPolicy","mergePolicies","retryPolicies","retryPolicy","servicePolicies","stepOptions","timeoutPolicies","timeoutPolicy","withPolicies","withPolicy","__toCommonJS","mergePolicies","policies","result","policy","createPolicyApplier","basePolicies","basePolicy","stepOptions","createPolicyBundle","name","retryPolicy","options","retryPolicies","attempts","delayMs","initialDelay","timeoutPolicy","timeoutPolicies","ms","seconds","error","servicePolicies","withPolicy","withPolicies","opts","conditionalPolicy","condition","elsePolicy","envPolicy","envPolicies","currentEnv","defaultPolicy","createPolicyRegistry","policyName","builder","key"]}
|
package/dist/policies.d.cts
DELETED
|
@@ -1,379 +0,0 @@
|
|
|
1
|
-
import { aj as StepOptions, ag as RetryOptions, ar as TimeoutOptions } from './run-entry-DGs0tySr.cjs';
|
|
2
|
-
import './errors.cjs';
|
|
3
|
-
import './tagged-error.cjs';
|
|
4
|
-
import './slugs.cjs';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* awaitly/policies
|
|
8
|
-
*
|
|
9
|
-
* Policy-Driven Step Middleware - Reusable bundles of StepOptions
|
|
10
|
-
* that can be composed and applied per-workflow or per-step.
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* A policy is a partial StepOptions that can be merged with other policies.
|
|
15
|
-
*/
|
|
16
|
-
type Policy = Partial<StepOptions>;
|
|
17
|
-
/**
|
|
18
|
-
* A policy factory that creates policies based on context.
|
|
19
|
-
*/
|
|
20
|
-
type PolicyFactory<T = void> = T extends void ? () => Policy : (context: T) => Policy;
|
|
21
|
-
/**
|
|
22
|
-
* Named policy with metadata.
|
|
23
|
-
*/
|
|
24
|
-
interface NamedPolicy {
|
|
25
|
-
name: string;
|
|
26
|
-
policy: Policy;
|
|
27
|
-
description?: string;
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Merge multiple policies into a single StepOptions object.
|
|
31
|
-
* Later policies override earlier ones for conflicting properties.
|
|
32
|
-
* Retry and timeout options are deep-merged.
|
|
33
|
-
*
|
|
34
|
-
* @param policies - Policies to merge (in order of precedence)
|
|
35
|
-
* @returns Merged StepOptions
|
|
36
|
-
*
|
|
37
|
-
* @example
|
|
38
|
-
* ```typescript
|
|
39
|
-
* const merged = mergePolicies(
|
|
40
|
-
* timeoutPolicies.api, // timeout: 5000ms
|
|
41
|
-
* retryPolicies.transient, // retry: 3 attempts
|
|
42
|
-
* { name: 'fetch-user' } // name override
|
|
43
|
-
* );
|
|
44
|
-
* ```
|
|
45
|
-
*/
|
|
46
|
-
declare function mergePolicies(...policies: Policy[]): StepOptions;
|
|
47
|
-
/**
|
|
48
|
-
* Create a policy applier that merges base policies with step-specific options.
|
|
49
|
-
*
|
|
50
|
-
* @param basePolicies - Base policies to apply to all steps
|
|
51
|
-
* @returns A function that applies policies to step options
|
|
52
|
-
*
|
|
53
|
-
* @example
|
|
54
|
-
* ```typescript
|
|
55
|
-
* const applyPolicy = createPolicyApplier(
|
|
56
|
-
* timeoutPolicies.api,
|
|
57
|
-
* retryPolicies.transient
|
|
58
|
-
* );
|
|
59
|
-
*
|
|
60
|
-
* // In workflow
|
|
61
|
-
* const user = await step(
|
|
62
|
-
* 'fetch-user',
|
|
63
|
-
* () => fetchUser(id),
|
|
64
|
-
* applyPolicy({ key: 'user:' + id })
|
|
65
|
-
* );
|
|
66
|
-
* ```
|
|
67
|
-
*/
|
|
68
|
-
declare function createPolicyApplier(...basePolicies: Policy[]): (stepOptions?: StepOptions) => StepOptions;
|
|
69
|
-
/**
|
|
70
|
-
* Create a named policy bundle for reuse across workflows.
|
|
71
|
-
*
|
|
72
|
-
* @param name - Policy bundle name
|
|
73
|
-
* @param policies - Policies to include in the bundle
|
|
74
|
-
* @returns Named policy object
|
|
75
|
-
*/
|
|
76
|
-
declare function createPolicyBundle(name: string, ...policies: Policy[]): NamedPolicy;
|
|
77
|
-
/**
|
|
78
|
-
* Create a retry policy with the given options.
|
|
79
|
-
*/
|
|
80
|
-
declare function retryPolicy(options: RetryOptions): Policy;
|
|
81
|
-
/**
|
|
82
|
-
* Pre-built retry policies for common scenarios.
|
|
83
|
-
*/
|
|
84
|
-
declare const retryPolicies: {
|
|
85
|
-
/**
|
|
86
|
-
* No retry - fail immediately on error.
|
|
87
|
-
*/
|
|
88
|
-
readonly none: Partial<StepOptions>;
|
|
89
|
-
/**
|
|
90
|
-
* Quick retry for transient errors (3 attempts, fast backoff).
|
|
91
|
-
*/
|
|
92
|
-
readonly transient: Partial<StepOptions>;
|
|
93
|
-
/**
|
|
94
|
-
* Standard retry for API calls (3 attempts, moderate backoff).
|
|
95
|
-
*/
|
|
96
|
-
readonly standard: Partial<StepOptions>;
|
|
97
|
-
/**
|
|
98
|
-
* Aggressive retry for critical operations (5 attempts, longer backoff).
|
|
99
|
-
*/
|
|
100
|
-
readonly aggressive: Partial<StepOptions>;
|
|
101
|
-
/**
|
|
102
|
-
* Fixed interval retry (useful for polling).
|
|
103
|
-
*/
|
|
104
|
-
readonly fixed: (attempts: number, delayMs: number) => Policy;
|
|
105
|
-
/**
|
|
106
|
-
* Linear backoff retry.
|
|
107
|
-
*/
|
|
108
|
-
readonly linear: (attempts: number, initialDelay: number) => Policy;
|
|
109
|
-
/**
|
|
110
|
-
* Custom retry policy builder.
|
|
111
|
-
*/
|
|
112
|
-
readonly custom: (options: Partial<RetryOptions> & {
|
|
113
|
-
attempts: number;
|
|
114
|
-
}) => Policy;
|
|
115
|
-
};
|
|
116
|
-
/**
|
|
117
|
-
* Create a timeout policy with the given options.
|
|
118
|
-
*/
|
|
119
|
-
declare function timeoutPolicy(options: TimeoutOptions): Policy;
|
|
120
|
-
/**
|
|
121
|
-
* Pre-built timeout policies for common scenarios.
|
|
122
|
-
*/
|
|
123
|
-
declare const timeoutPolicies: {
|
|
124
|
-
/**
|
|
125
|
-
* No timeout.
|
|
126
|
-
*/
|
|
127
|
-
readonly none: Policy;
|
|
128
|
-
/**
|
|
129
|
-
* Fast timeout for quick operations (1 second).
|
|
130
|
-
*/
|
|
131
|
-
readonly fast: Partial<StepOptions>;
|
|
132
|
-
/**
|
|
133
|
-
* Standard API timeout (5 seconds).
|
|
134
|
-
*/
|
|
135
|
-
readonly api: Partial<StepOptions>;
|
|
136
|
-
/**
|
|
137
|
-
* Extended timeout for slower operations (30 seconds).
|
|
138
|
-
*/
|
|
139
|
-
readonly extended: Partial<StepOptions>;
|
|
140
|
-
/**
|
|
141
|
-
* Long timeout for batch operations (2 minutes).
|
|
142
|
-
*/
|
|
143
|
-
readonly long: Partial<StepOptions>;
|
|
144
|
-
/**
|
|
145
|
-
* Custom timeout in milliseconds.
|
|
146
|
-
*/
|
|
147
|
-
readonly ms: (ms: number) => Policy;
|
|
148
|
-
/**
|
|
149
|
-
* Custom timeout in seconds.
|
|
150
|
-
*/
|
|
151
|
-
readonly seconds: (seconds: number) => Policy;
|
|
152
|
-
/**
|
|
153
|
-
* Timeout with custom error.
|
|
154
|
-
*/
|
|
155
|
-
readonly withError: <E>(ms: number, error: E) => Policy;
|
|
156
|
-
/**
|
|
157
|
-
* Timeout with AbortSignal support.
|
|
158
|
-
*/
|
|
159
|
-
readonly withSignal: (ms: number) => Policy;
|
|
160
|
-
};
|
|
161
|
-
/**
|
|
162
|
-
* Pre-built combined policies for common service patterns.
|
|
163
|
-
*/
|
|
164
|
-
declare const servicePolicies: {
|
|
165
|
-
/**
|
|
166
|
-
* Policy for external HTTP APIs.
|
|
167
|
-
* - 5 second timeout
|
|
168
|
-
* - 3 retries with exponential backoff
|
|
169
|
-
*/
|
|
170
|
-
readonly httpApi: StepOptions;
|
|
171
|
-
/**
|
|
172
|
-
* Policy for database operations.
|
|
173
|
-
* - 30 second timeout
|
|
174
|
-
* - 2 retries for transient errors
|
|
175
|
-
*/
|
|
176
|
-
readonly database: StepOptions;
|
|
177
|
-
/**
|
|
178
|
-
* Policy for cache operations.
|
|
179
|
-
* - 1 second timeout
|
|
180
|
-
* - No retry (cache misses are not errors)
|
|
181
|
-
*/
|
|
182
|
-
readonly cache: StepOptions;
|
|
183
|
-
/**
|
|
184
|
-
* Policy for message queue operations.
|
|
185
|
-
* - 30 second timeout
|
|
186
|
-
* - 5 retries with longer backoff
|
|
187
|
-
*/
|
|
188
|
-
readonly messageQueue: StepOptions;
|
|
189
|
-
/**
|
|
190
|
-
* Policy for file operations.
|
|
191
|
-
* - 2 minute timeout
|
|
192
|
-
* - 3 retries
|
|
193
|
-
*/
|
|
194
|
-
readonly fileSystem: StepOptions;
|
|
195
|
-
/**
|
|
196
|
-
* Policy for third-party services with rate limits.
|
|
197
|
-
* - 10 second timeout
|
|
198
|
-
* - 5 retries with linear backoff
|
|
199
|
-
*/
|
|
200
|
-
readonly rateLimited: StepOptions;
|
|
201
|
-
};
|
|
202
|
-
/**
|
|
203
|
-
* Options for withPolicies workflow wrapper.
|
|
204
|
-
*/
|
|
205
|
-
interface WithPoliciesOptions {
|
|
206
|
-
/**
|
|
207
|
-
* Base policies applied to all steps.
|
|
208
|
-
*/
|
|
209
|
-
policies: Policy[];
|
|
210
|
-
/**
|
|
211
|
-
* Step-specific policy overrides by name or key pattern.
|
|
212
|
-
*/
|
|
213
|
-
overrides?: Record<string, Policy>;
|
|
214
|
-
}
|
|
215
|
-
/**
|
|
216
|
-
* Create step options with policies applied.
|
|
217
|
-
* This is a helper for applying policies inline.
|
|
218
|
-
*
|
|
219
|
-
* @param policies - Policies to apply
|
|
220
|
-
* @param stepOptions - Step-specific options
|
|
221
|
-
* @returns Merged StepOptions
|
|
222
|
-
*
|
|
223
|
-
* @example
|
|
224
|
-
* ```typescript
|
|
225
|
-
* const user = await step(
|
|
226
|
-
* () => fetchUser(id),
|
|
227
|
-
* withPolicy(servicePolicies.httpApi, { name: 'fetch-user' })
|
|
228
|
-
* );
|
|
229
|
-
* ```
|
|
230
|
-
*/
|
|
231
|
-
declare function withPolicy(policy: Policy, stepOptions?: StepOptions): StepOptions;
|
|
232
|
-
/**
|
|
233
|
-
* Create step options with multiple policies applied.
|
|
234
|
-
*
|
|
235
|
-
* @param policies - Policies to apply (in order)
|
|
236
|
-
* @param stepOptions - Step-specific options
|
|
237
|
-
* @returns Merged StepOptions
|
|
238
|
-
*
|
|
239
|
-
* @example
|
|
240
|
-
* ```typescript
|
|
241
|
-
* const user = await step(
|
|
242
|
-
* 'fetch-user',
|
|
243
|
-
* () => fetchUser(id),
|
|
244
|
-
* withPolicies([timeoutPolicies.api, retryPolicies.standard])
|
|
245
|
-
* );
|
|
246
|
-
* ```
|
|
247
|
-
*/
|
|
248
|
-
declare function withPolicies(policies: Policy[], stepOptions?: StepOptions): StepOptions;
|
|
249
|
-
/**
|
|
250
|
-
* Create a policy that applies conditionally.
|
|
251
|
-
*
|
|
252
|
-
* @param condition - Condition to check
|
|
253
|
-
* @param policy - Policy to apply if condition is true
|
|
254
|
-
* @param elsePolicy - Policy to apply if condition is false (optional)
|
|
255
|
-
* @returns The selected policy
|
|
256
|
-
*
|
|
257
|
-
* @example
|
|
258
|
-
* ```typescript
|
|
259
|
-
* const policy = conditionalPolicy(
|
|
260
|
-
* isProduction,
|
|
261
|
-
* servicePolicies.httpApi, // Use in production
|
|
262
|
-
* retryPolicies.none // Skip in development
|
|
263
|
-
* );
|
|
264
|
-
* ```
|
|
265
|
-
*/
|
|
266
|
-
declare function conditionalPolicy(condition: boolean, policy: Policy, elsePolicy?: Policy): Policy;
|
|
267
|
-
/**
|
|
268
|
-
* Create a policy based on environment.
|
|
269
|
-
*
|
|
270
|
-
* @param envPolicies - Map of environment names to policies
|
|
271
|
-
* @param currentEnv - Current environment (defaults to NODE_ENV)
|
|
272
|
-
* @param defaultPolicy - Default policy if environment not found
|
|
273
|
-
* @returns The selected policy
|
|
274
|
-
*
|
|
275
|
-
* @example
|
|
276
|
-
* ```typescript
|
|
277
|
-
* const policy = envPolicy({
|
|
278
|
-
* production: servicePolicies.httpApi,
|
|
279
|
-
* development: retryPolicies.none,
|
|
280
|
-
* test: retryPolicies.none,
|
|
281
|
-
* });
|
|
282
|
-
* ```
|
|
283
|
-
*/
|
|
284
|
-
declare function envPolicy(envPolicies: Record<string, Policy>, currentEnv?: string, defaultPolicy?: Policy): Policy;
|
|
285
|
-
/**
|
|
286
|
-
* A registry for managing named policies.
|
|
287
|
-
*/
|
|
288
|
-
interface PolicyRegistry {
|
|
289
|
-
/**
|
|
290
|
-
* Register a named policy.
|
|
291
|
-
*/
|
|
292
|
-
register(name: string, policy: Policy): void;
|
|
293
|
-
/**
|
|
294
|
-
* Get a policy by name.
|
|
295
|
-
*/
|
|
296
|
-
get(name: string): Policy | undefined;
|
|
297
|
-
/**
|
|
298
|
-
* Check if a policy exists.
|
|
299
|
-
*/
|
|
300
|
-
has(name: string): boolean;
|
|
301
|
-
/**
|
|
302
|
-
* Get all registered policy names.
|
|
303
|
-
*/
|
|
304
|
-
names(): string[];
|
|
305
|
-
/**
|
|
306
|
-
* Create step options using a registered policy.
|
|
307
|
-
*/
|
|
308
|
-
apply(policyName: string, stepOptions?: StepOptions): StepOptions;
|
|
309
|
-
}
|
|
310
|
-
/**
|
|
311
|
-
* Create a policy registry for managing named policies.
|
|
312
|
-
*
|
|
313
|
-
* @returns PolicyRegistry instance
|
|
314
|
-
*
|
|
315
|
-
* @example
|
|
316
|
-
* ```typescript
|
|
317
|
-
* const registry = createPolicyRegistry();
|
|
318
|
-
*
|
|
319
|
-
* // Register policies
|
|
320
|
-
* registry.register('api', servicePolicies.httpApi);
|
|
321
|
-
* registry.register('db', servicePolicies.database);
|
|
322
|
-
*
|
|
323
|
-
* // Use in workflow
|
|
324
|
-
* const user = await step(
|
|
325
|
-
* 'fetch-user',
|
|
326
|
-
* () => fetchUser(id),
|
|
327
|
-
* registry.apply('api')
|
|
328
|
-
* );
|
|
329
|
-
* ```
|
|
330
|
-
*/
|
|
331
|
-
declare function createPolicyRegistry(): PolicyRegistry;
|
|
332
|
-
/**
|
|
333
|
-
* Fluent builder for constructing step options.
|
|
334
|
-
*/
|
|
335
|
-
interface StepOptionsBuilder {
|
|
336
|
-
/**
|
|
337
|
-
* Set step key for caching.
|
|
338
|
-
*/
|
|
339
|
-
key(key: string): StepOptionsBuilder;
|
|
340
|
-
/**
|
|
341
|
-
* Apply a policy.
|
|
342
|
-
*/
|
|
343
|
-
policy(policy: Policy): StepOptionsBuilder;
|
|
344
|
-
/**
|
|
345
|
-
* Set timeout in milliseconds.
|
|
346
|
-
*/
|
|
347
|
-
timeout(ms: number): StepOptionsBuilder;
|
|
348
|
-
/**
|
|
349
|
-
* Set retry options.
|
|
350
|
-
*/
|
|
351
|
-
retry(options: RetryOptions): StepOptionsBuilder;
|
|
352
|
-
/**
|
|
353
|
-
* Set retry attempts (with default exponential backoff).
|
|
354
|
-
*/
|
|
355
|
-
retries(attempts: number): StepOptionsBuilder;
|
|
356
|
-
/**
|
|
357
|
-
* Build the final StepOptions.
|
|
358
|
-
*/
|
|
359
|
-
build(): StepOptions;
|
|
360
|
-
}
|
|
361
|
-
/**
|
|
362
|
-
* Create a fluent builder for step options.
|
|
363
|
-
*
|
|
364
|
-
* @returns StepOptionsBuilder instance
|
|
365
|
-
*
|
|
366
|
-
* @example
|
|
367
|
-
* ```typescript
|
|
368
|
-
* const options = stepOptions()
|
|
369
|
-
* .key('user:123')
|
|
370
|
-
* .timeout(5000)
|
|
371
|
-
* .retries(3)
|
|
372
|
-
* .build();
|
|
373
|
-
*
|
|
374
|
-
* const user = await step('fetch-user', () => fetchUser(id), options);
|
|
375
|
-
* ```
|
|
376
|
-
*/
|
|
377
|
-
declare function stepOptions(): StepOptionsBuilder;
|
|
378
|
-
|
|
379
|
-
export { type NamedPolicy, type Policy, type PolicyFactory, type PolicyRegistry, type StepOptionsBuilder, type WithPoliciesOptions, conditionalPolicy, createPolicyApplier, createPolicyBundle, createPolicyRegistry, envPolicy, mergePolicies, retryPolicies, retryPolicy, servicePolicies, stepOptions, timeoutPolicies, timeoutPolicy, withPolicies, withPolicy };
|