actly 1.1.0 → 1.1.5

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 (70) hide show
  1. package/LICENSE +0 -0
  2. package/README.md +284 -52
  3. package/dist/core/act.cjs +183 -35
  4. package/dist/core/act.d.ts +81 -10
  5. package/dist/core/act.d.ts.map +1 -1
  6. package/dist/core/act.js +181 -35
  7. package/dist/core/act.js.map +1 -1
  8. package/dist/core/executor.cjs +19 -9
  9. package/dist/core/executor.d.ts +25 -5
  10. package/dist/core/executor.d.ts.map +1 -1
  11. package/dist/core/executor.js +19 -9
  12. package/dist/core/executor.js.map +1 -1
  13. package/dist/index.cjs +13 -3
  14. package/dist/index.d.ts +7 -3
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +8 -4
  17. package/dist/index.js.map +1 -1
  18. package/dist/policies/cache.cjs +85 -21
  19. package/dist/policies/cache.d.ts +29 -7
  20. package/dist/policies/cache.d.ts.map +1 -1
  21. package/dist/policies/cache.js +85 -21
  22. package/dist/policies/cache.js.map +1 -1
  23. package/dist/policies/dedupe.cjs +68 -20
  24. package/dist/policies/dedupe.d.ts +38 -13
  25. package/dist/policies/dedupe.d.ts.map +1 -1
  26. package/dist/policies/dedupe.js +68 -20
  27. package/dist/policies/dedupe.js.map +1 -1
  28. package/dist/policies/retry.cjs +65 -25
  29. package/dist/policies/retry.d.ts +25 -2
  30. package/dist/policies/retry.d.ts.map +1 -1
  31. package/dist/policies/retry.js +65 -25
  32. package/dist/policies/retry.js.map +1 -1
  33. package/dist/policies/timeout.cjs +87 -17
  34. package/dist/policies/timeout.d.ts +28 -8
  35. package/dist/policies/timeout.d.ts.map +1 -1
  36. package/dist/policies/timeout.js +87 -17
  37. package/dist/policies/timeout.js.map +1 -1
  38. package/dist/state/store.cjs +9 -2
  39. package/dist/state/store.d.ts +9 -0
  40. package/dist/state/store.d.ts.map +1 -1
  41. package/dist/state/store.js +9 -2
  42. package/dist/state/store.js.map +1 -1
  43. package/dist/stores/base.cjs +4 -4
  44. package/dist/stores/base.d.ts +32 -56
  45. package/dist/stores/base.d.ts.map +1 -1
  46. package/dist/stores/base.js +4 -4
  47. package/dist/stores/base.js.map +1 -1
  48. package/dist/stores/memory.cjs +77 -28
  49. package/dist/stores/memory.d.ts +44 -23
  50. package/dist/stores/memory.d.ts.map +1 -1
  51. package/dist/stores/memory.js +77 -28
  52. package/dist/stores/memory.js.map +1 -1
  53. package/dist/types/index.d.ts +141 -36
  54. package/dist/types/index.d.ts.map +1 -1
  55. package/dist/utils/abort.cjs +142 -0
  56. package/dist/utils/abort.d.ts +55 -0
  57. package/dist/utils/abort.d.ts.map +1 -0
  58. package/dist/utils/abort.js +136 -0
  59. package/dist/utils/abort.js.map +1 -0
  60. package/dist/utils/backoff.cjs +43 -0
  61. package/dist/utils/backoff.d.ts +14 -0
  62. package/dist/utils/backoff.d.ts.map +1 -0
  63. package/dist/utils/backoff.js +41 -0
  64. package/dist/utils/backoff.js.map +1 -0
  65. package/dist/utils/validate.cjs +79 -0
  66. package/dist/utils/validate.d.ts +15 -0
  67. package/dist/utils/validate.d.ts.map +1 -0
  68. package/dist/utils/validate.js +72 -0
  69. package/dist/utils/validate.js.map +1 -0
  70. package/package.json +19 -37
