actly 1.0.1 → 1.1.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 (44) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +380 -0
  3. package/dist/core/act.cjs +5 -3
  4. package/dist/core/act.d.ts.map +1 -1
  5. package/dist/core/act.js +4 -2
  6. package/dist/core/act.js.map +1 -1
  7. package/dist/core/executor.cjs +16 -0
  8. package/dist/core/executor.d.ts +9 -7
  9. package/dist/core/executor.d.ts.map +1 -1
  10. package/dist/core/executor.js +15 -0
  11. package/dist/core/executor.js.map +1 -1
  12. package/dist/index.cjs +2 -2
  13. package/dist/index.d.ts +3 -2
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +1 -1
  16. package/dist/index.js.map +1 -1
  17. package/dist/policies/cache.cjs +27 -7
  18. package/dist/policies/cache.d.ts +5 -0
  19. package/dist/policies/cache.d.ts.map +1 -1
  20. package/dist/policies/cache.js +27 -7
  21. package/dist/policies/cache.js.map +1 -1
  22. package/dist/policies/dedupe.cjs +24 -9
  23. package/dist/policies/dedupe.d.ts +7 -0
  24. package/dist/policies/dedupe.d.ts.map +1 -1
  25. package/dist/policies/dedupe.js +24 -9
  26. package/dist/policies/dedupe.js.map +1 -1
  27. package/dist/state/store.cjs +4 -38
  28. package/dist/state/store.d.ts +1 -12
  29. package/dist/state/store.d.ts.map +1 -1
  30. package/dist/state/store.js +3 -37
  31. package/dist/state/store.js.map +1 -1
  32. package/dist/stores/base.cjs +20 -0
  33. package/dist/stores/base.d.ts +112 -0
  34. package/dist/stores/base.d.ts.map +1 -0
  35. package/dist/stores/base.js +17 -0
  36. package/dist/stores/base.js.map +1 -0
  37. package/dist/stores/memory.cjs +91 -0
  38. package/dist/stores/memory.d.ts +58 -0
  39. package/dist/stores/memory.d.ts.map +1 -0
  40. package/dist/stores/memory.js +88 -0
  41. package/dist/stores/memory.js.map +1 -0
  42. package/dist/types/index.d.ts +20 -8
  43. package/dist/types/index.d.ts.map +1 -1
  44. package/package.json +1 -1
