flat-cache 6.1.18 → 6.1.19

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 (3) hide show
  1. package/dist/index.cjs +495 -1
  2. package/dist/index.js +455 -1
  3. package/package.json +12 -12
package/dist/index.cjs CHANGED
@@ -1 +1,495 @@
1
- "use strict";var F=Object.create;var u=Object.defineProperty;var O=Object.getOwnPropertyDescriptor;var C=Object.getOwnPropertyNames;var L=Object.getPrototypeOf,k=Object.prototype.hasOwnProperty;var A=(s,e)=>{for(var t in e)u(s,t,{get:e[t],enumerable:!0})},y=(s,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of C(e))!k.call(s,i)&&i!==t&&u(s,i,{get:()=>e[i],enumerable:!(r=O(e,i))||r.enumerable});return s};var g=(s,e,t)=>(t=s!=null?F(L(s)):{},y(e||!s||!s.__esModule?u(t,"default",{value:s,enumerable:!0}):t,s)),P=s=>y(u({},"__esModule",{value:!0}),s);var T={};A(T,{FlatCache:()=>l,FlatCacheEvents:()=>S,clearAll:()=>E,clearCacheById:()=>x,create:()=>I,createFromFile:()=>R,default:()=>p});module.exports=P(T);var a=g(require("fs"),1),o=g(require("path"),1),v=require("cacheable"),m=require("flatted"),b=require("hookified"),S=(h=>(h.SAVE="save",h.LOAD="load",h.DELETE="delete",h.CLEAR="clear",h.DESTROY="destroy",h.ERROR="error",h.EXPIRED="expired",h))(S||{}),l=class extends b.Hookified{_cache=new v.CacheableMemory;_cacheDir=".cache";_cacheId="cache1";_persistInterval=0;_persistTimer;_changesSinceLastSave=!1;_parse=m.parse;_stringify=m.stringify;constructor(e){super(),e&&(this._cache=new v.CacheableMemory({ttl:e.ttl,useClone:e.useClone,lruSize:e.lruSize,checkInterval:e.expirationInterval})),e?.cacheDir&&(this._cacheDir=e.cacheDir),e?.cacheId&&(this._cacheId=e.cacheId),e?.persistInterval&&(this._persistInterval=e.persistInterval,this.startAutoPersist()),e?.deserialize&&(this._parse=e.deserialize),e?.serialize&&(this._stringify=e.serialize)}get cache(){return this._cache}get cacheDir(){return this._cacheDir}set cacheDir(e){this._cacheDir=e}get cacheId(){return this._cacheId}set cacheId(e){this._cacheId=e}get changesSinceLastSave(){return this._changesSinceLastSave}get persistInterval(){return this._persistInterval}set persistInterval(e){this._persistInterval=e}load(e,t){try{let r=o.default.resolve(`${t??this._cacheDir}/${e??this._cacheId}`);this.loadFile(r),this.emit("load")}catch(r){this.emit("error",r)}}loadFile(e){if(a.default.existsSync(e)){let t=a.default.readFileSync(e,"utf8"),r=this._parse(t);if(Array.isArray(r))for(let i of r)i&&typeof i=="object"&&"key"in i&&(i.expires?this._cache.set(i.key,i.value,{expire:i.expires}):i.timestamp?this._cache.set(i.key,i.value,{expire:i.timestamp}):this._cache.set(i.key,i.value));else for(let i of Object.keys(r)){let c=r[i];c&&typeof c=="object"&&"key"in c?this._cache.set(c.key,c.value,{expire:c.expires}):c&&typeof c=="object"&&c.timestamp?this._cache.set(i,c,{expire:c.timestamp}):this._cache.set(i,c)}this._changesSinceLastSave=!0}}loadFileStream(e,t,r,i){if(a.default.existsSync(e)){let D=a.default.statSync(e).size,h=0,d="",f=a.default.createReadStream(e,{encoding:"utf8"});f.on("data",n=>{h+=n.length,d+=n,t(h,D)}),f.on("end",()=>{let n=this._parse(d);for(let _ of Object.keys(n))this._cache.set(n[_].key,n[_].value,{expire:n[_].expires});this._changesSinceLastSave=!0,r()}),f.on("error",n=>{this.emit("error",n),i&&i(n)})}else{let c=new Error(`Cache file ${e} does not exist`);this.emit("error",c),i&&i(c)}}all(){let e={},t=[...this._cache.items];for(let r of t)e[r.key]=r.value;return e}get items(){return[...this._cache.items]}get cacheFilePath(){return o.default.resolve(`${this._cacheDir}/${this._cacheId}`)}get cacheDirPath(){return o.default.resolve(this._cacheDir)}keys(){return[...this._cache.keys]}setKey(e,t,r){this.set(e,t,r)}set(e,t,r){this._cache.set(e,t,r),this._changesSinceLastSave=!0}removeKey(e){this.delete(e)}delete(e){this._cache.delete(e),this._changesSinceLastSave=!0,this.emit("delete",e)}getKey(e){return this.get(e)}get(e){return this._cache.get(e)}clear(){try{this._cache.clear(),this._changesSinceLastSave=!0,this.save(),this.emit("clear")}catch(e){this.emit("error",e)}}save(e=!1){try{if(this._changesSinceLastSave||e){let t=this.cacheFilePath,r=[...this._cache.items],i=this._stringify(r);a.default.existsSync(this._cacheDir)||a.default.mkdirSync(this._cacheDir,{recursive:!0}),a.default.writeFileSync(t,i),this._changesSinceLastSave=!1,this.emit("save")}}catch(t){this.emit("error",t)}}removeCacheFile(){try{if(a.default.existsSync(this.cacheFilePath))return a.default.rmSync(this.cacheFilePath),!0}catch(e){this.emit("error",e)}return!1}destroy(e=!1){try{this._cache.clear(),this.stopAutoPersist(),e?a.default.rmSync(this.cacheDirPath,{recursive:!0,force:!0}):a.default.rmSync(this.cacheFilePath,{recursive:!0,force:!0}),this._changesSinceLastSave=!1,this.emit("destroy")}catch(t){this.emit("error",t)}}startAutoPersist(){this._persistInterval>0&&(this._persistTimer&&(clearInterval(this._persistTimer),this._persistTimer=void 0),this._persistTimer=setInterval(()=>{this.save()},this._persistInterval))}stopAutoPersist(){this._persistTimer&&(clearInterval(this._persistTimer),this._persistTimer=void 0)}},p=class{static create=I;static createFromFile=R;static clearCacheById=x;static clearAll=E};function I(s){let e=new l(s);return e.load(),e}function R(s,e){let t=new l(e);return t.loadFile(s),t}function x(s,e){new l({cacheId:s,cacheDir:e}).destroy()}function E(s){a.default.rmSync(s??".cache",{recursive:!0,force:!0})}0&&(module.exports={FlatCache,FlatCacheEvents,clearAll,clearCacheById,create,createFromFile});
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ FlatCache: () => FlatCache,
34
+ FlatCacheEvents: () => FlatCacheEvents,
35
+ clearAll: () => clearAll,
36
+ clearCacheById: () => clearCacheById,
37
+ create: () => create,
38
+ createFromFile: () => createFromFile,
39
+ default: () => FlatCacheDefault
40
+ });
41
+ module.exports = __toCommonJS(index_exports);
42
+ var import_node_fs = __toESM(require("fs"), 1);
43
+ var import_node_path = __toESM(require("path"), 1);
44
+ var import_cacheable = require("cacheable");
45
+ var import_flatted = require("flatted");
46
+ var import_hookified = require("hookified");
47
+ var FlatCacheEvents = /* @__PURE__ */ ((FlatCacheEvents2) => {
48
+ FlatCacheEvents2["SAVE"] = "save";
49
+ FlatCacheEvents2["LOAD"] = "load";
50
+ FlatCacheEvents2["DELETE"] = "delete";
51
+ FlatCacheEvents2["CLEAR"] = "clear";
52
+ FlatCacheEvents2["DESTROY"] = "destroy";
53
+ FlatCacheEvents2["ERROR"] = "error";
54
+ FlatCacheEvents2["EXPIRED"] = "expired";
55
+ return FlatCacheEvents2;
56
+ })(FlatCacheEvents || {});
57
+ var FlatCache = class extends import_hookified.Hookified {
58
+ _cache = new import_cacheable.CacheableMemory();
59
+ _cacheDir = ".cache";
60
+ _cacheId = "cache1";
61
+ _persistInterval = 0;
62
+ _persistTimer;
63
+ _changesSinceLastSave = false;
64
+ _parse = import_flatted.parse;
65
+ _stringify = import_flatted.stringify;
66
+ constructor(options) {
67
+ super();
68
+ if (options) {
69
+ this._cache = new import_cacheable.CacheableMemory({
70
+ ttl: options.ttl,
71
+ useClone: options.useClone,
72
+ lruSize: options.lruSize,
73
+ checkInterval: options.expirationInterval
74
+ });
75
+ }
76
+ if (options?.cacheDir) {
77
+ this._cacheDir = options.cacheDir;
78
+ }
79
+ if (options?.cacheId) {
80
+ this._cacheId = options.cacheId;
81
+ }
82
+ if (options?.persistInterval) {
83
+ this._persistInterval = options.persistInterval;
84
+ this.startAutoPersist();
85
+ }
86
+ if (options?.deserialize) {
87
+ this._parse = options.deserialize;
88
+ }
89
+ if (options?.serialize) {
90
+ this._stringify = options.serialize;
91
+ }
92
+ }
93
+ /**
94
+ * The cache object
95
+ * @property cache
96
+ * @type {CacheableMemory}
97
+ */
98
+ get cache() {
99
+ return this._cache;
100
+ }
101
+ /**
102
+ * The cache directory
103
+ * @property cacheDir
104
+ * @type {String}
105
+ * @default '.cache'
106
+ */
107
+ get cacheDir() {
108
+ return this._cacheDir;
109
+ }
110
+ /**
111
+ * Set the cache directory
112
+ * @property cacheDir
113
+ * @type {String}
114
+ * @default '.cache'
115
+ */
116
+ set cacheDir(value) {
117
+ this._cacheDir = value;
118
+ }
119
+ /**
120
+ * The cache id
121
+ * @property cacheId
122
+ * @type {String}
123
+ * @default 'cache1'
124
+ */
125
+ get cacheId() {
126
+ return this._cacheId;
127
+ }
128
+ /**
129
+ * Set the cache id
130
+ * @property cacheId
131
+ * @type {String}
132
+ * @default 'cache1'
133
+ */
134
+ set cacheId(value) {
135
+ this._cacheId = value;
136
+ }
137
+ /**
138
+ * The flag to indicate if there are changes since the last save
139
+ * @property changesSinceLastSave
140
+ * @type {Boolean}
141
+ * @default false
142
+ */
143
+ get changesSinceLastSave() {
144
+ return this._changesSinceLastSave;
145
+ }
146
+ /**
147
+ * The interval to persist the cache to disk. 0 means no timed persistence
148
+ * @property persistInterval
149
+ * @type {Number}
150
+ * @default 0
151
+ */
152
+ get persistInterval() {
153
+ return this._persistInterval;
154
+ }
155
+ /**
156
+ * Set the interval to persist the cache to disk. 0 means no timed persistence
157
+ * @property persistInterval
158
+ * @type {Number}
159
+ * @default 0
160
+ */
161
+ set persistInterval(value) {
162
+ this._persistInterval = value;
163
+ }
164
+ /**
165
+ * Load a cache identified by the given Id. If the element does not exists, then initialize an empty
166
+ * cache storage. If specified `cacheDir` will be used as the directory to persist the data to. If omitted
167
+ * then the cache module directory `.cacheDir` will be used instead
168
+ *
169
+ * @method load
170
+ * @param cacheId {String} the id of the cache, would also be used as the name of the file cache
171
+ * @param cacheDir {String} directory for the cache entry
172
+ */
173
+ load(cacheId, cacheDir) {
174
+ try {
175
+ const filePath = import_node_path.default.resolve(
176
+ `${cacheDir ?? this._cacheDir}/${cacheId ?? this._cacheId}`
177
+ );
178
+ this.loadFile(filePath);
179
+ this.emit("load" /* LOAD */);
180
+ } catch (error) {
181
+ this.emit("error" /* ERROR */, error);
182
+ }
183
+ }
184
+ /**
185
+ * Load the cache from the provided file
186
+ * @method loadFile
187
+ * @param {String} pathToFile the path to the file containing the info for the cache
188
+ */
189
+ loadFile(pathToFile) {
190
+ if (import_node_fs.default.existsSync(pathToFile)) {
191
+ const data = import_node_fs.default.readFileSync(pathToFile, "utf8");
192
+ const items = this._parse(data);
193
+ if (Array.isArray(items)) {
194
+ for (const item of items) {
195
+ if (item && typeof item === "object" && "key" in item) {
196
+ if (item.expires) {
197
+ this._cache.set(item.key, item.value, { expire: item.expires });
198
+ } else if (item.timestamp) {
199
+ this._cache.set(item.key, item.value, { expire: item.timestamp });
200
+ } else {
201
+ this._cache.set(item.key, item.value);
202
+ }
203
+ }
204
+ }
205
+ } else {
206
+ for (const key of Object.keys(items)) {
207
+ const item = items[key];
208
+ if (item && typeof item === "object" && "key" in item) {
209
+ this._cache.set(item.key, item.value, {
210
+ expire: item.expires
211
+ });
212
+ } else {
213
+ if (item && typeof item === "object" && item.timestamp) {
214
+ this._cache.set(key, item, { expire: item.timestamp });
215
+ } else {
216
+ this._cache.set(key, item);
217
+ }
218
+ }
219
+ }
220
+ }
221
+ this._changesSinceLastSave = true;
222
+ }
223
+ }
224
+ loadFileStream(pathToFile, onProgress, onEnd, onError) {
225
+ if (import_node_fs.default.existsSync(pathToFile)) {
226
+ const stats = import_node_fs.default.statSync(pathToFile);
227
+ const total = stats.size;
228
+ let loaded = 0;
229
+ let streamData = "";
230
+ const readStream = import_node_fs.default.createReadStream(pathToFile, { encoding: "utf8" });
231
+ readStream.on("data", (chunk) => {
232
+ loaded += chunk.length;
233
+ streamData += chunk;
234
+ onProgress(loaded, total);
235
+ });
236
+ readStream.on("end", () => {
237
+ const items = this._parse(streamData);
238
+ for (const key of Object.keys(items)) {
239
+ this._cache.set(items[key].key, items[key].value, {
240
+ expire: items[key].expires
241
+ });
242
+ }
243
+ this._changesSinceLastSave = true;
244
+ onEnd();
245
+ });
246
+ readStream.on("error", (error) => {
247
+ this.emit("error" /* ERROR */, error);
248
+ if (onError) {
249
+ onError(error);
250
+ }
251
+ });
252
+ } else {
253
+ const error = new Error(`Cache file ${pathToFile} does not exist`);
254
+ this.emit("error" /* ERROR */, error);
255
+ if (onError) {
256
+ onError(error);
257
+ }
258
+ }
259
+ }
260
+ /**
261
+ * Returns the entire persisted object
262
+ * @method all
263
+ * @returns {*}
264
+ */
265
+ all() {
266
+ const result = {};
267
+ const items = [...this._cache.items];
268
+ for (const item of items) {
269
+ result[item.key] = item.value;
270
+ }
271
+ return result;
272
+ }
273
+ /**
274
+ * Returns an array with all the items in the cache { key, value, expires }
275
+ * @method items
276
+ * @returns {Array}
277
+ */
278
+ // biome-ignore lint/suspicious/noExplicitAny: cache items can store any value
279
+ get items() {
280
+ return [...this._cache.items];
281
+ }
282
+ /**
283
+ * Returns the path to the file where the cache is persisted
284
+ * @method cacheFilePath
285
+ * @returns {String}
286
+ */
287
+ get cacheFilePath() {
288
+ return import_node_path.default.resolve(`${this._cacheDir}/${this._cacheId}`);
289
+ }
290
+ /**
291
+ * Returns the path to the cache directory
292
+ * @method cacheDirPath
293
+ * @returns {String}
294
+ */
295
+ get cacheDirPath() {
296
+ return import_node_path.default.resolve(this._cacheDir);
297
+ }
298
+ /**
299
+ * Returns an array with all the keys in the cache
300
+ * @method keys
301
+ * @returns {Array}
302
+ */
303
+ keys() {
304
+ return [...this._cache.keys];
305
+ }
306
+ /**
307
+ * (Legacy) set key method. This method will be deprecated in the future
308
+ * @method setKey
309
+ * @param key {string} the key to set
310
+ * @param value {object} the value of the key. Could be any object that can be serialized with JSON.stringify
311
+ */
312
+ // biome-ignore lint/suspicious/noExplicitAny: type format
313
+ setKey(key, value, ttl) {
314
+ this.set(key, value, ttl);
315
+ }
316
+ /**
317
+ * Sets a key to a given value
318
+ * @method set
319
+ * @param key {string} the key to set
320
+ * @param value {object} the value of the key. Could be any object that can be serialized with JSON.stringify
321
+ * @param [ttl] {number} the time to live in milliseconds
322
+ */
323
+ // biome-ignore lint/suspicious/noExplicitAny: type format
324
+ set(key, value, ttl) {
325
+ this._cache.set(key, value, ttl);
326
+ this._changesSinceLastSave = true;
327
+ }
328
+ /**
329
+ * (Legacy) Remove a given key from the cache. This method will be deprecated in the future
330
+ * @method removeKey
331
+ * @param key {String} the key to remove from the object
332
+ */
333
+ removeKey(key) {
334
+ this.delete(key);
335
+ }
336
+ /**
337
+ * Remove a given key from the cache
338
+ * @method delete
339
+ * @param key {String} the key to remove from the object
340
+ */
341
+ delete(key) {
342
+ this._cache.delete(key);
343
+ this._changesSinceLastSave = true;
344
+ this.emit("delete" /* DELETE */, key);
345
+ }
346
+ /**
347
+ * (Legacy) Return the value of the provided key. This method will be deprecated in the future
348
+ * @method getKey<T>
349
+ * @param key {String} the name of the key to retrieve
350
+ * @returns {*} at T the value from the key
351
+ */
352
+ getKey(key) {
353
+ return this.get(key);
354
+ }
355
+ /**
356
+ * Return the value of the provided key
357
+ * @method get<T>
358
+ * @param key {String} the name of the key to retrieve
359
+ * @returns {*} at T the value from the key
360
+ */
361
+ get(key) {
362
+ return this._cache.get(key);
363
+ }
364
+ /**
365
+ * Clear the cache and save the state to disk
366
+ * @method clear
367
+ */
368
+ clear() {
369
+ try {
370
+ this._cache.clear();
371
+ this._changesSinceLastSave = true;
372
+ this.save();
373
+ this.emit("clear" /* CLEAR */);
374
+ } catch (error) {
375
+ this.emit("error" /* ERROR */, error);
376
+ }
377
+ }
378
+ /**
379
+ * Save the state of the cache identified by the docId to disk
380
+ * as a JSON structure
381
+ * @method save
382
+ */
383
+ save(force = false) {
384
+ try {
385
+ if (this._changesSinceLastSave || force) {
386
+ const filePath = this.cacheFilePath;
387
+ const items = [...this._cache.items];
388
+ const data = this._stringify(items);
389
+ if (!import_node_fs.default.existsSync(this._cacheDir)) {
390
+ import_node_fs.default.mkdirSync(this._cacheDir, { recursive: true });
391
+ }
392
+ import_node_fs.default.writeFileSync(filePath, data);
393
+ this._changesSinceLastSave = false;
394
+ this.emit("save" /* SAVE */);
395
+ }
396
+ } catch (error) {
397
+ this.emit("error" /* ERROR */, error);
398
+ }
399
+ }
400
+ /**
401
+ * Remove the file where the cache is persisted
402
+ * @method removeCacheFile
403
+ * @return {Boolean} true or false if the file was successfully deleted
404
+ */
405
+ removeCacheFile() {
406
+ try {
407
+ if (import_node_fs.default.existsSync(this.cacheFilePath)) {
408
+ import_node_fs.default.rmSync(this.cacheFilePath);
409
+ return true;
410
+ }
411
+ } catch (error) {
412
+ this.emit("error" /* ERROR */, error);
413
+ }
414
+ return false;
415
+ }
416
+ /**
417
+ * Destroy the cache. This will remove the directory, file, and memory cache
418
+ * @method destroy
419
+ * @param [includeCacheDir=false] {Boolean} if true, the cache directory will be removed
420
+ * @return {undefined}
421
+ */
422
+ destroy(includeCacheDirectory = false) {
423
+ try {
424
+ this._cache.clear();
425
+ this.stopAutoPersist();
426
+ if (includeCacheDirectory) {
427
+ import_node_fs.default.rmSync(this.cacheDirPath, { recursive: true, force: true });
428
+ } else {
429
+ import_node_fs.default.rmSync(this.cacheFilePath, { recursive: true, force: true });
430
+ }
431
+ this._changesSinceLastSave = false;
432
+ this.emit("destroy" /* DESTROY */);
433
+ } catch (error) {
434
+ this.emit("error" /* ERROR */, error);
435
+ }
436
+ }
437
+ /**
438
+ * Start the auto persist interval
439
+ * @method startAutoPersist
440
+ */
441
+ startAutoPersist() {
442
+ if (this._persistInterval > 0) {
443
+ if (this._persistTimer) {
444
+ clearInterval(this._persistTimer);
445
+ this._persistTimer = void 0;
446
+ }
447
+ this._persistTimer = setInterval(() => {
448
+ this.save();
449
+ }, this._persistInterval);
450
+ }
451
+ }
452
+ /**
453
+ * Stop the auto persist interval
454
+ * @method stopAutoPersist
455
+ */
456
+ stopAutoPersist() {
457
+ if (this._persistTimer) {
458
+ clearInterval(this._persistTimer);
459
+ this._persistTimer = void 0;
460
+ }
461
+ }
462
+ };
463
+ var FlatCacheDefault = class {
464
+ static create = create;
465
+ static createFromFile = createFromFile;
466
+ static clearCacheById = clearCacheById;
467
+ static clearAll = clearAll;
468
+ };
469
+ function create(options) {
470
+ const cache = new FlatCache(options);
471
+ cache.load();
472
+ return cache;
473
+ }
474
+ function createFromFile(filePath, options) {
475
+ const cache = new FlatCache(options);
476
+ cache.loadFile(filePath);
477
+ return cache;
478
+ }
479
+ function clearCacheById(cacheId, cacheDirectory) {
480
+ const cache = new FlatCache({ cacheId, cacheDir: cacheDirectory });
481
+ cache.destroy();
482
+ }
483
+ function clearAll(cacheDirectory) {
484
+ import_node_fs.default.rmSync(cacheDirectory ?? ".cache", { recursive: true, force: true });
485
+ }
486
+ // Annotate the CommonJS export names for ESM import in node:
487
+ 0 && (module.exports = {
488
+ FlatCache,
489
+ FlatCacheEvents,
490
+ clearAll,
491
+ clearCacheById,
492
+ create,
493
+ createFromFile
494
+ });
495
+ /* v8 ignore next -- @preserve */
package/dist/index.js CHANGED
@@ -1 +1,455 @@
1
- import c from"fs";import p from"path";import{CacheableMemory as _}from"cacheable";import{parse as d,stringify as y}from"flatted";import{Hookified as g}from"hookified";var b=(a=>(a.SAVE="save",a.LOAD="load",a.DELETE="delete",a.CLEAR="clear",a.DESTROY="destroy",a.ERROR="error",a.EXPIRED="expired",a))(b||{}),l=class extends g{_cache=new _;_cacheDir=".cache";_cacheId="cache1";_persistInterval=0;_persistTimer;_changesSinceLastSave=!1;_parse=d;_stringify=y;constructor(e){super(),e&&(this._cache=new _({ttl:e.ttl,useClone:e.useClone,lruSize:e.lruSize,checkInterval:e.expirationInterval})),e?.cacheDir&&(this._cacheDir=e.cacheDir),e?.cacheId&&(this._cacheId=e.cacheId),e?.persistInterval&&(this._persistInterval=e.persistInterval,this.startAutoPersist()),e?.deserialize&&(this._parse=e.deserialize),e?.serialize&&(this._stringify=e.serialize)}get cache(){return this._cache}get cacheDir(){return this._cacheDir}set cacheDir(e){this._cacheDir=e}get cacheId(){return this._cacheId}set cacheId(e){this._cacheId=e}get changesSinceLastSave(){return this._changesSinceLastSave}get persistInterval(){return this._persistInterval}set persistInterval(e){this._persistInterval=e}load(e,i){try{let s=p.resolve(`${i??this._cacheDir}/${e??this._cacheId}`);this.loadFile(s),this.emit("load")}catch(s){this.emit("error",s)}}loadFile(e){if(c.existsSync(e)){let i=c.readFileSync(e,"utf8"),s=this._parse(i);if(Array.isArray(s))for(let t of s)t&&typeof t=="object"&&"key"in t&&(t.expires?this._cache.set(t.key,t.value,{expire:t.expires}):t.timestamp?this._cache.set(t.key,t.value,{expire:t.timestamp}):this._cache.set(t.key,t.value));else for(let t of Object.keys(s)){let r=s[t];r&&typeof r=="object"&&"key"in r?this._cache.set(r.key,r.value,{expire:r.expires}):r&&typeof r=="object"&&r.timestamp?this._cache.set(t,r,{expire:r.timestamp}):this._cache.set(t,r)}this._changesSinceLastSave=!0}}loadFileStream(e,i,s,t){if(c.existsSync(e)){let v=c.statSync(e).size,a=0,f="",u=c.createReadStream(e,{encoding:"utf8"});u.on("data",h=>{a+=h.length,f+=h,i(a,v)}),u.on("end",()=>{let h=this._parse(f);for(let o of Object.keys(h))this._cache.set(h[o].key,h[o].value,{expire:h[o].expires});this._changesSinceLastSave=!0,s()}),u.on("error",h=>{this.emit("error",h),t&&t(h)})}else{let r=new Error(`Cache file ${e} does not exist`);this.emit("error",r),t&&t(r)}}all(){let e={},i=[...this._cache.items];for(let s of i)e[s.key]=s.value;return e}get items(){return[...this._cache.items]}get cacheFilePath(){return p.resolve(`${this._cacheDir}/${this._cacheId}`)}get cacheDirPath(){return p.resolve(this._cacheDir)}keys(){return[...this._cache.keys]}setKey(e,i,s){this.set(e,i,s)}set(e,i,s){this._cache.set(e,i,s),this._changesSinceLastSave=!0}removeKey(e){this.delete(e)}delete(e){this._cache.delete(e),this._changesSinceLastSave=!0,this.emit("delete",e)}getKey(e){return this.get(e)}get(e){return this._cache.get(e)}clear(){try{this._cache.clear(),this._changesSinceLastSave=!0,this.save(),this.emit("clear")}catch(e){this.emit("error",e)}}save(e=!1){try{if(this._changesSinceLastSave||e){let i=this.cacheFilePath,s=[...this._cache.items],t=this._stringify(s);c.existsSync(this._cacheDir)||c.mkdirSync(this._cacheDir,{recursive:!0}),c.writeFileSync(i,t),this._changesSinceLastSave=!1,this.emit("save")}}catch(i){this.emit("error",i)}}removeCacheFile(){try{if(c.existsSync(this.cacheFilePath))return c.rmSync(this.cacheFilePath),!0}catch(e){this.emit("error",e)}return!1}destroy(e=!1){try{this._cache.clear(),this.stopAutoPersist(),e?c.rmSync(this.cacheDirPath,{recursive:!0,force:!0}):c.rmSync(this.cacheFilePath,{recursive:!0,force:!0}),this._changesSinceLastSave=!1,this.emit("destroy")}catch(i){this.emit("error",i)}}startAutoPersist(){this._persistInterval>0&&(this._persistTimer&&(clearInterval(this._persistTimer),this._persistTimer=void 0),this._persistTimer=setInterval(()=>{this.save()},this._persistInterval))}stopAutoPersist(){this._persistTimer&&(clearInterval(this._persistTimer),this._persistTimer=void 0)}},m=class{static create=S;static createFromFile=I;static clearCacheById=R;static clearAll=x};function S(n){let e=new l(n);return e.load(),e}function I(n,e){let i=new l(e);return i.loadFile(n),i}function R(n,e){new l({cacheId:n,cacheDir:e}).destroy()}function x(n){c.rmSync(n??".cache",{recursive:!0,force:!0})}export{l as FlatCache,b as FlatCacheEvents,x as clearAll,R as clearCacheById,S as create,I as createFromFile,m as default};
1
+ // src/index.ts
2
+ import fs from "fs";
3
+ import path from "path";
4
+ import { CacheableMemory } from "cacheable";
5
+ import { parse, stringify } from "flatted";
6
+ import { Hookified } from "hookified";
7
+ var FlatCacheEvents = /* @__PURE__ */ ((FlatCacheEvents2) => {
8
+ FlatCacheEvents2["SAVE"] = "save";
9
+ FlatCacheEvents2["LOAD"] = "load";
10
+ FlatCacheEvents2["DELETE"] = "delete";
11
+ FlatCacheEvents2["CLEAR"] = "clear";
12
+ FlatCacheEvents2["DESTROY"] = "destroy";
13
+ FlatCacheEvents2["ERROR"] = "error";
14
+ FlatCacheEvents2["EXPIRED"] = "expired";
15
+ return FlatCacheEvents2;
16
+ })(FlatCacheEvents || {});
17
+ var FlatCache = class extends Hookified {
18
+ _cache = new CacheableMemory();
19
+ _cacheDir = ".cache";
20
+ _cacheId = "cache1";
21
+ _persistInterval = 0;
22
+ _persistTimer;
23
+ _changesSinceLastSave = false;
24
+ _parse = parse;
25
+ _stringify = stringify;
26
+ constructor(options) {
27
+ super();
28
+ if (options) {
29
+ this._cache = new CacheableMemory({
30
+ ttl: options.ttl,
31
+ useClone: options.useClone,
32
+ lruSize: options.lruSize,
33
+ checkInterval: options.expirationInterval
34
+ });
35
+ }
36
+ if (options?.cacheDir) {
37
+ this._cacheDir = options.cacheDir;
38
+ }
39
+ if (options?.cacheId) {
40
+ this._cacheId = options.cacheId;
41
+ }
42
+ if (options?.persistInterval) {
43
+ this._persistInterval = options.persistInterval;
44
+ this.startAutoPersist();
45
+ }
46
+ if (options?.deserialize) {
47
+ this._parse = options.deserialize;
48
+ }
49
+ if (options?.serialize) {
50
+ this._stringify = options.serialize;
51
+ }
52
+ }
53
+ /**
54
+ * The cache object
55
+ * @property cache
56
+ * @type {CacheableMemory}
57
+ */
58
+ get cache() {
59
+ return this._cache;
60
+ }
61
+ /**
62
+ * The cache directory
63
+ * @property cacheDir
64
+ * @type {String}
65
+ * @default '.cache'
66
+ */
67
+ get cacheDir() {
68
+ return this._cacheDir;
69
+ }
70
+ /**
71
+ * Set the cache directory
72
+ * @property cacheDir
73
+ * @type {String}
74
+ * @default '.cache'
75
+ */
76
+ set cacheDir(value) {
77
+ this._cacheDir = value;
78
+ }
79
+ /**
80
+ * The cache id
81
+ * @property cacheId
82
+ * @type {String}
83
+ * @default 'cache1'
84
+ */
85
+ get cacheId() {
86
+ return this._cacheId;
87
+ }
88
+ /**
89
+ * Set the cache id
90
+ * @property cacheId
91
+ * @type {String}
92
+ * @default 'cache1'
93
+ */
94
+ set cacheId(value) {
95
+ this._cacheId = value;
96
+ }
97
+ /**
98
+ * The flag to indicate if there are changes since the last save
99
+ * @property changesSinceLastSave
100
+ * @type {Boolean}
101
+ * @default false
102
+ */
103
+ get changesSinceLastSave() {
104
+ return this._changesSinceLastSave;
105
+ }
106
+ /**
107
+ * The interval to persist the cache to disk. 0 means no timed persistence
108
+ * @property persistInterval
109
+ * @type {Number}
110
+ * @default 0
111
+ */
112
+ get persistInterval() {
113
+ return this._persistInterval;
114
+ }
115
+ /**
116
+ * Set the interval to persist the cache to disk. 0 means no timed persistence
117
+ * @property persistInterval
118
+ * @type {Number}
119
+ * @default 0
120
+ */
121
+ set persistInterval(value) {
122
+ this._persistInterval = value;
123
+ }
124
+ /**
125
+ * Load a cache identified by the given Id. If the element does not exists, then initialize an empty
126
+ * cache storage. If specified `cacheDir` will be used as the directory to persist the data to. If omitted
127
+ * then the cache module directory `.cacheDir` will be used instead
128
+ *
129
+ * @method load
130
+ * @param cacheId {String} the id of the cache, would also be used as the name of the file cache
131
+ * @param cacheDir {String} directory for the cache entry
132
+ */
133
+ load(cacheId, cacheDir) {
134
+ try {
135
+ const filePath = path.resolve(
136
+ `${cacheDir ?? this._cacheDir}/${cacheId ?? this._cacheId}`
137
+ );
138
+ this.loadFile(filePath);
139
+ this.emit("load" /* LOAD */);
140
+ } catch (error) {
141
+ this.emit("error" /* ERROR */, error);
142
+ }
143
+ }
144
+ /**
145
+ * Load the cache from the provided file
146
+ * @method loadFile
147
+ * @param {String} pathToFile the path to the file containing the info for the cache
148
+ */
149
+ loadFile(pathToFile) {
150
+ if (fs.existsSync(pathToFile)) {
151
+ const data = fs.readFileSync(pathToFile, "utf8");
152
+ const items = this._parse(data);
153
+ if (Array.isArray(items)) {
154
+ for (const item of items) {
155
+ if (item && typeof item === "object" && "key" in item) {
156
+ if (item.expires) {
157
+ this._cache.set(item.key, item.value, { expire: item.expires });
158
+ } else if (item.timestamp) {
159
+ this._cache.set(item.key, item.value, { expire: item.timestamp });
160
+ } else {
161
+ this._cache.set(item.key, item.value);
162
+ }
163
+ }
164
+ }
165
+ } else {
166
+ for (const key of Object.keys(items)) {
167
+ const item = items[key];
168
+ if (item && typeof item === "object" && "key" in item) {
169
+ this._cache.set(item.key, item.value, {
170
+ expire: item.expires
171
+ });
172
+ } else {
173
+ if (item && typeof item === "object" && item.timestamp) {
174
+ this._cache.set(key, item, { expire: item.timestamp });
175
+ } else {
176
+ this._cache.set(key, item);
177
+ }
178
+ }
179
+ }
180
+ }
181
+ this._changesSinceLastSave = true;
182
+ }
183
+ }
184
+ loadFileStream(pathToFile, onProgress, onEnd, onError) {
185
+ if (fs.existsSync(pathToFile)) {
186
+ const stats = fs.statSync(pathToFile);
187
+ const total = stats.size;
188
+ let loaded = 0;
189
+ let streamData = "";
190
+ const readStream = fs.createReadStream(pathToFile, { encoding: "utf8" });
191
+ readStream.on("data", (chunk) => {
192
+ loaded += chunk.length;
193
+ streamData += chunk;
194
+ onProgress(loaded, total);
195
+ });
196
+ readStream.on("end", () => {
197
+ const items = this._parse(streamData);
198
+ for (const key of Object.keys(items)) {
199
+ this._cache.set(items[key].key, items[key].value, {
200
+ expire: items[key].expires
201
+ });
202
+ }
203
+ this._changesSinceLastSave = true;
204
+ onEnd();
205
+ });
206
+ readStream.on("error", (error) => {
207
+ this.emit("error" /* ERROR */, error);
208
+ if (onError) {
209
+ onError(error);
210
+ }
211
+ });
212
+ } else {
213
+ const error = new Error(`Cache file ${pathToFile} does not exist`);
214
+ this.emit("error" /* ERROR */, error);
215
+ if (onError) {
216
+ onError(error);
217
+ }
218
+ }
219
+ }
220
+ /**
221
+ * Returns the entire persisted object
222
+ * @method all
223
+ * @returns {*}
224
+ */
225
+ all() {
226
+ const result = {};
227
+ const items = [...this._cache.items];
228
+ for (const item of items) {
229
+ result[item.key] = item.value;
230
+ }
231
+ return result;
232
+ }
233
+ /**
234
+ * Returns an array with all the items in the cache { key, value, expires }
235
+ * @method items
236
+ * @returns {Array}
237
+ */
238
+ // biome-ignore lint/suspicious/noExplicitAny: cache items can store any value
239
+ get items() {
240
+ return [...this._cache.items];
241
+ }
242
+ /**
243
+ * Returns the path to the file where the cache is persisted
244
+ * @method cacheFilePath
245
+ * @returns {String}
246
+ */
247
+ get cacheFilePath() {
248
+ return path.resolve(`${this._cacheDir}/${this._cacheId}`);
249
+ }
250
+ /**
251
+ * Returns the path to the cache directory
252
+ * @method cacheDirPath
253
+ * @returns {String}
254
+ */
255
+ get cacheDirPath() {
256
+ return path.resolve(this._cacheDir);
257
+ }
258
+ /**
259
+ * Returns an array with all the keys in the cache
260
+ * @method keys
261
+ * @returns {Array}
262
+ */
263
+ keys() {
264
+ return [...this._cache.keys];
265
+ }
266
+ /**
267
+ * (Legacy) set key method. This method will be deprecated in the future
268
+ * @method setKey
269
+ * @param key {string} the key to set
270
+ * @param value {object} the value of the key. Could be any object that can be serialized with JSON.stringify
271
+ */
272
+ // biome-ignore lint/suspicious/noExplicitAny: type format
273
+ setKey(key, value, ttl) {
274
+ this.set(key, value, ttl);
275
+ }
276
+ /**
277
+ * Sets a key to a given value
278
+ * @method set
279
+ * @param key {string} the key to set
280
+ * @param value {object} the value of the key. Could be any object that can be serialized with JSON.stringify
281
+ * @param [ttl] {number} the time to live in milliseconds
282
+ */
283
+ // biome-ignore lint/suspicious/noExplicitAny: type format
284
+ set(key, value, ttl) {
285
+ this._cache.set(key, value, ttl);
286
+ this._changesSinceLastSave = true;
287
+ }
288
+ /**
289
+ * (Legacy) Remove a given key from the cache. This method will be deprecated in the future
290
+ * @method removeKey
291
+ * @param key {String} the key to remove from the object
292
+ */
293
+ removeKey(key) {
294
+ this.delete(key);
295
+ }
296
+ /**
297
+ * Remove a given key from the cache
298
+ * @method delete
299
+ * @param key {String} the key to remove from the object
300
+ */
301
+ delete(key) {
302
+ this._cache.delete(key);
303
+ this._changesSinceLastSave = true;
304
+ this.emit("delete" /* DELETE */, key);
305
+ }
306
+ /**
307
+ * (Legacy) Return the value of the provided key. This method will be deprecated in the future
308
+ * @method getKey<T>
309
+ * @param key {String} the name of the key to retrieve
310
+ * @returns {*} at T the value from the key
311
+ */
312
+ getKey(key) {
313
+ return this.get(key);
314
+ }
315
+ /**
316
+ * Return the value of the provided key
317
+ * @method get<T>
318
+ * @param key {String} the name of the key to retrieve
319
+ * @returns {*} at T the value from the key
320
+ */
321
+ get(key) {
322
+ return this._cache.get(key);
323
+ }
324
+ /**
325
+ * Clear the cache and save the state to disk
326
+ * @method clear
327
+ */
328
+ clear() {
329
+ try {
330
+ this._cache.clear();
331
+ this._changesSinceLastSave = true;
332
+ this.save();
333
+ this.emit("clear" /* CLEAR */);
334
+ } catch (error) {
335
+ this.emit("error" /* ERROR */, error);
336
+ }
337
+ }
338
+ /**
339
+ * Save the state of the cache identified by the docId to disk
340
+ * as a JSON structure
341
+ * @method save
342
+ */
343
+ save(force = false) {
344
+ try {
345
+ if (this._changesSinceLastSave || force) {
346
+ const filePath = this.cacheFilePath;
347
+ const items = [...this._cache.items];
348
+ const data = this._stringify(items);
349
+ if (!fs.existsSync(this._cacheDir)) {
350
+ fs.mkdirSync(this._cacheDir, { recursive: true });
351
+ }
352
+ fs.writeFileSync(filePath, data);
353
+ this._changesSinceLastSave = false;
354
+ this.emit("save" /* SAVE */);
355
+ }
356
+ } catch (error) {
357
+ this.emit("error" /* ERROR */, error);
358
+ }
359
+ }
360
+ /**
361
+ * Remove the file where the cache is persisted
362
+ * @method removeCacheFile
363
+ * @return {Boolean} true or false if the file was successfully deleted
364
+ */
365
+ removeCacheFile() {
366
+ try {
367
+ if (fs.existsSync(this.cacheFilePath)) {
368
+ fs.rmSync(this.cacheFilePath);
369
+ return true;
370
+ }
371
+ } catch (error) {
372
+ this.emit("error" /* ERROR */, error);
373
+ }
374
+ return false;
375
+ }
376
+ /**
377
+ * Destroy the cache. This will remove the directory, file, and memory cache
378
+ * @method destroy
379
+ * @param [includeCacheDir=false] {Boolean} if true, the cache directory will be removed
380
+ * @return {undefined}
381
+ */
382
+ destroy(includeCacheDirectory = false) {
383
+ try {
384
+ this._cache.clear();
385
+ this.stopAutoPersist();
386
+ if (includeCacheDirectory) {
387
+ fs.rmSync(this.cacheDirPath, { recursive: true, force: true });
388
+ } else {
389
+ fs.rmSync(this.cacheFilePath, { recursive: true, force: true });
390
+ }
391
+ this._changesSinceLastSave = false;
392
+ this.emit("destroy" /* DESTROY */);
393
+ } catch (error) {
394
+ this.emit("error" /* ERROR */, error);
395
+ }
396
+ }
397
+ /**
398
+ * Start the auto persist interval
399
+ * @method startAutoPersist
400
+ */
401
+ startAutoPersist() {
402
+ if (this._persistInterval > 0) {
403
+ if (this._persistTimer) {
404
+ clearInterval(this._persistTimer);
405
+ this._persistTimer = void 0;
406
+ }
407
+ this._persistTimer = setInterval(() => {
408
+ this.save();
409
+ }, this._persistInterval);
410
+ }
411
+ }
412
+ /**
413
+ * Stop the auto persist interval
414
+ * @method stopAutoPersist
415
+ */
416
+ stopAutoPersist() {
417
+ if (this._persistTimer) {
418
+ clearInterval(this._persistTimer);
419
+ this._persistTimer = void 0;
420
+ }
421
+ }
422
+ };
423
+ var FlatCacheDefault = class {
424
+ static create = create;
425
+ static createFromFile = createFromFile;
426
+ static clearCacheById = clearCacheById;
427
+ static clearAll = clearAll;
428
+ };
429
+ function create(options) {
430
+ const cache = new FlatCache(options);
431
+ cache.load();
432
+ return cache;
433
+ }
434
+ function createFromFile(filePath, options) {
435
+ const cache = new FlatCache(options);
436
+ cache.loadFile(filePath);
437
+ return cache;
438
+ }
439
+ function clearCacheById(cacheId, cacheDirectory) {
440
+ const cache = new FlatCache({ cacheId, cacheDir: cacheDirectory });
441
+ cache.destroy();
442
+ }
443
+ function clearAll(cacheDirectory) {
444
+ fs.rmSync(cacheDirectory ?? ".cache", { recursive: true, force: true });
445
+ }
446
+ export {
447
+ FlatCache,
448
+ FlatCacheEvents,
449
+ clearAll,
450
+ clearCacheById,
451
+ create,
452
+ createFromFile,
453
+ FlatCacheDefault as default
454
+ };
455
+ /* v8 ignore next -- @preserve */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flat-cache",
3
- "version": "6.1.18",
3
+ "version": "6.1.19",
4
4
  "description": "A simple key/value storage using files to persist the data",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -52,26 +52,26 @@