@@ -0,0 +1,14 @@
1
+ import type { RetryOptions } from '../types/index.js';
2
+ /**
3
+ * Compute the delay before the next retry attempt, applying backoff, cap, and
4
+ * jitter in that order.
5
+ *
6
+ * Order matters:
7
+ * 1. `backoff` grows the base delay geometrically/linearly.
8
+ * 2. `maxDelay` caps the result (prevents exponential blowup).
9
+ * 3. `jitter` randomises within `[0, delay]` (prevents thundering herd).
10
+ *
11
+ * Returns 0 if `delayMs` is 0 or undefined — skipping the sleep entirely.
12
+ */
13
+ export declare function computeDelay(attempt: number, opts: RetryOptions): number;
14
+ //# sourceMappingURL=backoff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backoff.d.ts","sourceRoot":"","sources":["../../src/utils/backoff.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAErD;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,GAAG,MAAM,CAyBxE"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Compute the delay before the next retry attempt, applying backoff, cap, and
3
+ * jitter in that order.
4
+ *
5
+ * Order matters:
6
+ * 1. `backoff` grows the base delay geometrically/linearly.
7
+ * 2. `maxDelay` caps the result (prevents exponential blowup).
8
+ * 3. `jitter` randomises within `[0, delay]` (prevents thundering herd).
9
+ *
10
+ * Returns 0 if `delayMs` is 0 or undefined — skipping the sleep entirely.
11
+ */
12
+ export function computeDelay(attempt, opts) {
13
+ const base = opts.delayMs ?? 0;
14
+ if (base === 0)
15
+ return 0;
16
+ // Step 1: backoff
17
+ let delay;
18
+ switch (opts.backoff ?? 'none') {
19
+ case 'linear':
20
+ delay = base * attempt;
21
+ break;
22
+ case 'exponential':
23
+ delay = base * 2 ** (attempt - 1);
24
+ break;
25
+ default: delay = base;
26
+ }
27
+ // Step 2: cap (guard against Infinity and NaN before Math.min)
28
+ const max = opts.maxDelay ?? Number.POSITIVE_INFINITY;
29
+ if (!Number.isFinite(delay))
30
+ delay = max;
31
+ delay = Math.min(delay, max);
32
+ // Step 3: jitter
33
+ switch (opts.jitter ?? 'full') {
34
+ case 'none': return delay;
35
+ case 'full': return Math.random() * delay;
36
+ case 'equal': return delay / 2 + Math.random() * delay / 2;
37
+ case 'decorrelated': return base + Math.random() * (delay - base);
38
+ default: return delay;
39
+ }
40
+ }
41
+ //# sourceMappingURL=backoff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backoff.js","sourceRoot":"","sources":["../../src/utils/backoff.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AACH,MAAM,UAAU,YAAY,CAAC,OAAe,EAAE,IAAkB;IAC9D,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,IAAI,CAAC,CAAA;IAC9B,IAAI,IAAI,KAAK,CAAC;QAAE,OAAO,CAAC,CAAA;IAExB,kBAAkB;IAClB,IAAI,KAAa,CAAA;IACjB,QAAQ,IAAI,CAAC,OAAO,IAAI,MAAM,EAAE,CAAC;QAC/B,KAAK,QAAQ;YAAO,KAAK,GAAG,IAAI,GAAG,OAAO,CAAC;YAAC,MAAK;QACjD,KAAK,aAAa;YAAE,KAAK,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;YAAC,MAAK;QAC5D,OAAO,CAAC,CAAY,KAAK,GAAG,IAAI,CAAA;IAClC,CAAC;IAED,+DAA+D;IAC/D,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,IAAI,MAAM,CAAC,iBAAiB,CAAA;IACrD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,KAAK,GAAG,GAAG,CAAA;IACxC,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;IAE5B,iBAAiB;IACjB,QAAQ,IAAI,CAAC,MAAM,IAAI,MAAM,EAAE,CAAC;QAC9B,KAAK,MAAM,CAAC,CAAS,OAAO,KAAK,CAAA;QACjC,KAAK,MAAM,CAAC,CAAS,OAAO,IAAI,CAAC,MAAM,EAAE,GAAG,KAAK,CAAA;QACjD,KAAK,OAAO,CAAC,CAAQ,OAAO,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,KAAK,GAAG,CAAC,CAAA;QACjE,KAAK,cAAc,CAAC,CAAC,OAAO,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,CAAA;QACjE,OAAO,CAAC,CAAa,OAAO,KAAK,CAAA;IACnC,CAAC;AACH,CAAC"}
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.assertKey = assertKey;
4
+ exports.assertRetryOptions = assertRetryOptions;
5
+ exports.assertTimeoutOptions = assertTimeoutOptions;
6
+ exports.assertCacheOptions = assertCacheOptions;
7
+ exports.assertDedupeOptions = assertDedupeOptions;
8
+ exports.assertOptions = assertOptions;
9
+ /**
10
+ * Validate user-facing option shapes. Throws `RangeError` / `TypeError` on
11
+ * invalid input — these are programmer errors, not runtime failures, so
12
+ * throwing (rather than returning an `ActFailure`) is the right call.
13
+ *
14
+ * Called once at the top of `act()` so policies can assume well-formed input.
15
+ */
16
+ function assertKey(key) {
17
+ if (typeof key !== 'string') {
18
+ throw new TypeError(`Actly: key must be a string, got ${typeof key}`);
19
+ }
20
+ if (key.length === 0) {
21
+ throw new RangeError("Actly: key must be non-empty. An empty key collapses every caller " +
22
+ "onto the same dedupe/cache slot — almost certainly a bug.");
23
+ }
24
+ // Reject reserved internal prefixes so user keys cannot collide with
25
+ // dedupe/cache namespace prefixes.
26
+ if (key.startsWith('dedupe:') || key.startsWith('cache:') || key.startsWith('__inflight:')) {
27
+ throw new RangeError(`Actly: key must not start with reserved prefix "dedupe:", "cache:", or "__inflight:" (got ${JSON.stringify(key)}).`);
28
+ }
29
+ }
30
+ function assertRetryOptions(opts) {
31
+ if (!Number.isInteger(opts.attempts) || opts.attempts < 1) {
32
+ throw new RangeError(`Actly: retry.attempts must be a positive integer, got ${opts.attempts}`);
33
+ }
34
+ if (opts.delayMs !== undefined) {
35
+ assertNonNegativeFinite('retry.delayMs', opts.delayMs);
36
+ }
37
+ if (opts.maxDelay !== undefined) {
38
+ assertNonNegativeFinite('retry.maxDelay', opts.maxDelay);
39
+ }
40
+ if (opts.shouldRetry !== undefined && typeof opts.shouldRetry !== 'function') {
41
+ throw new TypeError(`Actly: retry.shouldRetry must be a function, got ${typeof opts.shouldRetry}`);
42
+ }
43
+ }
44
+ function assertTimeoutOptions(opts, field) {
45
+ if (typeof opts.ms !== 'number' || !Number.isFinite(opts.ms) || opts.ms <= 0) {
46
+ throw new RangeError(`Actly: ${field}.ms must be a positive finite number, got ${opts.ms}`);
47
+ }
48
+ }
49
+ function assertCacheOptions(opts) {
50
+ if (typeof opts.ttl !== 'number' || !Number.isFinite(opts.ttl) || opts.ttl <= 0) {
51
+ throw new RangeError(`Actly: cache.ttl must be a positive finite number, got ${opts.ttl}`);
52
+ }
53
+ }
54
+ function assertDedupeOptions(opts) {
55
+ if (opts.inflightTtl !== undefined) {
56
+ assertNonNegativeFinite('dedupe.inflightTtl', opts.inflightTtl);
57
+ }
58
+ }
59
+ function assertOptions(options) {
60
+ if (options.retry)
61
+ assertRetryOptions(options.retry);
62
+ if (options.timeout)
63
+ assertTimeoutOptions(options.timeout, 'timeout');
64
+ if (options.totalTimeout)
65
+ assertTimeoutOptions(options.totalTimeout, 'totalTimeout');
66
+ if (options.cache)
67
+ assertCacheOptions(options.cache);
68
+ if (options.dedupe && typeof options.dedupe !== 'boolean') {
69
+ assertDedupeOptions(options.dedupe);
70
+ }
71
+ if (options.signal !== undefined && !(options.signal instanceof AbortSignal)) {
72
+ throw new TypeError(`Actly: signal must be an AbortSignal, got ${options.signal === null ? 'null' : typeof options.signal}`);
73
+ }
74
+ }
75
+ function assertNonNegativeFinite(field, value) {
76
+ if (typeof value !== 'number' || !Number.isFinite(value) || value < 0) {
77
+ throw new RangeError(`Actly: ${field} must be a non-negative finite number, got ${value}`);
78
+ }
79
+ }
@@ -0,0 +1,15 @@
1
+ import type { ActOptions, CacheOptions, DedupeOptions, RetryOptions, TimeoutOptions } from '../types/index.js';
2
+ /**
3
+ * Validate user-facing option shapes. Throws `RangeError` / `TypeError` on
4
+ * invalid input — these are programmer errors, not runtime failures, so
5
+ * throwing (rather than returning an `ActFailure`) is the right call.
6
+ *
7
+ * Called once at the top of `act()` so policies can assume well-formed input.
8
+ */
9
+ export declare function assertKey(key: string): void;
10
+ export declare function assertRetryOptions(opts: RetryOptions): void;
11
+ export declare function assertTimeoutOptions(opts: TimeoutOptions, field: string): void;
12
+ export declare function assertCacheOptions(opts: CacheOptions): void;
13
+ export declare function assertDedupeOptions(opts: DedupeOptions): void;
14
+ export declare function assertOptions(options: ActOptions): void;
15
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/utils/validate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,cAAc,EACf,MAAM,mBAAmB,CAAA;AAE1B;;;;;;GAMG;AAEH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAiB3C;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,CAiB3D;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAM9E;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,CAM3D;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI,CAI7D;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI,CAavD"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Validate user-facing option shapes. Throws `RangeError` / `TypeError` on
3
+ * invalid input — these are programmer errors, not runtime failures, so
4
+ * throwing (rather than returning an `ActFailure`) is the right call.
5
+ *
6
+ * Called once at the top of `act()` so policies can assume well-formed input.
7
+ */
8
+ export function assertKey(key) {
9
+ if (typeof key !== 'string') {
10
+ throw new TypeError(`Actly: key must be a string, got ${typeof key}`);
11
+ }
12
+ if (key.length === 0) {
13
+ throw new RangeError("Actly: key must be non-empty. An empty key collapses every caller " +
14
+ "onto the same dedupe/cache slot — almost certainly a bug.");
15
+ }
16
+ // Reject reserved internal prefixes so user keys cannot collide with
17
+ // dedupe/cache namespace prefixes.
18
+ if (key.startsWith('dedupe:') || key.startsWith('cache:') || key.startsWith('__inflight:')) {
19
+ throw new RangeError(`Actly: key must not start with reserved prefix "dedupe:", "cache:", or "__inflight:" (got ${JSON.stringify(key)}).`);
20
+ }
21
+ }
22
+ export function assertRetryOptions(opts) {
23
+ if (!Number.isInteger(opts.attempts) || opts.attempts < 1) {
24
+ throw new RangeError(`Actly: retry.attempts must be a positive integer, got ${opts.attempts}`);
25
+ }
26
+ if (opts.delayMs !== undefined) {
27
+ assertNonNegativeFinite('retry.delayMs', opts.delayMs);
28
+ }
29
+ if (opts.maxDelay !== undefined) {
30
+ assertNonNegativeFinite('retry.maxDelay', opts.maxDelay);
31
+ }
32
+ if (opts.shouldRetry !== undefined && typeof opts.shouldRetry !== 'function') {
33
+ throw new TypeError(`Actly: retry.shouldRetry must be a function, got ${typeof opts.shouldRetry}`);
34
+ }
35
+ }
36
+ export function assertTimeoutOptions(opts, field) {
37
+ if (typeof opts.ms !== 'number' || !Number.isFinite(opts.ms) || opts.ms <= 0) {
38
+ throw new RangeError(`Actly: ${field}.ms must be a positive finite number, got ${opts.ms}`);
39
+ }
40
+ }
41
+ export function assertCacheOptions(opts) {
42
+ if (typeof opts.ttl !== 'number' || !Number.isFinite(opts.ttl) || opts.ttl <= 0) {
43
+ throw new RangeError(`Actly: cache.ttl must be a positive finite number, got ${opts.ttl}`);
44
+ }
45
+ }
46
+ export function assertDedupeOptions(opts) {
47
+ if (opts.inflightTtl !== undefined) {
48
+ assertNonNegativeFinite('dedupe.inflightTtl', opts.inflightTtl);
49
+ }
50
+ }
51
+ export function assertOptions(options) {
52
+ if (options.retry)
53
+ assertRetryOptions(options.retry);
54
+ if (options.timeout)
55
+ assertTimeoutOptions(options.timeout, 'timeout');
56
+ if (options.totalTimeout)
57
+ assertTimeoutOptions(options.totalTimeout, 'totalTimeout');
58
+ if (options.cache)
59
+ assertCacheOptions(options.cache);
60
+ if (options.dedupe && typeof options.dedupe !== 'boolean') {
61
+ assertDedupeOptions(options.dedupe);
62
+ }
63
+ if (options.signal !== undefined && !(options.signal instanceof AbortSignal)) {
64
+ throw new TypeError(`Actly: signal must be an AbortSignal, got ${options.signal === null ? 'null' : typeof options.signal}`);
65
+ }
66
+ }
67
+ function assertNonNegativeFinite(field, value) {
68
+ if (typeof value !== 'number' || !Number.isFinite(value) || value < 0) {
69
+ throw new RangeError(`Actly: ${field} must be a non-negative finite number, got ${value}`);
70
+ }
71
+ }
72
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/utils/validate.ts"],"names":[],"mappings":"AAQA;;;;;;GAMG;AAEH,MAAM,UAAU,SAAS,CAAC,GAAW;IACnC,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,MAAM,IAAI,SAAS,CAAC,oCAAoC,OAAO,GAAG,EAAE,CAAC,CAAA;IACvE,CAAC;IACD,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,UAAU,CAClB,oEAAoE;YACpE,2DAA2D,CAC5D,CAAA;IACH,CAAC;IACD,qEAAqE;IACrE,mCAAmC;IACnC,IAAI,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QAC3F,MAAM,IAAI,UAAU,CAClB,6FAA6F,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CACrH,CAAA;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,IAAkB;IACnD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,GAAG,CAAC,EAAE,CAAC;QAC1D,MAAM,IAAI,UAAU,CAClB,yDAAyD,IAAI,CAAC,QAAQ,EAAE,CACzE,CAAA;IACH,CAAC;IACD,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QAC/B,uBAAuB,CAAC,eAAe,EAAE,IAAI,CAAC,OAAO,CAAC,CAAA;IACxD,CAAC;IACD,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QAChC,uBAAuB,CAAC,gBAAgB,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAA;IAC1D,CAAC;IACD,IAAI,IAAI,CAAC,WAAW,KAAK,SAAS,IAAI,OAAO,IAAI,CAAC,WAAW,KAAK,UAAU,EAAE,CAAC;QAC7E,MAAM,IAAI,SAAS,CACjB,oDAAoD,OAAO,IAAI,CAAC,WAAW,EAAE,CAC9E,CAAA;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,IAAoB,EAAE,KAAa;IACtE,IAAI,OAAO,IAAI,CAAC,EAAE,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC;QAC7E,MAAM,IAAI,UAAU,CAClB,UAAU,KAAK,6CAA6C,IAAI,CAAC,EAAE,EAAE,CACtE,CAAA;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,IAAkB;IACnD,IAAI,OAAO,IAAI,CAAC,GAAG,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC;QAChF,MAAM,IAAI,UAAU,CAClB,0DAA0D,IAAI,CAAC,GAAG,EAAE,CACrE,CAAA;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,IAAmB;IACrD,IAAI,IAAI,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;QACnC,uBAAuB,CAAC,oBAAoB,EAAE,IAAI,CAAC,WAAW,CAAC,CAAA;IACjE,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,OAAmB;IAC/C,IAAI,OAAO,CAAC,KAAK;QAAM,kBAAkB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;IACxD,IAAI,OAAO,CAAC,OAAO;QAAI,oBAAoB,CAAC,OAAO,CAAC,OAAO,EAAE,SAAS,CAAC,CAAA;IACvE,IAAI,OAAO,CAAC,YAAY;QAAE,oBAAoB,CAAC,OAAO,CAAC,YAAY,EAAE,cAAc,CAAC,CAAA;IACpF,IAAI,OAAO,CAAC,KAAK;QAAM,kBAAkB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;IACxD,IAAI,OAAO,CAAC,MAAM,IAAI,OAAO,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC1D,mBAAmB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;IACrC,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,YAAY,WAAW,CAAC,EAAE,CAAC;QAC7E,MAAM,IAAI,SAAS,CACjB,6CAA6C,OAAO,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,OAAO,CAAC,MAAM,EAAE,CACxG,CAAA;IACH,CAAC;AACH,CAAC;AAED,SAAS,uBAAuB,CAAC,KAAa,EAAE,KAAa;IAC3D,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACtE,MAAM,IAAI,UAAU,CAClB,UAAU,KAAK,8CAA8C,KAAK,EAAE,CACrE,CAAA;IACH,CAAC;AACH,CAAC"}
package/package.json CHANGED
@@ -1,14 +1,19 @@
1
1
  {
2
2
  "name": "actly",
3
- "version": "1.1.0",
4
- "description": "A reliability primitive for executing async actions safely.",
3
+ "version": "1.1.5",
4
+ "description": "A reliability primitive for executing async actions safely — with proper AbortSignal cancellation, single-flight cache, LRU store, and jittered backoff.",
5
5
  "keywords": [
6
6
  "reliability",
7
7
  "retry",
8
8
  "timeout",
9
9
  "dedupe",
10
10
  "cache",
11
- "async"
11
+ "async",
12
+ "backoff",
13
+ "abort",
14
+ "single-flight",
15
+ "resilience",
16
+ "jitter"
12
17
  ],
13
18
  "license": "MIT",
14
19
  "type": "module",
@@ -17,9 +22,9 @@
17
22
  "types": "./dist/index.d.ts",
18
23
  "exports": {
19
24
  ".": {
25
+ "types": "./dist/index.d.ts",
20
26
  "import": "./dist/index.js",
21
- "require": "./dist/index.cjs",
22
- "types": "./dist/index.d.ts"
27
+ "require": "./dist/index.cjs"
23
28
  }
24
29
  },
25
30
  "files": [
@@ -27,42 +32,19 @@
27
32
  "README.md",
28
33
  "LICENSE"
29
34
  ],
35
+ "engines": {
36
+ "node": ">=18"
37
+ },
38
+ "sideEffects": false,
30
39
  "scripts": {
31
40
  "build": "tsc --project tsconfig.build.json && tsc --project tsconfig.cjs.json && node scripts/postbuild.mjs",
32
41
  "typecheck": "tsc --noEmit",
33
- "test": "jest"
34
- },
35
- "jest": {
36
- "preset": "ts-jest/presets/default-esm",
37
- "testEnvironment": "node",
38
- "extensionsToTreatAsEsm": [
39
- ".ts"
40
- ],
41
- "moduleNameMapper": {
42
- "^(\\.{1,2}/.*)\\.js$": "$1"
43
- },
44
- "transform": {
45
- "^.+\\.tsx?$": [
46
- "ts-jest",
47
- {
48
- "useESM": true,
49
- "tsconfig": {
50
- "module": "ESNext",
51
- "moduleResolution": "bundler"
52
- }
53
- }
54
- ]
55
- },
56
- "testMatch": [
57
- "**/src/__tests__/**/*.test.ts"
58
- ],
59
- "clearMocks": true,
60
- "restoreMocks": true
42
+ "test": "vitest run",
43
+ "test:watch": "vitest"
61
44
  },
62
45
  "devDependencies": {
63
- "@types/jest": "^29.5.0",
64
- "jest": "^29.7.0",
65
- "ts-jest": "^29.4.0",
66
- "typescript": "^5.4.0"
46
+ "@types/node": "^18.19.0",
47
+ "typescript": "^5.4.0",
48
+ "vitest": "^1.6.0"
67
49
  }
68
50
  }