@@ -0,0 +1,88 @@
1
+ function isUnrefable(t) {
2
+ return typeof t.unref === 'function';
3
+ }
4
+ // ─── Implementation ───────────────────────────────────────────────────────────
5
+ export class InMemoryStore {
6
+ constructor(options = {}) {
7
+ // Discriminant read by isSyncStore() in execute() to enforce the dedupe
8
+ // constraint at runtime for JS callers who bypass TypeScript.
9
+ this._sync = true;
10
+ this.entries = new Map();
11
+ const { autoCleanup = false, cleanupIntervalMs = 30000 } = options;
12
+ if (autoCleanup) {
13
+ const timer = setInterval(() => this._sweep(), cleanupIntervalMs);
14
+ // Prevent the interval from keeping the Node.js process alive when the
15
+ // application has otherwise finished its work. Safe no-op in browsers.
16
+ if (isUnrefable(timer))
17
+ timer.unref();
18
+ this.cleanupTimer = timer;
19
+ }
20
+ }
21
+ get(key) {
22
+ const entry = this.entries.get(key);
23
+ if (!entry)
24
+ return undefined;
25
+ if (entry.expiresAt !== null && Date.now() > entry.expiresAt) {
26
+ this.entries.delete(key);
27
+ return undefined;
28
+ }
29
+ return entry.value;
30
+ }
31
+ set(key, value, ttlMs) {
32
+ // ttlMs = 0 or undefined → no expiry (sentinel null)
33
+ const expiresAt = ttlMs != null && ttlMs > 0 ? Date.now() + ttlMs : null;
34
+ this.entries.set(key, { value, expiresAt });
35
+ }
36
+ delete(key) {
37
+ this.entries.delete(key);
38
+ }
39
+ has(key) {
40
+ // Delegate to get() so expired entries are evicted on access.
41
+ return this.get(key) !== undefined;
42
+ }
43
+ /**
44
+ * Remove all entries.
45
+ * After this call, size() returns 0.
46
+ */
47
+ clear() {
48
+ this.entries.clear();
49
+ }
50
+ /**
51
+ * Return the count of live (non-expired) entries.
52
+ *
53
+ * Expired entries are evicted during the scan, so repeated calls are
54
+ * slightly cheaper as the map self-prunes. O(n) in the number of entries.
55
+ */
56
+ size() {
57
+ // Evict expired entries as we scan — keeps the map tidy between sweeps
58
+ // and ensures the returned count reflects only observable entries.
59
+ for (const key of this.entries.keys())
60
+ this.has(key);
61
+ return this.entries.size;
62
+ }
63
+ /**
64
+ * Stop the background cleanup timer and release internal state.
65
+ * Safe to call multiple times — subsequent calls are no-ops.
66
+ *
67
+ * Call destroy() when discarding a long-lived store instance to prevent
68
+ * timer leaks. Stores without autoCleanup enabled have nothing to release,
69
+ * but destroy() is safe to call on them regardless.
70
+ */
71
+ destroy() {
72
+ if (this.cleanupTimer !== undefined) {
73
+ clearInterval(this.cleanupTimer);
74
+ this.cleanupTimer = undefined;
75
+ }
76
+ }
77
+ // Sweep all entries and remove those past their expiry time.
78
+ // Called by the autoCleanup interval — not part of the public contract.
79
+ _sweep() {
80
+ const now = Date.now();
81
+ for (const [key, entry] of this.entries) {
82
+ if (entry.expiresAt !== null && now > entry.expiresAt) {
83
+ this.entries.delete(key);
84
+ }
85
+ }
86
+ }
87
+ }
88
+ //# sourceMappingURL=memory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.js","sourceRoot":"","sources":["../../src/stores/memory.ts"],"names":[],"mappings":"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"}
@@ -95,7 +95,7 @@ export interface RunMeta {
95
95
  /** Everything a policy receives about the current run */
96
96
  export interface PolicyContext {
97
97
  key: string;
98
- store: StateStore;
98
+ store: AnyStateStore;
99
99
  meta: RunMeta;
100
100
  }
101
101
  /**
@@ -106,11 +106,23 @@ export interface PolicyContext {
106
106
  * The executor never imports a concrete policy — only this type.
107
107
  */
108
108
  export type PolicyApplier<T> = (fn: ActFn<T>, ctx: PolicyContext) => ActFn<T>;
109
- /** Minimal key-value contract used by dedupe and cache policies */
110
- export interface StateStore {
111
- get<T>(key: string): T | undefined;
112
- set<T>(key: string, value: T, ttlMs?: number): void;
113
- delete(key: string): void;
114
- has(key: string): boolean;
115
- }
109
+ import type { SyncStateStore, AsyncStateStore } from '../stores/base.js';
110
+ export type { SyncStateStore, AsyncStateStore };
111
+ /**
112
+ * Public store type. v1.1: alias for SyncStateStore to preserve the
113
+ * existing contract — every v1.0 consumer typed against StateStore
114
+ * continues to compile without changes.
115
+ *
116
+ * A future major version may widen this to SyncStateStore | AsyncStateStore
117
+ * once call sites have been audited. For now: additive, non-breaking.
118
+ */
119
+ export type StateStore = SyncStateStore;
120
+ /**
121
+ * Accepted by policies that support both sync and async stores (e.g. cache).
122
+ * Not part of the public surface yet — internal use only until the
123
+ * async-store path is fully documented and example adapters ship.
124
+ *
125
+ * @internal
126
+ */
127
+ export type AnyStateStore = SyncStateStore | AsyncStateStore;
116
128
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAEA,mCAAmC;AACnC,MAAM,MAAM,KAAK,CAAC,CAAC,IAAI,MAAM,OAAO,CAAC,CAAC,CAAC,CAAA;AAEvC,0CAA0C;AAC1C,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,OAAO,CAAA;AAEzC,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B,EAAE,EAAE,IAAI,CAAA;IACR,KAAK,EAAE,CAAC,CAAA;IACR,MAAM,EAAE,SAAS,CAAA;IACjB,6CAA6C;IAC7C,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,KAAK,CAAA;IACT,KAAK,EAAE,OAAO,CAAA;IACd,mDAAmD;IACnD,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,GAAG,UAAU,CAAA;AAIrD,MAAM,WAAW,YAAY;IAC3B,uEAAuE;IACvE,QAAQ,EAAE,MAAM,CAAA;IAChB,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,aAAa,CAAA;IAC3C;;;;;;;;;;;;;OAaG;IACH,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAA;CAC3D;AAED,MAAM,WAAW,cAAc;IAC7B,+BAA+B;IAC/B,EAAE,EAAE,MAAM,CAAA;CACX;AAED,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,OAAO,EAAE,OAAO,CAAA;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,gDAAgD;IAChD,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,EAAS,YAAY,CAAA;IAC3B,OAAO,CAAC,EAAO,cAAc,CAAA;IAC7B;;;;;;;OAOG;IACH,MAAM,CAAC,EAAQ,OAAO,GAAG,aAAa,CAAA;IACtC,KAAK,CAAC,EAAS,YAAY,CAAA;IAC3B;;;;;;;;;OASG;IACH,YAAY,CAAC,EAAE,cAAc,CAAA;CAC9B;AAID;;;GAGG;AACH,MAAM,WAAW,OAAO;IACtB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAI,SAAS,CAAA;CACpB;AAED,yDAAyD;AACzD,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAI,MAAM,CAAA;IACb,KAAK,EAAE,UAAU,CAAA;IACjB,IAAI,EAAG,OAAO,CAAA;CACf;AAED;;;;;;GAMG;AACH,MAAM,MAAM,aAAa,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,aAAa,KAAK,KAAK,CAAC,CAAC,CAAC,CAAA;AAI7E,mEAAmE;AACnE,MAAM,WAAW,UAAU;IACzB,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAAA;IAClC,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACnD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAC1B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAEA,mCAAmC;AACnC,MAAM,MAAM,KAAK,CAAC,CAAC,IAAI,MAAM,OAAO,CAAC,CAAC,CAAC,CAAA;AAEvC,0CAA0C;AAC1C,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,OAAO,CAAA;AAEzC,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B,EAAE,EAAE,IAAI,CAAA;IACR,KAAK,EAAE,CAAC,CAAA;IACR,MAAM,EAAE,SAAS,CAAA;IACjB,6CAA6C;IAC7C,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,KAAK,CAAA;IACT,KAAK,EAAE,OAAO,CAAA;IACd,mDAAmD;IACnD,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,GAAG,UAAU,CAAA;AAIrD,MAAM,WAAW,YAAY;IAC3B,uEAAuE;IACvE,QAAQ,EAAE,MAAM,CAAA;IAChB,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,aAAa,CAAA;IAC3C;;;;;;;;;;;;;OAaG;IACH,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAA;CAC3D;AAED,MAAM,WAAW,cAAc;IAC7B,+BAA+B;IAC/B,EAAE,EAAE,MAAM,CAAA;CACX;AAED,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,OAAO,EAAE,OAAO,CAAA;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,gDAAgD;IAChD,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,EAAS,YAAY,CAAA;IAC3B,OAAO,CAAC,EAAO,cAAc,CAAA;IAC7B;;;;;;;OAOG;IACH,MAAM,CAAC,EAAQ,OAAO,GAAG,aAAa,CAAA;IACtC,KAAK,CAAC,EAAS,YAAY,CAAA;IAC3B;;;;;;;;;OASG;IACH,YAAY,CAAC,EAAE,cAAc,CAAA;CAC9B;AAID;;;GAGG;AACH,MAAM,WAAW,OAAO;IACtB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAI,SAAS,CAAA;CACpB;AAED,yDAAyD;AACzD,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAI,MAAM,CAAA;IACb,KAAK,EAAE,aAAa,CAAA;IACpB,IAAI,EAAG,OAAO,CAAA;CACf;AAED;;;;;;GAMG;AACH,MAAM,MAAM,aAAa,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,aAAa,KAAK,KAAK,CAAC,CAAC,CAAC,CAAA;AAO7E,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACxE,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,CAAA;AAE/C;;;;;;;GAOG;AACH,MAAM,MAAM,UAAU,GAAG,cAAc,CAAA;AAEvC;;;;;;GAMG;AACH,MAAM,MAAM,aAAa,GAAG,cAAc,GAAG,eAAe,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "actly",
3
- "version": "1.0.1",
3
+ "version": "1.1.0",
4
4
  "description": "A reliability primitive for executing async actions safely.",
5
5
  "keywords": [
6
6
  "reliability",