file-entry-cache 9.0.0 → 10.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 & 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,114 +1,200 @@
1
+ [<img align="center" src="https://cacheable.org/symbol.svg" alt="Cacheable" />](https://github.com/jaredwray/cacheable)
2
+
1
3
  # file-entry-cache
2
- > Super simple cache for file metadata, useful for process that work on a given series of files and that only need to repeat the job on the changed ones since the previous run of the process
4
+ > A lightweight cache for file metadata, ideal for processes that work on a specific set of files and only need to reprocess files that have changed since the last run
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
+
14
+ - Lightweight cache for file metadata
15
+ - Ideal for processes that work on a specific set of files
16
+ - Persists cache to Disk via `reconcile()` or `persistInterval` on `cache` options.
17
+ - Uses `checksum` to determine if a file has changed
18
+ - Supports `relative` and `absolute` paths
19
+ - Ability to rename keys in the cache. Useful when renaming directories.
20
+ - ESM and CommonJS support with Typescript
21
+
22
+ # Table of Contents
23
+
24
+ - [Installation](#installation)
25
+ - [Getting Started](#getting-started)
26
+ - [Changes from v9 to v10](#changes-from-v9-to-v10)
27
+ - [Global Default Functions](#global-default-functions)
28
+ - [FileEntryCache Options (FileEntryCacheOptions)](#fileentrycache-options-fileentrycacheoptions)
29
+ - [API](#api)
30
+ - [Get File Descriptor](#get-file-descriptor)
31
+ - [Using Checksums to Determine if a File has Changed (useCheckSum)](#using-checksums-to-determine-if-a-file-has-changed-usechecksum)
32
+ - [Setting Additional Meta Data](#setting-additional-meta-data)
33
+ - [How to Contribute](#how-to-contribute)
34
+ - [License and Copyright](#license-and-copyright)
35
+
36
+ # Installation
37
+ ```bash
38
+ npm install file-entry-cache
39
+ ```
3
40
 
4
- [![NPM Version](https://img.shields.io/npm/v/file-entry-cache.svg?style=flat)](https://npmjs.org/package/file-entry-cache)
5
- [![tests](https://github.com/jaredwray/file-entry-cache/actions/workflows/tests.yaml/badge.svg?branch=master)](https://github.com/jaredwray/file-entry-cache/actions/workflows/tests.yaml)
6
- [![codecov](https://codecov.io/github/jaredwray/file-entry-cache/graph/badge.svg?token=37tZMQE0Sy)](https://codecov.io/github/jaredwray/file-entry-cache)
7
- [![npm](https://img.shields.io/npm/dm/file-entry-cache)](https://npmjs.com/package/file-entry-cache)
41
+ # Getting Started
42
+
43
+ ```javascript
44
+ import fileEntryCache from 'file-entry-cache';
45
+ const cache = fileEntryCache.create('cache1');
46
+ let fileDescriptor = cache.getFileDescriptor('file.txt');
47
+ console.log(fileDescriptor.changed); // true as it is the first time
48
+ fileDescriptor = cache.getFileDescriptor('file.txt');
49
+ console.log(fileDescriptor.changed); // false as it has not changed
50
+ // do something to change the file
51
+ fs.writeFileSync('file.txt', 'new data foo bar');
52
+ // check if the file has changed
53
+ fileDescriptor = cache.getFileDescriptor('file.txt');
54
+ console.log(fileDescriptor.changed); // true
55
+ ```
8
56
 
57
+ Save it to Disk and Reconsile files that are no longer found
58
+ ```javascript
59
+ import fileEntryCache from 'file-entry-cache';
60
+ const cache = fileEntryCache.create('cache1');
61
+ let fileDescriptor = cache.getFileDescriptor('file.txt');
62
+ console.log(fileDescriptor.changed); // true as it is the first time
63
+ fileEntryCache.reconcile(); // save the cache to disk and remove files that are no longer found
64
+ ```
9
65
 
10
- ## install
66
+ Load the cache from a file:
11
67
 
12
- ```bash
13
- npm i --save file-entry-cache
68
+ ```javascript
69
+ import fileEntryCache from 'file-entry-cache';
70
+ const cache = fileEntryCache.createFromFile('/path/to/cache/file');
71
+ let fileDescriptor = cache.getFileDescriptor('file.txt');
72
+ console.log(fileDescriptor.changed); // false as it has not changed from the saved cache.
14
73
  ```
15
74
 
16
- ## Usage
17
-
18
- The module exposes two functions `create` and `createFromFile`.
19
-
20
- ## `create(cacheName, [directory, useCheckSum])`
21
- - **cacheName**: the name of the cache to be created
22
- - **directory**: Optional the directory to load the cache from
23
- - **usecheckSum**: Whether to use md5 checksum to verify if file changed. If false the default will be to use the mtime and size of the file.
24
-
25
- ## `createFromFile(pathToCache, [useCheckSum])`
26
- - **pathToCache**: the path to the cache file (this combines the cache name and directory)
27
- - **useCheckSum**: Whether to use md5 checksum to verify if file changed. If false the default will be to use the mtime and size of the file.
28
-
29
- ```js
30
- // loads the cache, if one does not exists for the given
31
- // Id a new one will be prepared to be created
32
- var fileEntryCache = require('file-entry-cache');
33
-
34
- var cache = fileEntryCache.create('testCache');
35
-
36
- var files = expand('../fixtures/*.txt');
37
-
38
- // the first time this method is called, will return all the files
39
- var oFiles = cache.getUpdatedFiles(files);
40
-
41
- // this will persist this to disk checking each file stats and
42
- // updating the meta attributes `size` and `mtime`.
43
- // custom fields could also be added to the meta object and will be persisted
44
- // in order to retrieve them later
45
- cache.reconcile();
46
-
47
- // use this if you want the non visited file entries to be kept in the cache
48
- // for more than one execution
49
- //
50
- // cache.reconcile( true /* noPrune */)
51
-
52
- // on a second run
53
- var cache2 = fileEntryCache.create('testCache');
54
-
55
- // will return now only the files that were modified or none
56
- // if no files were modified previous to the execution of this function
57
- var oFiles = cache.getUpdatedFiles(files);
58
-
59
- // if you want to prevent a file from being considered non modified
60
- // something useful if a file failed some sort of validation
61
- // you can then remove the entry from the cache doing
62
- cache.removeEntry('path/to/file'); // path to file should be the same path of the file received on `getUpdatedFiles`
63
- // that will effectively make the file to appear again as modified until the validation is passed. In that
64
- // case you should not remove it from the cache
65
-
66
- // if you need all the files, so you can determine what to do with the changed ones
67
- // you can call
68
- var oFiles = cache.normalizeEntries(files);
69
-
70
- // oFiles will be an array of objects like the following
71
- entry = {
72
- key: 'some/name/file', the path to the file
73
- changed: true, // if the file was changed since previous run
74
- meta: {
75
- size: 3242, // the size of the file
76
- mtime: 231231231, // the modification time of the file
77
- data: {} // some extra field stored for this file (useful to save the result of a transformation on the file
78
- }
79
- }
75
+ # Changes from v9 to v10
76
+
77
+ There have been many features added and changes made to the `file-entry-cache` class. Here are the main changes:
78
+ - Added `cache` object to the options to allow for more control over the cache
79
+ - Added `hashAlgorithm` to the options to allow for different checksum algorithms. Note that if you load from file it most likely will break if the value was something before.
80
+ - Updated more on using Relative or Absolute paths. We now support both on `getFileDescriptor()`. You can read more on this in the `Get File Descriptor` section.
81
+ - Migrated to Typescript with ESM and CommonJS support. This allows for better type checking and support for both ESM and CommonJS.
82
+ - Once options are passed in they get assigned as properties such as `hashAlgorithm` and `currentWorkingDirectory`. This allows for better control and access to the options. For the Cache options they are assigned to `cache` such as `cache.ttl` and `cache.lruSize`.
83
+ - Added `cache.persistInterval` to allow for saving the cache to disk at a specific interval. This will save the cache to disk at the interval specified instead of calling `reconsile()` to save. (`off` by default)
84
+ - Added `getFileDescriptorsByPath(filePath: string): FileEntryDescriptor[]` to get all the file descriptors that start with the path specified. This is useful when you want to get all the files in a directory or a specific path.
85
+ - Added `renameAbsolutePathKeys(oldPath: string, newPath: string): void` will rename the keys in the cache from the old path to the new path. This is useful when you rename a directory and want to update the cache without reanalyzing the files.
86
+ - Using `flat-cache` v6 which is a major update. This allows for better performance and more control over the cache.
87
+ - On `FileEntryDescriptor.meta` if using typescript you need to use the `meta.data` to set additional information. This is to allow for better type checking and to avoid conflicts with the `meta` object which was `any`.
88
+
89
+ # Global Default Functions
90
+ - `create(cacheId: string, cacheDirectory?: string, useCheckSum?: boolean, currentWorkingDirectory?: string)` - Creates a new instance of the `FileEntryCache` class
91
+ - `createFromFile(cachePath: string, useCheckSum?: boolean, currentWorkingDirectory?: string)` - Creates a new instance of the `FileEntryCache` class and loads the cache from a file.
92
+
93
+ # FileEntryCache Options (FileEntryCacheOptions)
94
+ - `currentWorkingDirectory?` - The current working directory. Used when resolving relative paths.
95
+ - `useCheckSum?` - If `true` it will use a checksum to determine if the file has changed. Default is `false`
96
+ - `hashAlgorithm?` - The algorithm to use for the checksum. Default is `md5` but can be any algorithm supported by `crypto.createHash`
97
+ - `cache.ttl?` - The time to live for the cache in milliseconds. Default is `0` which means no expiration
98
+ - `cache.lruSize?` - The number of items to keep in the cache. Default is `0` which means no limit
99
+ - `cache.useClone?` - If `true` it will clone the data before returning it. Default is `false`
100
+ - `cache.expirationInterval?` - The interval to check for expired items in the cache. Default is `0` which means no expiration
101
+ - `cache.persistInterval?` - The interval to save the data to disk. Default is `0` which means no persistence
102
+ - `cache.cacheDir?` - The directory to save the cache files. Default is `./cache`
103
+ - `cache.cacheId?` - The id of the cache. Default is `cache1`
104
+ - `cache.parse?` - The function to parse the data. Default is `flatted.parse`
105
+ - `cache.stringify?` - The function to stringify the data. Default is `flatted.stringify`
106
+
107
+ # API
108
+
109
+ - `constructor(options?: FileEntryCacheOptions)` - Creates a new instance of the `FileEntryCache` class
110
+ - `useCheckSum: boolean` - If `true` it will use a checksum to determine if the file has changed. Default is `false`
111
+ - `hashAlgorithm: string` - The algorithm to use for the checksum. Default is `md5` but can be any algorithm supported by `crypto.createHash`
112
+ - `currentWorkingDirectory: string` - The current working directory. Used when resolving relative paths.
113
+ - `getHash(buffer: Buffer): string` - Gets the hash of a buffer used for checksums
114
+ - `createFileKey(filePath: string): string` - Creates a key for the file path. This is used to store the data in the cache based on relative or absolute paths.
115
+ - `deleteCacheFile(filePath: string): void` - Deletes the cache file
116
+ - `destroy(): void` - Destroys the cache. This will also delete the cache file. If using cache persistence it will stop the interval.
117
+ - `removeEntry(filePath: string): void` - Removes an entry from the cache. This can be `relative` or `absolute` paths.
118
+ - `reconcile(): void` - Saves the cache to disk and removes any files that are no longer found.
119
+ - `hasFileChanged(filePath: string): boolean` - Checks if the file has changed. This will return `true` if the file has changed.
120
+ - `getFileDescriptor(filePath: string, options?: { useCheckSum?: boolean, currentWorkingDirectory?: string }): FileEntryDescriptor` - Gets the file descriptor for the file. Please refer to the entire section on `Get File Descriptor` for more information.
121
+ - `normalizeEntries(entries: FileEntryDescriptor[]): FileEntryDescriptor[]` - Normalizes the entries to have the correct paths. This is used when loading the cache from disk.
122
+ - `analyzeFiles(files: string[])` will return `AnalyzedFiles` object with `changedFiles`, `notFoundFiles`, and `notChangedFiles` as FileDescriptor arrays.
123
+ - `getUpdatedFiles(files: string[])` will return an array of `FileEntryDescriptor` objects that have changed.
124
+ - `getFileDescriptorsByPath(filePath: string): FileEntryDescriptor[]` will return an array of `FileEntryDescriptor` objects that starts with the path specified.
125
+ - `renameAbsolutePathKeys(oldPath: string, newPath: string): void` - Renames the keys in the cache from the old path to the new path. This is useful when you rename a directory and want to update the cache without reanalyzing the files.
126
+
127
+ # Get File Descriptor
128
+
129
+ The `getFileDescriptor(filePath: string, options?: { useCheckSum?: boolean, currentWorkingDirectory?: string }): FileEntryDescriptor` function is used to get the file descriptor for the file. This function will return a `FileEntryDescriptor` object that has the following properties:
130
+
131
+ - `key: string` - The key for the file. This is the relative or absolute path of the file.
132
+ - `changed: boolean` - If the file has changed since the last time it was analyzed.
133
+ - `notFound: boolean` - If the file was not found.
134
+ - `meta: FileEntryMeta` - The meta data for the file. This has the following prperties: `size`, `mtime`, `ctime`, `hash`, `data`. Note that `data` is an object that can be used to store additional information.
135
+ - `err` - If there was an error analyzing the file.
136
+
137
+ We have added the ability to use `relative` or `absolute` paths. If you pass in a `relative` path it will use the `currentWorkingDirectory` to resolve the path. If you pass in an `absolute` path it will use the path as is. This is useful when you want to use `relative` paths but also want to use `absolute` paths.
138
+
139
+ If you do not pass in `currentWorkingDirectory` in the class options or in the `getFileDescriptor` function it will use the `process.cwd()` as the default `currentWorkingDirectory`.
140
+
141
+ ```javascript
142
+ const fileEntryCache = new FileEntryCache();
143
+ const fileDescriptor = fileEntryCache.getFileDescriptor('file.txt', { currentWorkingDirectory: '/path/to/directory' });
144
+ ```
80
145
 
146
+ Since this is a relative path it will use the `currentWorkingDirectory` to resolve the path. If you want to use an absolute path you can do the following:
147
+
148
+ ```javascript
149
+ const fileEntryCache = new FileEntryCache();
150
+ const filePath = path.resolve('/path/to/directory', 'file.txt');
151
+ const fileDescriptor = fileEntryCache.getFileDescriptor(filePath);
81
152
  ```
82
153
 
83
- ## Motivation for this module
154
+ This will save the key as the absolute path.
155
+
156
+ If there is an error when trying to get the file descriptor it will return an ``notFound` and `err` property with the error.
157
+
158
+ ```javascript
159
+ const fileEntryCache = new FileEntryCache();
160
+ const fileDescriptor = fileEntryCache.getFileDescriptor('no-file');
161
+ if (fileDescriptor.err) {
162
+ console.error(fileDescriptor.err);
163
+ }
84
164
 
85
- I needed a super simple and dumb **in-memory cache** with optional disk persistence (write-back cache) in order to make
86
- a script that will beautify files with `esformatter` to execute only on the files that were changed since the last run.
165
+ if (fileDescriptor.notFound) {
166
+ console.error('File not found');
167
+ }
168
+ ```
87
169
 
88
- In doing so the process of beautifying files was reduced from several seconds to a small fraction of a second.
170
+ # Using Checksums to Determine if a File has Changed (useCheckSum)
89
171
 
90
- This module uses [flat-cache](https://www.npmjs.com/package/flat-cache) a super simple `key/value` cache storage with
91
- optional file persistance.
172
+ By default the `useCheckSum` is `false`. This means that the `FileEntryCache` will use the `mtime` and `ctime` to determine if the file has changed. If you set `useCheckSum` to `true` it will use a checksum to determine if the file has changed. This is useful when you want to make sure that the file has not changed at all.
92
173
 
93
- The main idea is to read the files when the task begins, apply the transforms required, and if the process succeed,
94
- then store the new state of the files. The next time this module request for `getChangedFiles` will return only
95
- the files that were modified. Making the process to end faster.
174
+ ```javascript
175
+ const fileEntryCache = new FileEntryCache();
176
+ const fileDescriptor = fileEntryCache.getFileDescriptor('file.txt', { useCheckSum: true });
177
+ ```
96
178
 
97
- This module could also be used by processes that modify the files applying a transform, in that case the result of the
98
- transform could be stored in the `meta` field, of the entries. Anything added to the meta field will be persisted.
99
- Those processes won't need to call `getChangedFiles` they will instead call `normalizeEntries` that will return the
100
- entries with a `changed` field that can be used to determine if the file was changed or not. If it was not changed
101
- the transformed stored data could be used instead of actually applying the transformation, saving time in case of only
102
- a few files changed.
179
+ You can pass `useCheckSum` in the FileEntryCache options, as a property `.useCheckSum` to make it default for all files, or in the `getFileDescriptor` function. Here is an example where you set it globally but then override it for a specific file:
103
180
 
104
- In the worst case scenario all the files will be processed. In the best case scenario only a few of them will be processed.
181
+ ```javascript
182
+ const fileEntryCache = new FileEntryCache({ useCheckSum: true });
183
+ const fileDescriptor = fileEntryCache.getFileDescriptor('file.txt', { useCheckSum: false });
184
+ ```
105
185
 
106
- ## Important notes
107
- - The values set on the meta attribute of the entries should be `stringify-able` ones if possible, flat-cache uses `circular-json` to try to persist circular structures, but this should be considered experimental. The best results are always obtained with non circular values
108
- - All the changes to the cache state are done to memory first and only persisted after reconcile.
186
+ # Setting Additional Meta Data
109
187
 
110
- ## License
188
+ In the past we have seen people do random values on the `meta` object. This can cause issues with the `meta` object. To avoid this we have `data` which can be anything.
111
189
 
112
- MIT
190
+ ```javascript
191
+ const fileEntryCache = new FileEntryCache();
192
+ const fileDescriptor = fileEntryCache.getFileDescriptor('file.txt');
193
+ fileDescriptor.meta.data = { myData: 'myData' }; //anything you want
194
+ ```
195
+ # How to Contribute
113
196
 
197
+ 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`.
114
198
 
199
+ # License and Copyright
200
+ [MIT © Jared Wray](./LICENSE)