awaitly 2.0.0 → 3.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.
Files changed (88) hide show
  1. package/dist/di-Biw_plBn.d.cts +15 -0
  2. package/dist/di-DxyH2N3i.d.ts +15 -0
  3. package/dist/durable.cjs +4670 -0
  4. package/dist/durable.cjs.map +1 -0
  5. package/dist/durable.d.cts +9 -0
  6. package/dist/durable.d.ts +9 -0
  7. package/dist/durable.js +4610 -0
  8. package/dist/durable.js.map +1 -0
  9. package/dist/{di-BbFFfO8y.d.ts → duration-BjVn3QpB.d.cts} +1 -15
  10. package/dist/{di-BDlT7InM.d.cts → duration-BjVn3QpB.d.ts} +1 -15
  11. package/dist/engine.cjs +4501 -0
  12. package/dist/engine.cjs.map +1 -0
  13. package/dist/engine.d.cts +113 -0
  14. package/dist/engine.d.ts +113 -0
  15. package/dist/engine.js +4474 -0
  16. package/dist/engine.js.map +1 -0
  17. package/dist/{errors-DtXvrCiO.d.cts → errors-sDSeaZBO.d.cts} +1 -1
  18. package/dist/{errors-DtXvrCiO.d.ts → errors-sDSeaZBO.d.ts} +1 -1
  19. package/dist/guards-CwQZro1F.d.ts +72 -0
  20. package/dist/guards-DhhOJZda.d.cts +72 -0
  21. package/dist/hitl-BnnnLzh2.d.cts +468 -0
  22. package/dist/hitl-pYfkQMv_.d.ts +468 -0
  23. package/dist/hitl.cjs +646 -0
  24. package/dist/hitl.cjs.map +1 -0
  25. package/dist/hitl.d.cts +440 -0
  26. package/dist/hitl.d.ts +440 -0
  27. package/dist/hitl.js +605 -0
  28. package/dist/hitl.js.map +1 -0
  29. package/dist/index-Bew12SZ8.d.ts +417 -0
  30. package/dist/index-Bwt-iz50.d.cts +417 -0
  31. package/dist/{types-B8NfNRGX.d.ts → index-Cv4K_3sZ.d.ts} +2 -1162
  32. package/dist/{types-BZ2f4MRR.d.cts → index-ICmfQi08.d.cts} +2 -1162
  33. package/dist/index.cjs.map +1 -1
  34. package/dist/index.d.cts +11 -1527
  35. package/dist/index.d.ts +11 -1527
  36. package/dist/persistence.cjs +552 -0
  37. package/dist/persistence.cjs.map +1 -0
  38. package/dist/persistence.d.cts +254 -0
  39. package/dist/persistence.d.ts +254 -0
  40. package/dist/persistence.js +499 -0
  41. package/dist/persistence.js.map +1 -0
  42. package/dist/reliability.cjs +1651 -0
  43. package/dist/reliability.cjs.map +1 -0
  44. package/dist/reliability.d.cts +1442 -0
  45. package/dist/reliability.d.ts +1442 -0
  46. package/dist/reliability.js +1589 -0
  47. package/dist/reliability.js.map +1 -0
  48. package/dist/result.d.cts +1 -1
  49. package/dist/result.d.ts +1 -1
  50. package/dist/run.cjs +2283 -0
  51. package/dist/run.cjs.map +1 -0
  52. package/dist/run.d.cts +90 -0
  53. package/dist/run.d.ts +90 -0
  54. package/dist/run.js +2247 -0
  55. package/dist/run.js.map +1 -0
  56. package/dist/saga.cjs +3699 -0
  57. package/dist/saga.cjs.map +1 -0
  58. package/dist/saga.d.cts +162 -0
  59. package/dist/saga.d.ts +162 -0
  60. package/dist/saga.js +3670 -0
  61. package/dist/saga.js.map +1 -0
  62. package/dist/store-contract-BI98VYmX.d.ts +66 -0
  63. package/dist/store-contract-C2HyR_o6.d.cts +66 -0
  64. package/dist/streaming.cjs +895 -0
  65. package/dist/streaming.cjs.map +1 -0
  66. package/dist/streaming.d.cts +594 -0
  67. package/dist/streaming.d.ts +594 -0
  68. package/dist/streaming.js +832 -0
  69. package/dist/streaming.js.map +1 -0
  70. package/dist/testing.d.cts +4 -2
  71. package/dist/testing.d.ts +4 -2
  72. package/dist/types-BDTxgKKc.d.ts +845 -0
  73. package/dist/types-C9Y71dua.d.cts +845 -0
  74. package/dist/types-d8q8iQlk.d.cts +323 -0
  75. package/dist/types-sObbY4mX.d.ts +323 -0
  76. package/dist/webhook.cjs +461 -0
  77. package/dist/webhook.cjs.map +1 -0
  78. package/dist/webhook.d.cts +497 -0
  79. package/dist/webhook.d.ts +497 -0
  80. package/dist/webhook.js +422 -0
  81. package/dist/webhook.js.map +1 -0
  82. package/dist/workflow.cjs +2 -2614
  83. package/dist/workflow.cjs.map +1 -1
  84. package/dist/workflow.d.cts +12 -3023
  85. package/dist/workflow.d.ts +12 -3023
  86. package/dist/workflow.js +2 -2535
  87. package/dist/workflow.js.map +1 -1
  88. package/package.json +46 -1
