cachetta 0.2.0 → 0.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.
- package/dist/index.js +258 -205
- package/dist/src/Cachetta.d.ts +6 -54
- package/dist/src/errors.d.ts +0 -3
- package/dist/src/index.d.ts +4 -4
- package/dist/src/read-cache.d.ts +3 -0
- package/dist/src/types.d.ts +1 -0
- package/dist/src/utils/cache-fn.d.ts +2 -1
- package/dist/src/utils/get-last-updated.d.ts +1 -0
- package/dist/src/utils/should-use-read-cache.d.ts +1 -0
- package/dist/src/write-cache.d.ts +1 -0
- package/package.json +22 -4
- package/dist/src/utils/get-extension.d.ts +0 -2
- package/dist/src/utils/get-extension.test.d.ts +0 -1
package/dist/index.js
CHANGED
|
@@ -1,51 +1,39 @@
|
|
|
1
|
-
import { promises as c } from "fs";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
class E extends m {
|
|
17
|
-
constructor(t) {
|
|
18
|
-
super(`Unsupported cache format: ${t}`), this.name = "UnsupportedFormatError";
|
|
1
|
+
import { promises as c, statSync as F, readFileSync as T, mkdirSync as G, writeFileSync as j, renameSync as A, unlinkSync as P } from "fs";
|
|
2
|
+
import { deserialize as E, serialize as z } from "v8";
|
|
3
|
+
import { normalize as W, resolve as b, dirname as x, join as S } from "path";
|
|
4
|
+
import { randomBytes as L, createHash as H } from "crypto";
|
|
5
|
+
import { inspect as J } from "util";
|
|
6
|
+
const K = (e) => typeof e == "object" && e !== null, k = (e) => K(e) && ("path" in e || "write" in e || "read" in e || "duration" in e || "lruSize" in e || "condition" in e || "staleDuration" in e), I = (e) => typeof e == "function" && "__cacheBuddy__" in e && e.__cacheBuddy__ === !0, d = Symbol("LRU_MISS");
|
|
7
|
+
async function f(e) {
|
|
8
|
+
try {
|
|
9
|
+
return (await c.stat(e)).mtime.getTime();
|
|
10
|
+
} catch (t) {
|
|
11
|
+
if (t.code === "ENOENT")
|
|
12
|
+
return null;
|
|
13
|
+
throw t;
|
|
19
14
|
}
|
|
20
15
|
}
|
|
21
|
-
function
|
|
22
|
-
var i;
|
|
23
|
-
const n = (i = String(e).split("/").pop()) == null ? void 0 : i.split(".");
|
|
24
|
-
if (!n || n.length === 1 || n[n.length - 1] === "")
|
|
25
|
-
throw new m(`Missing file extension: ${e}`);
|
|
26
|
-
return n[n.length - 1];
|
|
27
|
-
}
|
|
28
|
-
async function d(e) {
|
|
16
|
+
function p(e) {
|
|
29
17
|
try {
|
|
30
|
-
return (
|
|
18
|
+
return F(e).mtime.getTime();
|
|
31
19
|
} catch (t) {
|
|
32
20
|
if (t.code === "ENOENT")
|
|
33
21
|
return null;
|
|
34
22
|
throw t;
|
|
35
23
|
}
|
|
36
24
|
}
|
|
37
|
-
function
|
|
25
|
+
function N(e, t, n) {
|
|
38
26
|
if (e > t)
|
|
39
27
|
throw new Error(
|
|
40
28
|
`Invalid arguments, cache time ${e} cannot be greater than now ${t}`
|
|
41
29
|
);
|
|
42
30
|
return t - e >= n;
|
|
43
31
|
}
|
|
44
|
-
let
|
|
45
|
-
const
|
|
46
|
-
const t =
|
|
47
|
-
return
|
|
48
|
-
},
|
|
32
|
+
let R = "warn";
|
|
33
|
+
const D = ["error", "warn", "info", "debug"], q = (e) => {
|
|
34
|
+
const t = D.indexOf(R);
|
|
35
|
+
return D.indexOf(e) <= t;
|
|
36
|
+
}, Q = (e) => {
|
|
49
37
|
switch (e) {
|
|
50
38
|
case "debug":
|
|
51
39
|
return console.debug;
|
|
@@ -56,154 +44,239 @@ const x = ["error", "warn", "info", "debug"], G = (e) => {
|
|
|
56
44
|
case "error":
|
|
57
45
|
return console.error;
|
|
58
46
|
}
|
|
59
|
-
},
|
|
60
|
-
if (
|
|
61
|
-
const n =
|
|
47
|
+
}, w = (e) => (...t) => {
|
|
48
|
+
if (q(e)) {
|
|
49
|
+
const n = Q(e);
|
|
62
50
|
n && n("[Cachetta]", ...t);
|
|
63
51
|
}
|
|
64
52
|
};
|
|
65
|
-
let
|
|
66
|
-
debug:
|
|
67
|
-
info:
|
|
68
|
-
warn:
|
|
69
|
-
error:
|
|
53
|
+
let o = {
|
|
54
|
+
debug: w("debug"),
|
|
55
|
+
info: w("info"),
|
|
56
|
+
warn: w("warn"),
|
|
57
|
+
error: w("error")
|
|
70
58
|
};
|
|
71
|
-
function
|
|
72
|
-
|
|
59
|
+
function ct(e) {
|
|
60
|
+
R = e;
|
|
73
61
|
}
|
|
74
|
-
function
|
|
75
|
-
|
|
62
|
+
function ht(e) {
|
|
63
|
+
o = e;
|
|
76
64
|
}
|
|
77
|
-
async function
|
|
78
|
-
const i = e ?? 6048e5, r = await
|
|
65
|
+
async function V({ duration: e, read: t }, n) {
|
|
66
|
+
const i = e ?? 6048e5, r = await f(n);
|
|
79
67
|
if (r === null)
|
|
80
|
-
return
|
|
68
|
+
return o.debug(`Cache time is null for ${n}`), !1;
|
|
81
69
|
if (i <= 0)
|
|
82
|
-
return
|
|
70
|
+
return o.debug(`Cache length is ${i}, considering expired for ${n}`), !1;
|
|
83
71
|
const s = Date.now();
|
|
84
|
-
return r > s ? (
|
|
72
|
+
return r > s ? (o.debug(`Cache time ${r} is ahead of now ${s}, treating as valid cache for ${n}`), t ?? !0) : N(r, s, i) ? (o.debug(
|
|
85
73
|
`Cache is expired (${r}, expected ${r + i}) for ${n}`
|
|
86
|
-
), !1) : (
|
|
74
|
+
), !1) : (o.debug(
|
|
87
75
|
`Cache is not expired (${r}, expected ${r + i}) for ${n}`
|
|
88
76
|
), t ?? !0);
|
|
89
77
|
}
|
|
90
|
-
function
|
|
91
|
-
const
|
|
78
|
+
function X({ duration: e, read: t }, n) {
|
|
79
|
+
const i = e ?? 6048e5, r = p(n);
|
|
80
|
+
if (r === null)
|
|
81
|
+
return o.debug(`Cache time is null for ${n}`), !1;
|
|
82
|
+
if (i <= 0)
|
|
83
|
+
return o.debug(`Cache length is ${i}, considering expired for ${n}`), !1;
|
|
84
|
+
const s = Date.now();
|
|
85
|
+
return r > s ? (o.debug(`Cache time ${r} is ahead of now ${s}, treating as valid cache for ${n}`), t ?? !0) : N(r, s, i) ? (o.debug(
|
|
86
|
+
`Cache is expired (${r}, expected ${r + i}) for ${n}`
|
|
87
|
+
), !1) : (o.debug(
|
|
88
|
+
`Cache is not expired (${r}, expected ${r + i}) for ${n}`
|
|
89
|
+
), t ?? !0);
|
|
90
|
+
}
|
|
91
|
+
class C extends Error {
|
|
92
|
+
constructor(t) {
|
|
93
|
+
super(t), this.name = "CachettaError";
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
class Y extends C {
|
|
97
|
+
constructor(t) {
|
|
98
|
+
super(`Invalid cache path (path traversal detected): ${t}`), this.name = "InvalidPathError";
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
function u(e) {
|
|
102
|
+
const t = W(e);
|
|
92
103
|
if (t.split(/[/\\]/).includes(".."))
|
|
93
|
-
throw new
|
|
94
|
-
return
|
|
104
|
+
throw new Y(e);
|
|
105
|
+
return b(t);
|
|
95
106
|
}
|
|
96
|
-
|
|
97
|
-
async function z(e) {
|
|
98
|
-
const t = v(e);
|
|
99
|
-
if (t !== "json")
|
|
100
|
-
throw new E(t);
|
|
107
|
+
async function U(e) {
|
|
101
108
|
try {
|
|
102
|
-
const
|
|
103
|
-
return
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
+
const t = await c.readFile(e);
|
|
110
|
+
return E(t);
|
|
111
|
+
} catch (t) {
|
|
112
|
+
return t.code === "ENOENT" || o.error(`Read error: ${t}`), null;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
function M(e) {
|
|
116
|
+
try {
|
|
117
|
+
const t = T(e);
|
|
118
|
+
return E(t);
|
|
119
|
+
} catch (t) {
|
|
120
|
+
return t.code === "ENOENT" || o.error(`Read error: ${t}`), null;
|
|
109
121
|
}
|
|
110
122
|
}
|
|
111
|
-
async function
|
|
112
|
-
if (!
|
|
113
|
-
throw new
|
|
123
|
+
async function Z(e, ...t) {
|
|
124
|
+
if (!I(e))
|
|
125
|
+
throw new C(`Invalid value provided, you must provide an instance of Cachetta: ${e}`);
|
|
114
126
|
const n = e._getPath(...t);
|
|
115
|
-
|
|
127
|
+
u(n);
|
|
116
128
|
const i = e._lruGet(n);
|
|
117
|
-
if (i !==
|
|
118
|
-
return
|
|
119
|
-
if (await
|
|
120
|
-
|
|
121
|
-
const r = await
|
|
122
|
-
return r !== null && (
|
|
129
|
+
if (i !== d)
|
|
130
|
+
return o.debug(`LRU cache hit for ${n}`), i;
|
|
131
|
+
if (await V(e, n)) {
|
|
132
|
+
o.debug(`Using cache at ${n}`);
|
|
133
|
+
const r = await U(n);
|
|
134
|
+
return r !== null && (o.debug(`Used cache at ${n}`), e._lruSet(n, r)), r;
|
|
123
135
|
} else
|
|
124
|
-
return
|
|
136
|
+
return o.debug("cache.read is false, skipping cache"), null;
|
|
125
137
|
}
|
|
126
|
-
|
|
138
|
+
function B(e, ...t) {
|
|
139
|
+
if (!I(e))
|
|
140
|
+
throw new C(`Invalid value provided, you must provide an instance of Cachetta: ${e}`);
|
|
141
|
+
const n = e._getPath(...t);
|
|
142
|
+
u(n);
|
|
143
|
+
const i = e._lruGet(n);
|
|
144
|
+
if (i !== d)
|
|
145
|
+
return o.debug(`LRU cache hit for ${n}`), i;
|
|
146
|
+
if (X(e, n)) {
|
|
147
|
+
o.debug(`Using cache at ${n}`);
|
|
148
|
+
const r = M(n);
|
|
149
|
+
return r !== null && (o.debug(`Used cache at ${n}`), e._lruSet(n, r)), r;
|
|
150
|
+
} else
|
|
151
|
+
return o.debug("cache.read is false, skipping cache"), null;
|
|
152
|
+
}
|
|
153
|
+
async function tt(e, ...t) {
|
|
154
|
+
if (!e.staleDuration || !e.read) return null;
|
|
155
|
+
const n = e._getPath(...t);
|
|
156
|
+
u(n);
|
|
157
|
+
const i = await f(n);
|
|
158
|
+
if (i === null) return null;
|
|
159
|
+
const r = Date.now() - i, s = r >= e.duration, a = r < e.duration + e.staleDuration;
|
|
160
|
+
return s && a ? (o.debug(`Returning stale cache for ${n} (age: ${r}ms)`), U(n)) : null;
|
|
161
|
+
}
|
|
162
|
+
function et(e, ...t) {
|
|
127
163
|
if (!e.staleDuration || !e.read) return null;
|
|
128
164
|
const n = e._getPath(...t);
|
|
129
|
-
|
|
130
|
-
const i =
|
|
165
|
+
u(n);
|
|
166
|
+
const i = p(n);
|
|
131
167
|
if (i === null) return null;
|
|
132
|
-
const r = Date.now() - i, s = r >= e.duration,
|
|
133
|
-
return s &&
|
|
168
|
+
const r = Date.now() - i, s = r >= e.duration, a = r < e.duration + e.staleDuration;
|
|
169
|
+
return s && a ? (o.debug(`Returning stale cache for ${n} (age: ${r}ms)`), M(n)) : null;
|
|
134
170
|
}
|
|
135
|
-
const
|
|
136
|
-
async function
|
|
171
|
+
const y = /* @__PURE__ */ new Set();
|
|
172
|
+
async function v(e, t, ...n) {
|
|
137
173
|
if (!e || !e.write)
|
|
138
174
|
return;
|
|
139
175
|
const i = e._getPath(...n);
|
|
140
|
-
|
|
141
|
-
const r =
|
|
142
|
-
|
|
143
|
-
|
|
176
|
+
u(i);
|
|
177
|
+
const r = b(x(i));
|
|
178
|
+
y.has(r) || (await c.mkdir(r, { recursive: !0 }), y.add(r));
|
|
179
|
+
const s = z(t), a = S(r, `.cachetta-${L(8).toString("hex")}.tmp`);
|
|
180
|
+
try {
|
|
181
|
+
await c.writeFile(a, s), await c.rename(a, i), e._lruSet(i, t);
|
|
182
|
+
} catch (l) {
|
|
144
183
|
try {
|
|
145
|
-
await c.
|
|
146
|
-
} catch
|
|
147
|
-
try {
|
|
148
|
-
await c.unlink(u);
|
|
149
|
-
} catch {
|
|
150
|
-
}
|
|
151
|
-
throw l;
|
|
184
|
+
await c.unlink(a);
|
|
185
|
+
} catch {
|
|
152
186
|
}
|
|
153
|
-
|
|
154
|
-
|
|
187
|
+
throw l;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
function nt(e, t, ...n) {
|
|
191
|
+
if (!e || !e.write)
|
|
192
|
+
return;
|
|
193
|
+
const i = e._getPath(...n);
|
|
194
|
+
u(i);
|
|
195
|
+
const r = b(x(i));
|
|
196
|
+
y.has(r) || (G(r, { recursive: !0 }), y.add(r));
|
|
197
|
+
const s = z(t), a = S(r, `.cachetta-${L(8).toString("hex")}.tmp`);
|
|
198
|
+
try {
|
|
199
|
+
j(a, s), A(a, i), e._lruSet(i, t);
|
|
200
|
+
} catch (l) {
|
|
201
|
+
try {
|
|
202
|
+
P(a);
|
|
203
|
+
} catch {
|
|
204
|
+
}
|
|
205
|
+
throw l;
|
|
206
|
+
}
|
|
155
207
|
}
|
|
156
|
-
const
|
|
208
|
+
const m = /* @__PURE__ */ new Map(), $ = /* @__PURE__ */ new Set(), _ = (e, t) => {
|
|
157
209
|
async function n(...i) {
|
|
158
|
-
const r = await
|
|
210
|
+
const r = await Z(e, ...i);
|
|
159
211
|
if (r != null)
|
|
160
212
|
return r;
|
|
161
213
|
const s = e._getPath(...i);
|
|
162
214
|
if (e.staleDuration) {
|
|
163
|
-
const
|
|
164
|
-
if (
|
|
165
|
-
return
|
|
215
|
+
const h = await tt(e, ...i);
|
|
216
|
+
if (h != null)
|
|
217
|
+
return !$.has(s) && !m.has(s) && ($.add(s), (async () => {
|
|
166
218
|
try {
|
|
167
|
-
const
|
|
168
|
-
(!e.condition || e.condition(
|
|
169
|
-
} catch (
|
|
170
|
-
|
|
219
|
+
const g = await t.apply(this, i);
|
|
220
|
+
(!e.condition || e.condition(g)) && await v(e, g, ...i);
|
|
221
|
+
} catch (g) {
|
|
222
|
+
o.error(`Background revalidation failed for ${s}: ${g}`);
|
|
171
223
|
} finally {
|
|
172
|
-
|
|
224
|
+
$.delete(s);
|
|
173
225
|
}
|
|
174
|
-
})()),
|
|
226
|
+
})()), h;
|
|
175
227
|
}
|
|
176
|
-
const
|
|
177
|
-
if (
|
|
178
|
-
return
|
|
179
|
-
const
|
|
180
|
-
const
|
|
181
|
-
return (!e.condition || e.condition(
|
|
228
|
+
const a = m.get(s);
|
|
229
|
+
if (a)
|
|
230
|
+
return a;
|
|
231
|
+
const l = (async () => {
|
|
232
|
+
const h = await t.apply(this, i);
|
|
233
|
+
return (!e.condition || e.condition(h)) && await v(e, h, ...i), h;
|
|
182
234
|
})();
|
|
183
|
-
|
|
235
|
+
m.set(s, l);
|
|
184
236
|
try {
|
|
185
|
-
return await
|
|
237
|
+
return await l;
|
|
186
238
|
} finally {
|
|
187
|
-
|
|
239
|
+
m.delete(s);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return n;
|
|
243
|
+
}, it = (e, t) => {
|
|
244
|
+
function n(...i) {
|
|
245
|
+
const r = B(e, ...i);
|
|
246
|
+
if (r != null)
|
|
247
|
+
return r;
|
|
248
|
+
if (e.staleDuration) {
|
|
249
|
+
const a = et(e, ...i);
|
|
250
|
+
if (a != null)
|
|
251
|
+
return a;
|
|
188
252
|
}
|
|
253
|
+
const s = t.apply(this, i);
|
|
254
|
+
return (!e.condition || e.condition(s)) && nt(e, s, ...i), s;
|
|
189
255
|
}
|
|
190
256
|
return n;
|
|
191
|
-
},
|
|
192
|
-
class
|
|
257
|
+
}, rt = 10080 * 60 * 1e3;
|
|
258
|
+
class O extends Function {
|
|
193
259
|
constructor(t) {
|
|
194
|
-
super(), this.__cacheBuddy__ = !0, this.path = t.path, this.write = t.write ?? !0, this.read = t.read ?? !0, this.duration = t.duration ??
|
|
260
|
+
super(), this.__cacheBuddy__ = !0, this.path = t.path, this.write = t.write ?? !0, this.read = t.read ?? !0, this.duration = t.duration ?? rt, this.lruSize = t.lruSize, this.condition = t.condition, this.staleDuration = t.staleDuration, this._lru = this.lruSize ? /* @__PURE__ */ new Map() : void 0;
|
|
195
261
|
const n = this.call.bind(this), i = Object.assign(
|
|
196
262
|
n,
|
|
197
263
|
this,
|
|
198
264
|
{
|
|
199
265
|
copy: this.copy.bind(this),
|
|
200
266
|
wrap: this.wrap.bind(this),
|
|
267
|
+
wrapSync: this.wrapSync.bind(this),
|
|
201
268
|
invalidate: this.invalidate.bind(this),
|
|
269
|
+
invalidateSync: this.invalidateSync.bind(this),
|
|
202
270
|
clear: this.invalidate.bind(this),
|
|
203
271
|
// alias
|
|
272
|
+
clearSync: this.invalidateSync.bind(this),
|
|
273
|
+
// alias
|
|
204
274
|
exists: this.exists.bind(this),
|
|
275
|
+
existsSync: this.existsSync.bind(this),
|
|
205
276
|
age: this.age.bind(this),
|
|
277
|
+
ageSync: this.ageSync.bind(this),
|
|
206
278
|
info: this.info.bind(this),
|
|
279
|
+
infoSync: this.infoSync.bind(this),
|
|
207
280
|
_getPath: this._getPath.bind(this),
|
|
208
281
|
_lruGet: this._lruGet.bind(this),
|
|
209
282
|
_lruSet: this._lruSet.bind(this),
|
|
@@ -214,17 +287,10 @@ class L extends Function {
|
|
|
214
287
|
staleDuration: this.staleDuration
|
|
215
288
|
}
|
|
216
289
|
);
|
|
217
|
-
return i[
|
|
290
|
+
return i[J.custom] = () => `Cachetta { path: '${this.path}', write: ${this.write}, read: ${this.read}, duration: ${this.duration} }`, i;
|
|
218
291
|
}
|
|
219
|
-
/**
|
|
220
|
-
* Creates a copy of this Cachetta instance with overridden configuration.
|
|
221
|
-
* Useful for creating variations of a base cache configuration.
|
|
222
|
-
*
|
|
223
|
-
* @param kwargs - Partial configuration to override
|
|
224
|
-
* @returns A new Cachetta instance with the specified overrides
|
|
225
|
-
*/
|
|
226
292
|
copy(t) {
|
|
227
|
-
return new
|
|
293
|
+
return new O({
|
|
228
294
|
path: t.path ?? this.path,
|
|
229
295
|
write: t.write ?? this.write,
|
|
230
296
|
read: t.read ?? this.read,
|
|
@@ -234,24 +300,15 @@ class L extends Function {
|
|
|
234
300
|
staleDuration: t.staleDuration ?? this.staleDuration
|
|
235
301
|
});
|
|
236
302
|
}
|
|
237
|
-
/**
|
|
238
|
-
* Wraps a function with caching behavior. Alias for calling the cache instance directly.
|
|
239
|
-
*
|
|
240
|
-
* @param fn - The function to wrap
|
|
241
|
-
* @returns A cached version of the function
|
|
242
|
-
*/
|
|
243
303
|
wrap(t) {
|
|
244
|
-
return
|
|
304
|
+
return _(this, t);
|
|
305
|
+
}
|
|
306
|
+
wrapSync(t) {
|
|
307
|
+
return it(this, t);
|
|
245
308
|
}
|
|
246
|
-
/**
|
|
247
|
-
* Deletes the cache file on disk and clears LRU entries for this path.
|
|
248
|
-
* No-op if the cache file does not exist.
|
|
249
|
-
*
|
|
250
|
-
* @param args - Arguments to resolve the cache path (when using a path function)
|
|
251
|
-
*/
|
|
252
309
|
async invalidate(...t) {
|
|
253
310
|
const n = this._getPath(...t);
|
|
254
|
-
|
|
311
|
+
u(n), this._lru && this._lru.delete(n);
|
|
255
312
|
try {
|
|
256
313
|
await c.unlink(n);
|
|
257
314
|
} catch (i) {
|
|
@@ -259,76 +316,71 @@ class L extends Function {
|
|
|
259
316
|
throw i;
|
|
260
317
|
}
|
|
261
318
|
}
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
319
|
+
invalidateSync(...t) {
|
|
320
|
+
const n = this._getPath(...t);
|
|
321
|
+
u(n), this._lru && this._lru.delete(n);
|
|
322
|
+
try {
|
|
323
|
+
P(n);
|
|
324
|
+
} catch (i) {
|
|
325
|
+
if (i.code !== "ENOENT")
|
|
326
|
+
throw i;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
268
329
|
async exists(...t) {
|
|
269
330
|
const n = this._getPath(...t);
|
|
270
|
-
return
|
|
331
|
+
return u(n), await f(n) !== null;
|
|
332
|
+
}
|
|
333
|
+
existsSync(...t) {
|
|
334
|
+
const n = this._getPath(...t);
|
|
335
|
+
return u(n), p(n) !== null;
|
|
271
336
|
}
|
|
272
|
-
/**
|
|
273
|
-
* Returns the age of the cache file in milliseconds, or null if it does not exist.
|
|
274
|
-
*
|
|
275
|
-
* @param args - Arguments to resolve the cache path (when using a path function)
|
|
276
|
-
* @returns Age in ms, or null
|
|
277
|
-
*/
|
|
278
337
|
async age(...t) {
|
|
279
338
|
const n = this._getPath(...t);
|
|
280
|
-
|
|
281
|
-
const i = await
|
|
282
|
-
return i === null ? null : Date.now() - i;
|
|
339
|
+
u(n);
|
|
340
|
+
const i = await f(n);
|
|
341
|
+
return i === null ? null : Math.max(0, Date.now() - i);
|
|
342
|
+
}
|
|
343
|
+
ageSync(...t) {
|
|
344
|
+
const n = this._getPath(...t);
|
|
345
|
+
u(n);
|
|
346
|
+
const i = p(n);
|
|
347
|
+
return i === null ? null : Math.max(0, Date.now() - i);
|
|
283
348
|
}
|
|
284
|
-
/**
|
|
285
|
-
* Returns detailed information about the cache state.
|
|
286
|
-
*
|
|
287
|
-
* @param args - Arguments to resolve the cache path (when using a path function)
|
|
288
|
-
* @returns CacheInfo with exists, age, expired, stale, and path fields
|
|
289
|
-
*/
|
|
290
349
|
async info(...t) {
|
|
291
350
|
const n = this._getPath(...t);
|
|
292
|
-
|
|
293
|
-
const i = await
|
|
351
|
+
u(n);
|
|
352
|
+
const i = await f(n);
|
|
353
|
+
if (i === null)
|
|
354
|
+
return { exists: !1, age: null, expired: !1, stale: !1, path: n };
|
|
355
|
+
const r = Math.max(0, Date.now() - i), s = r >= this.duration, a = s && this.staleDuration != null && r < this.duration + this.staleDuration;
|
|
356
|
+
return { exists: !0, age: r, expired: s, stale: a, path: n };
|
|
357
|
+
}
|
|
358
|
+
infoSync(...t) {
|
|
359
|
+
const n = this._getPath(...t);
|
|
360
|
+
u(n);
|
|
361
|
+
const i = p(n);
|
|
294
362
|
if (i === null)
|
|
295
363
|
return { exists: !1, age: null, expired: !1, stale: !1, path: n };
|
|
296
|
-
const r = Date.now() - i, s = r >= this.duration,
|
|
297
|
-
return { exists: !0, age: r, expired: s, stale:
|
|
364
|
+
const r = Math.max(0, Date.now() - i), s = r >= this.duration, a = s && this.staleDuration != null && r < this.duration + this.staleDuration;
|
|
365
|
+
return { exists: !0, age: r, expired: s, stale: a, path: n };
|
|
298
366
|
}
|
|
299
|
-
/**
|
|
300
|
-
* Internal method to resolve the cache path.
|
|
301
|
-
* When path is a string and arguments are provided, auto-generates a unique
|
|
302
|
-
* cache path by hashing the arguments.
|
|
303
|
-
* @internal
|
|
304
|
-
*/
|
|
305
367
|
_getPath(...t) {
|
|
306
368
|
if (typeof this.path == "string") {
|
|
307
369
|
if (t.length === 0)
|
|
308
370
|
return this.path;
|
|
309
|
-
const n =
|
|
371
|
+
const n = H("sha256").update(JSON.stringify(t)).digest("hex").slice(0, 16), i = x(this.path), r = this.path.split("/").pop(), s = r.lastIndexOf(".");
|
|
310
372
|
if (s === -1)
|
|
311
|
-
return
|
|
312
|
-
const
|
|
313
|
-
return
|
|
373
|
+
return S(i, `${r}-${n}`);
|
|
374
|
+
const a = r.slice(0, s), l = r.slice(s);
|
|
375
|
+
return S(i, `${a}-${n}${l}`);
|
|
314
376
|
}
|
|
315
377
|
return this.path(...t);
|
|
316
378
|
}
|
|
317
|
-
/**
|
|
318
|
-
* Get a value from the in-memory LRU cache.
|
|
319
|
-
* Returns undefined if LRU is disabled, key not found, or entry is expired.
|
|
320
|
-
* @internal
|
|
321
|
-
*/
|
|
322
379
|
_lruGet(t) {
|
|
323
|
-
if (!this._lru) return
|
|
380
|
+
if (!this._lru) return d;
|
|
324
381
|
const n = this._lru.get(t);
|
|
325
|
-
return n ? Date.now() - n.timestamp > this.duration ? (this._lru.delete(t),
|
|
382
|
+
return n ? Date.now() - n.timestamp > this.duration ? (this._lru.delete(t), d) : (this._lru.delete(t), this._lru.set(t, n), n.value) : d;
|
|
326
383
|
}
|
|
327
|
-
/**
|
|
328
|
-
* Set a value in the in-memory LRU cache.
|
|
329
|
-
* No-op if LRU is disabled.
|
|
330
|
-
* @internal
|
|
331
|
-
*/
|
|
332
384
|
_lruSet(t, n) {
|
|
333
385
|
if (!(!this._lru || !this.lruSize)) {
|
|
334
386
|
if (this._lru.size >= this.lruSize && !this._lru.has(t)) {
|
|
@@ -340,29 +392,30 @@ class L extends Function {
|
|
|
340
392
|
}
|
|
341
393
|
// Implementation signature
|
|
342
394
|
call(t, n, i) {
|
|
343
|
-
if (
|
|
395
|
+
if (k(t)) {
|
|
344
396
|
const s = t;
|
|
345
397
|
return this.copy(s);
|
|
346
398
|
}
|
|
347
399
|
if (i) {
|
|
348
400
|
const s = i.value;
|
|
349
|
-
return i.value =
|
|
401
|
+
return i.value = _(this, s), i;
|
|
350
402
|
}
|
|
351
403
|
const r = t;
|
|
352
404
|
if (n) {
|
|
353
|
-
const s = n,
|
|
354
|
-
return
|
|
405
|
+
const s = n, a = this.copy(s);
|
|
406
|
+
return _(a, r);
|
|
355
407
|
}
|
|
356
|
-
return
|
|
408
|
+
return _(this, r);
|
|
357
409
|
}
|
|
358
410
|
}
|
|
359
411
|
export {
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
412
|
+
O as Cachetta,
|
|
413
|
+
C as CachettaError,
|
|
414
|
+
Y as InvalidPathError,
|
|
415
|
+
Z as readCache,
|
|
416
|
+
B as readCacheSync,
|
|
417
|
+
ct as setLogLevel,
|
|
418
|
+
ht as setLogger,
|
|
419
|
+
v as writeCache,
|
|
420
|
+
nt as writeCacheSync
|
|
368
421
|
};
|
package/dist/src/Cachetta.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CacheConfig, CacheInfo, CachableFunction, PathFn } from './types.js';
|
|
1
|
+
import { CacheConfig, CacheInfo, CachableFunction, CachableFunctionSync, PathFn } from './types.js';
|
|
2
2
|
import { LRU_MISS } from './constants.js';
|
|
3
3
|
interface LruEntry {
|
|
4
4
|
value: unknown;
|
|
@@ -18,67 +18,19 @@ export declare class Cachetta<Path extends string | PathFn<any> = string> extend
|
|
|
18
18
|
/** @internal */
|
|
19
19
|
_lru: Map<string, LruEntry> | undefined;
|
|
20
20
|
constructor(config: CacheConfig<Path>);
|
|
21
|
-
/**
|
|
22
|
-
* Creates a copy of this Cachetta instance with overridden configuration.
|
|
23
|
-
* Useful for creating variations of a base cache configuration.
|
|
24
|
-
*
|
|
25
|
-
* @param kwargs - Partial configuration to override
|
|
26
|
-
* @returns A new Cachetta instance with the specified overrides
|
|
27
|
-
*/
|
|
28
21
|
copy<NewPath extends string | PathFn<any> = string>(kwargs: Partial<CacheConfig<NewPath>>): Cachetta<NewPath>;
|
|
29
|
-
/**
|
|
30
|
-
* Wraps a function with caching behavior. Alias for calling the cache instance directly.
|
|
31
|
-
*
|
|
32
|
-
* @param fn - The function to wrap
|
|
33
|
-
* @returns A cached version of the function
|
|
34
|
-
*/
|
|
35
22
|
wrap(fn: CachableFunction): CachableFunction;
|
|
36
|
-
|
|
37
|
-
* Deletes the cache file on disk and clears LRU entries for this path.
|
|
38
|
-
* No-op if the cache file does not exist.
|
|
39
|
-
*
|
|
40
|
-
* @param args - Arguments to resolve the cache path (when using a path function)
|
|
41
|
-
*/
|
|
23
|
+
wrapSync(fn: CachableFunctionSync): CachableFunctionSync;
|
|
42
24
|
invalidate(...args: unknown[]): Promise<void>;
|
|
43
|
-
|
|
44
|
-
* Checks whether the cache file exists on disk.
|
|
45
|
-
*
|
|
46
|
-
* @param args - Arguments to resolve the cache path (when using a path function)
|
|
47
|
-
* @returns true if the cache file exists
|
|
48
|
-
*/
|
|
25
|
+
invalidateSync(...args: unknown[]): void;
|
|
49
26
|
exists(...args: unknown[]): Promise<boolean>;
|
|
50
|
-
|
|
51
|
-
* Returns the age of the cache file in milliseconds, or null if it does not exist.
|
|
52
|
-
*
|
|
53
|
-
* @param args - Arguments to resolve the cache path (when using a path function)
|
|
54
|
-
* @returns Age in ms, or null
|
|
55
|
-
*/
|
|
27
|
+
existsSync(...args: unknown[]): boolean;
|
|
56
28
|
age(...args: unknown[]): Promise<number | null>;
|
|
57
|
-
|
|
58
|
-
* Returns detailed information about the cache state.
|
|
59
|
-
*
|
|
60
|
-
* @param args - Arguments to resolve the cache path (when using a path function)
|
|
61
|
-
* @returns CacheInfo with exists, age, expired, stale, and path fields
|
|
62
|
-
*/
|
|
29
|
+
ageSync(...args: unknown[]): number | null;
|
|
63
30
|
info(...args: unknown[]): Promise<CacheInfo>;
|
|
64
|
-
|
|
65
|
-
* Internal method to resolve the cache path.
|
|
66
|
-
* When path is a string and arguments are provided, auto-generates a unique
|
|
67
|
-
* cache path by hashing the arguments.
|
|
68
|
-
* @internal
|
|
69
|
-
*/
|
|
31
|
+
infoSync(...args: unknown[]): CacheInfo;
|
|
70
32
|
_getPath(...args: unknown[]): string;
|
|
71
|
-
/**
|
|
72
|
-
* Get a value from the in-memory LRU cache.
|
|
73
|
-
* Returns undefined if LRU is disabled, key not found, or entry is expired.
|
|
74
|
-
* @internal
|
|
75
|
-
*/
|
|
76
33
|
_lruGet(key: string): unknown | typeof LRU_MISS;
|
|
77
|
-
/**
|
|
78
|
-
* Set a value in the in-memory LRU cache.
|
|
79
|
-
* No-op if LRU is disabled.
|
|
80
|
-
* @internal
|
|
81
|
-
*/
|
|
82
34
|
_lruSet(key: string, value: unknown): void;
|
|
83
35
|
call(target: CachableFunction, propertyKey: string, descriptor: PropertyDescriptor): PropertyDescriptor;
|
|
84
36
|
call(target: CachableFunction): CachableFunction;
|
package/dist/src/errors.d.ts
CHANGED
package/dist/src/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { Cachetta } from './Cachetta.js';
|
|
2
|
-
export { writeCache } from './write-cache.js';
|
|
3
|
-
export { readCache } from './read-cache.js';
|
|
2
|
+
export { writeCache, writeCacheSync } from './write-cache.js';
|
|
3
|
+
export { readCache, readCacheSync } from './read-cache.js';
|
|
4
4
|
export { setLogLevel, setLogger } from './utils/logger.js';
|
|
5
|
-
export { CachettaError, InvalidPathError
|
|
6
|
-
export type { CacheConfig, CacheInfo, PathFn, CachableFunction, Logger, LogLevel } from './types.js';
|
|
5
|
+
export { CachettaError, InvalidPathError } from './errors.js';
|
|
6
|
+
export type { CacheConfig, CacheInfo, PathFn, CachableFunction, CachableFunctionSync, Logger, LogLevel } from './types.js';
|
package/dist/src/read-cache.d.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { Cachetta } from './Cachetta.js';
|
|
2
2
|
export declare function readCache<T>(cacheBuddy: Cachetta<any>, ...args: unknown[]): Promise<T | null>;
|
|
3
|
+
export declare function readCacheSync<T>(cacheBuddy: Cachetta<any>, ...args: unknown[]): T | null;
|
|
3
4
|
/**
|
|
4
5
|
* Reads stale cache data: returns data only if the file exists and is within the
|
|
5
6
|
* staleDuration window (expired but not yet past duration + staleDuration).
|
|
6
7
|
* @internal
|
|
7
8
|
*/
|
|
8
9
|
export declare function readStaleCache<T>(cacheBuddy: Cachetta<any>, ...args: unknown[]): Promise<T | null>;
|
|
10
|
+
/** @internal */
|
|
11
|
+
export declare function readStaleCacheSync<T>(cacheBuddy: Cachetta<any>, ...args: unknown[]): T | null;
|
package/dist/src/types.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ export interface CacheInfo {
|
|
|
18
18
|
}
|
|
19
19
|
export type PathFn<T extends unknown[] = unknown[]> = (...args: T) => string;
|
|
20
20
|
export type CachableFunction = (...args: unknown[]) => unknown;
|
|
21
|
+
export type CachableFunctionSync = (...args: unknown[]) => unknown;
|
|
21
22
|
export interface Logger {
|
|
22
23
|
debug: (...messages: unknown[]) => void;
|
|
23
24
|
info: (...messages: unknown[]) => void;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import { Cachetta } from '../Cachetta.js';
|
|
2
|
-
import { CachableFunction } from '../types.js';
|
|
2
|
+
import { CachableFunction, CachableFunctionSync } from '../types.js';
|
|
3
3
|
export declare const cacheFn: (cache: Cachetta<any>, originalMethod: CachableFunction) => (this: ThisParameterType<typeof originalMethod>, ...args: Parameters<typeof originalMethod>) => Promise<unknown>;
|
|
4
|
+
export declare const cacheFnSync: (cache: Cachetta<any>, originalMethod: CachableFunctionSync) => (this: any, ...args: unknown[]) => unknown;
|
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
import { CacheConfig } from '../types.js';
|
|
2
2
|
export declare function shouldUseReadCache({ duration, read }: Pick<CacheConfig, 'duration' | 'read'>, cachePath: string): Promise<boolean>;
|
|
3
|
+
export declare function shouldUseReadCacheSync({ duration, read }: Pick<CacheConfig, 'duration' | 'read'>, cachePath: string): boolean;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cachetta",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -25,9 +25,25 @@
|
|
|
25
25
|
"test:unit:watch": "wireit",
|
|
26
26
|
"test:integration": "wireit",
|
|
27
27
|
"test:integration:watch": "wireit",
|
|
28
|
+
"lint": "wireit",
|
|
29
|
+
"typecheck": "wireit",
|
|
28
30
|
"build": "wireit"
|
|
29
31
|
},
|
|
30
32
|
"wireit": {
|
|
33
|
+
"lint": {
|
|
34
|
+
"command": "eslint src",
|
|
35
|
+
"files": [
|
|
36
|
+
"./src/**/*.ts",
|
|
37
|
+
"./eslint.config.js"
|
|
38
|
+
]
|
|
39
|
+
},
|
|
40
|
+
"typecheck": {
|
|
41
|
+
"command": "tsc --noEmit",
|
|
42
|
+
"files": [
|
|
43
|
+
"./src/**/*.ts",
|
|
44
|
+
"./tsconfig.json"
|
|
45
|
+
]
|
|
46
|
+
},
|
|
31
47
|
"test:unit": {
|
|
32
48
|
"command": "vitest run -c vitest.config.unit.ts"
|
|
33
49
|
},
|
|
@@ -61,13 +77,15 @@
|
|
|
61
77
|
}
|
|
62
78
|
},
|
|
63
79
|
"devDependencies": {
|
|
64
|
-
"
|
|
80
|
+
"@eslint/js": "^9.39.2",
|
|
65
81
|
"@types/node": "^22.10.0",
|
|
82
|
+
"cachetta": "workspace:*",
|
|
83
|
+
"eslint": "^9.39.2",
|
|
66
84
|
"typescript": "^5.7.2",
|
|
85
|
+
"typescript-eslint": "^8.55.0",
|
|
67
86
|
"vite": "^6.0.0",
|
|
68
87
|
"vite-plugin-dts": "^4.5.4",
|
|
69
88
|
"vitest": "^2.1.6",
|
|
70
89
|
"wireit": "^0.14.9"
|
|
71
|
-
}
|
|
72
|
-
"dependencies": {}
|
|
90
|
+
}
|
|
73
91
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|