flat-cache 4.0.1 → 6.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/LICENSE CHANGED
@@ -1,22 +1,19 @@
1
- The MIT License (MIT)
2
-
3
- Copyright (c) Roy Riojas and Jared Wray
1
+ MIT License & © Jared Wray
4
2
 
5
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
4
+ of this software and associated documentation files (the "Software"), to
5
+ deal in the Software without restriction, including without limitation the
6
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7
+ sell copies of the Software, and to permit persons to whom the Software is
10
8
  furnished to do so, subject to the following conditions:
11
9
 
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
14
12
 
15
13
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
14
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
15
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
16
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
22
-
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19
+ DEALINGS IN THE SOFTWARE.
package/README.md CHANGED
@@ -1,77 +1,85 @@
1
- # flat-cache
2
-
3
- > A stupidly simple key/value storage using files to persist the data
4
-
5
- [![NPM Version](https://img.shields.io/npm/v/flat-cache.svg?style=flat)](https://npmjs.org/package/flat-cache)
6
- [![tests](https://github.com/jaredwray/flat-cache/actions/workflows/tests.yaml/badge.svg?branch=master)](https://github.com/jaredwray/flat-cache/actions/workflows/tests.yaml)
7
- [![codecov](https://codecov.io/github/jaredwray/flat-cache/branch/master/graph/badge.svg?token=KxR95XT3NF)](https://codecov.io/github/jaredwray/flat-cache)
8
- [![npm](https://img.shields.io/npm/dm/flat-cache)](https://npmjs.com/package/flat-cache)
9
-
10
- ## install
1
+ [<img align="center" src="https://cacheable.org/logo.svg" alt="Cacheable" />](https://github.com/jaredwray/cacheable)
11
2
 
3
+ # flat-cache
4
+ > A simple key/value storage using files to persist the data
5
+
6
+ [![codecov](https://codecov.io/gh/jaredwray/cacheable/graph/badge.svg?token=lWZ9OBQ7GM)](https://codecov.io/gh/jaredwray/cacheable)
7
+ [![tests](https://github.com/jaredwray/cacheable/actions/workflows/tests.yml/badge.svg)](https://github.com/jaredwray/cacheable/actions/workflows/tests.yml)
8
+ [![npm](https://img.shields.io/npm/dm/flat-cache.svg)](https://www.npmjs.com/package/flat-cache)
9
+ [![npm](https://img.shields.io/npm/v/flat-cache)](https://www.npmjs.com/package/flat-cache)
10
+ [![GitHub](https://img.shields.io/github/license/jaredwray/cacheable)](https://github.com/jaredwray/cacheable/blob/main/LICENSE)
11
+
12
+ # Features
13
+ - A simple key/value storage using files to persist the data
14
+ - Uses a in-memory cache (via `CacheableMemory`) as the primary storage and then persists the data to disk
15
+ - Automatically saves the data to disk via `persistInterval` setting. Off By Default
16
+ - Easily Loads the data from disk and into memory
17
+ - Uses `ttl` and `lruSize` to manage the cache and persist the data
18
+ - Only saves the data to disk if the data has changed even when using `persistInterval` or calling `save()`
19
+ - Uses `flatted` to parse and stringify the data by default but can be overridden
20
+
21
+ # Installation
12
22
  ```bash
13
- npm i --save flat-cache
23
+ npm install flat-cache
14
24
  ```
15
25
 
16
- ## Usage
17
-
18
- ```js
19
- const flatCache = require('flat-cache');
20
- // loads the cache, if one does not exists for the given
21
- // Id a new one will be prepared to be created
22
- const cache = flatCache.load('cacheId');
23
-
24
- // sets a key on the cache
25
- cache.setKey('key', { foo: 'var' });
26
-
27
- // get a key from the cache
28
- cache.getKey('key'); // { foo: 'var' }
29
-
30
- // fetch the entire persisted object
31
- cache.all(); // { 'key': { foo: 'var' } }
32
-
33
- // remove a key
34
- cache.removeKey('key'); // removes a key from the cache
35
-
36
- // save it to disk
37
- cache.save(); // very important, if you don't save no changes will be persisted.
38
- // cache.save( true /* noPrune */) // can be used to prevent the removal of non visited keys
39
-
40
- // loads the cache from a given directory, if one does
41
- // not exists for the given Id a new one will be prepared to be created
42
- const cache = flatCache.load('cacheId', path.resolve('./path/to/folder'));
43
-
44
- // The following methods are useful to clear the cache
45
- // delete a given cache
46
- flatCache.clearCacheById('cacheId'); // removes the cacheId document if one exists.
47
-
48
- // delete all cache
49
- flatCache.clearAll(); // remove the cache directory
26
+ # Getting Started
27
+ ```javascript
28
+ import { FlatCache } from 'flat-cache';
29
+ const cache = new FlatCache();
30
+ cache.setKey('key', 'value');
31
+ cache.save(); // Saves the data to disk
50
32
  ```
51
33
 
52
- ## Motivation for this module
53
-
54
- I needed a super simple and dumb **in-memory cache** with optional disk persistance in order to make
55
- a script that will beutify files with `esformatter` only execute on the files that were changed since the last run.
56
- To make that possible we need to store the `fileSize` and `modificationTime` of the files. So a simple `key/value`
57
- storage was needed and Bam! this module was born.
58
-
59
- ## Important notes
60
-
61
- - If no directory is especified when the `load` method is called, a folder named `.cache` will be created
62
- inside the module directory when `cache.save` is called. If you're committing your `node_modules` to any vcs, you
63
- might want to ignore the default `.cache` folder, or specify a custom directory.
64
- - The values set on the keys of the cache should be `stringify-able` ones, meaning no circular references
65
- - All the changes to the cache state are done to memory
66
- - I could have used a timer or `Object.observe` to deliver the changes to disk, but I wanted to keep this module
67
- intentionally dumb and simple
68
- - Non visited keys are removed when `cache.save()` is called. If this is not desired, you can pass `true` to the save call
69
- like: `cache.save( true /* noPrune */ )`.
70
-
71
- ## License
72
-
73
- MIT
74
-
75
- ## Changelog
34
+ lets add it with `ttl`, `lruSize`, and `persistInterval`
35
+ ```javascript
36
+ import { FlatCache } from 'flat-cache';
37
+ const cache = new FlatCache({
38
+ ttl: 60 * 60 * 1000 , // 1 hour
39
+ lruSize: 10000, // 10,000 items
40
+ expirationInterval: 5 * 1000 * 60, // 5 minutes
41
+ persistInterval: 5 * 1000 * 60, // 5 minutes
42
+ });
43
+ cache.setKey('key', 'value');
44
+ ```
76
45
 
77
- [changelog](./changelog.md)
46
+ This will save the data to disk every 5 minutes and will remove any data that has not been accessed in 1 hour or if the cache has more than 10,000 items.
47
+
48
+ # FlatCache Options
49
+ - `ttl` - The time to live for the cache in milliseconds. Default is `0` which means no expiration
50
+ - `lruSize` - The number of items to keep in the cache. Default is `0` which means no limit
51
+ - `useClone` - If `true` it will clone the data before returning it. Default is `false`
52
+ - `expirationInterval` - The interval to check for expired items in the cache. Default is `0` which means no expiration
53
+ - `persistInterval` - The interval to save the data to disk. Default is `0` which means no persistence
54
+ - `cacheDir` - The directory to save the cache files. Default is `./cache`
55
+ - `cacheId` - The id of the cache. Default is `cache1`
56
+
57
+ # API
58
+
59
+ - `cache` - The in-memory cache as a `CacheableMemory` instance
60
+ - `cacheDir` - The directory to save the cache files
61
+ - `cacheId` - The id of the cache
62
+ - `cacheFilePath` - The full path to the cache file
63
+ - `cacheDirPath` - The full path to the cache directory
64
+ - `persistInterval` - The interval to save the data to disk
65
+ - `load(cacheId: string, cacheDir?: string)` - Loads the data from disk
66
+ - `loadFile(pathToFile: string)` - Loads the data from disk
67
+ - `all()` - Gets all the data in the cache
68
+ - `items()` - Gets all the items in the cache
69
+ - `keys()` - Gets all the keys in the cache
70
+ - `setKey(key: string, value: any, ttl?: string | number)` - (legacy) Sets the key/value pair in the cache
71
+ - `set(key: string, value: any, ttl?: string | number)` - Sets the key/value pair in the cache
72
+ - `getKey<T>(key: string)` - Gets the value for the key or the default value
73
+ - `get<T>(key: string)` - Gets the value for the key or the default value
74
+ - `removeKey(key: string)` - Removes the key from the cache
75
+ - `delete(key: string)` - Removes the key from the cache
76
+ - `clear()` - Clears the cache
77
+ - `save()` - Saves the data to disk
78
+ - `destroy()` - Destroys the cache and remove files
79
+
80
+ # How to Contribute
81
+
82
+ You can contribute by forking the repo and submitting a pull request. Please make sure to add tests and update the documentation. To learn more about how to contribute go to our main README [https://github.com/jaredwray/cacheable](https://github.com/jaredwray/cacheable). This will talk about how to `Open a Pull Request`, `Ask a Question`, or `Post an Issue`.
83
+
84
+ # License and Copyright
85
+ [MIT © Jared Wray](./LICENSE)
package/dist/index.cjs ADDED
@@ -0,0 +1,360 @@
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 src_exports = {};
32
+ __export(src_exports, {
33
+ FlatCache: () => FlatCache,
34
+ clearAll: () => clearAll,
35
+ clearCacheById: () => clearCacheById,
36
+ create: () => create,
37
+ createFromFile: () => createFromFile
38
+ });
39
+ module.exports = __toCommonJS(src_exports);
40
+ var import_node_path = __toESM(require("path"), 1);
41
+ var import_node_fs = __toESM(require("fs"), 1);
42
+ var import_cacheable = require("cacheable");
43
+ var import_flatted = require("flatted");
44
+ var FlatCache = class {
45
+ _cache = new import_cacheable.CacheableMemory();
46
+ _cacheDir = ".cache";
47
+ _cacheId = "cache1";
48
+ _persistInterval = 0;
49
+ _persistTimer;
50
+ constructor(options) {
51
+ if (options) {
52
+ this._cache = new import_cacheable.CacheableMemory({
53
+ ttl: options.ttl,
54
+ useClone: options.useClone,
55
+ lruSize: options.lruSize,
56
+ checkInterval: options.expirationInterval
57
+ });
58
+ }
59
+ if (options?.cacheDir) {
60
+ this._cacheDir = options.cacheDir;
61
+ }
62
+ if (options?.cacheId) {
63
+ this._cacheId = options.cacheId;
64
+ }
65
+ if (options?.persistInterval) {
66
+ this._persistInterval = options.persistInterval;
67
+ this.startAutoPersist();
68
+ }
69
+ }
70
+ /**
71
+ * The cache object
72
+ * @property cache
73
+ * @type {CacheableMemory}
74
+ */
75
+ get cache() {
76
+ return this._cache;
77
+ }
78
+ /**
79
+ * The cache directory
80
+ * @property cacheDir
81
+ * @type {String}
82
+ * @default '.cache'
83
+ */
84
+ get cacheDir() {
85
+ return this._cacheDir;
86
+ }
87
+ /**
88
+ * Set the cache directory
89
+ * @property cacheDir
90
+ * @type {String}
91
+ * @default '.cache'
92
+ */
93
+ set cacheDir(value) {
94
+ this._cacheDir = value;
95
+ }
96
+ /**
97
+ * The cache id
98
+ * @property cacheId
99
+ * @type {String}
100
+ * @default 'cache1'
101
+ */
102
+ get cacheId() {
103
+ return this._cacheId;
104
+ }
105
+ /**
106
+ * Set the cache id
107
+ * @property cacheId
108
+ * @type {String}
109
+ * @default 'cache1'
110
+ */
111
+ set cacheId(value) {
112
+ this._cacheId = value;
113
+ }
114
+ /**
115
+ * The interval to persist the cache to disk. 0 means no timed persistence
116
+ * @property persistInterval
117
+ * @type {Number}
118
+ * @default 0
119
+ */
120
+ get persistInterval() {
121
+ return this._persistInterval;
122
+ }
123
+ /**
124
+ * Set the interval to persist the cache to disk. 0 means no timed persistence
125
+ * @property persistInterval
126
+ * @type {Number}
127
+ * @default 0
128
+ */
129
+ set persistInterval(value) {
130
+ this._persistInterval = value;
131
+ }
132
+ /**
133
+ * Load a cache identified by the given Id. If the element does not exists, then initialize an empty
134
+ * cache storage. If specified `cacheDir` will be used as the directory to persist the data to. If omitted
135
+ * then the cache module directory `.cacheDir` will be used instead
136
+ *
137
+ * @method load
138
+ * @param docId {String} the id of the cache, would also be used as the name of the file cache
139
+ * @param [cacheDir] {String} directory for the cache entry
140
+ */
141
+ // eslint-disable-next-line unicorn/prevent-abbreviations
142
+ load(documentId, cacheDir) {
143
+ const filePath = import_node_path.default.resolve(`${cacheDir ?? this._cacheDir}/${documentId}`);
144
+ this.loadFile(filePath);
145
+ }
146
+ /**
147
+ * Load the cache from the provided file
148
+ * @method loadFile
149
+ * @param {String} pathToFile the path to the file containing the info for the cache
150
+ */
151
+ loadFile(pathToFile) {
152
+ if (import_node_fs.default.existsSync(pathToFile)) {
153
+ const data = import_node_fs.default.readFileSync(pathToFile, "utf8");
154
+ const items = (0, import_flatted.parse)(data);
155
+ for (const key of Object.keys(items)) {
156
+ this._cache.set(key, items[key]);
157
+ }
158
+ }
159
+ }
160
+ /**
161
+ * Returns the entire persisted object
162
+ * @method all
163
+ * @returns {*}
164
+ */
165
+ all() {
166
+ const result = {};
167
+ const items = Array.from(this._cache.items);
168
+ for (const item of items) {
169
+ result[item.key] = item.value;
170
+ }
171
+ return result;
172
+ }
173
+ /**
174
+ * Returns an array with all the items in the cache { key, value, ttl }
175
+ * @method items
176
+ * @returns {Array}
177
+ */
178
+ get items() {
179
+ return Array.from(this._cache.items);
180
+ }
181
+ /**
182
+ * Returns the path to the file where the cache is persisted
183
+ * @method cacheFilePath
184
+ * @returns {String}
185
+ */
186
+ get cacheFilePath() {
187
+ return import_node_path.default.resolve(`${this._cacheDir}/${this._cacheId}`);
188
+ }
189
+ /**
190
+ * Returns the path to the cache directory
191
+ * @method cacheDirPath
192
+ * @returns {String}
193
+ */
194
+ get cacheDirPath() {
195
+ return import_node_path.default.resolve(this._cacheDir);
196
+ }
197
+ /**
198
+ * Returns an array with all the keys in the cache
199
+ * @method keys
200
+ * @returns {Array}
201
+ */
202
+ keys() {
203
+ return Array.from(this._cache.keys);
204
+ }
205
+ /**
206
+ * (Legacy) set key method. This method will be deprecated in the future
207
+ * @method setKey
208
+ * @param key {string} the key to set
209
+ * @param value {object} the value of the key. Could be any object that can be serialized with JSON.stringify
210
+ */
211
+ setKey(key, value, ttl) {
212
+ this._cache.set(key, value, ttl);
213
+ }
214
+ /**
215
+ * Sets a key to a given value
216
+ * @method set
217
+ * @param key {string} the key to set
218
+ * @param value {object} the value of the key. Could be any object that can be serialized with JSON.stringify
219
+ * @param [ttl] {number} the time to live in milliseconds
220
+ */
221
+ set(key, value, ttl) {
222
+ this._cache.set(key, value, ttl);
223
+ }
224
+ /**
225
+ * (Legacy) Remove a given key from the cache. This method will be deprecated in the future
226
+ * @method removeKey
227
+ * @param key {String} the key to remove from the object
228
+ */
229
+ removeKey(key) {
230
+ this._cache.delete(key);
231
+ }
232
+ /**
233
+ * Remove a given key from the cache
234
+ * @method delete
235
+ * @param key {String} the key to remove from the object
236
+ */
237
+ delete(key) {
238
+ this._cache.delete(key);
239
+ }
240
+ /**
241
+ * (Legacy) Return the value of the provided key. This method will be deprecated in the future
242
+ * @method getKey<T>
243
+ * @param key {String} the name of the key to retrieve
244
+ * @returns {*} at T the value from the key
245
+ */
246
+ getKey(key) {
247
+ return this.get(key);
248
+ }
249
+ /**
250
+ * Return the value of the provided key
251
+ * @method get<T>
252
+ * @param key {String} the name of the key to retrieve
253
+ * @returns {*} at T the value from the key
254
+ */
255
+ get(key) {
256
+ return this._cache.get(key);
257
+ }
258
+ /**
259
+ * Clear the cache
260
+ * @method clear
261
+ */
262
+ clear() {
263
+ this._cache.clear();
264
+ }
265
+ /**
266
+ * Save the state of the cache identified by the docId to disk
267
+ * as a JSON structure
268
+ * @method save
269
+ */
270
+ save() {
271
+ const filePath = this.cacheFilePath;
272
+ const items = this.all();
273
+ const data = (0, import_flatted.stringify)(items);
274
+ if (!import_node_fs.default.existsSync(this._cacheDir)) {
275
+ import_node_fs.default.mkdirSync(this._cacheDir, { recursive: true });
276
+ }
277
+ import_node_fs.default.writeFileSync(filePath, data);
278
+ }
279
+ /**
280
+ * Remove the file where the cache is persisted
281
+ * @method removeCacheFile
282
+ * @return {Boolean} true or false if the file was successfully deleted
283
+ */
284
+ removeCacheFile() {
285
+ if (import_node_fs.default.existsSync(this.cacheFilePath)) {
286
+ import_node_fs.default.rmSync(this.cacheFilePath);
287
+ return true;
288
+ }
289
+ return false;
290
+ }
291
+ /**
292
+ * Destroy the cache. This will remove the directory, file, and memory cache
293
+ * @method destroy
294
+ * @param [includeCacheDir=false] {Boolean} if true, the cache directory will be removed
295
+ * @return {undefined}
296
+ */
297
+ destroy(includeCacheDirectory = false) {
298
+ this._cache.clear();
299
+ this.stopAutoPersist();
300
+ if (includeCacheDirectory) {
301
+ import_node_fs.default.rmSync(this.cacheDirPath, { recursive: true, force: true });
302
+ } else {
303
+ import_node_fs.default.rmSync(this.cacheFilePath, { recursive: true, force: true });
304
+ }
305
+ }
306
+ /**
307
+ * Start the auto persist interval
308
+ * @method startAutoPersist
309
+ */
310
+ startAutoPersist() {
311
+ if (this._persistInterval > 0) {
312
+ if (this._persistTimer) {
313
+ clearInterval(this._persistTimer);
314
+ this._persistTimer = void 0;
315
+ }
316
+ this._persistTimer = setInterval(() => {
317
+ this.save();
318
+ }, this._persistInterval);
319
+ }
320
+ }
321
+ /**
322
+ * Stop the auto persist interval
323
+ * @method stopAutoPersist
324
+ */
325
+ stopAutoPersist() {
326
+ if (this._persistTimer) {
327
+ clearInterval(this._persistTimer);
328
+ this._persistTimer = void 0;
329
+ }
330
+ }
331
+ };
332
+ function create(documentId, cacheDirectory, options) {
333
+ const cache = new FlatCache(options);
334
+ cache.cacheId = documentId;
335
+ if (cacheDirectory) {
336
+ cache.cacheDir = cacheDirectory;
337
+ }
338
+ cache.load(documentId, cacheDirectory);
339
+ return cache;
340
+ }
341
+ function createFromFile(filePath, options) {
342
+ const cache = new FlatCache(options);
343
+ cache.loadFile(filePath);
344
+ return cache;
345
+ }
346
+ function clearCacheById(cacheId, cacheDirectory) {
347
+ const cache = new FlatCache({ cacheId, cacheDir: cacheDirectory });
348
+ cache.destroy();
349
+ }
350
+ function clearAll(cacheDirectory) {
351
+ import_node_fs.default.rmSync(cacheDirectory ?? ".cache", { recursive: true, force: true });
352
+ }
353
+ // Annotate the CommonJS export names for ESM import in node:
354
+ 0 && (module.exports = {
355
+ FlatCache,
356
+ clearAll,
357
+ clearCacheById,
358
+ create,
359
+ createFromFile
360
+ });