actly 1.2.0 → 1.3.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 (151) hide show
  1. package/CHANGELOG.md +234 -0
  2. package/MIGRATION.md +141 -0
  3. package/README.md +326 -218
  4. package/SECURITY.md +56 -0
  5. package/dist/core/act.cjs +406 -220
  6. package/dist/core/act.d.ts +6 -84
  7. package/dist/core/act.d.ts.map +1 -1
  8. package/dist/core/act.js +405 -222
  9. package/dist/core/executor.cjs +0 -27
  10. package/dist/core/executor.d.ts +0 -41
  11. package/dist/core/executor.d.ts.map +1 -1
  12. package/dist/core/executor.js +0 -28
  13. package/dist/core/health.cjs +146 -17
  14. package/dist/core/health.d.ts +20 -5
  15. package/dist/core/health.d.ts.map +1 -1
  16. package/dist/core/health.js +140 -18
  17. package/dist/core/shutdown.cjs +19 -8
  18. package/dist/core/shutdown.d.ts +1 -4
  19. package/dist/core/shutdown.d.ts.map +1 -1
  20. package/dist/core/shutdown.js +18 -9
  21. package/dist/core/tenant.cjs +61 -19
  22. package/dist/core/tenant.d.ts +5 -10
  23. package/dist/core/tenant.d.ts.map +1 -1
  24. package/dist/core/tenant.js +61 -20
  25. package/dist/errors.cjs +70 -103
  26. package/dist/errors.d.ts +33 -90
  27. package/dist/errors.d.ts.map +1 -1
  28. package/dist/errors.js +66 -103
  29. package/dist/index.cjs +25 -22
  30. package/dist/index.d.ts +12 -8
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +7 -15
  33. package/dist/observability.cjs +0 -39
  34. package/dist/observability.d.ts +19 -78
  35. package/dist/observability.d.ts.map +1 -1
  36. package/dist/observability.js +0 -40
  37. package/dist/policies/bulkhead.cjs +44 -4
  38. package/dist/policies/bulkhead.d.ts +0 -0
  39. package/dist/policies/bulkhead.d.ts.map +1 -1
  40. package/dist/policies/bulkhead.js +44 -5
  41. package/dist/policies/cache.cjs +22 -142
  42. package/dist/policies/cache.d.ts +0 -46
  43. package/dist/policies/cache.d.ts.map +1 -1
  44. package/dist/policies/cache.js +22 -143
  45. package/dist/policies/circuitBreaker.cjs +125 -31
  46. package/dist/policies/circuitBreaker.d.ts +0 -0
  47. package/dist/policies/circuitBreaker.d.ts.map +1 -1
  48. package/dist/policies/circuitBreaker.js +125 -32
  49. package/dist/policies/dedupe.cjs +19 -66
  50. package/dist/policies/dedupe.d.ts +0 -23
  51. package/dist/policies/dedupe.d.ts.map +1 -1
  52. package/dist/policies/dedupe.js +19 -67
  53. package/dist/policies/noop.cjs +6 -0
  54. package/dist/policies/noop.d.ts +3 -0
  55. package/dist/policies/noop.d.ts.map +1 -0
  56. package/dist/policies/noop.js +3 -0
  57. package/dist/policies/rateLimit.cjs +15 -5
  58. package/dist/policies/rateLimit.d.ts +0 -0
  59. package/dist/policies/rateLimit.d.ts.map +1 -1
  60. package/dist/policies/rateLimit.js +15 -6
  61. package/dist/policies/retry.cjs +100 -65
  62. package/dist/policies/retry.d.ts +0 -27
  63. package/dist/policies/retry.d.ts.map +1 -1
  64. package/dist/policies/retry.js +100 -66
  65. package/dist/policies/timeout.cjs +32 -60
  66. package/dist/policies/timeout.d.ts +0 -13
  67. package/dist/policies/timeout.d.ts.map +1 -1
  68. package/dist/policies/timeout.js +32 -71
  69. package/dist/stores/base.cjs +0 -10
  70. package/dist/stores/base.d.ts +4 -67
  71. package/dist/stores/base.d.ts.map +1 -1
  72. package/dist/stores/base.js +0 -11
  73. package/dist/stores/memory.cjs +75 -88
  74. package/dist/stores/memory.d.ts +7 -74
  75. package/dist/stores/memory.d.ts.map +1 -1
  76. package/dist/stores/memory.js +75 -89
  77. package/dist/testing/index.cjs +56 -0
  78. package/dist/testing/index.d.ts +6 -0
  79. package/dist/testing/index.d.ts.map +1 -0
  80. package/dist/testing/index.js +52 -0
  81. package/dist/types/index.cjs +0 -1
  82. package/dist/types/index.d.ts +17 -307
  83. package/dist/types/index.d.ts.map +1 -1
  84. package/dist/types/index.js +0 -2
  85. package/dist/utils/abort.cjs +14 -111
  86. package/dist/utils/abort.d.ts +3 -74
  87. package/dist/utils/abort.d.ts.map +1 -1
  88. package/dist/utils/abort.js +14 -112
  89. package/dist/utils/abortPool.cjs +1 -2
  90. package/dist/utils/abortPool.d.ts +0 -0
  91. package/dist/utils/abortPool.d.ts.map +1 -1
  92. package/dist/utils/abortPool.js +1 -3
  93. package/dist/utils/backoff.cjs +3 -21
  94. package/dist/utils/backoff.d.ts +0 -11
  95. package/dist/utils/backoff.d.ts.map +1 -1
  96. package/dist/utils/backoff.js +3 -22
  97. package/dist/utils/decorator.cjs +44 -0
  98. package/dist/utils/decorator.d.ts +3 -0
  99. package/dist/utils/decorator.d.ts.map +1 -0
  100. package/dist/utils/decorator.js +41 -0
  101. package/dist/utils/key.cjs +13 -45
  102. package/dist/utils/key.d.ts +0 -27
  103. package/dist/utils/key.d.ts.map +1 -1
  104. package/dist/utils/key.js +13 -46
  105. package/dist/utils/limits.cjs +9 -27
  106. package/dist/utils/limits.d.ts +9 -27
  107. package/dist/utils/limits.d.ts.map +1 -1
  108. package/dist/utils/limits.js +9 -28
  109. package/dist/utils/safeCall.cjs +28 -0
  110. package/dist/utils/safeCall.d.ts +2 -0
  111. package/dist/utils/safeCall.d.ts.map +1 -0
  112. package/dist/utils/safeCall.js +25 -0
  113. package/dist/utils/sanitize.cjs +22 -1
  114. package/dist/utils/sanitize.d.ts +0 -0
  115. package/dist/utils/sanitize.d.ts.map +1 -1
  116. package/dist/utils/sanitize.js +22 -2
  117. package/dist/utils/validate.cjs +81 -18
  118. package/dist/utils/validate.d.ts +6 -19
  119. package/dist/utils/validate.d.ts.map +1 -1
  120. package/dist/utils/validate.js +81 -19
  121. package/package.json +38 -4
  122. package/dist/core/act.js.map +0 -1
  123. package/dist/core/executor.js.map +0 -1
  124. package/dist/core/health.js.map +0 -1
  125. package/dist/core/shutdown.js.map +0 -1
  126. package/dist/core/tenant.js.map +0 -1
  127. package/dist/errors.js.map +0 -1
  128. package/dist/index.js.map +0 -1
  129. package/dist/observability.js.map +0 -1
  130. package/dist/policies/bulkhead.js.map +0 -1
  131. package/dist/policies/cache.js.map +0 -1
  132. package/dist/policies/circuitBreaker.js.map +0 -1
  133. package/dist/policies/dedupe.js.map +0 -1
  134. package/dist/policies/rateLimit.js.map +0 -1
  135. package/dist/policies/retry.js.map +0 -1
  136. package/dist/policies/timeout.js.map +0 -1
  137. package/dist/state/store.cjs +0 -14
  138. package/dist/state/store.d.ts +0 -11
  139. package/dist/state/store.d.ts.map +0 -1
  140. package/dist/state/store.js +0 -11
  141. package/dist/state/store.js.map +0 -1
  142. package/dist/stores/base.js.map +0 -1
  143. package/dist/stores/memory.js.map +0 -1
  144. package/dist/types/index.js.map +0 -1
  145. package/dist/utils/abort.js.map +0 -1
  146. package/dist/utils/abortPool.js.map +0 -1
  147. package/dist/utils/backoff.js.map +0 -1
  148. package/dist/utils/key.js.map +0 -1
  149. package/dist/utils/limits.js.map +0 -1
  150. package/dist/utils/sanitize.js.map +0 -1
  151. package/dist/utils/validate.js.map +0 -1