@@ -0,0 +1,1442 @@
1
+ export { PolicyDelay, PolicyFn, RetryPolicyOptions, fallback, retry, timeout } from './run.js';
2
+ import { R as Result, A as AsyncResult, j as StepOptions, d as RetryOptions, T as TimeoutOptions } from './index-Cv4K_3sZ.js';
3
+ import { D as Duration } from './duration-BjVn3QpB.js';
4
+ import './result.js';
5
+ import './errors-sDSeaZBO.js';
6
+
7
+ /**
8
+ * Circuit Breaker for Steps
9
+ *
10
+ * Prevents cascading failures by tracking step failure rates and
11
+ * short-circuiting calls when a threshold is exceeded.
12
+ *
13
+ * Uses the circuit breaker pattern with three states:
14
+ * - CLOSED: Normal operation (steps executing)
15
+ * - OPEN: Fast-fail mode (steps blocked)
16
+ * - HALF_OPEN: Testing if service recovered
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * import { createCircuitBreaker } from 'awaitly';
21
+ *
22
+ * const breaker = createCircuitBreaker({
23
+ * failureThreshold: 5,
24
+ * resetTimeout: 30000,
25
+ * halfOpenMax: 3,
26
+ * });
27
+ *
28
+ * const result = await workflow(async ({ step }) => {
29
+ * const data = await breaker.execute(
30
+ * () => step(() => callExternalApi()),
31
+ * { name: 'external-api' }
32
+ * );
33
+ * return data;
34
+ * });
35
+ * ```
36
+ */
37
+
38
+ /**
39
+ * Circuit breaker state.
40
+ */
41
+ type CircuitState = "CLOSED" | "OPEN" | "HALF_OPEN";
42
+ /**
43
+ * Configuration for circuit breaker behavior.
44
+ */
45
+ interface CircuitBreakerConfig {
46
+ /**
47
+ * Number of failures within the window before opening the circuit.
48
+ * @default 5
49
+ */
50
+ failureThreshold: number;
51
+ /**
52
+ * Time in ms to wait before transitioning from OPEN to HALF_OPEN.
53
+ * @default 30000 (30 seconds)
54
+ */
55
+ resetTimeout: number;
56
+ /**
57
+ * Time window in ms for counting failures.
58
+ * Failures older than this are discarded.
59
+ * @default 60000 (1 minute)
60
+ */
61
+ windowSize: number;
62
+ /**
63
+ * Maximum number of test requests allowed in HALF_OPEN state.
64
+ * If all succeed, circuit closes. If any fail, circuit reopens.
65
+ * @default 3
66
+ */
67
+ halfOpenMax: number;
68
+ /**
69
+ * Optional callback when circuit state changes.
70
+ */
71
+ onStateChange?: (from: CircuitState, to: CircuitState, name?: string) => void;
72
+ }
73
+ /**
74
+ * Error thrown when the circuit is open and calls are blocked.
75
+ */
76
+ declare class CircuitOpenError extends Error {
77
+ readonly type: "CIRCUIT_OPEN";
78
+ readonly circuitName: string;
79
+ readonly state: CircuitState;
80
+ readonly retryAfterMs: number;
81
+ constructor(options: {
82
+ circuitName: string;
83
+ state: CircuitState;
84
+ retryAfterMs: number;
85
+ message?: string;
86
+ });
87
+ }
88
+ /**
89
+ * Type guard for CircuitOpenError.
90
+ */
91
+ declare function isCircuitOpenError(error: unknown): error is CircuitOpenError;
92
+ /**
93
+ * Circuit breaker statistics.
94
+ */
95
+ interface CircuitBreakerStats {
96
+ state: CircuitState;
97
+ failureCount: number;
98
+ successCount: number;
99
+ lastFailureTime: number | null;
100
+ lastSuccessTime: number | null;
101
+ halfOpenSuccesses: number;
102
+ }
103
+ /**
104
+ * Circuit breaker instance for protecting external calls.
105
+ */
106
+ interface CircuitBreaker {
107
+ /**
108
+ * Execute an operation with circuit breaker protection.
109
+ * Throws CircuitOpenError if the circuit is open.
110
+ *
111
+ * @param operation - The operation to execute
112
+ * @param options - Optional name for logging/metrics
113
+ * @returns The operation result
114
+ * @throws CircuitOpenError if circuit is open
115
+ */
116
+ execute<T>(operation: () => T | Promise<T>, options?: {
117
+ name?: string;
118
+ }): Promise<T>;
119
+ /**
120
+ * Execute a Result-returning operation with circuit breaker protection.
121
+ * Returns a CircuitOpenError result instead of throwing.
122
+ *
123
+ * @param operation - The operation returning a Result
124
+ * @param options - Optional name for logging/metrics
125
+ * @returns Result with the value or CircuitOpenError
126
+ */
127
+ executeResult<T, E>(operation: () => Result<T, E> | AsyncResult<T, E>, options?: {
128
+ name?: string;
129
+ }): AsyncResult<T, E | CircuitOpenError>;
130
+ /**
131
+ * Get current circuit state.
132
+ */
133
+ getState(): CircuitState;
134
+ /**
135
+ * Get circuit breaker statistics.
136
+ */
137
+ getStats(): CircuitBreakerStats;
138
+ /**
139
+ * Manually reset the circuit breaker to CLOSED state.
140
+ */
141
+ reset(): void;
142
+ /**
143
+ * Manually open the circuit (for testing or manual intervention).
144
+ */
145
+ forceOpen(): void;
146
+ /**
147
+ * Record a manual success (useful for health checks).
148
+ */
149
+ recordSuccess(): void;
150
+ /**
151
+ * Record a manual failure (useful for health checks).
152
+ */
153
+ recordFailure(error?: unknown): void;
154
+ }
155
+ /**
156
+ * Create a circuit breaker instance.
157
+ *
158
+ * @param name - Name for this circuit breaker (used in errors and logging)
159
+ * @param config - Configuration options
160
+ * @returns A CircuitBreaker instance
161
+ *
162
+ * @example
163
+ * ```typescript
164
+ * const apiBreaker = createCircuitBreaker('external-api', {
165
+ * failureThreshold: 5,
166
+ * resetTimeout: 30000,
167
+ * });
168
+ *
169
+ * // In workflow
170
+ * const data = await apiBreaker.execute(() =>
171
+ * step(() => fetchFromApi(id))
172
+ * );
173
+ * ```
174
+ */
175
+ declare function createCircuitBreaker(name: string, config?: Partial<CircuitBreakerConfig>): CircuitBreaker;
176
+ /**
177
+ * Preset configurations for common use cases.
178
+ */
179
+ declare const circuitBreakerPresets: {
180
+ /**
181
+ * Aggressive circuit breaker for critical paths.
182
+ * Opens quickly (3 failures) and recovers slowly (60s).
183
+ */
184
+ readonly critical: {
185
+ failureThreshold: number;
186
+ resetTimeout: number;
187
+ windowSize: number;
188
+ halfOpenMax: number;
189
+ };
190
+ /**
191
+ * Standard circuit breaker for typical API calls.
192
+ * Balanced between stability and availability.
193
+ */
194
+ readonly standard: {
195
+ failureThreshold: number;
196
+ resetTimeout: number;
197
+ windowSize: number;
198
+ halfOpenMax: number;
199
+ };
200
+ /**
201
+ * Lenient circuit breaker for non-critical operations.
202
+ * Opens slowly (10 failures) and recovers quickly (15s).
203
+ */
204
+ readonly lenient: {
205
+ failureThreshold: number;
206
+ resetTimeout: number;
207
+ windowSize: number;
208
+ halfOpenMax: number;
209
+ };
210
+ };
211
+
212
+ /**
213
+ * Rate Limiting / Concurrency Control
214
+ *
215
+ * Control throughput for steps that hit rate-limited APIs or shared resources.
216
+ *
217
+ * @example
218
+ * ```typescript
219
+ * import { createRateLimiter, createConcurrencyLimiter } from 'awaitly';
220
+ *
221
+ * // Rate limiting (requests per second)
222
+ * const rateLimiter = createRateLimiter({ maxPerSecond: 10 });
223
+ *
224
+ * // Concurrency limiting (max concurrent)
225
+ * const concurrencyLimiter = createConcurrencyLimiter({ maxConcurrent: 5 });
226
+ *
227
+ * const result = await workflow(async ({ step }) => {
228
+ * // Wrap operations with rate limiting
229
+ * const data = await rateLimiter.execute(() =>
230
+ * step(() => callRateLimitedApi())
231
+ * );
232
+ *
233
+ * // Wrap batch operations with concurrency control
234
+ * const results = await concurrencyLimiter.executeAll(
235
+ * ids.map(id => () => step(() => fetchItem(id)))
236
+ * );
237
+ *
238
+ * return { data, results };
239
+ * });
240
+ * ```
241
+ */
242
+
243
+ /**
244
+ * Configuration for rate limiter.
245
+ */
246
+ interface RateLimiterConfig {
247
+ /**
248
+ * Maximum operations per second.
249
+ */
250
+ maxPerSecond: number;
251
+ /**
252
+ * Burst capacity - allows brief spikes above the rate.
253
+ * @default maxPerSecond * 2
254
+ */
255
+ burstCapacity?: number;
256
+ /**
257
+ * Strategy when rate limit is exceeded.
258
+ * - 'wait': Wait until a slot is available (default)
259
+ * - 'reject': Reject immediately with error
260
+ * @default 'wait'
261
+ */
262
+ strategy?: "wait" | "reject";
263
+ }
264
+ /**
265
+ * Configuration for concurrency limiter.
266
+ */
267
+ interface ConcurrencyLimiterConfig {
268
+ /**
269
+ * Maximum concurrent operations.
270
+ */
271
+ maxConcurrent: number;
272
+ /**
273
+ * Strategy when limit is reached.
274
+ * - 'queue': Queue and wait (default)
275
+ * - 'reject': Reject immediately
276
+ * @default 'queue'
277
+ */
278
+ strategy?: "queue" | "reject";
279
+ /**
280
+ * Maximum queue size (only for 'queue' strategy).
281
+ * @default Infinity
282
+ */
283
+ maxQueueSize?: number;
284
+ }
285
+ /**
286
+ * Error when rate/concurrency limit is exceeded and strategy is 'reject'.
287
+ */
288
+ interface RateLimitExceededError {
289
+ type: "RATE_LIMIT_EXCEEDED";
290
+ limiterName: string;
291
+ retryAfterMs?: number;
292
+ }
293
+ /**
294
+ * Error when concurrency limit queue is full.
295
+ */
296
+ interface QueueFullError {
297
+ type: "QUEUE_FULL";
298
+ limiterName: string;
299
+ queueSize: number;
300
+ maxQueueSize: number;
301
+ }
302
+ /**
303
+ * Type guard for RateLimitExceededError.
304
+ */
305
+ declare function isRateLimitExceededError(error: unknown): error is RateLimitExceededError;
306
+ /**
307
+ * Type guard for QueueFullError.
308
+ */
309
+ declare function isQueueFullError(error: unknown): error is QueueFullError;
310
+ /**
311
+ * Statistics for rate limiter.
312
+ */
313
+ interface RateLimiterStats {
314
+ availableTokens: number;
315
+ maxTokens: number;
316
+ tokensPerSecond: number;
317
+ waitingCount: number;
318
+ }
319
+ /**
320
+ * Statistics for concurrency limiter.
321
+ */
322
+ interface ConcurrencyLimiterStats {
323
+ activeCount: number;
324
+ maxConcurrent: number;
325
+ queueSize: number;
326
+ maxQueueSize: number;
327
+ }
328
+ /**
329
+ * Rate limiter interface.
330
+ */
331
+ interface RateLimiter {
332
+ /**
333
+ * Execute an operation with rate limiting.
334
+ * @param operation - The operation to execute
335
+ * @returns The operation result
336
+ */
337
+ execute<T>(operation: () => T | Promise<T>): Promise<T>;
338
+ /**
339
+ * Execute a Result-returning operation with rate limiting.
340
+ */
341
+ executeResult<T, E>(operation: () => Result<T, E> | AsyncResult<T, E>): AsyncResult<T, E | RateLimitExceededError>;
342
+ /**
343
+ * Get current statistics.
344
+ */
345
+ getStats(): RateLimiterStats;
346
+ /**
347
+ * Reset the rate limiter.
348
+ */
349
+ reset(): void;
350
+ }
351
+ /**
352
+ * Create a token bucket rate limiter.
353
+ *
354
+ * @param name - Name for the limiter (used in errors)
355
+ * @param config - Rate limiter configuration
356
+ * @returns A RateLimiter instance
357
+ *
358
+ * @example
359
+ * ```typescript
360
+ * const limiter = createRateLimiter('api-calls', {
361
+ * maxPerSecond: 10,
362
+ * burstCapacity: 20,
363
+ * });
364
+ *
365
+ * // In workflow
366
+ * const data = await limiter.execute(() =>
367
+ * step(() => callApi())
368
+ * );
369
+ * ```
370
+ */
371
+ declare function createRateLimiter(name: string, config: RateLimiterConfig): RateLimiter;
372
+ /**
373
+ * Concurrency limiter interface.
374
+ */
375
+ interface ConcurrencyLimiter {
376
+ /**
377
+ * Execute an operation with concurrency limiting.
378
+ * @param operation - The operation to execute
379
+ * @returns The operation result
380
+ */
381
+ execute<T>(operation: () => T | Promise<T>): Promise<T>;
382
+ /**
383
+ * Execute multiple operations with concurrency control.
384
+ * @param operations - Array of operation factories
385
+ * @returns Array of results (in order)
386
+ */
387
+ executeAll<T>(operations: Array<() => T | Promise<T>>): Promise<T[]>;
388
+ /**
389
+ * Execute a Result-returning operation with concurrency limiting.
390
+ */
391
+ executeResult<T, E>(operation: () => Result<T, E> | AsyncResult<T, E>): AsyncResult<T, E | QueueFullError>;
392
+ /**
393
+ * Get current statistics.
394
+ */
395
+ getStats(): ConcurrencyLimiterStats;
396
+ /**
397
+ * Reset the concurrency limiter.
398
+ */
399
+ reset(): void;
400
+ }
401
+ /**
402
+ * Create a concurrency limiter.
403
+ *
404
+ * @param name - Name for the limiter (used in errors)
405
+ * @param config - Concurrency limiter configuration
406
+ * @returns A ConcurrencyLimiter instance
407
+ *
408
+ * @example
409
+ * ```typescript
410
+ * const limiter = createConcurrencyLimiter('db-pool', {
411
+ * maxConcurrent: 10,
412
+ * });
413
+ *
414
+ * // Execute with concurrency control
415
+ * const results = await limiter.executeAll(
416
+ * ids.map(id => () => fetchItem(id))
417
+ * );
418
+ * ```
419
+ */
420
+ declare function createConcurrencyLimiter(name: string, config: ConcurrencyLimiterConfig): ConcurrencyLimiter;
421
+ /**
422
+ * Configuration for combined rate + concurrency limiter.
423
+ */
424
+ interface CombinedLimiterConfig {
425
+ /**
426
+ * Rate limiting configuration.
427
+ */
428
+ rate?: RateLimiterConfig;
429
+ /**
430
+ * Concurrency limiting configuration.
431
+ */
432
+ concurrency?: ConcurrencyLimiterConfig;
433
+ }
434
+ /**
435
+ * Create a combined rate + concurrency limiter.
436
+ *
437
+ * Operations are first rate-limited, then concurrency-limited.
438
+ *
439
+ * @param name - Name for the limiter
440
+ * @param config - Combined limiter configuration
441
+ * @returns An object with both limiters and a combined execute function
442
+ *
443
+ * @example
444
+ * ```typescript
445
+ * const limiter = createCombinedLimiter('api', {
446
+ * rate: { maxPerSecond: 10 },
447
+ * concurrency: { maxConcurrent: 5 },
448
+ * });
449
+ *
450
+ * const result = await limiter.execute(() => callApi());
451
+ * ```
452
+ */
453
+ declare function createCombinedLimiter(name: string, config: CombinedLimiterConfig): {
454
+ rate?: RateLimiter;
455
+ concurrency?: ConcurrencyLimiter;
456
+ execute: <T>(operation: () => T | Promise<T>) => Promise<T>;
457
+ };
458
+ /**
459
+ * Configuration for fixed window rate limiter.
460
+ */
461
+ interface FixedWindowLimiterConfig {
462
+ /**
463
+ * Maximum requests allowed per window.
464
+ */
465
+ limit: number;
466
+ /**
467
+ * Window duration in milliseconds.
468
+ * @default 1000 (1 second)
469
+ */
470
+ windowMs?: number;
471
+ /**
472
+ * Strategy when rate limit is exceeded.
473
+ * - 'wait': Wait until window resets (default)
474
+ * - 'reject': Reject immediately with error
475
+ * @default 'wait'
476
+ */
477
+ strategy?: "wait" | "reject";
478
+ }
479
+ /**
480
+ * Statistics for fixed window rate limiter.
481
+ */
482
+ interface FixedWindowLimiterStats {
483
+ /** Requests made in current window */
484
+ requestCount: number;
485
+ /** Maximum requests allowed per window */
486
+ limit: number;
487
+ /** Window duration in milliseconds */
488
+ windowMs: number;
489
+ /** Time remaining until window reset (ms) */
490
+ remainingMs: number;
491
+ /** Number of requests waiting for next window */
492
+ waitingCount: number;
493
+ }
494
+ /**
495
+ * Fixed window rate limiter interface.
496
+ */
497
+ interface FixedWindowLimiter {
498
+ /**
499
+ * Execute an operation with rate limiting.
500
+ * @param operation - The operation to execute
501
+ * @param cost - Optional cost for this operation (default: 1)
502
+ * @returns The operation result
503
+ */
504
+ execute<T>(operation: () => T | Promise<T>, cost?: number): Promise<T>;
505
+ /**
506
+ * Execute a Result-returning operation with rate limiting.
507
+ * @param operation - The operation to execute
508
+ * @param cost - Optional cost for this operation (default: 1)
509
+ */
510
+ executeResult<T, E>(operation: () => Result<T, E> | AsyncResult<T, E>, cost?: number): AsyncResult<T, E | RateLimitExceededError>;
511
+ /**
512
+ * Get current statistics.
513
+ */
514
+ getStats(): FixedWindowLimiterStats;
515
+ /**
516
+ * Reset the rate limiter.
517
+ */
518
+ reset(): void;
519
+ }
520
+ /**
521
+ * Create a fixed window rate limiter.
522
+ *
523
+ * Unlike token bucket, fixed window resets at fixed intervals.
524
+ * Simpler to reason about but can allow bursts at window boundaries.
525
+ *
526
+ * @param name - Name for the limiter (used in errors)
527
+ * @param config - Rate limiter configuration
528
+ * @returns A FixedWindowLimiter instance
529
+ *
530
+ * @example
531
+ * ```typescript
532
+ * const limiter = createFixedWindowLimiter('api-calls', {
533
+ * limit: 100, // 100 requests
534
+ * windowMs: 60000, // per minute
535
+ * });
536
+ *
537
+ * // In workflow
538
+ * const data = await limiter.execute(() => callApi());
539
+ *
540
+ * // Cost-based limiting (e.g., batch operations cost more)
541
+ * const batchData = await limiter.execute(() => callBatchApi(), 10);
542
+ * ```
543
+ */
544
+ declare function createFixedWindowLimiter(name: string, config: FixedWindowLimiterConfig): FixedWindowLimiter;
545
+ /**
546
+ * Configuration for cost-based rate limiter.
547
+ */
548
+ interface CostBasedRateLimiterConfig {
549
+ /**
550
+ * Maximum tokens (credits) per second refill rate.
551
+ */
552
+ tokensPerSecond: number;
553
+ /**
554
+ * Maximum token capacity (burst capacity).
555
+ * @default tokensPerSecond * 2
556
+ */
557
+ maxTokens?: number;
558
+ /**
559
+ * Strategy when rate limit is exceeded.
560
+ * - 'wait': Wait until tokens are available (default)
561
+ * - 'reject': Reject immediately with error
562
+ * @default 'wait'
563
+ */
564
+ strategy?: "wait" | "reject";
565
+ }
566
+ /**
567
+ * Statistics for cost-based rate limiter.
568
+ */
569
+ interface CostBasedRateLimiterStats {
570
+ /** Available tokens (can be fractional) */
571
+ availableTokens: number;
572
+ /** Maximum token capacity */
573
+ maxTokens: number;
574
+ /** Token refill rate per second */
575
+ tokensPerSecond: number;
576
+ /** Number of operations waiting */
577
+ waitingCount: number;
578
+ }
579
+ /**
580
+ * Cost-based rate limiter interface.
581
+ */
582
+ interface CostBasedRateLimiter {
583
+ /**
584
+ * Execute an operation with cost-based rate limiting.
585
+ * @param operation - The operation to execute
586
+ * @param cost - Token cost for this operation (default: 1)
587
+ * @returns The operation result
588
+ */
589
+ execute<T>(operation: () => T | Promise<T>, cost?: number): Promise<T>;
590
+ /**
591
+ * Execute a Result-returning operation with cost-based rate limiting.
592
+ * @param operation - The operation to execute
593
+ * @param cost - Token cost for this operation (default: 1)
594
+ */
595
+ executeResult<T, E>(operation: () => Result<T, E> | AsyncResult<T, E>, cost?: number): AsyncResult<T, E | RateLimitExceededError>;
596
+ /**
597
+ * Get current statistics.
598
+ */
599
+ getStats(): CostBasedRateLimiterStats;
600
+ /**
601
+ * Reset the rate limiter.
602
+ */
603
+ reset(): void;
604
+ }
605
+ /**
606
+ * Create a cost-based token bucket rate limiter.
607
+ *
608
+ * Different operations can have different costs, allowing fine-grained
609
+ * control over resource usage. For example, a batch API call might cost
610
+ * 10 tokens while a simple query costs 1.
611
+ *
612
+ * @param name - Name for the limiter (used in errors)
613
+ * @param config - Rate limiter configuration
614
+ * @returns A CostBasedRateLimiter instance
615
+ *
616
+ * @example
617
+ * ```typescript
618
+ * const limiter = createCostBasedRateLimiter('api', {
619
+ * tokensPerSecond: 100, // 100 tokens/second refill
620
+ * maxTokens: 200, // Can burst up to 200 tokens
621
+ * });
622
+ *
623
+ * // Simple query costs 1 token
624
+ * await limiter.execute(() => simpleQuery());
625
+ *
626
+ * // Batch operation costs 10 tokens
627
+ * await limiter.execute(() => batchOperation(), 10);
628
+ *
629
+ * // Heavy export costs 50 tokens
630
+ * await limiter.execute(() => exportData(), 50);
631
+ * ```
632
+ */
633
+ declare function createCostBasedRateLimiter(name: string, config: CostBasedRateLimiterConfig): CostBasedRateLimiter;
634
+ /**
635
+ * Preset configurations for common use cases.
636
+ */
637
+ declare const rateLimiterPresets: {
638
+ /**
639
+ * Typical API rate limit (10 req/s).
640
+ */
641
+ readonly api: {
642
+ maxPerSecond: number;
643
+ burstCapacity: number;
644
+ strategy: "wait";
645
+ };
646
+ /**
647
+ * Database pool limit (concurrent connections).
648
+ */
649
+ readonly database: {
650
+ maxConcurrent: number;
651
+ strategy: "queue";
652
+ maxQueueSize: number;
653
+ };
654
+ /**
655
+ * Aggressive rate limit for external APIs (5 req/s).
656
+ */
657
+ readonly external: {
658
+ maxPerSecond: number;
659
+ burstCapacity: number;
660
+ strategy: "wait";
661
+ };
662
+ };
663
+
664
+ /**
665
+ * awaitly/cache
666
+ *
667
+ * Caching utilities for memoization and deduplication.
668
+ * Inspired by Effect.js caching patterns.
669
+ *
670
+ * @example
671
+ * ```typescript
672
+ * import { cached, cachedWithTTL, cachedFunction, once } from 'awaitly';
673
+ *
674
+ * // Compute once, reuse forever
675
+ * const getConfig = cached(() => loadConfig());
676
+ *
677
+ * // Expire after duration
678
+ * const getUser = cachedWithTTL(() => fetchUser(id), { ttl: '5m' });
679
+ *
680
+ * // Memoize by arguments
681
+ * const fetchUserMemo = cachedFunction((id: string) => fetchUser(id));
682
+ *
683
+ * // Execute exactly once (for initialization)
684
+ * const initDb = once(() => connectToDatabase());
685
+ * ```
686
+ */
687
+
688
+ /**
689
+ * Duration input type - supports Duration objects or string shorthand.
690
+ */
691
+ type DurationInput = Duration | string;
692
+ /**
693
+ * Cache entry with metadata.
694
+ */
695
+ interface CacheEntry<T> {
696
+ value: T;
697
+ timestamp: number;
698
+ expiresAt?: number;
699
+ }
700
+ /**
701
+ * Cache options.
702
+ */
703
+ interface CacheOptions {
704
+ /**
705
+ * Time-to-live for cached values.
706
+ * Accepts Duration or string shorthand like "5m", "1h", "30s".
707
+ */
708
+ ttl?: DurationInput;
709
+ }
710
+ /**
711
+ * Cached function options.
712
+ */
713
+ interface CachedFunctionOptions<Args extends unknown[]> {
714
+ /**
715
+ * Custom key generator for arguments.
716
+ * Default: JSON.stringify(args)
717
+ */
718
+ keyFn?: (...args: Args) => string;
719
+ /**
720
+ * Time-to-live for cached values.
721
+ */
722
+ ttl?: DurationInput;
723
+ /**
724
+ * Maximum cache size. When exceeded, oldest entries are evicted.
725
+ * @default Infinity
726
+ */
727
+ maxSize?: number;
728
+ }
729
+ /**
730
+ * Cache statistics.
731
+ */
732
+ interface CacheStats {
733
+ hits: number;
734
+ misses: number;
735
+ size: number;
736
+ }
737
+ /**
738
+ * Create a cached computation that executes once and reuses the result.
739
+ *
740
+ * The function is called at most once, even with concurrent calls.
741
+ * Subsequent calls return the cached value immediately.
742
+ *
743
+ * @param fn - Function to compute the cached value
744
+ * @returns Function that returns the cached value
745
+ *
746
+ * @example
747
+ * ```typescript
748
+ * const getConfig = cached(async () => {
749
+ * console.log('Loading config...');
750
+ * return await loadConfigFromFile();
751
+ * });
752
+ *
753
+ * // First call executes the function
754
+ * const config1 = await getConfig(); // "Loading config..."
755
+ *
756
+ * // Subsequent calls return cached value
757
+ * const config2 = await getConfig(); // No log, instant return
758
+ * const config3 = await getConfig(); // No log, instant return
759
+ * ```
760
+ */
761
+ declare function cached<T>(fn: () => T | Promise<T>): () => Promise<T>;
762
+ /**
763
+ * Create a cached computation that expires after a duration.
764
+ *
765
+ * The function is re-executed when the TTL expires.
766
+ * Concurrent calls while computing share the same promise.
767
+ *
768
+ * @param fn - Function to compute the cached value
769
+ * @param options - Cache options including TTL
770
+ * @returns Function that returns the cached value
771
+ *
772
+ * @example
773
+ * ```typescript
774
+ * const getUser = cachedWithTTL(
775
+ * async () => await fetchUser(userId),
776
+ * { ttl: '5m' } // Cache for 5 minutes
777
+ * );
778
+ *
779
+ * const user1 = await getUser(); // Fetches from API
780
+ * const user2 = await getUser(); // Returns cached (within 5 min)
781
+ *
782
+ * // After 5 minutes...
783
+ * const user3 = await getUser(); // Fetches again
784
+ * ```
785
+ */
786
+ declare function cachedWithTTL<T>(fn: () => T | Promise<T>, options: {
787
+ ttl: DurationInput;
788
+ }): () => Promise<T>;
789
+ /**
790
+ * Memoized function interface.
791
+ */
792
+ interface MemoizedFunction<Args extends unknown[], T> {
793
+ (...args: Args): Promise<T>;
794
+ /** Clear the entire cache */
795
+ clear(): void;
796
+ /** Clear a specific cache entry */
797
+ delete(...args: Args): boolean;
798
+ /** Check if an entry exists */
799
+ has(...args: Args): boolean;
800
+ /** Get cache statistics */
801
+ getStats(): CacheStats;
802
+ }
803
+ /**
804
+ * Create a memoized function that caches results by arguments.
805
+ *
806
+ * Each unique set of arguments produces a cached result.
807
+ * Supports TTL and max size limits.
808
+ *
809
+ * @param fn - Function to memoize
810
+ * @param options - Memoization options
811
+ * @returns Memoized function with cache control methods
812
+ *
813
+ * @example
814
+ * ```typescript
815
+ * const fetchUserMemo = cachedFunction(
816
+ * async (id: string) => await fetchUser(id),
817
+ * { ttl: '5m', maxSize: 100 }
818
+ * );
819
+ *
820
+ * const user1 = await fetchUserMemo('user-1'); // Fetches
821
+ * const user2 = await fetchUserMemo('user-2'); // Fetches
822
+ * const user1Again = await fetchUserMemo('user-1'); // Cached!
823
+ *
824
+ * // Cache control
825
+ * fetchUserMemo.delete('user-1'); // Remove specific entry
826
+ * fetchUserMemo.clear(); // Clear all
827
+ * console.log(fetchUserMemo.getStats()); // { hits: 1, misses: 2, size: 0 }
828
+ * ```
829
+ */
830
+ declare function cachedFunction<Args extends unknown[], T>(fn: (...args: Args) => T | Promise<T>, options?: CachedFunctionOptions<Args>): MemoizedFunction<Args, T>;
831
+ /**
832
+ * Once-executed function interface.
833
+ */
834
+ interface OnceFunction<T> {
835
+ (): Promise<T>;
836
+ /** Check if the function has been called */
837
+ called: boolean;
838
+ /** Check if execution completed successfully */
839
+ completed: boolean;
840
+ /** Check if execution failed */
841
+ failed: boolean;
842
+ /** Reset to allow re-execution */
843
+ reset(): void;
844
+ }
845
+ /**
846
+ * Create a function that executes exactly once.
847
+ *
848
+ * Useful for initialization code that should only run once.
849
+ * Subsequent calls return the same result or re-throw the same error.
850
+ *
851
+ * @param fn - Function to execute once
852
+ * @returns Function that executes once and returns the result
853
+ *
854
+ * @example
855
+ * ```typescript
856
+ * const initDb = once(async () => {
857
+ * console.log('Connecting to database...');
858
+ * const conn = await createConnection();
859
+ * return conn;
860
+ * });
861
+ *
862
+ * // First call executes
863
+ * const db1 = await initDb(); // "Connecting to database..."
864
+ *
865
+ * // Subsequent calls return cached result
866
+ * const db2 = await initDb(); // Instant, same connection
867
+ * const db3 = await initDb(); // Instant, same connection
868
+ *
869
+ * console.log(initDb.called); // true
870
+ * console.log(initDb.completed); // true
871
+ * ```
872
+ */
873
+ declare function once<T>(fn: () => T | Promise<T>): OnceFunction<T>;
874
+ /**
875
+ * General purpose cache interface.
876
+ */
877
+ interface Cache<K, V> {
878
+ /** Get a value from the cache */
879
+ get(key: K): V | undefined;
880
+ /** Set a value in the cache */
881
+ set(key: K, value: V, options?: {
882
+ ttl?: DurationInput;
883
+ }): void;
884
+ /** Check if a key exists */
885
+ has(key: K): boolean;
886
+ /** Delete a key from the cache */
887
+ delete(key: K): boolean;
888
+ /** Clear the entire cache */
889
+ clear(): void;
890
+ /** Get the cache size */
891
+ size: number;
892
+ /** Get cache statistics */
893
+ getStats(): CacheStats;
894
+ }
895
+ /**
896
+ * Cache configuration.
897
+ */
898
+ interface CacheConfig {
899
+ /**
900
+ * Default TTL for all entries.
901
+ */
902
+ defaultTTL?: DurationInput;
903
+ /**
904
+ * Maximum cache size.
905
+ * @default Infinity
906
+ */
907
+ maxSize?: number;
908
+ }
909
+ /**
910
+ * Create a general-purpose cache with TTL and size limits.
911
+ *
912
+ * @param config - Cache configuration
913
+ * @returns A Cache instance
914
+ *
915
+ * @example
916
+ * ```typescript
917
+ * const cache = createCache<string, User>({
918
+ * defaultTTL: '5m',
919
+ * maxSize: 1000,
920
+ * });
921
+ *
922
+ * cache.set('user:1', user);
923
+ * cache.set('user:2', user2, { ttl: '1h' }); // Override TTL
924
+ *
925
+ * const user = cache.get('user:1');
926
+ * ```
927
+ */
928
+ declare function createCache<K, V>(config?: CacheConfig): Cache<K, V>;
929
+
930
+ /**
931
+ * awaitly/singleflight
932
+ *
933
+ * Request coalescing - dedupe concurrent identical requests.
934
+ * Multiple concurrent calls with the same key share one in-flight request.
935
+ *
936
+ * @example
937
+ * ```typescript
938
+ * import { singleflight } from 'awaitly';
939
+ *
940
+ * const fetchUserOnce = singleflight(
941
+ * (id: string) => fetchUser(id),
942
+ * { key: (id) => `user:${id}` }
943
+ * );
944
+ *
945
+ * // All concurrent calls share one request
946
+ * const [user1, user2] = await Promise.all([
947
+ * fetchUserOnce('1'),
948
+ * fetchUserOnce('1'), // Same key - shares request
949
+ * ]);
950
+ * ```
951
+ */
952
+
953
+ /**
954
+ * Options for the singleflight wrapper.
955
+ */
956
+ type SingleflightOptions<Args extends unknown[]> = {
957
+ /**
958
+ * Extract cache key from arguments.
959
+ * Calls with the same key will share one in-flight request.
960
+ */
961
+ key: (...args: Args) => string;
962
+ /**
963
+ * Optional TTL in milliseconds to cache successful results.
964
+ * After TTL expires, next call will trigger a fresh request.
965
+ * @default 0 (no caching after completion - only dedupes in-flight requests)
966
+ */
967
+ ttl?: number;
968
+ };
969
+ /**
970
+ * Create a singleflight-wrapped function.
971
+ * Concurrent calls with the same key share one in-flight request.
972
+ *
973
+ * ## How It Works
974
+ *
975
+ * 1. First caller with a key starts the operation
976
+ * 2. Subsequent callers with the same key get the same Promise
977
+ * 3. When operation completes, all callers receive the same Result
978
+ * 4. Key is removed from in-flight tracking (unless TTL is set)
979
+ *
980
+ * ## Use Cases
981
+ *
982
+ * - **Prevent thundering herd**: Multiple requests for the same user
983
+ * - **API deduplication**: Avoid duplicate network calls
984
+ * - **Expensive operations**: Share computation across callers
985
+ *
986
+ * @param operation - The async operation that returns an AsyncResult
987
+ * @param options - Configuration with key extraction function
988
+ * @returns A wrapped function that deduplicates concurrent calls
989
+ *
990
+ * @example
991
+ * ```typescript
992
+ * import { singleflight } from 'awaitly';
993
+ * import { ok, err, type AsyncResult } from 'awaitly';
994
+ *
995
+ * const fetchUser = async (id: string): AsyncResult<User, 'NOT_FOUND'> =>
996
+ * id !== '0' ? ok({ id, name: `User ${id}` }) : err('NOT_FOUND');
997
+ *
998
+ * const fetchUserOnce = singleflight(fetchUser, {
999
+ * key: (id) => `user:${id}`,
1000
+ * });
1001
+ *
1002
+ * // Concurrent calls share one request
1003
+ * const [a, b, c] = await Promise.all([
1004
+ * fetchUserOnce('1'), // Triggers fetch
1005
+ * fetchUserOnce('1'), // Joins existing fetch
1006
+ * fetchUserOnce('2'), // Different key - new fetch
1007
+ * ]);
1008
+ * ```
1009
+ *
1010
+ * @example
1011
+ * ```typescript
1012
+ * // With TTL for result caching
1013
+ * const fetchUserCached = singleflight(fetchUser, {
1014
+ * key: (id) => `user:${id}`,
1015
+ * ttl: 5000, // Cache successful results for 5 seconds
1016
+ * });
1017
+ *
1018
+ * const user1 = await fetchUserCached('1'); // Fetches
1019
+ * const user2 = await fetchUserCached('1'); // Returns cached (within TTL)
1020
+ * // After 5 seconds...
1021
+ * const user3 = await fetchUserCached('1'); // Fetches again
1022
+ * ```
1023
+ */
1024
+ declare function singleflight<Args extends unknown[], T, E, C = unknown>(operation: (...args: Args) => AsyncResult<T, E, C>, options: SingleflightOptions<Args>): (...args: Args) => AsyncResult<T, E, C>;
1025
+ /**
1026
+ * Create a singleflight group with manual key management.
1027
+ * More flexible but lower-level API than the `singleflight` wrapper.
1028
+ *
1029
+ * @returns A group object with execute, isInflight, and clear methods
1030
+ *
1031
+ * @example
1032
+ * ```typescript
1033
+ * import { createSingleflightGroup } from 'awaitly';
1034
+ *
1035
+ * const group = createSingleflightGroup<User, 'NOT_FOUND'>();
1036
+ *
1037
+ * // Execute with manual key
1038
+ * const user1 = await group.execute('user:1', () => fetchUser('1'));
1039
+ * const user2 = await group.execute('user:1', () => fetchUser('1')); // Shares request
1040
+ *
1041
+ * // Check if request is in-flight
1042
+ * if (group.isInflight('user:1')) {
1043
+ * console.log('Request pending');
1044
+ * }
1045
+ *
1046
+ * // Clear all in-flight requests
1047
+ * group.clear();
1048
+ * ```
1049
+ */
1050
+ declare function createSingleflightGroup<T, E, C = unknown>(): {
1051
+ /**
1052
+ * Execute or join an in-flight request for the given key.
1053
+ */
1054
+ execute: (key: string, operation: () => AsyncResult<T, E, C>) => AsyncResult<T, E, C>;
1055
+ /**
1056
+ * Check if a request is currently in-flight for the key.
1057
+ */
1058
+ isInflight: (key: string) => boolean;
1059
+ /**
1060
+ * Get the number of in-flight requests.
1061
+ */
1062
+ size: () => number;
1063
+ /**
1064
+ * Clear all in-flight tracking (does not cancel operations).
1065
+ */
1066
+ clear: () => void;
1067
+ };
1068
+
1069
+ /**
1070
+ * awaitly/policies
1071
+ *
1072
+ * Policy-Driven Step Middleware - Reusable bundles of StepOptions
1073
+ * that can be composed and applied per-workflow or per-step.
1074
+ */
1075
+
1076
+ /**
1077
+ * A policy is a partial StepOptions that can be merged with other policies.
1078
+ */
1079
+ type Policy = Partial<StepOptions>;
1080
+ /**
1081
+ * A policy factory that creates policies based on context.
1082
+ */
1083
+ type PolicyFactory<T = void> = T extends void ? () => Policy : (context: T) => Policy;
1084
+ /**
1085
+ * Named policy with metadata.
1086
+ */
1087
+ interface NamedPolicy {
1088
+ name: string;
1089
+ policy: Policy;
1090
+ description?: string;
1091
+ }
1092
+ /**
1093
+ * Merge multiple policies into a single StepOptions object.
1094
+ * Later policies override earlier ones for conflicting properties.
1095
+ * Retry and timeout options are deep-merged.
1096
+ *
1097
+ * @param policies - Policies to merge (in order of precedence)
1098
+ * @returns Merged StepOptions
1099
+ *
1100
+ * @example
1101
+ * ```typescript
1102
+ * const merged = mergePolicies(
1103
+ * timeoutPolicies.api, // timeout: 5000ms
1104
+ * retryPolicies.transient, // retry: 3 attempts
1105
+ * { name: 'fetch-user' } // name override
1106
+ * );
1107
+ * ```
1108
+ */
1109
+ declare function mergePolicies(...policies: Policy[]): StepOptions;
1110
+ /**
1111
+ * Create a policy applier that merges base policies with step-specific options.
1112
+ *
1113
+ * @param basePolicies - Base policies to apply to all steps
1114
+ * @returns A function that applies policies to step options
1115
+ *
1116
+ * @example
1117
+ * ```typescript
1118
+ * const applyPolicy = createPolicyApplier(
1119
+ * timeoutPolicies.api,
1120
+ * retryPolicies.transient
1121
+ * );
1122
+ *
1123
+ * // In workflow
1124
+ * const user = await step(
1125
+ * 'fetch-user',
1126
+ * () => fetchUser(id),
1127
+ * applyPolicy({ key: 'user:' + id })
1128
+ * );
1129
+ * ```
1130
+ */
1131
+ declare function createPolicyApplier(...basePolicies: Policy[]): (stepOptions?: StepOptions) => StepOptions;
1132
+ /**
1133
+ * Create a named policy bundle for reuse across workflows.
1134
+ *
1135
+ * @param name - Policy bundle name
1136
+ * @param policies - Policies to include in the bundle
1137
+ * @returns Named policy object
1138
+ */
1139
+ declare function createPolicyBundle(name: string, ...policies: Policy[]): NamedPolicy;
1140
+ /**
1141
+ * Create a retry policy with the given options.
1142
+ */
1143
+ declare function retryPolicy(options: RetryOptions): Policy;
1144
+ /**
1145
+ * Pre-built retry policies for common scenarios.
1146
+ */
1147
+ declare const retryPolicies: {
1148
+ /**
1149
+ * No retry - fail immediately on error.
1150
+ */
1151
+ readonly none: Partial<StepOptions>;
1152
+ /**
1153
+ * Quick retry for transient errors (3 attempts, fast backoff).
1154
+ */
1155
+ readonly transient: Partial<StepOptions>;
1156
+ /**
1157
+ * Standard retry for API calls (3 attempts, moderate backoff).
1158
+ */
1159
+ readonly standard: Partial<StepOptions>;
1160
+ /**
1161
+ * Aggressive retry for critical operations (5 attempts, longer backoff).
1162
+ */
1163
+ readonly aggressive: Partial<StepOptions>;
1164
+ /**
1165
+ * Fixed interval retry (useful for polling).
1166
+ */
1167
+ readonly fixed: (attempts: number, delayMs: number) => Policy;
1168
+ /**
1169
+ * Linear backoff retry.
1170
+ */
1171
+ readonly linear: (attempts: number, initialDelay: number) => Policy;
1172
+ /**
1173
+ * Custom retry policy builder.
1174
+ */
1175
+ readonly custom: (options: Partial<RetryOptions> & {
1176
+ attempts: number;
1177
+ }) => Policy;
1178
+ };
1179
+ /**
1180
+ * Create a timeout policy with the given options.
1181
+ */
1182
+ declare function timeoutPolicy(options: TimeoutOptions): Policy;
1183
+ /**
1184
+ * Pre-built timeout policies for common scenarios.
1185
+ */
1186
+ declare const timeoutPolicies: {
1187
+ /**
1188
+ * No timeout.
1189
+ */
1190
+ readonly none: Policy;
1191
+ /**
1192
+ * Fast timeout for quick operations (1 second).
1193
+ */
1194
+ readonly fast: Partial<StepOptions>;
1195
+ /**
1196
+ * Standard API timeout (5 seconds).
1197
+ */
1198
+ readonly api: Partial<StepOptions>;
1199
+ /**
1200
+ * Extended timeout for slower operations (30 seconds).
1201
+ */
1202
+ readonly extended: Partial<StepOptions>;
1203
+ /**
1204
+ * Long timeout for batch operations (2 minutes).
1205
+ */
1206
+ readonly long: Partial<StepOptions>;
1207
+ /**
1208
+ * Custom timeout in milliseconds.
1209
+ */
1210
+ readonly ms: (ms: number) => Policy;
1211
+ /**
1212
+ * Custom timeout in seconds.
1213
+ */
1214
+ readonly seconds: (seconds: number) => Policy;
1215
+ /**
1216
+ * Timeout with custom error.
1217
+ */
1218
+ readonly withError: <E>(ms: number, error: E) => Policy;
1219
+ /**
1220
+ * Timeout with AbortSignal support.
1221
+ */
1222
+ readonly withSignal: (ms: number) => Policy;
1223
+ };
1224
+ /**
1225
+ * Pre-built combined policies for common service patterns.
1226
+ */
1227
+ declare const servicePolicies: {
1228
+ /**
1229
+ * Policy for external HTTP APIs.
1230
+ * - 5 second timeout
1231
+ * - 3 retries with exponential backoff
1232
+ */
1233
+ readonly httpApi: StepOptions;
1234
+ /**
1235
+ * Policy for database operations.
1236
+ * - 30 second timeout
1237
+ * - 2 retries for transient errors
1238
+ */
1239
+ readonly database: StepOptions;
1240
+ /**
1241
+ * Policy for cache operations.
1242
+ * - 1 second timeout
1243
+ * - No retry (cache misses are not errors)
1244
+ */
1245
+ readonly cache: StepOptions;
1246
+ /**
1247
+ * Policy for message queue operations.
1248
+ * - 30 second timeout
1249
+ * - 5 retries with longer backoff
1250
+ */
1251
+ readonly messageQueue: StepOptions;
1252
+ /**
1253
+ * Policy for file operations.
1254
+ * - 2 minute timeout
1255
+ * - 3 retries
1256
+ */
1257
+ readonly fileSystem: StepOptions;
1258
+ /**
1259
+ * Policy for third-party services with rate limits.
1260
+ * - 10 second timeout
1261
+ * - 5 retries with linear backoff
1262
+ */
1263
+ readonly rateLimited: StepOptions;
1264
+ };
1265
+ /**
1266
+ * Options for withPolicies workflow wrapper.
1267
+ */
1268
+ interface WithPoliciesOptions {
1269
+ /**
1270
+ * Base policies applied to all steps.
1271
+ */
1272
+ policies: Policy[];
1273
+ /**
1274
+ * Step-specific policy overrides by name or key pattern.
1275
+ */
1276
+ overrides?: Record<string, Policy>;
1277
+ }
1278
+ /**
1279
+ * Create step options with policies applied.
1280
+ * This is a helper for applying policies inline.
1281
+ *
1282
+ * @param policies - Policies to apply
1283
+ * @param stepOptions - Step-specific options
1284
+ * @returns Merged StepOptions
1285
+ *
1286
+ * @example
1287
+ * ```typescript
1288
+ * const user = await step(
1289
+ * () => fetchUser(id),
1290
+ * withPolicy(servicePolicies.httpApi, { name: 'fetch-user' })
1291
+ * );
1292
+ * ```
1293
+ */
1294
+ declare function withPolicy(policy: Policy, stepOptions?: StepOptions): StepOptions;
1295
+ /**
1296
+ * Create step options with multiple policies applied.
1297
+ *
1298
+ * @param policies - Policies to apply (in order)
1299
+ * @param stepOptions - Step-specific options
1300
+ * @returns Merged StepOptions
1301
+ *
1302
+ * @example
1303
+ * ```typescript
1304
+ * const user = await step(
1305
+ * 'fetch-user',
1306
+ * () => fetchUser(id),
1307
+ * withPolicies([timeoutPolicies.api, retryPolicies.standard])
1308
+ * );
1309
+ * ```
1310
+ */
1311
+ declare function withPolicies(policies: Policy[], stepOptions?: StepOptions): StepOptions;
1312
+ /**
1313
+ * Create a policy that applies conditionally.
1314
+ *
1315
+ * @param condition - Condition to check
1316
+ * @param policy - Policy to apply if condition is true
1317
+ * @param elsePolicy - Policy to apply if condition is false (optional)
1318
+ * @returns The selected policy
1319
+ *
1320
+ * @example
1321
+ * ```typescript
1322
+ * const policy = conditionalPolicy(
1323
+ * isProduction,
1324
+ * servicePolicies.httpApi, // Use in production
1325
+ * retryPolicies.none // Skip in development
1326
+ * );
1327
+ * ```
1328
+ */
1329
+ declare function conditionalPolicy(condition: boolean, policy: Policy, elsePolicy?: Policy): Policy;
1330
+ /**
1331
+ * Create a policy based on environment.
1332
+ *
1333
+ * @param envPolicies - Map of environment names to policies
1334
+ * @param currentEnv - Current environment (defaults to NODE_ENV)
1335
+ * @param defaultPolicy - Default policy if environment not found
1336
+ * @returns The selected policy
1337
+ *
1338
+ * @example
1339
+ * ```typescript
1340
+ * const policy = envPolicy({
1341
+ * production: servicePolicies.httpApi,
1342
+ * development: retryPolicies.none,
1343
+ * test: retryPolicies.none,
1344
+ * });
1345
+ * ```
1346
+ */
1347
+ declare function envPolicy(envPolicies: Record<string, Policy>, currentEnv?: string, defaultPolicy?: Policy): Policy;
1348
+ /**
1349
+ * A registry for managing named policies.
1350
+ */
1351
+ interface PolicyRegistry {
1352
+ /**
1353
+ * Register a named policy.
1354
+ */
1355
+ register(name: string, policy: Policy): void;
1356
+ /**
1357
+ * Get a policy by name.
1358
+ */
1359
+ get(name: string): Policy | undefined;
1360
+ /**
1361
+ * Check if a policy exists.
1362
+ */
1363
+ has(name: string): boolean;
1364
+ /**
1365
+ * Get all registered policy names.
1366
+ */
1367
+ names(): string[];
1368
+ /**
1369
+ * Create step options using a registered policy.
1370
+ */
1371
+ apply(policyName: string, stepOptions?: StepOptions): StepOptions;
1372
+ }
1373
+ /**
1374
+ * Create a policy registry for managing named policies.
1375
+ *
1376
+ * @returns PolicyRegistry instance
1377
+ *
1378
+ * @example
1379
+ * ```typescript
1380
+ * const registry = createPolicyRegistry();
1381
+ *
1382
+ * // Register policies
1383
+ * registry.register('api', servicePolicies.httpApi);
1384
+ * registry.register('db', servicePolicies.database);
1385
+ *
1386
+ * // Use in workflow
1387
+ * const user = await step(
1388
+ * 'fetch-user',
1389
+ * () => fetchUser(id),
1390
+ * registry.apply('api')
1391
+ * );
1392
+ * ```
1393
+ */
1394
+ declare function createPolicyRegistry(): PolicyRegistry;
1395
+ /**
1396
+ * Fluent builder for constructing step options.
1397
+ */
1398
+ interface StepOptionsBuilder {
1399
+ /**
1400
+ * Set step key for caching.
1401
+ */
1402
+ key(key: string): StepOptionsBuilder;
1403
+ /**
1404
+ * Apply a policy.
1405
+ */
1406
+ policy(policy: Policy): StepOptionsBuilder;
1407
+ /**
1408
+ * Set timeout in milliseconds.
1409
+ */
1410
+ timeout(ms: number): StepOptionsBuilder;
1411
+ /**
1412
+ * Set retry options.
1413
+ */
1414
+ retry(options: RetryOptions): StepOptionsBuilder;
1415
+ /**
1416
+ * Set retry attempts (with default exponential backoff).
1417
+ */
1418
+ retries(attempts: number): StepOptionsBuilder;
1419
+ /**
1420
+ * Build the final StepOptions.
1421
+ */
1422
+ build(): StepOptions;
1423
+ }
1424
+ /**
1425
+ * Create a fluent builder for step options.
1426
+ *
1427
+ * @returns StepOptionsBuilder instance
1428
+ *
1429
+ * @example
1430
+ * ```typescript
1431
+ * const options = stepOptions()
1432
+ * .key('user:123')
1433
+ * .timeout(5000)
1434
+ * .retries(3)
1435
+ * .build();
1436
+ *
1437
+ * const user = await step('fetch-user', () => fetchUser(id), options);
1438
+ * ```
1439
+ */
1440
+ declare function stepOptions(): StepOptionsBuilder;
1441
+
1442
+ export { type Cache, type CacheConfig, type CacheEntry, type CacheOptions, type CacheStats, type CachedFunctionOptions, type CircuitBreaker, type CircuitBreakerConfig, type CircuitBreakerStats, CircuitOpenError, type CircuitState, type CombinedLimiterConfig, type ConcurrencyLimiter, type ConcurrencyLimiterConfig, type ConcurrencyLimiterStats, type CostBasedRateLimiter, type CostBasedRateLimiterConfig, type CostBasedRateLimiterStats, type DurationInput, type FixedWindowLimiter, type FixedWindowLimiterConfig, type FixedWindowLimiterStats, type MemoizedFunction, type NamedPolicy, type OnceFunction, type Policy, type PolicyFactory, type PolicyRegistry, type QueueFullError, type RateLimitExceededError, type RateLimiter, type RateLimiterConfig, type RateLimiterStats, type SingleflightOptions, type StepOptionsBuilder, type WithPoliciesOptions, cached, cachedFunction, cachedWithTTL, circuitBreakerPresets, conditionalPolicy, createCache, createCircuitBreaker, createCombinedLimiter, createConcurrencyLimiter, createCostBasedRateLimiter, createFixedWindowLimiter, createPolicyApplier, createPolicyBundle, createPolicyRegistry, createRateLimiter, createSingleflightGroup, envPolicy, isCircuitOpenError, isQueueFullError, isRateLimitExceededError, mergePolicies, once, rateLimiterPresets, retryPolicies, retryPolicy, servicePolicies, singleflight, stepOptions, timeoutPolicies, timeoutPolicy, withPolicies, withPolicy };