52
52
  "file-system-cache"
53
53
  ],
54
54
  "devDependencies": {
55
- "@biomejs/biome": "^2.2.4",
56
- "@faker-js/faker": "^10.0.0",
57
- "@types/node": "^24.5.0",
58
- "@vitest/coverage-v8": "^3.2.4",
59
- "rimraf": "^6.0.1",
60
- "tsup": "^8.5.0",
61
- "typescript": "^5.9.2",
62
- "vitest": "^3.2.4"
55
+ "@biomejs/biome": "^2.3.5",
56
+ "@faker-js/faker": "^10.1.0",
57
+ "@types/node": "^24.10.1",
58
+ "@vitest/coverage-v8": "^4.0.9",
59
+ "rimraf": "^6.1.0",
60
+ "tsup": "^8.5.1",
61
+ "typescript": "^5.9.3",
62
+ "vitest": "^4.0.9"
63
63
  },
64
64
  "dependencies": {
65
65
  "flatted": "^3.3.3",
66
- "hookified": "^1.12.0",
67
- "cacheable": "^2.1.0"
66
+ "hookified": "^1.13.0",
67
+ "cacheable": "^2.2.0"
68
68
  },
69
69
  "files": [
70
70
  "dist",
71
71
  "license"
72
72
  ],
73
73
  "scripts": {
74
- "build": "rimraf ./dist && tsup src/index.ts --format cjs,esm --dts --clean --minify",
74
+ "build": "rimraf ./dist && tsup src/index.ts --format cjs,esm --dts --clean",
75
75
  "prepublish": "pnpm build",
76
76
  "lint": "biome check --write --error-on-warnings",
77
77
  "test": "pnpm lint && vitest run --coverage",