@@ -1,97 +1,19 @@
1
1
  import type { ActFn, ActOptions, ActResult, AnyStateStore, SyncStateStore, AsyncStateStore } from '../types/index.js';
2
- /**
3
- * Execute `fn` with the given reliability policies.
4
- *
5
- * @param key Stable identifier for this action. Scopes dedupe + cache.
6
- * @param fn The async work to run. Receives an `AbortSignal` for
7
- * cooperative cancellation (legacy `() => Promise<T>` is
8
- * still accepted — the signal is simply ignored).
9
- * @param options Which policies to apply and how. All fields are optional.
10
- *
11
- * @returns `ActResult<T>` — always resolves, never throws.
12
- * Check `result.ok` before reading `result.value`.
13
- *
14
- * @example
15
- * // With cooperative cancellation
16
- * const result = await act('user:42', async (signal) => {
17
- * return fetch(`/api/users/42`, { signal })
18
- * }, {
19
- * retry: { attempts: 3, delayMs: 200, backoff: 'exponential' },
20
- * timeout: { ms: 5_000 },
21
- * totalTimeout: { ms: 12_000 },
22
- * dedupe: true,
23
- * cache: { ttl: 60_000 },
24
- * })
25
- *
26
- * if (result.ok) {
27
- * console.log(result.value, result.source, result.attempts)
28
- * } else {
29
- * console.error(result.error)
30
- * }
31
- */
32
- export declare function act<T>(key: string, fn: ActFn<T>, options?: ActOptions): Promise<ActResult<T>>;
33
- /**
34
- * Invalidate the cached value for `key` on the default module-level store.
35
- *
36
- * Only clears the cache slot — does not affect in-flight dedupe entries
37
- * (those will settle on their own). Returns `true` if a cache entry was
38
- * removed, `false` otherwise.
39
- *
40
- * Useful when you know the underlying data has changed and you want the
41
- * next `act()` call to re-run `fn` instead of serving stale cache:
42
- *
43
- * ```ts
44
- * await act('user:42', () => fetchUser(42), { cache: { ttl: 60_000 } })
45
- * // ... user updates their profile ...
46
- * invalidate('user:42') // next call will re-fetch
47
- * ```
48
- */
2
+ export declare function act<T>(key: string, fn: ActFn<T>, options?: ActOptions<T>): Promise<ActResult<T>>;
3
+ export { HedgeTimeoutError } from '../errors.js';
49
4
  export declare function invalidate(key: string): boolean;
