file-entry-cache 1.2.4 → 4.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/README.md +25 -14
- package/cache.js +58 -20
- package/changelog.md +62 -0
- package/package.json +11 -12
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# file-entry-cache
|
|
2
|
-
> Super simple cache for file metadata, useful for process that work o a given series of files
|
|
2
|
+
> Super simple cache for file metadata, useful for process that work o a given series of files
|
|
3
3
|
> and that only need to repeat the job on the changed ones since the previous run of the process — Edit
|
|
4
4
|
|
|
5
5
|
[](https://npmjs.org/package/file-entry-cache)
|
|
@@ -14,7 +14,7 @@ npm i --save file-entry-cache
|
|
|
14
14
|
## Usage
|
|
15
15
|
|
|
16
16
|
```js
|
|
17
|
-
// loads the cache, if one does not exists for the given
|
|
17
|
+
// loads the cache, if one does not exists for the given
|
|
18
18
|
// Id a new one will be prepared to be created
|
|
19
19
|
var fileEntryCache = require('file-entry-cache');
|
|
20
20
|
|
|
@@ -25,18 +25,23 @@ var files = expand('../fixtures/*.txt');
|
|
|
25
25
|
// the first time this method is called, will return all the files
|
|
26
26
|
var oFiles = cache.getUpdatedFiles(files);
|
|
27
27
|
|
|
28
|
-
// this will persist this to disk checking each file stats and
|
|
28
|
+
// this will persist this to disk checking each file stats and
|
|
29
29
|
// updating the meta attributes `size` and `mtime`.
|
|
30
30
|
// custom fields could also be added to the meta object and will be persisted
|
|
31
31
|
// in order to retrieve them later
|
|
32
|
-
cache.reconcile();
|
|
32
|
+
cache.reconcile();
|
|
33
|
+
|
|
34
|
+
// use this if you want the non visited file entries to be kept in the cache
|
|
35
|
+
// for more than one execution
|
|
36
|
+
//
|
|
37
|
+
// cache.reconcile( true /* noPrune */)
|
|
33
38
|
|
|
34
39
|
// on a second run
|
|
35
40
|
var cache2 = fileEntryCache.create('testCache');
|
|
36
41
|
|
|
37
42
|
// will return now only the files that were modified or none
|
|
38
43
|
// if no files were modified previous to the execution of this function
|
|
39
|
-
var oFiles = cache.getUpdatedFiles(files);
|
|
44
|
+
var oFiles = cache.getUpdatedFiles(files);
|
|
40
45
|
|
|
41
46
|
// if you want to prevent a file from being considered non modified
|
|
42
47
|
// something useful if a file failed some sort of validation
|
|
@@ -64,21 +69,21 @@ entry = {
|
|
|
64
69
|
|
|
65
70
|
## Motivation for this module
|
|
66
71
|
|
|
67
|
-
I needed a super simple and dumb **in-memory cache** with optional disk persistence (write-back cache) in order to make
|
|
72
|
+
I needed a super simple and dumb **in-memory cache** with optional disk persistence (write-back cache) in order to make
|
|
68
73
|
a script that will beautify files with `esformatter` to execute only on the files that were changed since the last run.
|
|
69
74
|
|
|
70
75
|
In doing so the process of beautifying files was reduced from several seconds to a small fraction of a second.
|
|
71
76
|
|
|
72
|
-
This module uses [flat-cache](https://www.npmjs.com/package/flat-cache) a super simple `key/value` cache storage with
|
|
77
|
+
This module uses [flat-cache](https://www.npmjs.com/package/flat-cache) a super simple `key/value` cache storage with
|
|
73
78
|
optional file persistance.
|
|
74
79
|
|
|
75
|
-
The main idea is to read the files when the task begins, apply the transforms required, and if the process succeed,
|
|
76
|
-
then store the new state of the files. The next time this module request for `getChangedFiles` will return only
|
|
80
|
+
The main idea is to read the files when the task begins, apply the transforms required, and if the process succeed,
|
|
81
|
+
then store the new state of the files. The next time this module request for `getChangedFiles` will return only
|
|
77
82
|
the files that were modified. Making the process to end faster.
|
|
78
83
|
|
|
79
84
|
This module could also be used by processes that modify the files applying a transform, in that case the result of the
|
|
80
|
-
transform could be stored in the `meta` field, of the entries. Anything added to the meta field will be persisted.
|
|
81
|
-
Those processes won't need to call `getChangedFiles` they will instead call `normalizeEntries` that will return the
|
|
85
|
+
transform could be stored in the `meta` field, of the entries. Anything added to the meta field will be persisted.
|
|
86
|
+
Those processes won't need to call `getChangedFiles` they will instead call `normalizeEntries` that will return the
|
|
82
87
|
entries with a `changed` field that can be used to determine if the file was changed or not. If it was not changed
|
|
83
88
|
the transformed stored data could be used instead of actually applying the transformation, saving time in case of only
|
|
84
89
|
a few files changed.
|
|
@@ -86,10 +91,16 @@ a few files changed.
|
|
|
86
91
|
In the worst case scenario all the files will be processed. In the best case scenario only a few of them will be processed.
|
|
87
92
|
|
|
88
93
|
## Important notes
|
|
89
|
-
- The values set on the meta attribute of the entries should be `stringify-able` ones,
|
|
90
|
-
- All the changes to the cache state are done to memory first and only persisted after reconcile
|
|
94
|
+
- 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
|
|
95
|
+
- All the changes to the cache state are done to memory first and only persisted after reconcile.
|
|
96
|
+
- By default non visited entries are removed from the cache. This is done to prevent the file from growing too much. If this is not an issue and
|
|
97
|
+
you prefer to do a manual pruning of the cache files, you can pass `true` to the `reconcile` call. Like this:
|
|
98
|
+
|
|
99
|
+
```javascript
|
|
100
|
+
cache.reconcile( true /* noPrune */ );
|
|
101
|
+
```
|
|
91
102
|
|
|
92
|
-
## License
|
|
103
|
+
## License
|
|
93
104
|
|
|
94
105
|
MIT
|
|
95
106
|
|
package/cache.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
var path = require( 'path' );
|
|
2
|
+
var crypto = require( 'crypto' );
|
|
2
3
|
|
|
3
4
|
module.exports = {
|
|
4
5
|
createFromFile: function ( filePath ) {
|
|
@@ -11,15 +12,44 @@ module.exports = {
|
|
|
11
12
|
var fs = require( 'fs' );
|
|
12
13
|
var flatCache = require( 'flat-cache' );
|
|
13
14
|
var cache = flatCache.load( cacheId, _path );
|
|
14
|
-
var assign = require( 'object-assign' );
|
|
15
15
|
var normalizedEntries = { };
|
|
16
16
|
|
|
17
|
+
var removeNotFoundFiles = function removeNotFoundFiles() {
|
|
18
|
+
const cachedEntries = cache.keys();
|
|
19
|
+
// remove not found entries
|
|
20
|
+
cachedEntries.forEach( function remover( fPath ) {
|
|
21
|
+
try {
|
|
22
|
+
fs.statSync( fPath );
|
|
23
|
+
} catch (err) {
|
|
24
|
+
if ( err.code === 'ENOENT' ) {
|
|
25
|
+
cache.removeKey( fPath );
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
} );
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
removeNotFoundFiles();
|
|
32
|
+
|
|
17
33
|
return {
|
|
18
34
|
/**
|
|
19
|
-
* the flat cache storage used to persist the metadata of the files
|
|
35
|
+
* the flat cache storage used to persist the metadata of the `files
|
|
20
36
|
* @type {Object}
|
|
21
37
|
*/
|
|
22
38
|
cache: cache,
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Given a buffer, calculate md5 hash of its content.
|
|
42
|
+
* @method getHash
|
|
43
|
+
* @param {Buffer} buffer buffer to calculate hash on
|
|
44
|
+
* @return {String} content hash digest
|
|
45
|
+
*/
|
|
46
|
+
getHash: function ( buffer ) {
|
|
47
|
+
return crypto
|
|
48
|
+
.createHash( 'md5' )
|
|
49
|
+
.update( buffer )
|
|
50
|
+
.digest( 'hex' );
|
|
51
|
+
},
|
|
52
|
+
|
|
23
53
|
/**
|
|
24
54
|
* Return whether or not a file has changed since last time reconcile was called.
|
|
25
55
|
* @method hasFileChanged
|
|
@@ -66,29 +96,28 @@ module.exports = {
|
|
|
66
96
|
getFileDescriptor: function ( file ) {
|
|
67
97
|
var meta = cache.getKey( file );
|
|
68
98
|
var cacheExists = !!meta;
|
|
69
|
-
var fstat;
|
|
70
99
|
var me = this;
|
|
100
|
+
var contentBuffer;
|
|
71
101
|
|
|
72
102
|
try {
|
|
73
|
-
|
|
103
|
+
contentBuffer = fs.readFileSync( file );
|
|
74
104
|
} catch (ex) {
|
|
75
105
|
me.removeEntry( file );
|
|
76
106
|
return { key: file, notFound: true, err: ex };
|
|
77
107
|
}
|
|
78
108
|
|
|
79
|
-
var
|
|
80
|
-
var
|
|
109
|
+
var isDifferent = true;
|
|
110
|
+
var hash = this.getHash( contentBuffer );
|
|
81
111
|
|
|
82
112
|
if ( !meta ) {
|
|
83
|
-
meta = {
|
|
113
|
+
meta = { hash: hash };
|
|
84
114
|
} else {
|
|
85
|
-
|
|
86
|
-
var isDifferentSize = cSize !== meta.size;
|
|
115
|
+
isDifferent = hash !== meta.hash;
|
|
87
116
|
}
|
|
88
117
|
|
|
89
118
|
var nEntry = normalizedEntries[ file ] = {
|
|
90
119
|
key: file,
|
|
91
|
-
changed: !cacheExists ||
|
|
120
|
+
changed: !cacheExists || isDifferent,
|
|
92
121
|
meta: meta
|
|
93
122
|
};
|
|
94
123
|
|
|
@@ -161,29 +190,38 @@ module.exports = {
|
|
|
161
190
|
},
|
|
162
191
|
/**
|
|
163
192
|
* Sync the files and persist them to the cache
|
|
164
|
-
*
|
|
165
193
|
* @method reconcile
|
|
166
194
|
*/
|
|
167
195
|
reconcile: function () {
|
|
168
|
-
|
|
196
|
+
removeNotFoundFiles();
|
|
169
197
|
|
|
198
|
+
var entries = normalizedEntries;
|
|
170
199
|
var keys = Object.keys( entries );
|
|
200
|
+
var me = this;
|
|
201
|
+
|
|
171
202
|
if ( keys.length === 0 ) {
|
|
172
203
|
return;
|
|
173
204
|
}
|
|
205
|
+
|
|
174
206
|
keys.forEach( function ( entryName ) {
|
|
175
207
|
var cacheEntry = entries[ entryName ];
|
|
176
|
-
var stat = fs.statSync( cacheEntry.key );
|
|
177
208
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
209
|
+
try {
|
|
210
|
+
var contentBuffer = fs.readFileSync( cacheEntry.key );
|
|
211
|
+
var hash = me.getHash( contentBuffer );
|
|
212
|
+
var meta = Object.assign( cacheEntry.meta, { hash: hash } );
|
|
213
|
+
|
|
214
|
+
cache.setKey( entryName, meta );
|
|
215
|
+
} catch (err) {
|
|
216
|
+
// if the file does not exists we don't save it
|
|
217
|
+
// other errors are just thrown
|
|
218
|
+
if ( err.code !== 'ENOENT' ) {
|
|
219
|
+
throw err;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
184
222
|
} );
|
|
185
223
|
|
|
186
|
-
cache.save();
|
|
224
|
+
cache.save( true );
|
|
187
225
|
}
|
|
188
226
|
};
|
|
189
227
|
}
|
package/changelog.md
CHANGED
|
@@ -1,5 +1,67 @@
|
|
|
1
1
|
|
|
2
2
|
# file-entry-cache - Changelog
|
|
3
|
+
## v4.0.0
|
|
4
|
+
- **Build Scripts Changes**
|
|
5
|
+
- use the same node versions eslint use - [563cfee]( https://github.com/royriojas/file-entry-cache/commit/563cfee ), [Roy Riojas](https://github.com/Roy Riojas), 08/01/2019 23:29:34
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
- **Other changes**
|
|
9
|
+
- Remove object-assign dependency. - [d0f598e]( https://github.com/royriojas/file-entry-cache/commit/d0f598e ), [Corey Farrell](https://github.com/Corey Farrell), 08/01/2019 23:09:51
|
|
10
|
+
|
|
11
|
+
node.js >=4 is required so object-assign is no longer needed, the native
|
|
12
|
+
Object.assign can be used instead.
|
|
13
|
+
|
|
14
|
+
## v3.0.0
|
|
15
|
+
- **Build Scripts Changes**
|
|
16
|
+
- Upgrade flat-cache dep to latest - [078b0df]( https://github.com/royriojas/file-entry-cache/commit/078b0df ), [Roy Riojas](https://github.com/Roy Riojas), 08/01/2019 21:54:40
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
- Commit new package-lock.json file - [245fe62]( https://github.com/royriojas/file-entry-cache/commit/245fe62 ), [Roy Riojas](https://github.com/Roy Riojas), 08/01/2019 20:56:21
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
- **Refactoring**
|
|
23
|
+
- add eslintrc file - [6dd32d8]( https://github.com/royriojas/file-entry-cache/commit/6dd32d8 ), [Roy Riojas](https://github.com/Roy Riojas), 22/08/2018 11:58:17
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
- **Other changes**
|
|
27
|
+
- Move variable definition out of else block - [ea05441]( https://github.com/royriojas/file-entry-cache/commit/ea05441 ), [Zakhar Shapurau](https://github.com/Zakhar Shapurau), 25/04/2017 13:19:00
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
- Add script and cmd to test hash/checksum performance - [7f60e0a]( https://github.com/royriojas/file-entry-cache/commit/7f60e0a ), [Zakhar Shapurau](https://github.com/Zakhar Shapurau), 24/04/2017 16:43:12
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
- Calculate md5 hexdigest instead of Adler-32 checksum - [f9e5c69]( https://github.com/royriojas/file-entry-cache/commit/f9e5c69 ), [Zakhar Shapurau](https://github.com/Zakhar Shapurau), 24/04/2017 16:43:12
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
- How to reproduce - [4edc2dc]( https://github.com/royriojas/file-entry-cache/commit/4edc2dc ), [Zakhar Shapurau](https://github.com/Zakhar Shapurau), 24/04/2017 15:49:32
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
- Test handling of removed files - [09d9ec5]( https://github.com/royriojas/file-entry-cache/commit/09d9ec5 ), [Zakhar Shapurau](https://github.com/Zakhar Shapurau), 19/04/2017 21:51:50
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
- Use content checksum instead of mtime and fsize - [343b340]( https://github.com/royriojas/file-entry-cache/commit/343b340 ), [Zakhar Shapurau](https://github.com/Zakhar Shapurau), 19/04/2017 21:51:47
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
- **Revert**
|
|
46
|
+
- Revert "How to reproduce" - [4b4e54a]( https://github.com/royriojas/file-entry-cache/commit/4b4e54a ), [Zakhar Shapurau](https://github.com/Zakhar Shapurau), 25/04/2017 13:15:36
|
|
47
|
+
|
|
48
|
+
This reverts commit 4edc2dcec01574247bfc2e0a2fe26527332b7df3.
|
|
49
|
+
|
|
50
|
+
## v2.0.0
|
|
51
|
+
- **Features**
|
|
52
|
+
- do not persist and prune removed files from cache. Relates to [#2](https://github.com/royriojas/file-entry-cache/issues/2) - [408374d]( https://github.com/royriojas/file-entry-cache/commit/408374d ), [Roy Riojas](https://github.com/Roy Riojas), 16/08/2016 15:47:58
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
## v1.3.1
|
|
56
|
+
- **Build Scripts Changes**
|
|
57
|
+
- remove older node version - [0a26ac4]( https://github.com/royriojas/file-entry-cache/commit/0a26ac4 ), [Roy Riojas](https://github.com/Roy Riojas), 01/08/2016 06:09:17
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
## v1.3.0
|
|
61
|
+
- **Features**
|
|
62
|
+
- Add an option to not prune non visited keys. Closes [#2](https://github.com/royriojas/file-entry-cache/issues/2) - [b1a64db]( https://github.com/royriojas/file-entry-cache/commit/b1a64db ), [Roy Riojas](https://github.com/Roy Riojas), 01/08/2016 05:52:12
|
|
63
|
+
|
|
64
|
+
|
|
3
65
|
## v1.2.4
|
|
4
66
|
- **Enhancements**
|
|
5
67
|
- Expose the flat-cache instance - [f34c557]( https://github.com/royriojas/file-entry-cache/commit/f34c557 ), [royriojas](https://github.com/royriojas), 23/09/2015 20:26:33
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "file-entry-cache",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"description": "Super simple cache for file metadata, useful for process that work o a given series of files and that only need to repeat the job on the changed ones since the previous run of the process",
|
|
5
5
|
"repository": "royriojas/file-entry-cache",
|
|
6
6
|
"license": "MIT",
|
|
@@ -13,23 +13,24 @@
|
|
|
13
13
|
"cache.js"
|
|
14
14
|
],
|
|
15
15
|
"engines": {
|
|
16
|
-
"node": ">=
|
|
16
|
+
"node": ">=4"
|
|
17
17
|
},
|
|
18
18
|
"scripts": {
|
|
19
|
-
"beautify": "esbeautifier 'cache.js' '
|
|
20
|
-
"beautify-check": "
|
|
21
|
-
"eslint": "eslinter 'cache.js' 'specs/**/*.js'",
|
|
19
|
+
"beautify": "esbeautifier 'cache.js' 'test/**/*.js' 'perf.js'",
|
|
20
|
+
"beautify-check": "npm run beautify -- -k",
|
|
21
|
+
"eslint": "eslinter 'cache.js' 'specs/**/*.js' 'perf.js'",
|
|
22
22
|
"lint": "npm run beautify && npm run eslint",
|
|
23
23
|
"verify": "npm run beautify-check && npm run eslint",
|
|
24
24
|
"install-hooks": "prepush install && changelogx install-hook && precommit install",
|
|
25
25
|
"changelog": "changelogx -f markdown -o ./changelog.md",
|
|
26
26
|
"do-changelog": "npm run changelog && git add ./changelog.md && git commit -m 'DOC: Generate changelog' --no-verify",
|
|
27
|
-
"pre-v": "npm run
|
|
27
|
+
"pre-v": "npm run test",
|
|
28
28
|
"post-v": "npm run do-changelog && git push --no-verify && git push --tags --no-verify",
|
|
29
29
|
"bump-major": "npm run pre-v && npm version major -m 'BLD: Release v%s' && npm run post-v",
|
|
30
30
|
"bump-minor": "npm run pre-v && npm version minor -m 'BLD: Release v%s' && npm run post-v",
|
|
31
31
|
"bump-patch": "npm run pre-v && npm version patch -m 'BLD: Release v%s' && npm run post-v",
|
|
32
|
-
"test": "mocha -R spec test/specs",
|
|
32
|
+
"test": "npm run verify --silent && mocha -R spec test/specs",
|
|
33
|
+
"perf": "node perf.js",
|
|
33
34
|
"cover": "istanbul cover test/runner.js html text-summary",
|
|
34
35
|
"watch": "watch-run -i -p 'test/specs/**/*.js' istanbul cover test/runner.js html text-summary"
|
|
35
36
|
},
|
|
@@ -61,7 +62,7 @@
|
|
|
61
62
|
},
|
|
62
63
|
"devDependencies": {
|
|
63
64
|
"chai": "^3.2.0",
|
|
64
|
-
"changelogx": "
|
|
65
|
+
"changelogx": "3.0.0",
|
|
65
66
|
"commander": "^2.6.0",
|
|
66
67
|
"del": "^2.0.2",
|
|
67
68
|
"esbeautifier": "^4.2.11",
|
|
@@ -72,14 +73,12 @@
|
|
|
72
73
|
"precommit": "^1.1.5",
|
|
73
74
|
"prepush": "^3.1.4",
|
|
74
75
|
"proxyquire": "^1.3.1",
|
|
75
|
-
"read-file": "^0.2.0",
|
|
76
76
|
"sinon": "^1.12.2",
|
|
77
77
|
"sinon-chai": "^2.7.0",
|
|
78
78
|
"watch-run": "^1.2.1",
|
|
79
|
-
"write": "^0.
|
|
79
|
+
"write": "^0.3.1"
|
|
80
80
|
},
|
|
81
81
|
"dependencies": {
|
|
82
|
-
"flat-cache": "^
|
|
83
|
-
"object-assign": "^4.0.1"
|
|
82
|
+
"flat-cache": "^2.0.1"
|
|
84
83
|
}
|
|
85
84
|
}
|