awaitly 1.34.0 → 2.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/dist/{duration.d.ts → di-BDlT7InM.d.cts} +15 -1
- package/dist/{duration.d.cts → di-BbFFfO8y.d.ts} +15 -1
- package/dist/errors-DtXvrCiO.d.cts +708 -0
- package/dist/errors-DtXvrCiO.d.ts +708 -0
- package/dist/index.cjs +4594 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1970 -141
- package/dist/index.d.ts +1970 -141
- package/dist/index.js +4398 -1
- package/dist/index.js.map +1 -1
- package/dist/result.cjs +641 -1
- package/dist/result.cjs.map +1 -1
- package/dist/result.d.cts +35 -5
- package/dist/result.d.ts +35 -5
- package/dist/result.js +561 -1
- package/dist/result.js.map +1 -1
- package/dist/testing.cjs +4202 -8
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +2 -6
- package/dist/testing.d.ts +2 -6
- package/dist/testing.js +4154 -8
- package/dist/testing.js.map +1 -1
- package/dist/{run-entry-D2MmJFj9.d.cts → types-B8NfNRGX.d.ts} +1152 -1499
- package/dist/{run-entry-Dduz-is2.d.ts → types-BZ2f4MRR.d.cts} +1152 -1499
- package/dist/workflow.cjs +7096 -6
- package/dist/workflow.cjs.map +1 -1
- package/dist/workflow.d.cts +3346 -22
- package/dist/workflow.d.ts +3346 -22
- package/dist/workflow.js +6929 -6
- package/dist/workflow.js.map +1 -1
- package/package.json +13 -178
- package/dist/adapters.cjs +0 -7
- package/dist/adapters.cjs.map +0 -1
- package/dist/adapters.d.cts +0 -179
- package/dist/adapters.d.ts +0 -179
- package/dist/adapters.js +0 -7
- package/dist/adapters.js.map +0 -1
- package/dist/batch.cjs +0 -7
- package/dist/batch.cjs.map +0 -1
- package/dist/batch.d.cts +0 -200
- package/dist/batch.d.ts +0 -200
- package/dist/batch.js +0 -7
- package/dist/batch.js.map +0 -1
- package/dist/bind-deps.cjs +0 -2
- package/dist/bind-deps.cjs.map +0 -1
- package/dist/bind-deps.d.cts +0 -28
- package/dist/bind-deps.d.ts +0 -28
- package/dist/bind-deps.js +0 -2
- package/dist/bind-deps.js.map +0 -1
- package/dist/cache.cjs +0 -2
- package/dist/cache.cjs.map +0 -1
- package/dist/cache.d.cts +0 -269
- package/dist/cache.d.ts +0 -269
- package/dist/cache.js +0 -2
- package/dist/cache.js.map +0 -1
- package/dist/circuit-breaker.cjs +0 -7
- package/dist/circuit-breaker.cjs.map +0 -1
- package/dist/circuit-breaker.d.cts +0 -211
- package/dist/circuit-breaker.d.ts +0 -211
- package/dist/circuit-breaker.js +0 -7
- package/dist/circuit-breaker.js.map +0 -1
- package/dist/conditional.cjs +0 -2
- package/dist/conditional.cjs.map +0 -1
- package/dist/conditional.d.cts +0 -252
- package/dist/conditional.d.ts +0 -252
- package/dist/conditional.js +0 -2
- package/dist/conditional.js.map +0 -1
- package/dist/core.cjs +0 -7
- package/dist/core.cjs.map +0 -1
- package/dist/core.d.cts +0 -5
- package/dist/core.d.ts +0 -5
- package/dist/core.js +0 -7
- package/dist/core.js.map +0 -1
- package/dist/di-COl5oFnR.d.cts +0 -15
- package/dist/di-CyDj_JyZ.d.ts +0 -15
- package/dist/diagnostics.cjs +0 -8
- package/dist/diagnostics.cjs.map +0 -1
- package/dist/diagnostics.d.cts +0 -68
- package/dist/diagnostics.d.ts +0 -68
- package/dist/diagnostics.js +0 -8
- package/dist/diagnostics.js.map +0 -1
- package/dist/durable.cjs +0 -11
- package/dist/durable.cjs.map +0 -1
- package/dist/durable.d.cts +0 -9
- package/dist/durable.d.ts +0 -9
- package/dist/durable.js +0 -11
- package/dist/durable.js.map +0 -1
- package/dist/duration.cjs +0 -2
- package/dist/duration.cjs.map +0 -1
- package/dist/duration.js +0 -2
- package/dist/duration.js.map +0 -1
- package/dist/engine.cjs +0 -11
- package/dist/engine.cjs.map +0 -1
- package/dist/engine.d.cts +0 -115
- package/dist/engine.d.ts +0 -115
- package/dist/engine.js +0 -11
- package/dist/engine.js.map +0 -1
- package/dist/errors.cjs +0 -2
- package/dist/errors.cjs.map +0 -1
- package/dist/errors.d.cts +0 -361
- package/dist/errors.d.ts +0 -361
- package/dist/errors.js +0 -2
- package/dist/errors.js.map +0 -1
- package/dist/fetch.cjs +0 -7
- package/dist/fetch.cjs.map +0 -1
- package/dist/fetch.d.cts +0 -86
- package/dist/fetch.d.ts +0 -86
- package/dist/fetch.js +0 -7
- package/dist/fetch.js.map +0 -1
- package/dist/flow.cjs +0 -7
- package/dist/flow.cjs.map +0 -1
- package/dist/flow.d.cts +0 -163
- package/dist/flow.d.ts +0 -163
- package/dist/flow.js +0 -7
- package/dist/flow.js.map +0 -1
- package/dist/functional.cjs +0 -2
- package/dist/functional.cjs.map +0 -1
- package/dist/functional.d.cts +0 -444
- package/dist/functional.d.ts +0 -444
- package/dist/functional.js +0 -2
- package/dist/functional.js.map +0 -1
- package/dist/guards-BodHXLzX.d.cts +0 -72
- package/dist/guards-CeWoQ8fn.d.ts +0 -72
- package/dist/hitl-BPE_1UiM.d.cts +0 -468
- package/dist/hitl-byp570uC.d.ts +0 -468
- package/dist/hitl.cjs +0 -7
- package/dist/hitl.cjs.map +0 -1
- package/dist/hitl.d.cts +0 -442
- package/dist/hitl.d.ts +0 -442
- package/dist/hitl.js +0 -7
- package/dist/hitl.js.map +0 -1
- package/dist/index-BYT3amEz.d.ts +0 -417
- package/dist/index-C_ak66jy.d.cts +0 -417
- package/dist/match-entry-DjI2bLpD.d.cts +0 -209
- package/dist/match-entry-DjI2bLpD.d.ts +0 -209
- package/dist/match.cjs +0 -2
- package/dist/match.cjs.map +0 -1
- package/dist/match.d.cts +0 -1
- package/dist/match.d.ts +0 -1
- package/dist/match.js +0 -2
- package/dist/match.js.map +0 -1
- package/dist/otel.cjs +0 -2
- package/dist/otel.cjs.map +0 -1
- package/dist/otel.d.cts +0 -188
- package/dist/otel.d.ts +0 -188
- package/dist/otel.js +0 -2
- package/dist/otel.js.map +0 -1
- package/dist/persistence-entry-DOMx3woy.d.ts +0 -822
- package/dist/persistence-entry-ymCA4iDu.d.cts +0 -822
- package/dist/persistence.cjs +0 -2
- package/dist/persistence.cjs.map +0 -1
- package/dist/persistence.d.cts +0 -7
- package/dist/persistence.d.ts +0 -7
- package/dist/persistence.js +0 -2
- package/dist/persistence.js.map +0 -1
- package/dist/policies.cjs +0 -2
- package/dist/policies.cjs.map +0 -1
- package/dist/policies.d.cts +0 -379
- package/dist/policies.d.ts +0 -379
- package/dist/policies.js +0 -2
- package/dist/policies.js.map +0 -1
- package/dist/ratelimit.cjs +0 -7
- package/dist/ratelimit.cjs.map +0 -1
- package/dist/ratelimit.d.cts +0 -458
- package/dist/ratelimit.d.ts +0 -458
- package/dist/ratelimit.js +0 -7
- package/dist/ratelimit.js.map +0 -1
- package/dist/reliability.cjs +0 -11
- package/dist/reliability.cjs.map +0 -1
- package/dist/reliability.d.cts +0 -11
- package/dist/reliability.d.ts +0 -11
- package/dist/reliability.js +0 -11
- package/dist/reliability.js.map +0 -1
- package/dist/resolver.cjs +0 -7
- package/dist/resolver.cjs.map +0 -1
- package/dist/resolver.d.cts +0 -68
- package/dist/resolver.d.ts +0 -68
- package/dist/resolver.js +0 -7
- package/dist/resolver.js.map +0 -1
- package/dist/resource.cjs +0 -7
- package/dist/resource.cjs.map +0 -1
- package/dist/resource.d.cts +0 -174
- package/dist/resource.d.ts +0 -174
- package/dist/resource.js +0 -7
- package/dist/resource.js.map +0 -1
- package/dist/result/retry.cjs +0 -2
- package/dist/result/retry.cjs.map +0 -1
- package/dist/result/retry.d.cts +0 -70
- package/dist/result/retry.d.ts +0 -70
- package/dist/result/retry.js +0 -2
- package/dist/result/retry.js.map +0 -1
- package/dist/retry.cjs +0 -2
- package/dist/retry.cjs.map +0 -1
- package/dist/retry.d.cts +0 -388
- package/dist/retry.d.ts +0 -388
- package/dist/retry.js +0 -2
- package/dist/retry.js.map +0 -1
- package/dist/run.cjs +0 -7
- package/dist/run.cjs.map +0 -1
- package/dist/run.d.cts +0 -4
- package/dist/run.d.ts +0 -4
- package/dist/run.js +0 -7
- package/dist/run.js.map +0 -1
- package/dist/saga.cjs +0 -11
- package/dist/saga.cjs.map +0 -1
- package/dist/saga.d.cts +0 -164
- package/dist/saga.d.ts +0 -164
- package/dist/saga.js +0 -11
- package/dist/saga.js.map +0 -1
- package/dist/singleflight.cjs +0 -2
- package/dist/singleflight.cjs.map +0 -1
- package/dist/singleflight.d.cts +0 -145
- package/dist/singleflight.d.ts +0 -145
- package/dist/singleflight.js +0 -2
- package/dist/singleflight.js.map +0 -1
- package/dist/slugs.cjs +0 -2
- package/dist/slugs.cjs.map +0 -1
- package/dist/slugs.d.cts +0 -67
- package/dist/slugs.d.ts +0 -67
- package/dist/slugs.js +0 -2
- package/dist/slugs.js.map +0 -1
- package/dist/streaming.cjs +0 -9
- package/dist/streaming.cjs.map +0 -1
- package/dist/streaming.d.cts +0 -596
- package/dist/streaming.d.ts +0 -596
- package/dist/streaming.js +0 -9
- package/dist/streaming.js.map +0 -1
- package/dist/tagged-error.cjs +0 -2
- package/dist/tagged-error.cjs.map +0 -1
- package/dist/tagged-error.d.cts +0 -275
- package/dist/tagged-error.d.ts +0 -275
- package/dist/tagged-error.js +0 -2
- package/dist/tagged-error.js.map +0 -1
- package/dist/types-DQmzO9f4.d.ts +0 -323
- package/dist/types-qBUOYi-4.d.cts +0 -323
- package/dist/webhook.cjs +0 -7
- package/dist/webhook.cjs.map +0 -1
- package/dist/webhook.d.cts +0 -499
- package/dist/webhook.d.ts +0 -499
- package/dist/webhook.js +0 -7
- package/dist/webhook.js.map +0 -1
package/dist/bind-deps.cjs
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
"use strict";var t=Object.defineProperty;var o=Object.getOwnPropertyDescriptor;var d=Object.getOwnPropertyNames;var n=Object.prototype.hasOwnProperty;var A=(e,s)=>{for(var p in s)t(e,p,{get:s[p],enumerable:!0})},b=(e,s,p,D)=>{if(s&&typeof s=="object"||typeof s=="function")for(let r of d(s))!n.call(e,r)&&r!==p&&t(e,r,{get:()=>s[r],enumerable:!(D=o(s,r))||D.enumerable});return e};var i=e=>b(t({},"__esModule",{value:!0}),e);var u={};A(u,{bindDeps:()=>g});module.exports=i(u);var g=e=>s=>p=>e(p,s);0&&(module.exports={bindDeps});
|
|
2
|
-
//# sourceMappingURL=bind-deps.cjs.map
|
package/dist/bind-deps.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/bind-deps-entry.ts","../src/bind-deps.ts"],"sourcesContent":["/**\n * awaitly/bind-deps\n *\n * Partial application utility for the fn(args, deps) pattern.\n */\nexport { bindDeps } from \"./bind-deps\";\n","/**\n * awaitly/bind-deps\n *\n * Partial application utility for the fn(args, deps) pattern.\n * Transforms a function from fn(args, deps) => out into a curried form:\n * (deps) => (args) => out\n *\n * Use at composition boundaries to bind deps once, then call with args.\n * Keep core implementations in the explicit fn(args, deps) form for testing.\n *\n * @example\n * ```typescript\n * import { bindDeps } from 'awaitly/bind-deps';\n *\n * // Core function stays explicit and testable\n * const notify = (args: { name: string }, deps: { send: SendFn }) =>\n * deps.send(args.name);\n *\n * // At composition boundary, bind deps once\n * const notifySlack = bindDeps(notify)(slackDeps);\n *\n * // Call site is clean\n * await notifySlack({ name: 'Alice' });\n * ```\n */\n\nexport const bindDeps =\n <Args, Deps, Out>(fn: (args: Args, deps: Deps) => Out) =>\n (deps: Deps) =>\n (args: Args) =>\n fn(args, deps);\n"],"mappings":"yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,cAAAE,IAAA,eAAAC,EAAAH,GC0BO,IAAMI,EACOC,GACjBC,GACAC,GACCF,EAAGE,EAAMD,CAAI","names":["bind_deps_entry_exports","__export","bindDeps","__toCommonJS","bindDeps","fn","deps","args"]}
|
package/dist/bind-deps.d.cts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* awaitly/bind-deps
|
|
3
|
-
*
|
|
4
|
-
* Partial application utility for the fn(args, deps) pattern.
|
|
5
|
-
* Transforms a function from fn(args, deps) => out into a curried form:
|
|
6
|
-
* (deps) => (args) => out
|
|
7
|
-
*
|
|
8
|
-
* Use at composition boundaries to bind deps once, then call with args.
|
|
9
|
-
* Keep core implementations in the explicit fn(args, deps) form for testing.
|
|
10
|
-
*
|
|
11
|
-
* @example
|
|
12
|
-
* ```typescript
|
|
13
|
-
* import { bindDeps } from 'awaitly/bind-deps';
|
|
14
|
-
*
|
|
15
|
-
* // Core function stays explicit and testable
|
|
16
|
-
* const notify = (args: { name: string }, deps: { send: SendFn }) =>
|
|
17
|
-
* deps.send(args.name);
|
|
18
|
-
*
|
|
19
|
-
* // At composition boundary, bind deps once
|
|
20
|
-
* const notifySlack = bindDeps(notify)(slackDeps);
|
|
21
|
-
*
|
|
22
|
-
* // Call site is clean
|
|
23
|
-
* await notifySlack({ name: 'Alice' });
|
|
24
|
-
* ```
|
|
25
|
-
*/
|
|
26
|
-
declare const bindDeps: <Args, Deps, Out>(fn: (args: Args, deps: Deps) => Out) => (deps: Deps) => (args: Args) => Out;
|
|
27
|
-
|
|
28
|
-
export { bindDeps };
|
package/dist/bind-deps.d.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* awaitly/bind-deps
|
|
3
|
-
*
|
|
4
|
-
* Partial application utility for the fn(args, deps) pattern.
|
|
5
|
-
* Transforms a function from fn(args, deps) => out into a curried form:
|
|
6
|
-
* (deps) => (args) => out
|
|
7
|
-
*
|
|
8
|
-
* Use at composition boundaries to bind deps once, then call with args.
|
|
9
|
-
* Keep core implementations in the explicit fn(args, deps) form for testing.
|
|
10
|
-
*
|
|
11
|
-
* @example
|
|
12
|
-
* ```typescript
|
|
13
|
-
* import { bindDeps } from 'awaitly/bind-deps';
|
|
14
|
-
*
|
|
15
|
-
* // Core function stays explicit and testable
|
|
16
|
-
* const notify = (args: { name: string }, deps: { send: SendFn }) =>
|
|
17
|
-
* deps.send(args.name);
|
|
18
|
-
*
|
|
19
|
-
* // At composition boundary, bind deps once
|
|
20
|
-
* const notifySlack = bindDeps(notify)(slackDeps);
|
|
21
|
-
*
|
|
22
|
-
* // Call site is clean
|
|
23
|
-
* await notifySlack({ name: 'Alice' });
|
|
24
|
-
* ```
|
|
25
|
-
*/
|
|
26
|
-
declare const bindDeps: <Args, Deps, Out>(fn: (args: Args, deps: Deps) => Out) => (deps: Deps) => (args: Args) => Out;
|
|
27
|
-
|
|
28
|
-
export { bindDeps };
|
package/dist/bind-deps.js
DELETED
package/dist/bind-deps.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/bind-deps.ts"],"sourcesContent":["/**\n * awaitly/bind-deps\n *\n * Partial application utility for the fn(args, deps) pattern.\n * Transforms a function from fn(args, deps) => out into a curried form:\n * (deps) => (args) => out\n *\n * Use at composition boundaries to bind deps once, then call with args.\n * Keep core implementations in the explicit fn(args, deps) form for testing.\n *\n * @example\n * ```typescript\n * import { bindDeps } from 'awaitly/bind-deps';\n *\n * // Core function stays explicit and testable\n * const notify = (args: { name: string }, deps: { send: SendFn }) =>\n * deps.send(args.name);\n *\n * // At composition boundary, bind deps once\n * const notifySlack = bindDeps(notify)(slackDeps);\n *\n * // Call site is clean\n * await notifySlack({ name: 'Alice' });\n * ```\n */\n\nexport const bindDeps =\n <Args, Deps, Out>(fn: (args: Args, deps: Deps) => Out) =>\n (deps: Deps) =>\n (args: Args) =>\n fn(args, deps);\n"],"mappings":"AA0BO,IAAMA,EACOC,GACjBC,GACAC,GACCF,EAAGE,EAAMD,CAAI","names":["bindDeps","fn","deps","args"]}
|
package/dist/cache.cjs
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
"use strict";var g=Object.defineProperty;var M=Object.getOwnPropertyDescriptor;var S=Object.getOwnPropertyNames;var z=Object.prototype.hasOwnProperty;var O=(e,t)=>{for(var r in t)g(e,r,{get:t[r],enumerable:!0})},F=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of S(t))!z.call(e,i)&&i!==r&&g(e,i,{get:()=>t[i],enumerable:!(n=M(t,i))||n.enumerable});return e};var I=e=>F(g({},"__esModule",{value:!0}),e);var V={};O(V,{cached:()=>b,cachedFunction:()=>C,cachedWithTTL:()=>A,createCache:()=>P,once:()=>w});module.exports=I(V);function K(e){return{_tag:"Duration",millis:e}}function k(e){return{_tag:"Duration",millis:e*1e3}}function _(e){return{_tag:"Duration",millis:e*60*1e3}}function E(e){return{_tag:"Duration",millis:e*60*60*1e3}}function L(e){return{_tag:"Duration",millis:e*24*60*60*1e3}}function T(e){let t=e.trim().match(/^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)$/i);if(!t)return;let r=parseFloat(t[1]);switch(t[2].toLowerCase()){case"ms":return K(r);case"s":return k(r);case"m":return _(r);case"h":return E(r);case"d":return L(r);default:return}}function h(e){if(typeof e=="string"){let t=T(e);if(!t)throw new Error(`Invalid duration string: ${e}`);return t.millis}return e.millis}function b(e){let t={status:"empty"};return async()=>{if(t.status==="filled")return t.value;if(t.status==="pending")return t.promise;let r=Promise.resolve(e()).then(n=>(t={status:"filled",value:n},n));return t={status:"pending",promise:r},r}}function A(e,t){let r=h(t.ttl),n={status:"empty"};return async()=>{let i=Date.now();if(n.status==="filled"&&i<n.expiresAt)return n.value;if(n.status==="pending")return n.promise;let s=Promise.resolve(e()).then(c=>(n={status:"filled",value:c,expiresAt:Date.now()+r},c));return n={status:"pending",promise:s},s}}function C(e,t={}){let{keyFn:r=(...u)=>JSON.stringify(u),maxSize:n=1/0}=t,i=t.ttl?h(t.ttl):void 0,s=new Map,c=new Map,d=0,o=0;function l(){if(s.size<=n)return;let u=null,a=1/0;for(let[p,f]of s.entries())f.timestamp<a&&(a=f.timestamp,u=p);u&&s.delete(u)}let m=async(...u)=>{let a=r(...u),p=Date.now(),f=s.get(a);if(f)if(f.expiresAt&&p>=f.expiresAt)s.delete(a);else return d++,f.value;let x=c.get(a);if(x)return x;o++;let y=Promise.resolve(e(...u)).then(D=>{let v={value:D,timestamp:Date.now(),expiresAt:i?Date.now()+i:void 0};return s.set(a,v),c.delete(a),l(),D});c.set(a,y);try{return await y}catch(D){throw c.delete(a),D}};return m.clear=()=>{s.clear(),c.clear()},m.delete=(...u)=>{let a=r(...u);return s.delete(a)},m.has=(...u)=>{let a=r(...u),p=s.get(a);return p?p.expiresAt&&Date.now()>=p.expiresAt?(s.delete(a),!1):!0:!1},m.getStats=()=>({hits:d,misses:o,size:s.size}),m}function w(e){let t={status:"idle"},r=async()=>{if(t.status==="done")return t.value;if(t.status==="failed")throw t.error;if(t.status==="running")return t.promise;let n=Promise.resolve(e()).then(i=>(t={status:"done",value:i},i)).catch(i=>{throw t={status:"failed",error:i},i});return t={status:"running",promise:n},n};return Object.defineProperty(r,"called",{get:()=>t.status!=="idle"}),Object.defineProperty(r,"completed",{get:()=>t.status==="done"}),Object.defineProperty(r,"failed",{get:()=>t.status==="failed"}),r.reset=()=>{t={status:"idle"}},r}function P(e={}){let{maxSize:t=1/0}=e,r=e.defaultTTL?h(e.defaultTTL):void 0,n=new Map,i=0,s=0;function c(o){return o.expiresAt!==void 0&&Date.now()>=o.expiresAt}function d(){if(n.size<=t)return;let o=null,l=1/0;for(let[m,u]of n.entries())u.timestamp<l&&(l=u.timestamp,o=m);o!==null&&n.delete(o)}return{get(o){let l=n.get(o);if(!l){s++;return}if(c(l)){n.delete(o),s++;return}return i++,l.value},set(o,l,m){let u=m?.ttl?h(m.ttl):r,a=Date.now();n.set(o,{value:l,timestamp:a,expiresAt:u?a+u:void 0}),d()},has(o){let l=n.get(o);return l?c(l)?(n.delete(o),!1):!0:!1},delete(o){return n.delete(o)},clear(){n.clear()},get size(){return n.size},getStats(){return{hits:i,misses:s,size:n.size}}}}0&&(module.exports={cached,cachedFunction,cachedWithTTL,createCache,once});
|
|
2
|
-
//# sourceMappingURL=cache.cjs.map
|
package/dist/cache.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cache-entry.ts","../src/duration.ts","../src/cache.ts"],"sourcesContent":["/**\n * awaitly/cache\n *\n * Caching utilities for memoization and deduplication.\n *\n * @example\n * ```typescript\n * import { cached, cachedWithTTL, cachedFunction, once } from 'awaitly/cache';\n *\n * // Compute once, reuse forever\n * const getConfig = cached(() => loadConfig());\n *\n * // Expire after duration\n * const getUser = cachedWithTTL(() => fetchUser(id), { ttl: '5m' });\n *\n * // Memoize by arguments\n * const fetchUserMemo = cachedFunction((id: string) => fetchUser(id));\n *\n * // Execute exactly once\n * const initDb = once(() => connectToDatabase());\n * ```\n */\n\nexport {\n // Types\n type DurationInput,\n type CacheEntry,\n type CacheOptions,\n type CachedFunctionOptions,\n type CacheStats,\n type MemoizedFunction,\n type OnceFunction,\n type Cache,\n type CacheConfig,\n\n // Functions\n cached,\n cachedWithTTL,\n cachedFunction,\n once,\n createCache,\n} from \"./cache\";\n","/**\n * awaitly/duration\n *\n * Type-safe duration handling inspired by Effect's Duration module.\n * Prevents unit confusion (milliseconds vs seconds) with explicit constructors.\n */\n\n// =============================================================================\n// Duration Type\n// =============================================================================\n\n/**\n * A type-safe representation of a time duration.\n * Use the constructor functions (millis, seconds, etc.) to create durations.\n */\nexport interface Duration {\n readonly _tag: \"Duration\";\n readonly millis: number;\n}\n\n// =============================================================================\n// Constructors\n// =============================================================================\n\n/**\n * Create a Duration from milliseconds.\n *\n * @example\n * ```typescript\n * const d = Duration.millis(500)\n * ```\n */\nexport function millis(ms: number): Duration {\n return { _tag: \"Duration\", millis: ms };\n}\n\n/**\n * Create a Duration from seconds.\n *\n * @example\n * ```typescript\n * const d = Duration.seconds(5) // 5000ms\n * ```\n */\nexport function seconds(s: number): Duration {\n return { _tag: \"Duration\", millis: s * 1000 };\n}\n\n/**\n * Create a Duration from minutes.\n *\n * @example\n * ```typescript\n * const d = Duration.minutes(2) // 120000ms\n * ```\n */\nexport function minutes(m: number): Duration {\n return { _tag: \"Duration\", millis: m * 60 * 1000 };\n}\n\n/**\n * Create a Duration from hours.\n *\n * @example\n * ```typescript\n * const d = Duration.hours(1) // 3600000ms\n * ```\n */\nexport function hours(h: number): Duration {\n return { _tag: \"Duration\", millis: h * 60 * 60 * 1000 };\n}\n\n/**\n * Create a Duration from days.\n *\n * @example\n * ```typescript\n * const d = Duration.days(1) // 86400000ms\n * ```\n */\nexport function days(d: number): Duration {\n return { _tag: \"Duration\", millis: d * 24 * 60 * 60 * 1000 };\n}\n\n/**\n * Zero duration.\n */\nexport const zero: Duration = { _tag: \"Duration\", millis: 0 };\n\n/**\n * Infinite duration (represented as Infinity milliseconds).\n */\nexport const infinity: Duration = { _tag: \"Duration\", millis: Infinity };\n\n// =============================================================================\n// Conversions\n// =============================================================================\n\n/**\n * Convert a Duration to milliseconds.\n */\nexport function toMillis(duration: Duration): number {\n return duration.millis;\n}\n\n/**\n * Convert a Duration to seconds.\n */\nexport function toSeconds(duration: Duration): number {\n return duration.millis / 1000;\n}\n\n/**\n * Convert a Duration to minutes.\n */\nexport function toMinutes(duration: Duration): number {\n return duration.millis / (60 * 1000);\n}\n\n/**\n * Convert a Duration to hours.\n */\nexport function toHours(duration: Duration): number {\n return duration.millis / (60 * 60 * 1000);\n}\n\n/**\n * Convert a Duration to days.\n */\nexport function toDays(duration: Duration): number {\n return duration.millis / (24 * 60 * 60 * 1000);\n}\n\n// =============================================================================\n// Operations\n// =============================================================================\n\n/**\n * Add two durations.\n *\n * @example\n * ```typescript\n * const total = Duration.add(Duration.seconds(5), Duration.millis(500))\n * // 5500ms\n * ```\n */\nexport function add(a: Duration, b: Duration): Duration {\n return { _tag: \"Duration\", millis: a.millis + b.millis };\n}\n\n/**\n * Subtract duration b from duration a.\n * Result is clamped to zero (no negative durations).\n *\n * @example\n * ```typescript\n * const remaining = Duration.subtract(Duration.seconds(5), Duration.seconds(2))\n * // 3000ms\n * ```\n */\nexport function subtract(a: Duration, b: Duration): Duration {\n return { _tag: \"Duration\", millis: Math.max(0, a.millis - b.millis) };\n}\n\n/**\n * Multiply a duration by a factor.\n *\n * @example\n * ```typescript\n * const doubled = Duration.multiply(Duration.seconds(5), 2)\n * // 10000ms\n * ```\n */\nexport function multiply(duration: Duration, factor: number): Duration {\n return { _tag: \"Duration\", millis: duration.millis * factor };\n}\n\n/**\n * Divide a duration by a divisor.\n *\n * @example\n * ```typescript\n * const half = Duration.divide(Duration.seconds(10), 2)\n * // 5000ms\n * ```\n */\nexport function divide(duration: Duration, divisor: number): Duration {\n return { _tag: \"Duration\", millis: duration.millis / divisor };\n}\n\n// =============================================================================\n// Comparisons\n// =============================================================================\n\n/**\n * Check if duration a is less than duration b.\n */\nexport function lessThan(a: Duration, b: Duration): boolean {\n return a.millis < b.millis;\n}\n\n/**\n * Check if duration a is less than or equal to duration b.\n */\nexport function lessThanOrEqual(a: Duration, b: Duration): boolean {\n return a.millis <= b.millis;\n}\n\n/**\n * Check if duration a is greater than duration b.\n */\nexport function greaterThan(a: Duration, b: Duration): boolean {\n return a.millis > b.millis;\n}\n\n/**\n * Check if duration a is greater than or equal to duration b.\n */\nexport function greaterThanOrEqual(a: Duration, b: Duration): boolean {\n return a.millis >= b.millis;\n}\n\n/**\n * Check if two durations are equal.\n */\nexport function equals(a: Duration, b: Duration): boolean {\n return a.millis === b.millis;\n}\n\n/**\n * Get the minimum of two durations.\n */\nexport function min(a: Duration, b: Duration): Duration {\n return a.millis <= b.millis ? a : b;\n}\n\n/**\n * Get the maximum of two durations.\n */\nexport function max(a: Duration, b: Duration): Duration {\n return a.millis >= b.millis ? a : b;\n}\n\n/**\n * Clamp a duration between a minimum and maximum.\n */\nexport function clamp(duration: Duration, minimum: Duration, maximum: Duration): Duration {\n return min(max(duration, minimum), maximum);\n}\n\n// =============================================================================\n// Predicates\n// =============================================================================\n\n/**\n * Check if a duration is zero.\n */\nexport function isZero(duration: Duration): boolean {\n return duration.millis === 0;\n}\n\n/**\n * Check if a duration is infinite.\n */\nexport function isInfinite(duration: Duration): boolean {\n return duration.millis === Infinity;\n}\n\n/**\n * Check if a duration is finite and positive.\n */\nexport function isFinite(duration: Duration): boolean {\n return Number.isFinite(duration.millis) && duration.millis > 0;\n}\n\n/**\n * Type guard to check if a value is a Duration.\n */\nexport function isDuration(value: unknown): value is Duration {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"_tag\" in value &&\n value._tag === \"Duration\" &&\n \"millis\" in value &&\n typeof value.millis === \"number\"\n );\n}\n\n// =============================================================================\n// Formatting\n// =============================================================================\n\n/**\n * Format a duration as a human-readable string.\n *\n * @example\n * ```typescript\n * Duration.format(Duration.seconds(90)) // \"1m 30s\"\n * Duration.format(Duration.millis(500)) // \"500ms\"\n * ```\n */\nexport function format(duration: Duration): string {\n const ms = duration.millis;\n\n if (ms === Infinity) return \"∞\";\n if (ms === 0) return \"0ms\";\n\n const days = Math.floor(ms / (24 * 60 * 60 * 1000));\n const hours = Math.floor((ms % (24 * 60 * 60 * 1000)) / (60 * 60 * 1000));\n const minutes = Math.floor((ms % (60 * 60 * 1000)) / (60 * 1000));\n const seconds = Math.floor((ms % (60 * 1000)) / 1000);\n const millis = ms % 1000;\n\n const parts: string[] = [];\n if (days > 0) parts.push(`${days}d`);\n if (hours > 0) parts.push(`${hours}h`);\n if (minutes > 0) parts.push(`${minutes}m`);\n if (seconds > 0) parts.push(`${seconds}s`);\n if (millis > 0 && parts.length === 0) parts.push(`${millis}ms`);\n\n return parts.join(\" \") || \"0ms\";\n}\n\n// =============================================================================\n// Parsing\n// =============================================================================\n\n/**\n * Parse a duration from a string like \"100ms\", \"5s\", \"2m\", \"1h\", \"1d\".\n * Returns undefined if parsing fails.\n *\n * @example\n * ```typescript\n * Duration.parse(\"5s\") // Duration.seconds(5)\n * Duration.parse(\"100ms\") // Duration.millis(100)\n * Duration.parse(\"2m\") // Duration.minutes(2)\n * ```\n */\nexport function parse(input: string): Duration | undefined {\n const match = input.trim().match(/^(\\d+(?:\\.\\d+)?)\\s*(ms|s|m|h|d)$/i);\n if (!match) return undefined;\n\n const value = parseFloat(match[1]);\n const unit = match[2].toLowerCase();\n\n switch (unit) {\n case \"ms\":\n return millis(value);\n case \"s\":\n return seconds(value);\n case \"m\":\n return minutes(value);\n case \"h\":\n return hours(value);\n case \"d\":\n return days(value);\n default:\n return undefined;\n }\n}\n\n// =============================================================================\n// Namespace Export\n// =============================================================================\n\n/**\n * Duration namespace with all functions for convenient access.\n *\n * @example\n * ```typescript\n * import { Duration } from \"awaitly\";\n *\n * const timeout = Duration.seconds(30);\n * const delay = Duration.millis(100);\n * const total = Duration.add(timeout, delay);\n *\n * console.log(Duration.format(total)); // \"30s 100ms\"\n * ```\n */\nexport const Duration = {\n // Constructors\n millis,\n seconds,\n minutes,\n hours,\n days,\n zero,\n infinity,\n\n // Conversions\n toMillis,\n toSeconds,\n toMinutes,\n toHours,\n toDays,\n\n // Operations\n add,\n subtract,\n multiply,\n divide,\n\n // Comparisons\n lessThan,\n lessThanOrEqual,\n greaterThan,\n greaterThanOrEqual,\n equals,\n min,\n max,\n clamp,\n\n // Predicates\n isZero,\n isInfinite,\n isFinite,\n isDuration,\n\n // Formatting\n format,\n parse,\n} as const;\n\nexport type { Duration as DurationType };\n","/**\n * awaitly/cache\n *\n * Caching utilities for memoization and deduplication.\n * Inspired by Effect.js caching patterns.\n *\n * @example\n * ```typescript\n * import { cached, cachedWithTTL, cachedFunction, once } from 'awaitly/cache';\n *\n * // Compute once, reuse forever\n * const getConfig = cached(() => loadConfig());\n *\n * // Expire after duration\n * const getUser = cachedWithTTL(() => fetchUser(id), { ttl: '5m' });\n *\n * // Memoize by arguments\n * const fetchUserMemo = cachedFunction((id: string) => fetchUser(id));\n *\n * // Execute exactly once (for initialization)\n * const initDb = once(() => connectToDatabase());\n * ```\n */\n\nimport { Duration, parse as parseDuration } from \"./duration\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/**\n * Duration input type - supports Duration objects or string shorthand.\n */\nexport type DurationInput = Duration | string;\n\n/**\n * Cache entry with metadata.\n */\nexport interface CacheEntry<T> {\n value: T;\n timestamp: number;\n expiresAt?: number;\n}\n\n/**\n * Cache options.\n */\nexport interface CacheOptions {\n /**\n * Time-to-live for cached values.\n * Accepts Duration or string shorthand like \"5m\", \"1h\", \"30s\".\n */\n ttl?: DurationInput;\n}\n\n/**\n * Cached function options.\n */\nexport interface CachedFunctionOptions<Args extends unknown[]> {\n /**\n * Custom key generator for arguments.\n * Default: JSON.stringify(args)\n */\n keyFn?: (...args: Args) => string;\n\n /**\n * Time-to-live for cached values.\n */\n ttl?: DurationInput;\n\n /**\n * Maximum cache size. When exceeded, oldest entries are evicted.\n * @default Infinity\n */\n maxSize?: number;\n}\n\n/**\n * Cache statistics.\n */\nexport interface CacheStats {\n hits: number;\n misses: number;\n size: number;\n}\n\n// =============================================================================\n// Helper Functions\n// =============================================================================\n\n/**\n * Convert DurationInput to milliseconds.\n */\nfunction toMs(duration: DurationInput): number {\n if (typeof duration === \"string\") {\n const parsed = parseDuration(duration);\n if (!parsed) {\n throw new Error(`Invalid duration string: ${duration}`);\n }\n return parsed.millis;\n }\n return duration.millis;\n}\n\n// =============================================================================\n// cached() - Compute once, reuse forever\n// =============================================================================\n\n/**\n * State for a cached value.\n */\ntype CachedState<T> =\n | { status: \"empty\" }\n | { status: \"pending\"; promise: Promise<T> }\n | { status: \"filled\"; value: T };\n\n/**\n * Create a cached computation that executes once and reuses the result.\n *\n * The function is called at most once, even with concurrent calls.\n * Subsequent calls return the cached value immediately.\n *\n * @param fn - Function to compute the cached value\n * @returns Function that returns the cached value\n *\n * @example\n * ```typescript\n * const getConfig = cached(async () => {\n * console.log('Loading config...');\n * return await loadConfigFromFile();\n * });\n *\n * // First call executes the function\n * const config1 = await getConfig(); // \"Loading config...\"\n *\n * // Subsequent calls return cached value\n * const config2 = await getConfig(); // No log, instant return\n * const config3 = await getConfig(); // No log, instant return\n * ```\n */\nexport function cached<T>(fn: () => T | Promise<T>): () => Promise<T> {\n let state: CachedState<T> = { status: \"empty\" };\n\n return async () => {\n if (state.status === \"filled\") {\n return state.value;\n }\n\n if (state.status === \"pending\") {\n return state.promise;\n }\n\n // Compute the value\n const promise = Promise.resolve(fn()).then((value) => {\n state = { status: \"filled\", value };\n return value;\n });\n\n state = { status: \"pending\", promise };\n return promise;\n };\n}\n\n// =============================================================================\n// cachedWithTTL() - Expire after duration\n// =============================================================================\n\n/**\n * State for a TTL-cached value.\n */\ntype CachedTTLState<T> =\n | { status: \"empty\" }\n | { status: \"pending\"; promise: Promise<T> }\n | { status: \"filled\"; value: T; expiresAt: number };\n\n/**\n * Create a cached computation that expires after a duration.\n *\n * The function is re-executed when the TTL expires.\n * Concurrent calls while computing share the same promise.\n *\n * @param fn - Function to compute the cached value\n * @param options - Cache options including TTL\n * @returns Function that returns the cached value\n *\n * @example\n * ```typescript\n * const getUser = cachedWithTTL(\n * async () => await fetchUser(userId),\n * { ttl: '5m' } // Cache for 5 minutes\n * );\n *\n * const user1 = await getUser(); // Fetches from API\n * const user2 = await getUser(); // Returns cached (within 5 min)\n *\n * // After 5 minutes...\n * const user3 = await getUser(); // Fetches again\n * ```\n */\nexport function cachedWithTTL<T>(\n fn: () => T | Promise<T>,\n options: { ttl: DurationInput }\n): () => Promise<T> {\n const ttlMs = toMs(options.ttl);\n let state: CachedTTLState<T> = { status: \"empty\" };\n\n return async () => {\n const now = Date.now();\n\n // Check if cached value is still valid\n if (state.status === \"filled\" && now < state.expiresAt) {\n return state.value;\n }\n\n // Check if already computing\n if (state.status === \"pending\") {\n return state.promise;\n }\n\n // Compute the value\n const promise = Promise.resolve(fn()).then((value) => {\n state = {\n status: \"filled\",\n value,\n expiresAt: Date.now() + ttlMs,\n };\n return value;\n });\n\n state = { status: \"pending\", promise };\n return promise;\n };\n}\n\n// =============================================================================\n// cachedFunction() - Memoize by arguments\n// =============================================================================\n\n/**\n * Cache entry for memoized functions.\n */\ninterface MemoEntry<T> {\n value: T;\n timestamp: number;\n expiresAt?: number;\n}\n\n/**\n * Memoized function interface.\n */\nexport interface MemoizedFunction<Args extends unknown[], T> {\n (...args: Args): Promise<T>;\n /** Clear the entire cache */\n clear(): void;\n /** Clear a specific cache entry */\n delete(...args: Args): boolean;\n /** Check if an entry exists */\n has(...args: Args): boolean;\n /** Get cache statistics */\n getStats(): CacheStats;\n}\n\n/**\n * Create a memoized function that caches results by arguments.\n *\n * Each unique set of arguments produces a cached result.\n * Supports TTL and max size limits.\n *\n * @param fn - Function to memoize\n * @param options - Memoization options\n * @returns Memoized function with cache control methods\n *\n * @example\n * ```typescript\n * const fetchUserMemo = cachedFunction(\n * async (id: string) => await fetchUser(id),\n * { ttl: '5m', maxSize: 100 }\n * );\n *\n * const user1 = await fetchUserMemo('user-1'); // Fetches\n * const user2 = await fetchUserMemo('user-2'); // Fetches\n * const user1Again = await fetchUserMemo('user-1'); // Cached!\n *\n * // Cache control\n * fetchUserMemo.delete('user-1'); // Remove specific entry\n * fetchUserMemo.clear(); // Clear all\n * console.log(fetchUserMemo.getStats()); // { hits: 1, misses: 2, size: 0 }\n * ```\n */\nexport function cachedFunction<Args extends unknown[], T>(\n fn: (...args: Args) => T | Promise<T>,\n options: CachedFunctionOptions<Args> = {}\n): MemoizedFunction<Args, T> {\n const {\n keyFn = (...args: Args) => JSON.stringify(args),\n maxSize = Infinity,\n } = options;\n const ttlMs = options.ttl ? toMs(options.ttl) : undefined;\n\n const cache = new Map<string, MemoEntry<T>>();\n const pending = new Map<string, Promise<T>>();\n let hits = 0;\n let misses = 0;\n\n /**\n * Evict oldest entries if over max size.\n */\n function evictOldest(): void {\n if (cache.size <= maxSize) return;\n\n // Find oldest entry\n let oldestKey: string | null = null;\n let oldestTime = Infinity;\n\n for (const [key, entry] of cache.entries()) {\n if (entry.timestamp < oldestTime) {\n oldestTime = entry.timestamp;\n oldestKey = key;\n }\n }\n\n if (oldestKey) {\n cache.delete(oldestKey);\n }\n }\n\n const memoized = async (...args: Args): Promise<T> => {\n const key = keyFn(...args);\n const now = Date.now();\n\n // Check cache\n const cached = cache.get(key);\n if (cached) {\n // Check if expired\n if (cached.expiresAt && now >= cached.expiresAt) {\n cache.delete(key);\n } else {\n hits++;\n return cached.value;\n }\n }\n\n // Check if already computing\n const pendingPromise = pending.get(key);\n if (pendingPromise) {\n return pendingPromise;\n }\n\n // Compute the value\n misses++;\n const promise = Promise.resolve(fn(...args)).then((value) => {\n const entry: MemoEntry<T> = {\n value,\n timestamp: Date.now(),\n expiresAt: ttlMs ? Date.now() + ttlMs : undefined,\n };\n cache.set(key, entry);\n pending.delete(key);\n evictOldest();\n return value;\n });\n\n pending.set(key, promise);\n\n try {\n return await promise;\n } catch (error) {\n pending.delete(key);\n throw error;\n }\n };\n\n memoized.clear = () => {\n cache.clear();\n pending.clear();\n };\n\n memoized.delete = (...args: Args) => {\n const key = keyFn(...args);\n return cache.delete(key);\n };\n\n memoized.has = (...args: Args) => {\n const key = keyFn(...args);\n const entry = cache.get(key);\n if (!entry) return false;\n if (entry.expiresAt && Date.now() >= entry.expiresAt) {\n cache.delete(key);\n return false;\n }\n return true;\n };\n\n memoized.getStats = () => ({\n hits,\n misses,\n size: cache.size,\n });\n\n return memoized;\n}\n\n// =============================================================================\n// once() - Execute exactly once\n// =============================================================================\n\n/**\n * State for a once-executed function.\n */\ntype OnceState<T> =\n | { status: \"idle\" }\n | { status: \"running\"; promise: Promise<T> }\n | { status: \"done\"; value: T }\n | { status: \"failed\"; error: unknown };\n\n/**\n * Once-executed function interface.\n */\nexport interface OnceFunction<T> {\n (): Promise<T>;\n /** Check if the function has been called */\n called: boolean;\n /** Check if execution completed successfully */\n completed: boolean;\n /** Check if execution failed */\n failed: boolean;\n /** Reset to allow re-execution */\n reset(): void;\n}\n\n/**\n * Create a function that executes exactly once.\n *\n * Useful for initialization code that should only run once.\n * Subsequent calls return the same result or re-throw the same error.\n *\n * @param fn - Function to execute once\n * @returns Function that executes once and returns the result\n *\n * @example\n * ```typescript\n * const initDb = once(async () => {\n * console.log('Connecting to database...');\n * const conn = await createConnection();\n * return conn;\n * });\n *\n * // First call executes\n * const db1 = await initDb(); // \"Connecting to database...\"\n *\n * // Subsequent calls return cached result\n * const db2 = await initDb(); // Instant, same connection\n * const db3 = await initDb(); // Instant, same connection\n *\n * console.log(initDb.called); // true\n * console.log(initDb.completed); // true\n * ```\n */\nexport function once<T>(fn: () => T | Promise<T>): OnceFunction<T> {\n let state: OnceState<T> = { status: \"idle\" };\n\n const onceFn = async (): Promise<T> => {\n if (state.status === \"done\") {\n return state.value;\n }\n\n if (state.status === \"failed\") {\n throw state.error;\n }\n\n if (state.status === \"running\") {\n return state.promise;\n }\n\n // Execute the function\n const promise = Promise.resolve(fn())\n .then((value) => {\n state = { status: \"done\", value };\n return value;\n })\n .catch((error) => {\n state = { status: \"failed\", error };\n throw error;\n });\n\n state = { status: \"running\", promise };\n return promise;\n };\n\n Object.defineProperty(onceFn, \"called\", {\n get: () => state.status !== \"idle\",\n });\n\n Object.defineProperty(onceFn, \"completed\", {\n get: () => state.status === \"done\",\n });\n\n Object.defineProperty(onceFn, \"failed\", {\n get: () => state.status === \"failed\",\n });\n\n onceFn.reset = () => {\n state = { status: \"idle\" };\n };\n\n return onceFn as OnceFunction<T>;\n}\n\n// =============================================================================\n// createCache() - General purpose cache\n// =============================================================================\n\n/**\n * General purpose cache interface.\n */\nexport interface Cache<K, V> {\n /** Get a value from the cache */\n get(key: K): V | undefined;\n /** Set a value in the cache */\n set(key: K, value: V, options?: { ttl?: DurationInput }): void;\n /** Check if a key exists */\n has(key: K): boolean;\n /** Delete a key from the cache */\n delete(key: K): boolean;\n /** Clear the entire cache */\n clear(): void;\n /** Get the cache size */\n size: number;\n /** Get cache statistics */\n getStats(): CacheStats;\n}\n\n/**\n * Cache configuration.\n */\nexport interface CacheConfig {\n /**\n * Default TTL for all entries.\n */\n defaultTTL?: DurationInput;\n\n /**\n * Maximum cache size.\n * @default Infinity\n */\n maxSize?: number;\n}\n\n/**\n * Create a general-purpose cache with TTL and size limits.\n *\n * @param config - Cache configuration\n * @returns A Cache instance\n *\n * @example\n * ```typescript\n * const cache = createCache<string, User>({\n * defaultTTL: '5m',\n * maxSize: 1000,\n * });\n *\n * cache.set('user:1', user);\n * cache.set('user:2', user2, { ttl: '1h' }); // Override TTL\n *\n * const user = cache.get('user:1');\n * ```\n */\nexport function createCache<K, V>(config: CacheConfig = {}): Cache<K, V> {\n const { maxSize = Infinity } = config;\n const defaultTTLMs = config.defaultTTL ? toMs(config.defaultTTL) : undefined;\n\n interface Entry {\n value: V;\n timestamp: number;\n expiresAt?: number;\n }\n\n const store = new Map<K, Entry>();\n let hits = 0;\n let misses = 0;\n\n /**\n * Check if an entry is expired.\n */\n function isExpired(entry: Entry): boolean {\n return entry.expiresAt !== undefined && Date.now() >= entry.expiresAt;\n }\n\n /**\n * Evict oldest entries if over max size.\n */\n function evictOldest(): void {\n if (store.size <= maxSize) return;\n\n let oldestKey: K | null = null;\n let oldestTime = Infinity;\n\n for (const [key, entry] of store.entries()) {\n if (entry.timestamp < oldestTime) {\n oldestTime = entry.timestamp;\n oldestKey = key;\n }\n }\n\n if (oldestKey !== null) {\n store.delete(oldestKey);\n }\n }\n\n return {\n get(key: K): V | undefined {\n const entry = store.get(key);\n if (!entry) {\n misses++;\n return undefined;\n }\n if (isExpired(entry)) {\n store.delete(key);\n misses++;\n return undefined;\n }\n hits++;\n return entry.value;\n },\n\n set(key: K, value: V, options?: { ttl?: DurationInput }): void {\n const ttlMs = options?.ttl ? toMs(options.ttl) : defaultTTLMs;\n const now = Date.now();\n\n store.set(key, {\n value,\n timestamp: now,\n expiresAt: ttlMs ? now + ttlMs : undefined,\n });\n\n evictOldest();\n },\n\n has(key: K): boolean {\n const entry = store.get(key);\n if (!entry) return false;\n if (isExpired(entry)) {\n store.delete(key);\n return false;\n }\n return true;\n },\n\n delete(key: K): boolean {\n return store.delete(key);\n },\n\n clear(): void {\n store.clear();\n },\n\n get size(): number {\n return store.size;\n },\n\n getStats(): CacheStats {\n return { hits, misses, size: store.size };\n },\n };\n}\n"],"mappings":"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","names":["cache_entry_exports","__export","cached","cachedFunction","cachedWithTTL","createCache","once","__toCommonJS","millis","ms","seconds","s","minutes","m","hours","h","days","d","parse","input","match","value","millis","seconds","minutes","hours","days","toMs","duration","parsed","parse","cached","fn","state","promise","value","cachedWithTTL","options","ttlMs","now","cachedFunction","keyFn","args","maxSize","cache","pending","hits","misses","evictOldest","oldestKey","oldestTime","key","entry","memoized","pendingPromise","error","once","onceFn","createCache","config","defaultTTLMs","store","isExpired"]}
|
package/dist/cache.d.cts
DELETED
|
@@ -1,269 +0,0 @@
|
|
|
1
|
-
import { Duration } from './duration.cjs';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* awaitly/cache
|
|
5
|
-
*
|
|
6
|
-
* Caching utilities for memoization and deduplication.
|
|
7
|
-
* Inspired by Effect.js caching patterns.
|
|
8
|
-
*
|
|
9
|
-
* @example
|
|
10
|
-
* ```typescript
|
|
11
|
-
* import { cached, cachedWithTTL, cachedFunction, once } from 'awaitly/cache';
|
|
12
|
-
*
|
|
13
|
-
* // Compute once, reuse forever
|
|
14
|
-
* const getConfig = cached(() => loadConfig());
|
|
15
|
-
*
|
|
16
|
-
* // Expire after duration
|
|
17
|
-
* const getUser = cachedWithTTL(() => fetchUser(id), { ttl: '5m' });
|
|
18
|
-
*
|
|
19
|
-
* // Memoize by arguments
|
|
20
|
-
* const fetchUserMemo = cachedFunction((id: string) => fetchUser(id));
|
|
21
|
-
*
|
|
22
|
-
* // Execute exactly once (for initialization)
|
|
23
|
-
* const initDb = once(() => connectToDatabase());
|
|
24
|
-
* ```
|
|
25
|
-
*/
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Duration input type - supports Duration objects or string shorthand.
|
|
29
|
-
*/
|
|
30
|
-
type DurationInput = Duration | string;
|
|
31
|
-
/**
|
|
32
|
-
* Cache entry with metadata.
|
|
33
|
-
*/
|
|
34
|
-
interface CacheEntry<T> {
|
|
35
|
-
value: T;
|
|
36
|
-
timestamp: number;
|
|
37
|
-
expiresAt?: number;
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Cache options.
|
|
41
|
-
*/
|
|
42
|
-
interface CacheOptions {
|
|
43
|
-
/**
|
|
44
|
-
* Time-to-live for cached values.
|
|
45
|
-
* Accepts Duration or string shorthand like "5m", "1h", "30s".
|
|
46
|
-
*/
|
|
47
|
-
ttl?: DurationInput;
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Cached function options.
|
|
51
|
-
*/
|
|
52
|
-
interface CachedFunctionOptions<Args extends unknown[]> {
|
|
53
|
-
/**
|
|
54
|
-
* Custom key generator for arguments.
|
|
55
|
-
* Default: JSON.stringify(args)
|
|
56
|
-
*/
|
|
57
|
-
keyFn?: (...args: Args) => string;
|
|
58
|
-
/**
|
|
59
|
-
* Time-to-live for cached values.
|
|
60
|
-
*/
|
|
61
|
-
ttl?: DurationInput;
|
|
62
|
-
/**
|
|
63
|
-
* Maximum cache size. When exceeded, oldest entries are evicted.
|
|
64
|
-
* @default Infinity
|
|
65
|
-
*/
|
|
66
|
-
maxSize?: number;
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* Cache statistics.
|
|
70
|
-
*/
|
|
71
|
-
interface CacheStats {
|
|
72
|
-
hits: number;
|
|
73
|
-
misses: number;
|
|
74
|
-
size: number;
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Create a cached computation that executes once and reuses the result.
|
|
78
|
-
*
|
|
79
|
-
* The function is called at most once, even with concurrent calls.
|
|
80
|
-
* Subsequent calls return the cached value immediately.
|
|
81
|
-
*
|
|
82
|
-
* @param fn - Function to compute the cached value
|
|
83
|
-
* @returns Function that returns the cached value
|
|
84
|
-
*
|
|
85
|
-
* @example
|
|
86
|
-
* ```typescript
|
|
87
|
-
* const getConfig = cached(async () => {
|
|
88
|
-
* console.log('Loading config...');
|
|
89
|
-
* return await loadConfigFromFile();
|
|
90
|
-
* });
|
|
91
|
-
*
|
|
92
|
-
* // First call executes the function
|
|
93
|
-
* const config1 = await getConfig(); // "Loading config..."
|
|
94
|
-
*
|
|
95
|
-
* // Subsequent calls return cached value
|
|
96
|
-
* const config2 = await getConfig(); // No log, instant return
|
|
97
|
-
* const config3 = await getConfig(); // No log, instant return
|
|
98
|
-
* ```
|
|
99
|
-
*/
|
|
100
|
-
declare function cached<T>(fn: () => T | Promise<T>): () => Promise<T>;
|
|
101
|
-
/**
|
|
102
|
-
* Create a cached computation that expires after a duration.
|
|
103
|
-
*
|
|
104
|
-
* The function is re-executed when the TTL expires.
|
|
105
|
-
* Concurrent calls while computing share the same promise.
|
|
106
|
-
*
|
|
107
|
-
* @param fn - Function to compute the cached value
|
|
108
|
-
* @param options - Cache options including TTL
|
|
109
|
-
* @returns Function that returns the cached value
|
|
110
|
-
*
|
|
111
|
-
* @example
|
|
112
|
-
* ```typescript
|
|
113
|
-
* const getUser = cachedWithTTL(
|
|
114
|
-
* async () => await fetchUser(userId),
|
|
115
|
-
* { ttl: '5m' } // Cache for 5 minutes
|
|
116
|
-
* );
|
|
117
|
-
*
|
|
118
|
-
* const user1 = await getUser(); // Fetches from API
|
|
119
|
-
* const user2 = await getUser(); // Returns cached (within 5 min)
|
|
120
|
-
*
|
|
121
|
-
* // After 5 minutes...
|
|
122
|
-
* const user3 = await getUser(); // Fetches again
|
|
123
|
-
* ```
|
|
124
|
-
*/
|
|
125
|
-
declare function cachedWithTTL<T>(fn: () => T | Promise<T>, options: {
|
|
126
|
-
ttl: DurationInput;
|
|
127
|
-
}): () => Promise<T>;
|
|
128
|
-
/**
|
|
129
|
-
* Memoized function interface.
|
|
130
|
-
*/
|
|
131
|
-
interface MemoizedFunction<Args extends unknown[], T> {
|
|
132
|
-
(...args: Args): Promise<T>;
|
|
133
|
-
/** Clear the entire cache */
|
|
134
|
-
clear(): void;
|
|
135
|
-
/** Clear a specific cache entry */
|
|
136
|
-
delete(...args: Args): boolean;
|
|
137
|
-
/** Check if an entry exists */
|
|
138
|
-
has(...args: Args): boolean;
|
|
139
|
-
/** Get cache statistics */
|
|
140
|
-
getStats(): CacheStats;
|
|
141
|
-
}
|
|
142
|
-
/**
|
|
143
|
-
* Create a memoized function that caches results by arguments.
|
|
144
|
-
*
|
|
145
|
-
* Each unique set of arguments produces a cached result.
|
|
146
|
-
* Supports TTL and max size limits.
|
|
147
|
-
*
|
|
148
|
-
* @param fn - Function to memoize
|
|
149
|
-
* @param options - Memoization options
|
|
150
|
-
* @returns Memoized function with cache control methods
|
|
151
|
-
*
|
|
152
|
-
* @example
|
|
153
|
-
* ```typescript
|
|
154
|
-
* const fetchUserMemo = cachedFunction(
|
|
155
|
-
* async (id: string) => await fetchUser(id),
|
|
156
|
-
* { ttl: '5m', maxSize: 100 }
|
|
157
|
-
* );
|
|
158
|
-
*
|
|
159
|
-
* const user1 = await fetchUserMemo('user-1'); // Fetches
|
|
160
|
-
* const user2 = await fetchUserMemo('user-2'); // Fetches
|
|
161
|
-
* const user1Again = await fetchUserMemo('user-1'); // Cached!
|
|
162
|
-
*
|
|
163
|
-
* // Cache control
|
|
164
|
-
* fetchUserMemo.delete('user-1'); // Remove specific entry
|
|
165
|
-
* fetchUserMemo.clear(); // Clear all
|
|
166
|
-
* console.log(fetchUserMemo.getStats()); // { hits: 1, misses: 2, size: 0 }
|
|
167
|
-
* ```
|
|
168
|
-
*/
|
|
169
|
-
declare function cachedFunction<Args extends unknown[], T>(fn: (...args: Args) => T | Promise<T>, options?: CachedFunctionOptions<Args>): MemoizedFunction<Args, T>;
|
|
170
|
-
/**
|
|
171
|
-
* Once-executed function interface.
|
|
172
|
-
*/
|
|
173
|
-
interface OnceFunction<T> {
|
|
174
|
-
(): Promise<T>;
|
|
175
|
-
/** Check if the function has been called */
|
|
176
|
-
called: boolean;
|
|
177
|
-
/** Check if execution completed successfully */
|
|
178
|
-
completed: boolean;
|
|
179
|
-
/** Check if execution failed */
|
|
180
|
-
failed: boolean;
|
|
181
|
-
/** Reset to allow re-execution */
|
|
182
|
-
reset(): void;
|
|
183
|
-
}
|
|
184
|
-
/**
|
|
185
|
-
* Create a function that executes exactly once.
|
|
186
|
-
*
|
|
187
|
-
* Useful for initialization code that should only run once.
|
|
188
|
-
* Subsequent calls return the same result or re-throw the same error.
|
|
189
|
-
*
|
|
190
|
-
* @param fn - Function to execute once
|
|
191
|
-
* @returns Function that executes once and returns the result
|
|
192
|
-
*
|
|
193
|
-
* @example
|
|
194
|
-
* ```typescript
|
|
195
|
-
* const initDb = once(async () => {
|
|
196
|
-
* console.log('Connecting to database...');
|
|
197
|
-
* const conn = await createConnection();
|
|
198
|
-
* return conn;
|
|
199
|
-
* });
|
|
200
|
-
*
|
|
201
|
-
* // First call executes
|
|
202
|
-
* const db1 = await initDb(); // "Connecting to database..."
|
|
203
|
-
*
|
|
204
|
-
* // Subsequent calls return cached result
|
|
205
|
-
* const db2 = await initDb(); // Instant, same connection
|
|
206
|
-
* const db3 = await initDb(); // Instant, same connection
|
|
207
|
-
*
|
|
208
|
-
* console.log(initDb.called); // true
|
|
209
|
-
* console.log(initDb.completed); // true
|
|
210
|
-
* ```
|
|
211
|
-
*/
|
|
212
|
-
declare function once<T>(fn: () => T | Promise<T>): OnceFunction<T>;
|
|
213
|
-
/**
|
|
214
|
-
* General purpose cache interface.
|
|
215
|
-
*/
|
|
216
|
-
interface Cache<K, V> {
|
|
217
|
-
/** Get a value from the cache */
|
|
218
|
-
get(key: K): V | undefined;
|
|
219
|
-
/** Set a value in the cache */
|
|
220
|
-
set(key: K, value: V, options?: {
|
|
221
|
-
ttl?: DurationInput;
|
|
222
|
-
}): void;
|
|
223
|
-
/** Check if a key exists */
|
|
224
|
-
has(key: K): boolean;
|
|
225
|
-
/** Delete a key from the cache */
|
|
226
|
-
delete(key: K): boolean;
|
|
227
|
-
/** Clear the entire cache */
|
|
228
|
-
clear(): void;
|
|
229
|
-
/** Get the cache size */
|
|
230
|
-
size: number;
|
|
231
|
-
/** Get cache statistics */
|
|
232
|
-
getStats(): CacheStats;
|
|
233
|
-
}
|
|
234
|
-
/**
|
|
235
|
-
* Cache configuration.
|
|
236
|
-
*/
|
|
237
|
-
interface CacheConfig {
|
|
238
|
-
/**
|
|
239
|
-
* Default TTL for all entries.
|
|
240
|
-
*/
|
|
241
|
-
defaultTTL?: DurationInput;
|
|
242
|
-
/**
|
|
243
|
-
* Maximum cache size.
|
|
244
|
-
* @default Infinity
|
|
245
|
-
*/
|
|
246
|
-
maxSize?: number;
|
|
247
|
-
}
|
|
248
|
-
/**
|
|
249
|
-
* Create a general-purpose cache with TTL and size limits.
|
|
250
|
-
*
|
|
251
|
-
* @param config - Cache configuration
|
|
252
|
-
* @returns A Cache instance
|
|
253
|
-
*
|
|
254
|
-
* @example
|
|
255
|
-
* ```typescript
|
|
256
|
-
* const cache = createCache<string, User>({
|
|
257
|
-
* defaultTTL: '5m',
|
|
258
|
-
* maxSize: 1000,
|
|
259
|
-
* });
|
|
260
|
-
*
|
|
261
|
-
* cache.set('user:1', user);
|
|
262
|
-
* cache.set('user:2', user2, { ttl: '1h' }); // Override TTL
|
|
263
|
-
*
|
|
264
|
-
* const user = cache.get('user:1');
|
|
265
|
-
* ```
|
|
266
|
-
*/
|
|
267
|
-
declare function createCache<K, V>(config?: CacheConfig): Cache<K, V>;
|
|
268
|
-
|
|
269
|
-
export { type Cache, type CacheConfig, type CacheEntry, type CacheOptions, type CacheStats, type CachedFunctionOptions, type DurationInput, type MemoizedFunction, type OnceFunction, cached, cachedFunction, cachedWithTTL, createCache, once };
|