50
- /** Result of `withStore()` for a sync store: `act` + sync `invalidate`. */
51
5
  export interface ScopedActSync {
52
- <T>(key: string, fn: ActFn<T>, options?: ActOptions): Promise<ActResult<T>>;
6
+ <T>(key: string, fn: ActFn<T>, options?: ActOptions<T>): Promise<ActResult<T>>;
53
7
  invalidate(key: string): boolean;
54
- /** The store this scope is bound to. Useful for `store.destroy()` etc. */
55
8
  readonly store: AnyStateStore;
9
+ readonly scope: string;
56
10
  }
57
- /** Result of `withStore()` for an async store: `act` + async `invalidate`. */
58
11
  export interface ScopedActAsync {
59
- <T>(key: string, fn: ActFn<T>, options?: ActOptions): Promise<ActResult<T>>;
12
+ <T>(key: string, fn: ActFn<T>, options?: ActOptions<T>): Promise<ActResult<T>>;
60
13
  invalidate(key: string): Promise<boolean>;
61
14
  readonly store: AnyStateStore;
15
+ readonly scope: string;
62
16
  }
63
- /**
64
- * Create a scoped `act` function bound to an explicit store.
65
- *
66
- * Use this for:
67
- * - **SSR request isolation**: one store per request, no cross-request
68
- * cache/dedupe leakage.
69
- * - **Multi-tenant scenarios**: one store per tenant, no cross-tenant
70
- * data leakage.
71
- * - **Test isolation**: each test gets a fresh store, no shared state.
72
- *
73
- * The returned function has the same signature as `act()`. It also exposes
74
- * an `invalidate(key)` method and a `store` reference for cleanup.
75
- *
76
- * For sync stores, `invalidate` returns `boolean` synchronously.
77
- * For async stores, `invalidate` returns `Promise<boolean>`.
78
- *
79
- * @example
80
- * ```ts
81
- * import { withStore, InMemoryStore } from 'actly'
82
- *
83
- * const store = new InMemoryStore({ maxSize: 1000, autoCleanup: true })
84
- * const act = withStore(store)
85
- *
86
- * try {
87
- * await act('user:42', () => fetchUser(42), { cache: { ttl: 60_000 } })
88
- * // ... user updates their profile ...
89
- * act.invalidate('user:42') // next call re-fetches
90
- * } finally {
91
- * store.destroy()
92
- * }
93
- * ```
94
- */
95
17
  export declare function withStore(store: SyncStateStore): ScopedActSync;
