flowshield 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +30 -0
- package/LICENSE +21 -0
- package/README.md +272 -0
- package/dist/cjs/compose.js +53 -0
- package/dist/cjs/compose.js.map +1 -0
- package/dist/cjs/index.js +32 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/policies/bulkhead.js +75 -0
- package/dist/cjs/policies/bulkhead.js.map +1 -0
- package/dist/cjs/policies/cache.js +99 -0
- package/dist/cjs/policies/cache.js.map +1 -0
- package/dist/cjs/policies/circuit-breaker.js +110 -0
- package/dist/cjs/policies/circuit-breaker.js.map +1 -0
- package/dist/cjs/policies/fallback.js +33 -0
- package/dist/cjs/policies/fallback.js.map +1 -0
- package/dist/cjs/policies/hedge.js +74 -0
- package/dist/cjs/policies/hedge.js.map +1 -0
- package/dist/cjs/policies/rate-limiter.js +92 -0
- package/dist/cjs/policies/rate-limiter.js.map +1 -0
- package/dist/cjs/policies/retry.js +61 -0
- package/dist/cjs/policies/retry.js.map +1 -0
- package/dist/cjs/policies/timeout.js +45 -0
- package/dist/cjs/policies/timeout.js.map +1 -0
- package/dist/cjs/types.js +55 -0
- package/dist/cjs/types.js.map +1 -0
- package/dist/cjs/utils.js +84 -0
- package/dist/cjs/utils.js.map +1 -0
- package/dist/esm/compose.js +49 -0
- package/dist/esm/compose.js.map +1 -0
- package/dist/esm/index.js +13 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/policies/bulkhead.js +72 -0
- package/dist/esm/policies/bulkhead.js.map +1 -0
- package/dist/esm/policies/cache.js +96 -0
- package/dist/esm/policies/cache.js.map +1 -0
- package/dist/esm/policies/circuit-breaker.js +107 -0
- package/dist/esm/policies/circuit-breaker.js.map +1 -0
- package/dist/esm/policies/fallback.js +30 -0
- package/dist/esm/policies/fallback.js.map +1 -0
- package/dist/esm/policies/hedge.js +71 -0
- package/dist/esm/policies/hedge.js.map +1 -0
- package/dist/esm/policies/rate-limiter.js +89 -0
- package/dist/esm/policies/rate-limiter.js.map +1 -0
- package/dist/esm/policies/retry.js +58 -0
- package/dist/esm/policies/retry.js.map +1 -0
- package/dist/esm/policies/timeout.js +42 -0
- package/dist/esm/policies/timeout.js.map +1 -0
- package/dist/esm/types.js +46 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/esm/utils.js +77 -0
- package/dist/esm/utils.js.map +1 -0
- package/dist/types/compose.d.ts +32 -0
- package/dist/types/compose.d.ts.map +1 -0
- package/dist/types/index.d.ts +12 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/policies/bulkhead.d.ts +20 -0
- package/dist/types/policies/bulkhead.d.ts.map +1 -0
- package/dist/types/policies/cache.d.ts +19 -0
- package/dist/types/policies/cache.d.ts.map +1 -0
- package/dist/types/policies/circuit-breaker.d.ts +19 -0
- package/dist/types/policies/circuit-breaker.d.ts.map +1 -0
- package/dist/types/policies/fallback.d.ts +14 -0
- package/dist/types/policies/fallback.d.ts.map +1 -0
- package/dist/types/policies/hedge.d.ts +15 -0
- package/dist/types/policies/hedge.d.ts.map +1 -0
- package/dist/types/policies/rate-limiter.d.ts +19 -0
- package/dist/types/policies/rate-limiter.d.ts.map +1 -0
- package/dist/types/policies/retry.d.ts +14 -0
- package/dist/types/policies/retry.d.ts.map +1 -0
- package/dist/types/policies/timeout.d.ts +15 -0
- package/dist/types/policies/timeout.d.ts.map +1 -0
- package/dist/types/types.d.ts +133 -0
- package/dist/types/types.d.ts.map +1 -0
- package/dist/types/utils.d.ts +21 -0
- package/dist/types/utils.d.ts.map +1 -0
- package/package.json +80 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// ─── Core Types ─────────────────────────────────────────────────────────────
|
|
2
|
+
// ─── Errors ─────────────────────────────────────────────────────────────────
|
|
3
|
+
export class FlowShieldError extends Error {
|
|
4
|
+
constructor(message, cause) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.name = 'FlowShieldError';
|
|
7
|
+
// Fix prototype chain for instanceof checks
|
|
8
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
9
|
+
if (cause !== undefined) {
|
|
10
|
+
this.cause = cause;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export class TimeoutError extends FlowShieldError {
|
|
15
|
+
constructor(ms) {
|
|
16
|
+
super(`Operation timed out after ${ms}ms`);
|
|
17
|
+
this.name = 'TimeoutError';
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export class CircuitOpenError extends FlowShieldError {
|
|
21
|
+
constructor() {
|
|
22
|
+
super('Circuit breaker is open — request rejected');
|
|
23
|
+
this.name = 'CircuitOpenError';
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export class BulkheadRejectedError extends FlowShieldError {
|
|
27
|
+
constructor() {
|
|
28
|
+
super('Bulkhead capacity exceeded — request rejected');
|
|
29
|
+
this.name = 'BulkheadRejectedError';
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export class RateLimitExceededError extends FlowShieldError {
|
|
33
|
+
constructor() {
|
|
34
|
+
super('Rate limit exceeded — request rejected');
|
|
35
|
+
this.name = 'RateLimitExceededError';
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export class RetryExhaustedError extends FlowShieldError {
|
|
39
|
+
attempts;
|
|
40
|
+
constructor(attempts, lastError) {
|
|
41
|
+
super(`All ${attempts} retry attempts exhausted`, lastError);
|
|
42
|
+
this.name = 'RetryExhaustedError';
|
|
43
|
+
this.attempts = attempts;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAkJ/E,+EAA+E;AAE/E,MAAM,OAAO,eAAgB,SAAQ,KAAK;IACxC,YAAY,OAAe,EAAE,KAAe;QAC1C,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;QAC9B,4CAA4C;QAC5C,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAClD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACvB,IAA4B,CAAC,KAAK,GAAG,KAAK,CAAC;QAC9C,CAAC;IACH,CAAC;CACF;AAED,MAAM,OAAO,YAAa,SAAQ,eAAe;IAC/C,YAAY,EAAU;QACpB,KAAK,CAAC,6BAA6B,EAAE,IAAI,CAAC,CAAC;QAC3C,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;IAC7B,CAAC;CACF;AAED,MAAM,OAAO,gBAAiB,SAAQ,eAAe;IACnD;QACE,KAAK,CAAC,4CAA4C,CAAC,CAAC;QACpD,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;IACjC,CAAC;CACF;AAED,MAAM,OAAO,qBAAsB,SAAQ,eAAe;IACxD;QACE,KAAK,CAAC,+CAA+C,CAAC,CAAC;QACvD,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IACtC,CAAC;CACF;AAED,MAAM,OAAO,sBAAuB,SAAQ,eAAe;IACzD;QACE,KAAK,CAAC,wCAAwC,CAAC,CAAC;QAChD,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;IACvC,CAAC;CACF;AAED,MAAM,OAAO,mBAAoB,SAAQ,eAAe;IACtC,QAAQ,CAAS;IACjC,YAAY,QAAgB,EAAE,SAAkB;QAC9C,KAAK,CAAC,OAAO,QAAQ,2BAA2B,EAAE,SAAS,CAAC,CAAC;QAC7D,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;QAClC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;CACF"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sleep for `ms` milliseconds. Supports cooperative cancellation via AbortSignal.
|
|
3
|
+
*/
|
|
4
|
+
export function sleep(ms, signal) {
|
|
5
|
+
return new Promise((resolve, reject) => {
|
|
6
|
+
if (signal?.aborted) {
|
|
7
|
+
reject(signal.reason);
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
let done = false;
|
|
11
|
+
const timer = setTimeout(() => {
|
|
12
|
+
done = true;
|
|
13
|
+
if (signal) {
|
|
14
|
+
signal.removeEventListener('abort', onAbort);
|
|
15
|
+
}
|
|
16
|
+
resolve();
|
|
17
|
+
}, ms);
|
|
18
|
+
const onAbort = () => {
|
|
19
|
+
if (!done) {
|
|
20
|
+
done = true;
|
|
21
|
+
clearTimeout(timer);
|
|
22
|
+
reject(signal.reason);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
if (signal) {
|
|
26
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Calculate the delay for a given attempt using the specified backoff strategy.
|
|
32
|
+
*/
|
|
33
|
+
export function calculateDelay(attempt, baseDelay, strategy, maxDelay, previousDelay) {
|
|
34
|
+
let delay;
|
|
35
|
+
switch (strategy) {
|
|
36
|
+
case 'constant':
|
|
37
|
+
delay = baseDelay;
|
|
38
|
+
break;
|
|
39
|
+
case 'linear':
|
|
40
|
+
delay = baseDelay * attempt;
|
|
41
|
+
break;
|
|
42
|
+
case 'exponential':
|
|
43
|
+
delay = baseDelay * Math.pow(2, attempt - 1);
|
|
44
|
+
break;
|
|
45
|
+
case 'decorrelatedJitter': {
|
|
46
|
+
const prev = previousDelay ?? baseDelay;
|
|
47
|
+
delay = Math.random() * (prev * 3 - baseDelay) + baseDelay;
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return Math.min(delay, maxDelay);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Validate that a number is a positive integer.
|
|
55
|
+
*/
|
|
56
|
+
export function assertPositiveInteger(value, name) {
|
|
57
|
+
if (!Number.isFinite(value) || value < 1 || Math.floor(value) !== value) {
|
|
58
|
+
throw new RangeError(`${name} must be a positive integer, got ${value}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Validate that a number is a positive finite number.
|
|
63
|
+
*/
|
|
64
|
+
export function assertPositive(value, name) {
|
|
65
|
+
if (!Number.isFinite(value) || value <= 0) {
|
|
66
|
+
throw new RangeError(`${name} must be a positive number, got ${value}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Validate that a number is a non-negative finite number.
|
|
71
|
+
*/
|
|
72
|
+
export function assertNonNegative(value, name) {
|
|
73
|
+
if (!Number.isFinite(value) || value < 0) {
|
|
74
|
+
throw new RangeError(`${name} must be a non-negative number, got ${value}`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,UAAU,KAAK,CAAC,EAAU,EAAE,MAAoB;IACpD,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC3C,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;YACpB,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACtB,OAAO;QACT,CAAC;QAED,IAAI,IAAI,GAAG,KAAK,CAAC;QAEjB,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,IAAI,GAAG,IAAI,CAAC;YACZ,IAAI,MAAM,EAAE,CAAC;gBACX,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC/C,CAAC;YACD,OAAO,EAAE,CAAC;QACZ,CAAC,EAAE,EAAE,CAAC,CAAC;QAEP,MAAM,OAAO,GAAG,GAAG,EAAE;YACnB,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,IAAI,GAAG,IAAI,CAAC;gBACZ,YAAY,CAAC,KAAK,CAAC,CAAC;gBACpB,MAAM,CAAC,MAAO,CAAC,MAAM,CAAC,CAAC;YACzB,CAAC;QACH,CAAC,CAAC;QAEF,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAC5B,OAAe,EACf,SAAiB,EACjB,QAAsE,EACtE,QAAgB,EAChB,aAAsB;IAEtB,IAAI,KAAa,CAAC;IAElB,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,UAAU;YACb,KAAK,GAAG,SAAS,CAAC;YAClB,MAAM;QACR,KAAK,QAAQ;YACX,KAAK,GAAG,SAAS,GAAG,OAAO,CAAC;YAC5B,MAAM;QACR,KAAK,aAAa;YAChB,KAAK,GAAG,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC;YAC7C,MAAM;QACR,KAAK,oBAAoB,CAAC,CAAC,CAAC;YAC1B,MAAM,IAAI,GAAG,aAAa,IAAI,SAAS,CAAC;YACxC,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,GAAG,CAAC,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC;YAC3D,MAAM;QACR,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;AACnC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAAa,EAAE,IAAY;IAC/D,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,KAAK,EAAE,CAAC;QACxE,MAAM,IAAI,UAAU,CAAC,GAAG,IAAI,oCAAoC,KAAK,EAAE,CAAC,CAAC;IAC3E,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,KAAa,EAAE,IAAY;IACxD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;QAC1C,MAAM,IAAI,UAAU,CAAC,GAAG,IAAI,mCAAmC,KAAK,EAAE,CAAC,CAAC;IAC1E,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAa,EAAE,IAAY;IAC3D,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACzC,MAAM,IAAI,UAAU,CAAC,GAAG,IAAI,uCAAuC,KAAK,EAAE,CAAC,CAAC;IAC9E,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Policy } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Composes multiple policies into a single policy.
|
|
4
|
+
* Policies are applied **left-to-right** (outermost first).
|
|
5
|
+
*
|
|
6
|
+
* `pipe(a, b, c)(fn)` is equivalent to `a(()=> b(()=> c(fn)))`.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* const resilient = pipe(
|
|
11
|
+
* timeout({ ms: 5000 }),
|
|
12
|
+
* retry({ maxAttempts: 3 }),
|
|
13
|
+
* );
|
|
14
|
+
* const result = await resilient(() => fetch('/api'));
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export declare function pipe(...policies: Policy[]): Policy;
|
|
18
|
+
/**
|
|
19
|
+
* Wraps an inner policy with an outer policy.
|
|
20
|
+
* `wrap(outer, inner)(fn)` is equivalent to `outer(() => inner(fn))`.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* const policy = wrap(
|
|
25
|
+
* timeout({ ms: 5000 }),
|
|
26
|
+
* retry({ maxAttempts: 3 }),
|
|
27
|
+
* );
|
|
28
|
+
* const result = await policy(() => fetch('/api'));
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export declare function wrap(outer: Policy, inner: Policy): Policy;
|
|
32
|
+
//# sourceMappingURL=compose.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compose.d.ts","sourceRoot":"","sources":["../../src/compose.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,IAAI,CAAC,GAAG,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAiBlD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAIzD"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { retry } from './policies/retry.js';
|
|
2
|
+
export { circuitBreaker } from './policies/circuit-breaker.js';
|
|
3
|
+
export { timeout } from './policies/timeout.js';
|
|
4
|
+
export { bulkhead } from './policies/bulkhead.js';
|
|
5
|
+
export { fallback } from './policies/fallback.js';
|
|
6
|
+
export { rateLimiter } from './policies/rate-limiter.js';
|
|
7
|
+
export { hedge } from './policies/hedge.js';
|
|
8
|
+
export { cache } from './policies/cache.js';
|
|
9
|
+
export { pipe, wrap } from './compose.js';
|
|
10
|
+
export type { Policy, RetryOptions, BackoffStrategy, CircuitBreakerOptions, CircuitBreakerHandle, CircuitState, TimeoutOptions, BulkheadOptions, BulkheadHandle, FallbackOptions, RateLimiterOptions, RateLimiterHandle, HedgeOptions, CacheOptions, CacheHandle, } from './types.js';
|
|
11
|
+
export { FlowShieldError, TimeoutError, CircuitOpenError, BulkheadRejectedError, RateLimitExceededError, RetryExhaustedError, } from './types.js';
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAC5C,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAG5C,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAG1C,YAAY,EACV,MAAM,EACN,YAAY,EACZ,eAAe,EACf,qBAAqB,EACrB,oBAAoB,EACpB,YAAY,EACZ,cAAc,EACd,eAAe,EACf,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,WAAW,GACZ,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,qBAAqB,EACrB,sBAAsB,EACtB,mBAAmB,GACpB,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { BulkheadOptions, BulkheadHandle } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Creates a bulkhead (concurrency limiter) policy that limits the number
|
|
4
|
+
* of concurrent executions of the wrapped operation.
|
|
5
|
+
*
|
|
6
|
+
* Returns an object with `execute` (the policy function) and `handle`
|
|
7
|
+
* (an interface to inspect the bulkhead's running / queued counts).
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* const bh = bulkhead({ maxConcurrent: 5, maxQueue: 10 });
|
|
12
|
+
* const result = await bh.execute(() => fetch('/api/data'));
|
|
13
|
+
* console.log(bh.handle.running); // number of active calls
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export declare function bulkhead(options?: BulkheadOptions): {
|
|
17
|
+
execute: <T>(fn: () => Promise<T>) => Promise<T>;
|
|
18
|
+
handle: BulkheadHandle;
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=bulkhead.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bulkhead.d.ts","sourceRoot":"","sources":["../../../src/policies/bulkhead.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAenE;;;;;;;;;;;;;GAaG;AACH,wBAAgB,QAAQ,CAAC,OAAO,GAAE,eAAoB,GAAG;IACvD,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IACjD,MAAM,EAAE,cAAc,CAAC;CACxB,CA8DA"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { CacheOptions, CacheHandle } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Creates a TTL-based cache policy that memoizes the result of the wrapped
|
|
4
|
+
* async operation. Supports stale-while-revalidate for background refresh.
|
|
5
|
+
*
|
|
6
|
+
* Returns an object with `execute` (the policy function) and `handle`
|
|
7
|
+
* (an interface to inspect / invalidate the cache).
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* const c = cache({ ttl: 10_000 });
|
|
12
|
+
* const result = await c.execute(() => fetch('/api/data').then(r => r.json()));
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export declare function cache<V = unknown>(options?: CacheOptions<V>): {
|
|
16
|
+
execute: <T extends V>(fn: () => Promise<T>) => Promise<T>;
|
|
17
|
+
handle: CacheHandle;
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../src/policies/cache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAc7D;;;;;;;;;;;;GAYG;AACH,wBAAgB,KAAK,CAAC,CAAC,GAAG,OAAO,EAAE,OAAO,GAAE,YAAY,CAAC,CAAC,CAAM,GAAG;IACjE,OAAO,EAAE,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IAC3D,MAAM,EAAE,WAAW,CAAC;CACrB,CAqFA"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { CircuitBreakerOptions, CircuitBreakerHandle } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Creates a circuit breaker policy that prevents calls to a failing service.
|
|
4
|
+
*
|
|
5
|
+
* Returns an object with `execute` (the policy function) and `handle`
|
|
6
|
+
* (an interface to inspect / reset the breaker state).
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* const cb = circuitBreaker({ failureThreshold: 3, resetTimeout: 10_000 });
|
|
11
|
+
* const result = await cb.execute(() => fetch('/api/health'));
|
|
12
|
+
* console.log(cb.handle.state); // 'closed'
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export declare function circuitBreaker(options?: CircuitBreakerOptions): {
|
|
16
|
+
execute: <T>(fn: () => Promise<T>) => Promise<T>;
|
|
17
|
+
handle: CircuitBreakerHandle;
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=circuit-breaker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"circuit-breaker.d.ts","sourceRoot":"","sources":["../../../src/policies/circuit-breaker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,oBAAoB,EAAgB,MAAM,aAAa,CAAC;AAU7F;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,OAAO,GAAE,qBAA0B,GAAG;IACnE,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IACjD,MAAM,EAAE,oBAAoB,CAAC;CAC9B,CA+FA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { FallbackOptions } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Creates a fallback policy that returns a fallback value (or the result
|
|
4
|
+
* of a fallback function) when the wrapped operation fails.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* const result = await fallback({ fallback: [] })(
|
|
9
|
+
* () => fetch('/api/items').then(r => r.json()),
|
|
10
|
+
* );
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
export declare function fallback<F>(options: FallbackOptions<F>): <T>(fn: () => Promise<T>) => Promise<T | F>;
|
|
14
|
+
//# sourceMappingURL=fallback.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fallback.d.ts","sourceRoot":"","sources":["../../../src/policies/fallback.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD;;;;;;;;;;GAUG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC,IAGvC,CAAC,EAAE,IAAI,MAAM,OAAO,CAAC,CAAC,CAAC,KAAG,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAevD"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { HedgeOptions } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Creates a hedge policy that sends a parallel (hedged) request if the
|
|
4
|
+
* primary request doesn't resolve within the configured delay.
|
|
5
|
+
* The first request to resolve wins; the other's result is discarded.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* const result = await hedge({ hedgeDelay: 1000 })(
|
|
10
|
+
* () => fetch('/api/data').then(r => r.json()),
|
|
11
|
+
* );
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export declare function hedge(options?: HedgeOptions): <T>(fn: () => Promise<T>) => Promise<T>;
|
|
15
|
+
//# sourceMappingURL=hedge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hedge.d.ts","sourceRoot":"","sources":["../../../src/policies/hedge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAOhD;;;;;;;;;;;GAWG;AACH,wBAAgB,KAAK,CAAC,OAAO,GAAE,YAAiB,IAKhC,CAAC,EAAE,IAAI,MAAM,OAAO,CAAC,CAAC,CAAC,KAAG,OAAO,CAAC,CAAC,CAAC,CAyDnD"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { RateLimiterOptions, RateLimiterHandle } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Creates a token-bucket rate limiter policy that limits how many times
|
|
4
|
+
* the wrapped operation can be executed within a time interval.
|
|
5
|
+
*
|
|
6
|
+
* Returns an object with `execute` (the policy function) and `handle`
|
|
7
|
+
* (an interface to inspect / reset the bucket).
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* const rl = rateLimiter({ tokensPerInterval: 5, interval: 1000 });
|
|
12
|
+
* const result = await rl.execute(() => fetch('/api/data'));
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export declare function rateLimiter(options?: RateLimiterOptions): {
|
|
16
|
+
execute: <T>(fn: () => Promise<T>) => Promise<T>;
|
|
17
|
+
handle: RateLimiterHandle;
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=rate-limiter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limiter.d.ts","sourceRoot":"","sources":["../../../src/policies/rate-limiter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAczE;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CAAC,OAAO,GAAE,kBAAuB,GAAG;IAC7D,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IACjD,MAAM,EAAE,iBAAiB,CAAC;CAC3B,CAgFA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { RetryOptions } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Creates a retry policy that re-executes the wrapped operation on failure
|
|
4
|
+
* using the configured backoff strategy.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* const result = await retry({ maxAttempts: 5, backoff: 'exponential' })(
|
|
9
|
+
* () => fetch('/api/data'),
|
|
10
|
+
* );
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
export declare function retry(options?: RetryOptions): <T>(fn: () => Promise<T>) => Promise<T>;
|
|
14
|
+
//# sourceMappingURL=retry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../../../src/policies/retry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAWhD;;;;;;;;;;GAUG;AACH,wBAAgB,KAAK,CAAC,OAAO,GAAE,YAAiB,IAahC,CAAC,EAAE,IAAI,MAAM,OAAO,CAAC,CAAC,CAAC,KAAG,OAAO,CAAC,CAAC,CAAC,CAiCnD"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { TimeoutOptions } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Creates a timeout policy that rejects if the wrapped operation
|
|
4
|
+
* does not resolve within the specified deadline.
|
|
5
|
+
*
|
|
6
|
+
* Uses AbortController for cooperative cancellation when the
|
|
7
|
+
* wrapped function supports it.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* const result = await timeout({ ms: 5000 })(() => fetch('/api/data'));
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export declare function timeout(options: TimeoutOptions): <T>(fn: () => Promise<T>) => Promise<T>;
|
|
15
|
+
//# sourceMappingURL=timeout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timeout.d.ts","sourceRoot":"","sources":["../../../src/policies/timeout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAIlD;;;;;;;;;;;GAWG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,cAAc,IAG/B,CAAC,EAAE,IAAI,MAAM,OAAO,CAAC,CAAC,CAAC,KAAG,OAAO,CAAC,CAAC,CAAC,CA6BnD"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A policy is a higher-order function that wraps an async operation
|
|
3
|
+
* with fault-tolerance behaviour.
|
|
4
|
+
*/
|
|
5
|
+
export type Policy = <T>(fn: () => Promise<T>) => Promise<T>;
|
|
6
|
+
/**
|
|
7
|
+
* A policy factory returns a Policy and, optionally, a handle to
|
|
8
|
+
* inspect / control the policy at runtime (e.g. circuit-breaker state).
|
|
9
|
+
*/
|
|
10
|
+
export type PolicyFactory<H = void> = H extends void ? Policy : {
|
|
11
|
+
execute: Policy;
|
|
12
|
+
handle: H;
|
|
13
|
+
};
|
|
14
|
+
export type BackoffStrategy = 'constant' | 'linear' | 'exponential' | 'decorrelatedJitter';
|
|
15
|
+
export interface RetryOptions {
|
|
16
|
+
/** Maximum number of attempts (including the initial call). Default: 3 */
|
|
17
|
+
maxAttempts?: number;
|
|
18
|
+
/** Base delay in ms between retries. Default: 200 */
|
|
19
|
+
delay?: number;
|
|
20
|
+
/** Backoff strategy. Default: 'exponential' */
|
|
21
|
+
backoff?: BackoffStrategy;
|
|
22
|
+
/** Maximum delay cap in ms. Default: 30 000 */
|
|
23
|
+
maxDelay?: number;
|
|
24
|
+
/** Predicate – return `true` to retry on this error. Default: always retry */
|
|
25
|
+
shouldRetry?: (error: unknown, attempt: number) => boolean;
|
|
26
|
+
/** Called before each retry */
|
|
27
|
+
onRetry?: (error: unknown, attempt: number, delayMs: number) => void;
|
|
28
|
+
/** AbortSignal for cooperative cancellation */
|
|
29
|
+
signal?: AbortSignal;
|
|
30
|
+
}
|
|
31
|
+
export type CircuitState = 'closed' | 'open' | 'half-open';
|
|
32
|
+
export interface CircuitBreakerOptions {
|
|
33
|
+
/** Number of consecutive failures to trip the breaker. Default: 5 */
|
|
34
|
+
failureThreshold?: number;
|
|
35
|
+
/** Number of successes in half-open to close the breaker. Default: 1 */
|
|
36
|
+
successThreshold?: number;
|
|
37
|
+
/** Time in ms the breaker stays open before moving to half-open. Default: 30 000 */
|
|
38
|
+
resetTimeout?: number;
|
|
39
|
+
/** Called when the circuit opens */
|
|
40
|
+
onOpen?: () => void;
|
|
41
|
+
/** Called when the circuit closes */
|
|
42
|
+
onClose?: () => void;
|
|
43
|
+
/** Called when the circuit transitions to half-open */
|
|
44
|
+
onHalfOpen?: () => void;
|
|
45
|
+
}
|
|
46
|
+
export interface CircuitBreakerHandle {
|
|
47
|
+
/** Current state of the circuit */
|
|
48
|
+
readonly state: CircuitState;
|
|
49
|
+
/** Current consecutive failure count */
|
|
50
|
+
readonly failureCount: number;
|
|
51
|
+
/** Current consecutive success count (in half-open) */
|
|
52
|
+
readonly successCount: number;
|
|
53
|
+
/** Manually reset the breaker to closed */
|
|
54
|
+
reset(): void;
|
|
55
|
+
}
|
|
56
|
+
export interface TimeoutOptions {
|
|
57
|
+
/** Timeout deadline in milliseconds */
|
|
58
|
+
ms: number;
|
|
59
|
+
}
|
|
60
|
+
export interface BulkheadOptions {
|
|
61
|
+
/** Maximum concurrent executions. Default: 10 */
|
|
62
|
+
maxConcurrent?: number;
|
|
63
|
+
/** Maximum queue size. Default: 0 (no queue) */
|
|
64
|
+
maxQueue?: number;
|
|
65
|
+
}
|
|
66
|
+
export interface BulkheadHandle {
|
|
67
|
+
/** Number of currently running executions */
|
|
68
|
+
readonly running: number;
|
|
69
|
+
/** Number of queued executions */
|
|
70
|
+
readonly queued: number;
|
|
71
|
+
}
|
|
72
|
+
export interface FallbackOptions<T> {
|
|
73
|
+
/** The fallback value or async function producing one */
|
|
74
|
+
fallback: T | ((error: unknown) => T) | ((error: unknown) => Promise<T>);
|
|
75
|
+
/** Predicate – return `true` to use fallback for this error. Default: always */
|
|
76
|
+
shouldFallback?: (error: unknown) => boolean;
|
|
77
|
+
}
|
|
78
|
+
export interface RateLimiterOptions {
|
|
79
|
+
/** Maximum number of tokens (requests) per interval. Default: 10 */
|
|
80
|
+
tokensPerInterval?: number;
|
|
81
|
+
/** Interval duration in ms. Default: 1000 */
|
|
82
|
+
interval?: number;
|
|
83
|
+
/** If true, reject immediately when no tokens. If false, queue. Default: false */
|
|
84
|
+
rejectOnLimit?: boolean;
|
|
85
|
+
}
|
|
86
|
+
export interface RateLimiterHandle {
|
|
87
|
+
/** Number of tokens currently available */
|
|
88
|
+
readonly availableTokens: number;
|
|
89
|
+
/** Reset the bucket to full */
|
|
90
|
+
reset(): void;
|
|
91
|
+
}
|
|
92
|
+
export interface HedgeOptions {
|
|
93
|
+
/** Delay in ms before sending the hedged (parallel) request. Default: 2000 */
|
|
94
|
+
hedgeDelay?: number;
|
|
95
|
+
}
|
|
96
|
+
export interface CacheOptions<T> {
|
|
97
|
+
/** Time-to-live in ms. Default: 60 000 */
|
|
98
|
+
ttl?: number;
|
|
99
|
+
/** If true, return stale value while revalidating in the background. Default: false */
|
|
100
|
+
staleWhileRevalidate?: boolean;
|
|
101
|
+
/** Custom cache key generator. Default: 'default' */
|
|
102
|
+
keyFn?: () => string;
|
|
103
|
+
/** Called when a cache entry is evicted */
|
|
104
|
+
onEvict?: (key: string, value: T) => void;
|
|
105
|
+
}
|
|
106
|
+
export interface CacheHandle {
|
|
107
|
+
/** Number of entries currently in cache */
|
|
108
|
+
readonly size: number;
|
|
109
|
+
/** Invalidate a specific cache key */
|
|
110
|
+
invalidate(key?: string): void;
|
|
111
|
+
/** Clear all cache entries */
|
|
112
|
+
clear(): void;
|
|
113
|
+
}
|
|
114
|
+
export declare class FlowShieldError extends Error {
|
|
115
|
+
constructor(message: string, cause?: unknown);
|
|
116
|
+
}
|
|
117
|
+
export declare class TimeoutError extends FlowShieldError {
|
|
118
|
+
constructor(ms: number);
|
|
119
|
+
}
|
|
120
|
+
export declare class CircuitOpenError extends FlowShieldError {
|
|
121
|
+
constructor();
|
|
122
|
+
}
|
|
123
|
+
export declare class BulkheadRejectedError extends FlowShieldError {
|
|
124
|
+
constructor();
|
|
125
|
+
}
|
|
126
|
+
export declare class RateLimitExceededError extends FlowShieldError {
|
|
127
|
+
constructor();
|
|
128
|
+
}
|
|
129
|
+
export declare class RetryExhaustedError extends FlowShieldError {
|
|
130
|
+
readonly attempts: number;
|
|
131
|
+
constructor(attempts: number, lastError: unknown);
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sleep for `ms` milliseconds. Supports cooperative cancellation via AbortSignal.
|
|
3
|
+
*/
|
|
4
|
+
export declare function sleep(ms: number, signal?: AbortSignal): Promise<void>;
|
|
5
|
+
/**
|
|
6
|
+
* Calculate the delay for a given attempt using the specified backoff strategy.
|
|
7
|
+
*/
|
|
8
|
+
export declare function calculateDelay(attempt: number, baseDelay: number, strategy: 'constant' | 'linear' | 'exponential' | 'decorrelatedJitter', maxDelay: number, previousDelay?: number): number;
|
|
9
|
+
/**
|
|
10
|
+
* Validate that a number is a positive integer.
|
|
11
|
+
*/
|
|
12
|
+
export declare function assertPositiveInteger(value: number, name: string): void;
|
|
13
|
+
/**
|
|
14
|
+
* Validate that a number is a positive finite number.
|
|
15
|
+
*/
|
|
16
|
+
export declare function assertPositive(value: number, name: string): void;
|
|
17
|
+
/**
|
|
18
|
+
* Validate that a number is a non-negative finite number.
|
|
19
|
+
*/
|
|
20
|
+
export declare function assertNonNegative(value: number, name: string): void;
|
|
21
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CA6BrE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,UAAU,GAAG,QAAQ,GAAG,aAAa,GAAG,oBAAoB,EACtE,QAAQ,EAAE,MAAM,EAChB,aAAa,CAAC,EAAE,MAAM,GACrB,MAAM,CAqBR;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAIvE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAIhE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAInE"}
|
package/package.json
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "flowshield",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Zero-dependency, TypeScript-first resilience & fault-tolerance toolkit. Composable policies: retry, circuit breaker, timeout, bulkhead, fallback, rate limiter, hedge, cache.",
|
|
5
|
+
"main": "./dist/cjs/index.js",
|
|
6
|
+
"module": "./dist/esm/index.js",
|
|
7
|
+
"types": "./dist/types/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/esm/index.js",
|
|
11
|
+
"require": "./dist/cjs/index.js",
|
|
12
|
+
"types": "./dist/types/index.d.ts"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"README.md",
|
|
18
|
+
"LICENSE",
|
|
19
|
+
"CHANGELOG.md"
|
|
20
|
+
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build:esm": "tsc -p tsconfig.esm.json",
|
|
23
|
+
"build:cjs": "tsc -p tsconfig.cjs.json",
|
|
24
|
+
"build:types": "tsc -p tsconfig.types.json",
|
|
25
|
+
"build": "npm run clean && npm run build:esm && npm run build:cjs && npm run build:types",
|
|
26
|
+
"clean": "node -e \"const fs=require('fs');if(fs.existsSync('dist'))fs.rmSync('dist',{recursive:true})\"",
|
|
27
|
+
"test": "vitest run",
|
|
28
|
+
"test:watch": "vitest",
|
|
29
|
+
"test:coverage": "vitest run --coverage",
|
|
30
|
+
"lint": "eslint src/ --ext .ts",
|
|
31
|
+
"typecheck": "tsc --noEmit",
|
|
32
|
+
"prepublishOnly": "npm run build"
|
|
33
|
+
},
|
|
34
|
+
"keywords": [
|
|
35
|
+
"resilience",
|
|
36
|
+
"fault-tolerance",
|
|
37
|
+
"retry",
|
|
38
|
+
"circuit-breaker",
|
|
39
|
+
"timeout",
|
|
40
|
+
"bulkhead",
|
|
41
|
+
"fallback",
|
|
42
|
+
"rate-limiter",
|
|
43
|
+
"hedge",
|
|
44
|
+
"cache",
|
|
45
|
+
"typescript",
|
|
46
|
+
"zero-dependency",
|
|
47
|
+
"composable",
|
|
48
|
+
"microservices",
|
|
49
|
+
"error-handling",
|
|
50
|
+
"exponential-backoff",
|
|
51
|
+
"polly",
|
|
52
|
+
"cockatiel",
|
|
53
|
+
"fault-tolerant",
|
|
54
|
+
"resilient",
|
|
55
|
+
"policies",
|
|
56
|
+
"edge-runtime"
|
|
57
|
+
],
|
|
58
|
+
"author": "Avinash Velu <avinashvelu03@gmail.com>",
|
|
59
|
+
"license": "MIT",
|
|
60
|
+
"repository": {
|
|
61
|
+
"type": "git",
|
|
62
|
+
"url": "https://github.com/Avinashvelu03/flowshield.git"
|
|
63
|
+
},
|
|
64
|
+
"bugs": {
|
|
65
|
+
"url": "https://github.com/Avinashvelu03/flowshield/issues"
|
|
66
|
+
},
|
|
67
|
+
"homepage": "https://github.com/Avinashvelu03/flowshield#readme",
|
|
68
|
+
"devDependencies": {
|
|
69
|
+
"@vitest/coverage-v8": "^3.1.1",
|
|
70
|
+
"eslint": "^8.57.0",
|
|
71
|
+
"@typescript-eslint/eslint-plugin": "^7.0.0",
|
|
72
|
+
"@typescript-eslint/parser": "^7.0.0",
|
|
73
|
+
"typescript": "^5.7.0",
|
|
74
|
+
"vitest": "^3.1.1"
|
|
75
|
+
},
|
|
76
|
+
"engines": {
|
|
77
|
+
"node": ">=18.0.0"
|
|
78
|
+
},
|
|
79
|
+
"sideEffects": false
|
|
80
|
+
}
|