96
18
  export declare function withStore(store: AsyncStateStore): ScopedActAsync;
97
19
  export declare function withStore(store: AnyStateStore): ScopedActSync | ScopedActAsync;
@@ -1 +1 @@
1
- {"version":3,"file":"act.d.ts","sourceRoot":"","sources":["../../src/core/act.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,KAAK,EACL,UAAU,EACV,SAAS,EAGT,aAAa,EACb,cAAc,EACd,eAAe,EAEhB,MAAM,mBAAmB,CAAA;AA4L1B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAsB,GAAG,CAAC,CAAC,EACzB,GAAG,EAAE,MAAM,EACX,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,EACZ,OAAO,GAAE,UAAe,GACvB,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CA8JvB;AA+BD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAM/C;AAID,2EAA2E;AAC3E,MAAM,WAAW,aAAa;IAC5B,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAA;IAC3E,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;IAChC,0EAA0E;IAC1E,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAA;CAC9B;AAED,8EAA8E;AAC9E,MAAM,WAAW,cAAc;IAC7B,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAA;IAC3E,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IACzC,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAA;CAC9B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,aAAa,CAAA;AAC/D,wBAAgB,SAAS,CAAC,KAAK,EAAE,eAAe,GAAG,cAAc,CAAA;AACjE,wBAAgB,SAAS,CAAC,KAAK,EAAE,aAAa,GAAG,aAAa,GAAG,cAAc,CAAA"}
1
+ {"version":3,"file":"act.d.ts","sourceRoot":"","sources":["../../src/core/act.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,KAAK,EACL,UAAU,EACV,SAAS,EAGT,aAAa,EACb,cAAc,EACd,eAAe,EAGhB,MAAM,mBAAmB,CAAA;AA0N1B,wBAAsB,GAAG,CAAC,CAAC,EACzB,GAAG,EAAE,MAAM,EACX,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,EACZ,OAAO,GAAE,UAAU,CAAC,CAAC,CAAM,GAC1B,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAgSvB;AAcD,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AA4JhD,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAM/C;AAKD,MAAM,WAAW,aAAa;IAC5B,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAA;IAC9E,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;IAEhC,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAA;IAM7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB;AAGD,MAAM,WAAW,cAAc;IAC7B,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAA;IAC9E,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IACzC,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAA;IAE7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB;AAsBD,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,aAAa,CAAA;AAC/D,wBAAgB,SAAS,CAAC,KAAK,EAAE,eAAe,GAAG,cAAc,CAAA;AACjE,wBAAgB,SAAS,CAAC,KAAK,EAAE,aAAa,GAAG,aAAa,GAAG,cAAc,CAAA"}