file-entry-cache 11.0.0-beta.4 → 11.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 +139 -47
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +27 -15
- package/dist/index.d.ts +27 -15
- package/dist/index.js +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -72,6 +72,23 @@ fileDescriptor = cache.getFileDescriptor('./src/file.txt');
|
|
|
72
72
|
console.log(fileDescriptor.changed); // true
|
|
73
73
|
```
|
|
74
74
|
|
|
75
|
+
Using `create()` with options for more control:
|
|
76
|
+
```javascript
|
|
77
|
+
import fileEntryCache from 'file-entry-cache';
|
|
78
|
+
|
|
79
|
+
// Create cache with options
|
|
80
|
+
const cache = fileEntryCache.create('myCache', './.cache', {
|
|
81
|
+
useCheckSum: true, // Use checksums for more reliable change detection
|
|
82
|
+
cwd: '/path/to/project', // Custom working directory
|
|
83
|
+
restrictAccessToCwd: false, // Allow access outside cwd (use with caution)
|
|
84
|
+
useAbsolutePathAsKey: false // Store relative paths in cache
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
let fileDescriptor = cache.getFileDescriptor('./src/file.txt');
|
|
88
|
+
console.log(fileDescriptor.changed); // true
|
|
89
|
+
console.log(fileDescriptor.meta.hash); // checksum hash
|
|
90
|
+
```
|
|
91
|
+
|
|
75
92
|
Save it to Disk and Reconcile files that are no longer found
|
|
76
93
|
```javascript
|
|
77
94
|
import fileEntryCache from 'file-entry-cache';
|
|
@@ -85,20 +102,80 @@ Load the cache from a file:
|
|
|
85
102
|
|
|
86
103
|
```javascript
|
|
87
104
|
import fileEntryCache from 'file-entry-cache';
|
|
105
|
+
|
|
106
|
+
// Basic usage
|
|
88
107
|
const cache = fileEntryCache.createFromFile('/path/to/cache/file');
|
|
89
108
|
let fileDescriptor = cache.getFileDescriptor('./src/file.txt');
|
|
90
109
|
console.log(fileDescriptor.changed); // false as it has not changed from the saved cache.
|
|
110
|
+
|
|
111
|
+
// With options
|
|
112
|
+
const cache2 = fileEntryCache.createFromFile('/path/to/cache/file', {
|
|
113
|
+
useCheckSum: true,
|
|
114
|
+
cwd: '/path/to/project'
|
|
115
|
+
});
|
|
91
116
|
```
|
|
92
117
|
|
|
93
118
|
|
|
94
119
|
# Changes from v10 to v11
|
|
95
120
|
|
|
96
121
|
**BREAKING CHANGES:**
|
|
97
|
-
|
|
122
|
+
|
|
123
|
+
- **`create()` and `createFromFile()` now use `CreateOptions` object** - The function signatures have changed to accept an options object instead of individual parameters for better extensibility and clarity.
|
|
124
|
+
|
|
125
|
+
**Old API (v10):**
|
|
126
|
+
```javascript
|
|
127
|
+
// v10 - positional parameters
|
|
128
|
+
const cache = fileEntryCache.create(cacheId, cacheDirectory, useCheckSum, cwd);
|
|
129
|
+
const cache2 = fileEntryCache.createFromFile(filePath, useCheckSum, cwd);
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
**New API (v11):**
|
|
133
|
+
```javascript
|
|
134
|
+
// v11 - options object
|
|
135
|
+
const cache = fileEntryCache.create(cacheId, cacheDirectory, {
|
|
136
|
+
useCheckSum: true,
|
|
137
|
+
cwd: '/path/to/project',
|
|
138
|
+
restrictAccessToCwd: false
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
const cache2 = fileEntryCache.createFromFile(filePath, {
|
|
142
|
+
useCheckSum: true,
|
|
143
|
+
cwd: '/path/to/project',
|
|
144
|
+
restrictAccessToCwd: false
|
|
145
|
+
});
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
- **Renamed `strictPaths` to `restrictAccessToCwd`** - For better clarity and self-documentation, the option that restricts file access to the current working directory has been renamed.
|
|
149
|
+
|
|
150
|
+
**Migration:**
|
|
151
|
+
```javascript
|
|
152
|
+
// Old
|
|
153
|
+
const cache = new FileEntryCache({ strictPaths: true });
|
|
154
|
+
cache.strictPaths = false;
|
|
155
|
+
|
|
156
|
+
// New
|
|
157
|
+
const cache = new FileEntryCache({ restrictAccessToCwd: true });
|
|
158
|
+
cache.restrictAccessToCwd = false;
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
- **Renamed `currentWorkingDirectory` to `cwd`** - For consistency with common conventions and brevity, the property has been renamed to `cwd`.
|
|
162
|
+
|
|
163
|
+
**Migration:**
|
|
164
|
+
```javascript
|
|
165
|
+
// Old
|
|
166
|
+
const cache = new FileEntryCache({ currentWorkingDirectory: '/path/to/project' });
|
|
167
|
+
cache.currentWorkingDirectory = '/new/path';
|
|
168
|
+
|
|
169
|
+
// New
|
|
170
|
+
const cache = new FileEntryCache({ cwd: '/path/to/project' });
|
|
171
|
+
cache.cwd = '/new/path';
|
|
172
|
+
```
|
|
98
173
|
|
|
99
174
|
**NEW FEATURES:**
|
|
100
175
|
- **Added `cwd` option** - You can now specify a custom current working directory for resolving relative paths
|
|
101
|
-
- **Added `
|
|
176
|
+
- **Added `restrictAccessToCwd` option** - Provides protection against path traversal attacks (disabled by default for backwards compatibility)
|
|
177
|
+
- **Added `useAbsolutePathAsKey` option** - When `true`, cache keys use absolute paths instead of the provided paths. Default is `false` for better cache portability with relative paths
|
|
178
|
+
- **Added `logger` option** - Support for Pino-compatible logger instances to enable debugging and monitoring of cache operations. See [Logger Support](#logger-support) section for details
|
|
102
179
|
- **Improved cache portability** - When using relative paths with the same `cwd`, cache files are portable across different environments
|
|
103
180
|
|
|
104
181
|
# Changes from v9 to v10
|
|
@@ -114,15 +191,24 @@ There have been many features added and changes made to the `file-entry-cache` c
|
|
|
114
191
|
- 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`.
|
|
115
192
|
|
|
116
193
|
# Global Default Functions
|
|
117
|
-
- `create(cacheId: string, cacheDirectory?: string,
|
|
118
|
-
- `createFromFile(
|
|
194
|
+
- `create(cacheId: string, cacheDirectory?: string, options?: CreateOptions)` - Creates a new instance of the `FileEntryCache` class
|
|
195
|
+
- `createFromFile(filePath: string, options?: CreateOptions)` - Creates a new instance of the `FileEntryCache` class and loads the cache from a file.
|
|
196
|
+
|
|
197
|
+
## CreateOptions Type
|
|
198
|
+
All options from `FileEntryCacheOptions` except `cache`:
|
|
199
|
+
- `useCheckSum?` - If `true` it will use a checksum to determine if the file has changed. Default is `false`
|
|
200
|
+
- `hashAlgorithm?` - The algorithm to use for the checksum. Default is `md5`
|
|
201
|
+
- `cwd?` - The current working directory for resolving relative paths. Default is `process.cwd()`
|
|
202
|
+
- `restrictAccessToCwd?` - If `true` restricts file access to within `cwd` boundaries. Default is `false`
|
|
203
|
+
- `useAbsolutePathAsKey?` - If `true` uses absolute paths as cache keys. Default is `false`
|
|
204
|
+
- `logger?` - A logger instance for debugging. Default is `undefined`
|
|
119
205
|
|
|
120
206
|
# FileEntryCache Options (FileEntryCacheOptions)
|
|
121
207
|
- `useModifiedTime?` - If `true` it will use the modified time to determine if the file has changed. Default is `true`
|
|
122
208
|
- `useCheckSum?` - If `true` it will use a checksum to determine if the file has changed. Default is `false`
|
|
123
209
|
- `hashAlgorithm?` - The algorithm to use for the checksum. Default is `md5` but can be any algorithm supported by `crypto.createHash`
|
|
124
210
|
- `cwd?` - The current working directory for resolving relative paths. Default is `process.cwd()`
|
|
125
|
-
- `
|
|
211
|
+
- `restrictAccessToCwd?` - If `true` restricts file access to within `cwd` boundaries, preventing path traversal attacks. Default is `true`
|
|
126
212
|
- `logger?` - A logger instance compatible with Pino logger interface for debugging and monitoring. Default is `undefined`
|
|
127
213
|
- `cache.ttl?` - The time to live for the cache in milliseconds. Default is `0` which means no expiration
|
|
128
214
|
- `cache.lruSize?` - The number of items to keep in the cache. Default is `0` which means no limit
|
|
@@ -141,9 +227,10 @@ There have been many features added and changes made to the `file-entry-cache` c
|
|
|
141
227
|
- `hashAlgorithm: string` - The algorithm to use for the checksum. Default is `md5` but can be any algorithm supported by `crypto.createHash`
|
|
142
228
|
- `getHash(buffer: Buffer): string` - Gets the hash of a buffer used for checksums
|
|
143
229
|
- `cwd: string` - The current working directory for resolving relative paths. Default is `process.cwd()`
|
|
144
|
-
- `
|
|
230
|
+
- `restrictAccessToCwd: boolean` - If `true` restricts file access to within `cwd` boundaries. Default is `true`
|
|
231
|
+
- `useAbsolutePathAsKey: boolean` - If `true` uses absolute paths as cache keys. Default is `false` to maintain better cache portability
|
|
145
232
|
- `logger: ILogger | undefined` - A logger instance for debugging and monitoring cache operations
|
|
146
|
-
- `createFileKey(filePath: string): string` - Returns the cache key for the file path (returns the path exactly as provided).
|
|
233
|
+
- `createFileKey(filePath: string): string` - Returns the cache key for the file path (returns the path exactly as provided when `useAbsolutePathAsKey` is `false`, otherwise returns the absolute path).
|
|
147
234
|
- `deleteCacheFile(): boolean` - Deletes the cache file from disk
|
|
148
235
|
- `destroy(): void` - Destroys the cache. This will clear the cache in memory. If using cache persistence it will stop the interval.
|
|
149
236
|
- `removeEntry(filePath: string): void` - Removes an entry from the cache.
|
|
@@ -154,8 +241,8 @@ There have been many features added and changes made to the `file-entry-cache` c
|
|
|
154
241
|
- `analyzeFiles(files: string[])` will return `AnalyzedFiles` object with `changedFiles`, `notFoundFiles`, and `notChangedFiles` as FileDescriptor arrays.
|
|
155
242
|
- `getUpdatedFiles(files: string[])` will return an array of `FileEntryDescriptor` objects that have changed.
|
|
156
243
|
- `getFileDescriptorsByPath(filePath: string): FileEntryDescriptor[]` will return an array of `FileEntryDescriptor` objects that starts with the path prefix specified.
|
|
157
|
-
- `getAbsolutePath(filePath: string): string` - Resolves a relative path to absolute using the configured `cwd`. Returns absolute paths unchanged. When `
|
|
158
|
-
- `getAbsolutePathWithCwd(filePath: string, cwd: string): string` - Resolves a relative path to absolute using a custom working directory. When `
|
|
244
|
+
- `getAbsolutePath(filePath: string): string` - Resolves a relative path to absolute using the configured `cwd`. Returns absolute paths unchanged. When `restrictAccessToCwd` is enabled, throws an error if the path resolves outside `cwd`.
|
|
245
|
+
- `getAbsolutePathWithCwd(filePath: string, cwd: string): string` - Resolves a relative path to absolute using a custom working directory. When `restrictAccessToCwd` is enabled, throws an error if the path resolves outside the provided `cwd`.
|
|
159
246
|
|
|
160
247
|
# Get File Descriptor
|
|
161
248
|
|
|
@@ -175,9 +262,12 @@ The cache stores paths exactly as they are provided (relative or absolute). When
|
|
|
175
262
|
// Default: uses process.cwd()
|
|
176
263
|
const cache1 = fileEntryCache.create('cache1');
|
|
177
264
|
|
|
178
|
-
// Custom working directory
|
|
179
|
-
const cache2 = fileEntryCache.create('cache2', './cache',
|
|
180
|
-
|
|
265
|
+
// Custom working directory using options object
|
|
266
|
+
const cache2 = fileEntryCache.create('cache2', './cache', {
|
|
267
|
+
cwd: '/project/root'
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
// Or using the class constructor directly
|
|
181
271
|
const cache3 = new FileEntryCache({ cwd: '/project/root' });
|
|
182
272
|
|
|
183
273
|
// The cache key is always the provided path
|
|
@@ -192,12 +282,16 @@ Using relative paths with a consistent `cwd` (defaults to `process.cwd()`) makes
|
|
|
192
282
|
|
|
193
283
|
```javascript
|
|
194
284
|
// On machine A (project at /home/user/project)
|
|
195
|
-
const cacheA = fileEntryCache.create('build-cache', './cache',
|
|
285
|
+
const cacheA = fileEntryCache.create('build-cache', './cache', {
|
|
286
|
+
cwd: '/home/user/project'
|
|
287
|
+
});
|
|
196
288
|
cacheA.getFileDescriptor('./src/index.js'); // Resolves to /home/user/project/src/index.js
|
|
197
289
|
cacheA.reconcile();
|
|
198
290
|
|
|
199
291
|
// On machine B (project at /workspace/project)
|
|
200
|
-
const cacheB = fileEntryCache.create('build-cache', './cache',
|
|
292
|
+
const cacheB = fileEntryCache.create('build-cache', './cache', {
|
|
293
|
+
cwd: '/workspace/project'
|
|
294
|
+
});
|
|
201
295
|
cacheB.getFileDescriptor('./src/index.js'); // Resolves to /workspace/project/src/index.js
|
|
202
296
|
// Cache hit! File hasn't changed since machine A
|
|
203
297
|
```
|
|
@@ -208,11 +302,9 @@ For maximum cache portability across different environments, use checksums (`use
|
|
|
208
302
|
|
|
209
303
|
```javascript
|
|
210
304
|
// Development machine
|
|
211
|
-
const devCache = fileEntryCache.create(
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
true // Use checksums for content-based comparison
|
|
215
|
-
);
|
|
305
|
+
const devCache = fileEntryCache.create('.buildcache', './cache', {
|
|
306
|
+
useCheckSum: true // Use checksums for content-based comparison
|
|
307
|
+
});
|
|
216
308
|
|
|
217
309
|
// Process files using relative paths
|
|
218
310
|
const descriptor = devCache.getFileDescriptor('./src/index.js');
|
|
@@ -223,12 +315,10 @@ if (descriptor.changed) {
|
|
|
223
315
|
devCache.reconcile(); // Save cache
|
|
224
316
|
|
|
225
317
|
// CI/CD Pipeline or another developer's machine
|
|
226
|
-
const ciCache = fileEntryCache.create(
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
process.cwd() // Different absolute path, same relative structure
|
|
231
|
-
);
|
|
318
|
+
const ciCache = fileEntryCache.create('.buildcache', './node_modules/.cache', {
|
|
319
|
+
useCheckSum: true, // Same checksum setting
|
|
320
|
+
cwd: process.cwd() // Different absolute path, same relative structure
|
|
321
|
+
});
|
|
232
322
|
|
|
233
323
|
// Same relative path works across environments
|
|
234
324
|
const descriptor2 = ciCache.getFileDescriptor('./src/index.js');
|
|
@@ -244,12 +334,18 @@ Cache remains valid even when projects are moved or renamed:
|
|
|
244
334
|
|
|
245
335
|
```javascript
|
|
246
336
|
// Original location: /projects/my-app
|
|
247
|
-
const cache1 = fileEntryCache.create('.cache', './cache',
|
|
337
|
+
const cache1 = fileEntryCache.create('.cache', './cache', {
|
|
338
|
+
useCheckSum: true,
|
|
339
|
+
cwd: '/projects/my-app'
|
|
340
|
+
});
|
|
248
341
|
cache1.getFileDescriptor('./src/app.js');
|
|
249
342
|
cache1.reconcile();
|
|
250
343
|
|
|
251
344
|
// After moving project to: /archived/2024/my-app
|
|
252
|
-
const cache2 = fileEntryCache.create('.cache', './cache',
|
|
345
|
+
const cache2 = fileEntryCache.create('.cache', './cache', {
|
|
346
|
+
useCheckSum: true,
|
|
347
|
+
cwd: '/archived/2024/my-app'
|
|
348
|
+
});
|
|
253
349
|
cache2.getFileDescriptor('./src/app.js'); // Still finds cached entry!
|
|
254
350
|
// Cache valid as long as relative structure unchanged
|
|
255
351
|
```
|
|
@@ -270,12 +366,12 @@ if (fileDescriptor.notFound) {
|
|
|
270
366
|
|
|
271
367
|
# Path Security and Traversal Prevention
|
|
272
368
|
|
|
273
|
-
The `
|
|
369
|
+
The `restrictAccessToCwd` option provides security against path traversal attacks by restricting file access to within the configured `cwd` boundaries. **This is enabled by default (since v11)** to ensure secure defaults when processing untrusted input or when running in security-sensitive environments.
|
|
274
370
|
|
|
275
371
|
## Basic Usage
|
|
276
372
|
|
|
277
373
|
```javascript
|
|
278
|
-
//
|
|
374
|
+
// restrictAccessToCwd is enabled by default for security
|
|
279
375
|
const cache = new FileEntryCache({
|
|
280
376
|
cwd: '/project/root'
|
|
281
377
|
});
|
|
@@ -293,13 +389,13 @@ try {
|
|
|
293
389
|
// To allow parent directory access (not recommended for untrusted input)
|
|
294
390
|
const unsafeCache = new FileEntryCache({
|
|
295
391
|
cwd: '/project/root',
|
|
296
|
-
|
|
392
|
+
restrictAccessToCwd: false // Explicitly disable protection
|
|
297
393
|
});
|
|
298
394
|
```
|
|
299
395
|
|
|
300
396
|
## Security Features
|
|
301
397
|
|
|
302
|
-
When `
|
|
398
|
+
When `restrictAccessToCwd` is enabled:
|
|
303
399
|
- **Path Traversal Prevention**: Blocks attempts to access files outside the working directory using `../` sequences
|
|
304
400
|
- **Null Byte Protection**: Automatically removes null bytes from paths to prevent injection attacks
|
|
305
401
|
- **Path Normalization**: Cleans and normalizes paths to prevent bypass attempts
|
|
@@ -309,15 +405,11 @@ When `strictPaths` is enabled:
|
|
|
309
405
|
### Build Tools with Untrusted Input
|
|
310
406
|
```javascript
|
|
311
407
|
// Secure build tool configuration
|
|
312
|
-
const cache = fileEntryCache.create(
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
);
|
|
318
|
-
|
|
319
|
-
// Enable strict path checking for security
|
|
320
|
-
cache.strictPaths = true;
|
|
408
|
+
const cache = fileEntryCache.create('.buildcache', './cache', {
|
|
409
|
+
useCheckSum: true,
|
|
410
|
+
cwd: process.cwd(),
|
|
411
|
+
restrictAccessToCwd: true // Enable strict path checking for security
|
|
412
|
+
});
|
|
321
413
|
|
|
322
414
|
// Process user-provided file paths safely
|
|
323
415
|
function processUserFile(userProvidedPath) {
|
|
@@ -340,7 +432,7 @@ function processUserFile(userProvidedPath) {
|
|
|
340
432
|
// Strict security for CI/CD pipelines
|
|
341
433
|
const cache = new FileEntryCache({
|
|
342
434
|
cwd: process.env.GITHUB_WORKSPACE || process.cwd(),
|
|
343
|
-
|
|
435
|
+
restrictAccessToCwd: true, // Prevent access outside workspace
|
|
344
436
|
useCheckSum: true // Content-based validation
|
|
345
437
|
});
|
|
346
438
|
|
|
@@ -355,20 +447,20 @@ cache.getFileDescriptor('../../../root'); // ✗ Blocked (path traversal)
|
|
|
355
447
|
const cache = new FileEntryCache({ cwd: '/safe/directory' });
|
|
356
448
|
|
|
357
449
|
// Start with relaxed mode for trusted operations
|
|
358
|
-
cache.
|
|
450
|
+
cache.restrictAccessToCwd = false;
|
|
359
451
|
processInternalFiles();
|
|
360
452
|
|
|
361
453
|
// Enable strict mode for untrusted input
|
|
362
|
-
cache.
|
|
454
|
+
cache.restrictAccessToCwd = true;
|
|
363
455
|
processUserUploadedPaths();
|
|
364
456
|
|
|
365
457
|
// Return to relaxed mode if needed
|
|
366
|
-
cache.
|
|
458
|
+
cache.restrictAccessToCwd = false;
|
|
367
459
|
```
|
|
368
460
|
|
|
369
461
|
## Default Behavior
|
|
370
462
|
|
|
371
|
-
**As of v11, `
|
|
463
|
+
**As of v11, `restrictAccessToCwd` is enabled by default** to provide secure defaults. This means:
|
|
372
464
|
- Path traversal attempts using `../` are blocked
|
|
373
465
|
- File access is restricted to within the configured `cwd`
|
|
374
466
|
- Null bytes in paths are automatically sanitized
|
|
@@ -380,11 +472,11 @@ If you're upgrading from v10 or earlier and need to maintain the previous behavi
|
|
|
380
472
|
```javascript
|
|
381
473
|
const cache = new FileEntryCache({
|
|
382
474
|
cwd: process.cwd(),
|
|
383
|
-
|
|
475
|
+
restrictAccessToCwd: false // Restore v10 behavior
|
|
384
476
|
});
|
|
385
477
|
```
|
|
386
478
|
|
|
387
|
-
However, we strongly recommend keeping `
|
|
479
|
+
However, we strongly recommend keeping `restrictAccessToCwd: true` and adjusting your code to work within the security boundaries, especially when processing any untrusted input.
|
|
388
480
|
|
|
389
481
|
# Using Checksums to Determine if a File has Changed (useCheckSum)
|
|
390
482
|
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var C=Object.create;var g=Object.defineProperty;var k=Object.getOwnPropertyDescriptor;var w=Object.getOwnPropertyNames;var A=Object.getPrototypeOf,v=Object.prototype.hasOwnProperty;var z=(c,e)=>{for(var s in e)g(c,s,{get:e[s],enumerable:!0})},y=(c,e,s,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of w(e))!v.call(c,t)&&t!==s&&g(c,t,{get:()=>e[t],enumerable:!(i=k(e,t))||i.enumerable});return c};var p=(c,e,s)=>(s=c!=null?C(A(c)):{},y(e||!c||!c.__esModule?g(s,"default",{value:c,enumerable:!0}):s,c)),D=c=>y(g({},"__esModule",{value:!0}),c);var K={};z(K,{FileEntryCache:()=>m,create:()=>f,createFromFile:()=>_,default:()=>d});module.exports=D(K);var F=p(require("crypto"),1),u=p(require("fs"),1),o=p(require("path"),1),l=require("flat-cache");function _(c,e){let s=o.default.basename(c),i=o.default.dirname(c);return f(s,i,e)}function f(c,e,s){let i={...s,cache:{cacheId:c,cacheDir:e}},t=new m(i);if(e){let r=`${e}/${c}`;u.default.existsSync(r)&&(t.cache=(0,l.createFromFile)(r,i.cache))}return t}var d=class{static create=f;static createFromFile=_},m=class{_cache=new l.FlatCache({useClone:!1});_useCheckSum=!1;_hashAlgorithm="md5";_cwd=process.cwd();_restrictAccessToCwd=!1;_logger;_useAbsolutePathAsKey=!1;constructor(e){e?.cache&&(this._cache=new l.FlatCache(e.cache)),e?.useCheckSum&&(this._useCheckSum=e.useCheckSum),e?.hashAlgorithm&&(this._hashAlgorithm=e.hashAlgorithm),e?.cwd&&(this._cwd=e.cwd),e?.restrictAccessToCwd!==void 0&&(this._restrictAccessToCwd=e.restrictAccessToCwd),e?.useAbsolutePathAsKey!==void 0&&(this._useAbsolutePathAsKey=e.useAbsolutePathAsKey),e?.logger&&(this._logger=e.logger)}get cache(){return this._cache}set cache(e){this._cache=e}get logger(){return this._logger}set logger(e){this._logger=e}get useCheckSum(){return this._useCheckSum}set useCheckSum(e){this._useCheckSum=e}get hashAlgorithm(){return this._hashAlgorithm}set hashAlgorithm(e){this._hashAlgorithm=e}get cwd(){return this._cwd}set cwd(e){this._cwd=e}get restrictAccessToCwd(){return this._restrictAccessToCwd}set restrictAccessToCwd(e){this._restrictAccessToCwd=e}get useAbsolutePathAsKey(){return this._useAbsolutePathAsKey}set useAbsolutePathAsKey(e){this._useAbsolutePathAsKey=e}getHash(e){return F.default.createHash(this._hashAlgorithm).update(e).digest("hex")}createFileKey(e){let s=e;return this._useAbsolutePathAsKey&&this.isRelativePath(e)&&(s=this.getAbsolutePathWithCwd(e,this._cwd)),s}isRelativePath(e){return!o.default.isAbsolute(e)}deleteCacheFile(){return this._cache.removeCacheFile()}destroy(){this._cache.destroy()}removeEntry(e){let s=this.createFileKey(e);this._cache.removeKey(s)}reconcile(){let{items:e}=this._cache;for(let s of e)this.getFileDescriptor(s.key).notFound&&this._cache.removeKey(s.key);this._cache.save()}hasFileChanged(e){let s=!1,i=this.getFileDescriptor(e);return(!i.err||!i.notFound)&&i.changed&&(s=!0),s}getFileDescriptor(e,s){this._logger?.debug({filePath:e,options:s},"Getting file descriptor");let i,t={key:this.createFileKey(e),changed:!1,meta:{}};this._logger?.trace({key:t.key},"Created file key");let r=this._cache.getKey(t.key);r?this._logger?.trace({metaCache:r},"Found cached meta"):this._logger?.trace("No cached meta found"),t.meta=r?{...r}:{};let n=this.getAbsolutePath(e);this._logger?.trace({absolutePath:n},"Resolved absolute path");let a=s?.useCheckSum??this._useCheckSum;this._logger?.debug({useCheckSum:a},"Using checksum setting");try{if(i=u.default.statSync(n),t.meta.size=i.size,t.meta.mtime=i.mtime.getTime(),this._logger?.trace({size:t.meta.size,mtime:t.meta.mtime},"Read file stats"),a){let h=u.default.readFileSync(n);t.meta.hash=this.getHash(h),this._logger?.trace({hash:t.meta.hash},"Calculated file hash")}}catch(h){this._logger?.error({filePath:e,error:h},"Error reading file"),this.removeEntry(e);let b=!1;return h.message.includes("ENOENT")&&(b=!0,this._logger?.debug({filePath:e},"File not found")),{key:t.key,err:h,notFound:b,meta:{}}}return r?(a===!1&&r?.mtime!==t.meta?.mtime&&(t.changed=!0,this._logger?.debug({filePath:e,oldMtime:r.mtime,newMtime:t.meta.mtime},"File changed: mtime differs")),r?.size!==t.meta?.size&&(t.changed=!0,this._logger?.debug({filePath:e,oldSize:r.size,newSize:t.meta.size},"File changed: size differs")),a&&r?.hash!==t.meta?.hash&&(t.changed=!0,this._logger?.debug({filePath:e,oldHash:r.hash,newHash:t.meta.hash},"File changed: hash differs")),this._cache.setKey(t.key,t.meta),t.changed?this._logger?.info({filePath:e},"File has changed"):this._logger?.debug({filePath:e},"File unchanged"),t):(t.changed=!0,this._cache.setKey(t.key,t.meta),this._logger?.debug({filePath:e},"File not in cache, marked as changed"),t)}normalizeEntries(e){let s=[];if(e){for(let t of e){let r=this.getFileDescriptor(t);s.push(r)}return s}let i=this.cache.keys();for(let t of i){let r=this.getFileDescriptor(t);!r.notFound&&!r.err&&s.push(r)}return s}analyzeFiles(e){let s={changedFiles:[],notFoundFiles:[],notChangedFiles:[]},i=this.normalizeEntries(e);for(let t of i)t.notFound?s.notFoundFiles.push(t.key):t.changed?s.changedFiles.push(t.key):s.notChangedFiles.push(t.key);return s}getUpdatedFiles(e){let s=[],i=this.normalizeEntries(e);for(let t of i)t.changed&&s.push(t.key);return s}getFileDescriptorsByPath(e){let s=[],i=this._cache.keys();for(let t of i)if(t.startsWith(e)){let r=this.getFileDescriptor(t);s.push(r)}return s}getAbsolutePath(e){if(this.isRelativePath(e)){let s=e.replace(/\0/g,""),i=o.default.resolve(this._cwd,s);if(this._restrictAccessToCwd){let t=o.default.normalize(i),r=o.default.normalize(this._cwd);if(!(t===r||t.startsWith(r+o.default.sep)))throw new Error(`Path traversal attempt blocked: "${e}" resolves outside of working directory "${this._cwd}"`)}return i}return e}getAbsolutePathWithCwd(e,s){if(this.isRelativePath(e)){let i=e.replace(/\0/g,""),t=o.default.resolve(s,i);if(this._restrictAccessToCwd){let r=o.default.normalize(t),n=o.default.normalize(s);if(!(r===n||r.startsWith(n+o.default.sep)))throw new Error(`Path traversal attempt blocked: "${e}" resolves outside of working directory "${s}"`)}return t}return e}renameCacheKeys(e,s){let i=this._cache.keys();for(let t of i)if(t.startsWith(e)){let r=t.replace(e,s),n=this._cache.getKey(t);this._cache.removeKey(t),this._cache.setKey(r,n)}}};0&&(module.exports={FileEntryCache,create,createFromFile});
|
package/dist/index.d.cts
CHANGED
|
@@ -27,7 +27,9 @@ type FileEntryCacheOptions = {
|
|
|
27
27
|
/** Current working directory for resolving relative paths (default: process.cwd()) */
|
|
28
28
|
cwd?: string;
|
|
29
29
|
/** Restrict file access to within cwd boundaries (default: true) */
|
|
30
|
-
|
|
30
|
+
restrictAccessToCwd?: boolean;
|
|
31
|
+
/** Whether to use absolute path as cache key (default: false) */
|
|
32
|
+
useAbsolutePathAsKey?: boolean;
|
|
31
33
|
/** Logger instance for logging (default: undefined) */
|
|
32
34
|
logger?: ILogger;
|
|
33
35
|
/** Options for the underlying flat cache */
|
|
@@ -72,20 +74,19 @@ type AnalyzedFiles = {
|
|
|
72
74
|
/**
|
|
73
75
|
* Create a new FileEntryCache instance from a file path
|
|
74
76
|
* @param filePath - The path to the cache file
|
|
75
|
-
* @param
|
|
76
|
-
* @param cwd - The current working directory for resolving relative paths (default: process.cwd())
|
|
77
|
+
* @param options - create options such as useChecksum, cwd, and more
|
|
77
78
|
* @returns A new FileEntryCache instance
|
|
78
79
|
*/
|
|
79
|
-
declare function createFromFile(filePath: string,
|
|
80
|
+
declare function createFromFile(filePath: string, options?: CreateOptions): FileEntryCache;
|
|
81
|
+
type CreateOptions = Omit<FileEntryCacheOptions, "cache">;
|
|
80
82
|
/**
|
|
81
83
|
* Create a new FileEntryCache instance
|
|
82
84
|
* @param cacheId - The cache file name
|
|
83
85
|
* @param cacheDirectory - The directory to store the cache file (default: undefined, cache won't be persisted)
|
|
84
|
-
* @param
|
|
85
|
-
* @param cwd - The current working directory for resolving relative paths (default: process.cwd())
|
|
86
|
+
* @param options - Whether to use checksum to detect file changes (default: false)
|
|
86
87
|
* @returns A new FileEntryCache instance
|
|
87
88
|
*/
|
|
88
|
-
declare function create(cacheId: string, cacheDirectory?: string,
|
|
89
|
+
declare function create(cacheId: string, cacheDirectory?: string, options?: CreateOptions): FileEntryCache;
|
|
89
90
|
declare class FileEntryDefault {
|
|
90
91
|
static create: typeof create;
|
|
91
92
|
static createFromFile: typeof createFromFile;
|
|
@@ -95,8 +96,9 @@ declare class FileEntryCache {
|
|
|
95
96
|
private _useCheckSum;
|
|
96
97
|
private _hashAlgorithm;
|
|
97
98
|
private _cwd;
|
|
98
|
-
private
|
|
99
|
+
private _restrictAccessToCwd;
|
|
99
100
|
private _logger?;
|
|
101
|
+
private _useAbsolutePathAsKey;
|
|
100
102
|
/**
|
|
101
103
|
* Create a new FileEntryCache instance
|
|
102
104
|
* @param options - The options for the FileEntryCache (all properties are optional with defaults)
|
|
@@ -156,12 +158,22 @@ declare class FileEntryCache {
|
|
|
156
158
|
* Get whether to restrict paths to cwd boundaries
|
|
157
159
|
* @returns {boolean} Whether strict path checking is enabled (default: true)
|
|
158
160
|
*/
|
|
159
|
-
get
|
|
161
|
+
get restrictAccessToCwd(): boolean;
|
|
160
162
|
/**
|
|
161
163
|
* Set whether to restrict paths to cwd boundaries
|
|
162
164
|
* @param {boolean} value - The value to set
|
|
163
165
|
*/
|
|
164
|
-
set
|
|
166
|
+
set restrictAccessToCwd(value: boolean);
|
|
167
|
+
/**
|
|
168
|
+
* Get whether to use absolute path as cache key
|
|
169
|
+
* @returns {boolean} Whether cache keys use absolute paths (default: false)
|
|
170
|
+
*/
|
|
171
|
+
get useAbsolutePathAsKey(): boolean;
|
|
172
|
+
/**
|
|
173
|
+
* Set whether to use absolute path as cache key
|
|
174
|
+
* @param {boolean} value - The value to set
|
|
175
|
+
*/
|
|
176
|
+
set useAbsolutePathAsKey(value: boolean);
|
|
165
177
|
/**
|
|
166
178
|
* Given a buffer, calculate md5 hash of its content.
|
|
167
179
|
* @method getHash
|
|
@@ -250,21 +262,21 @@ declare class FileEntryCache {
|
|
|
250
262
|
getFileDescriptorsByPath(filePath: string): FileDescriptor[];
|
|
251
263
|
/**
|
|
252
264
|
* Get the Absolute Path. If it is already absolute it will return the path as is.
|
|
253
|
-
* When
|
|
265
|
+
* When restrictAccessToCwd is enabled, ensures the resolved path stays within cwd boundaries.
|
|
254
266
|
* @method getAbsolutePath
|
|
255
267
|
* @param filePath - The file path to get the absolute path for
|
|
256
268
|
* @returns {string}
|
|
257
|
-
* @throws {Error} When
|
|
269
|
+
* @throws {Error} When restrictAccessToCwd is true and path would resolve outside cwd
|
|
258
270
|
*/
|
|
259
271
|
getAbsolutePath(filePath: string): string;
|
|
260
272
|
/**
|
|
261
273
|
* Get the Absolute Path with a custom working directory. If it is already absolute it will return the path as is.
|
|
262
|
-
* When
|
|
274
|
+
* When restrictAccessToCwd is enabled, ensures the resolved path stays within the provided cwd boundaries.
|
|
263
275
|
* @method getAbsolutePathWithCwd
|
|
264
276
|
* @param filePath - The file path to get the absolute path for
|
|
265
277
|
* @param cwd - The custom working directory to resolve relative paths from
|
|
266
278
|
* @returns {string}
|
|
267
|
-
* @throws {Error} When
|
|
279
|
+
* @throws {Error} When restrictAccessToCwd is true and path would resolve outside the provided cwd
|
|
268
280
|
*/
|
|
269
281
|
getAbsolutePathWithCwd(filePath: string, cwd: string): string;
|
|
270
282
|
/**
|
|
@@ -276,4 +288,4 @@ declare class FileEntryCache {
|
|
|
276
288
|
renameCacheKeys(oldPath: string, newPath: string): void;
|
|
277
289
|
}
|
|
278
290
|
|
|
279
|
-
export { type AnalyzedFiles, type FileDescriptor, type FileDescriptorMeta, FileEntryCache, type FileEntryCacheOptions, type GetFileDescriptorOptions, type ILogger, create, createFromFile, FileEntryDefault as default };
|
|
291
|
+
export { type AnalyzedFiles, type CreateOptions, type FileDescriptor, type FileDescriptorMeta, FileEntryCache, type FileEntryCacheOptions, type GetFileDescriptorOptions, type ILogger, create, createFromFile, FileEntryDefault as default };
|
package/dist/index.d.ts
CHANGED
|
@@ -27,7 +27,9 @@ type FileEntryCacheOptions = {
|
|
|
27
27
|
/** Current working directory for resolving relative paths (default: process.cwd()) */
|
|
28
28
|
cwd?: string;
|
|
29
29
|
/** Restrict file access to within cwd boundaries (default: true) */
|
|
30
|
-
|
|
30
|
+
restrictAccessToCwd?: boolean;
|
|
31
|
+
/** Whether to use absolute path as cache key (default: false) */
|
|
32
|
+
useAbsolutePathAsKey?: boolean;
|
|
31
33
|
/** Logger instance for logging (default: undefined) */
|
|
32
34
|
logger?: ILogger;
|
|
33
35
|
/** Options for the underlying flat cache */
|
|
@@ -72,20 +74,19 @@ type AnalyzedFiles = {
|
|
|
72
74
|
/**
|
|
73
75
|
* Create a new FileEntryCache instance from a file path
|
|
74
76
|
* @param filePath - The path to the cache file
|
|
75
|
-
* @param
|
|
76
|
-
* @param cwd - The current working directory for resolving relative paths (default: process.cwd())
|
|
77
|
+
* @param options - create options such as useChecksum, cwd, and more
|
|
77
78
|
* @returns A new FileEntryCache instance
|
|
78
79
|
*/
|
|
79
|
-
declare function createFromFile(filePath: string,
|
|
80
|
+
declare function createFromFile(filePath: string, options?: CreateOptions): FileEntryCache;
|
|
81
|
+
type CreateOptions = Omit<FileEntryCacheOptions, "cache">;
|
|
80
82
|
/**
|
|
81
83
|
* Create a new FileEntryCache instance
|
|
82
84
|
* @param cacheId - The cache file name
|
|
83
85
|
* @param cacheDirectory - The directory to store the cache file (default: undefined, cache won't be persisted)
|
|
84
|
-
* @param
|
|
85
|
-
* @param cwd - The current working directory for resolving relative paths (default: process.cwd())
|
|
86
|
+
* @param options - Whether to use checksum to detect file changes (default: false)
|
|
86
87
|
* @returns A new FileEntryCache instance
|
|
87
88
|
*/
|
|
88
|
-
declare function create(cacheId: string, cacheDirectory?: string,
|
|
89
|
+
declare function create(cacheId: string, cacheDirectory?: string, options?: CreateOptions): FileEntryCache;
|
|
89
90
|
declare class FileEntryDefault {
|
|
90
91
|
static create: typeof create;
|
|
91
92
|
static createFromFile: typeof createFromFile;
|
|
@@ -95,8 +96,9 @@ declare class FileEntryCache {
|
|
|
95
96
|
private _useCheckSum;
|
|
96
97
|
private _hashAlgorithm;
|
|
97
98
|
private _cwd;
|
|
98
|
-
private
|
|
99
|
+
private _restrictAccessToCwd;
|
|
99
100
|
private _logger?;
|
|
101
|
+
private _useAbsolutePathAsKey;
|
|
100
102
|
/**
|
|
101
103
|
* Create a new FileEntryCache instance
|
|
102
104
|
* @param options - The options for the FileEntryCache (all properties are optional with defaults)
|
|
@@ -156,12 +158,22 @@ declare class FileEntryCache {
|
|
|
156
158
|
* Get whether to restrict paths to cwd boundaries
|
|
157
159
|
* @returns {boolean} Whether strict path checking is enabled (default: true)
|
|
158
160
|
*/
|
|
159
|
-
get
|
|
161
|
+
get restrictAccessToCwd(): boolean;
|
|
160
162
|
/**
|
|
161
163
|
* Set whether to restrict paths to cwd boundaries
|
|
162
164
|
* @param {boolean} value - The value to set
|
|
163
165
|
*/
|
|
164
|
-
set
|
|
166
|
+
set restrictAccessToCwd(value: boolean);
|
|
167
|
+
/**
|
|
168
|
+
* Get whether to use absolute path as cache key
|
|
169
|
+
* @returns {boolean} Whether cache keys use absolute paths (default: false)
|
|
170
|
+
*/
|
|
171
|
+
get useAbsolutePathAsKey(): boolean;
|
|
172
|
+
/**
|
|
173
|
+
* Set whether to use absolute path as cache key
|
|
174
|
+
* @param {boolean} value - The value to set
|
|
175
|
+
*/
|
|
176
|
+
set useAbsolutePathAsKey(value: boolean);
|
|
165
177
|
/**
|
|
166
178
|
* Given a buffer, calculate md5 hash of its content.
|
|
167
179
|
* @method getHash
|
|
@@ -250,21 +262,21 @@ declare class FileEntryCache {
|
|
|
250
262
|
getFileDescriptorsByPath(filePath: string): FileDescriptor[];
|
|
251
263
|
/**
|
|
252
264
|
* Get the Absolute Path. If it is already absolute it will return the path as is.
|
|
253
|
-
* When
|
|
265
|
+
* When restrictAccessToCwd is enabled, ensures the resolved path stays within cwd boundaries.
|
|
254
266
|
* @method getAbsolutePath
|
|
255
267
|
* @param filePath - The file path to get the absolute path for
|
|
256
268
|
* @returns {string}
|
|
257
|
-
* @throws {Error} When
|
|
269
|
+
* @throws {Error} When restrictAccessToCwd is true and path would resolve outside cwd
|
|
258
270
|
*/
|
|
259
271
|
getAbsolutePath(filePath: string): string;
|
|
260
272
|
/**
|
|
261
273
|
* Get the Absolute Path with a custom working directory. If it is already absolute it will return the path as is.
|
|
262
|
-
* When
|
|
274
|
+
* When restrictAccessToCwd is enabled, ensures the resolved path stays within the provided cwd boundaries.
|
|
263
275
|
* @method getAbsolutePathWithCwd
|
|
264
276
|
* @param filePath - The file path to get the absolute path for
|
|
265
277
|
* @param cwd - The custom working directory to resolve relative paths from
|
|
266
278
|
* @returns {string}
|
|
267
|
-
* @throws {Error} When
|
|
279
|
+
* @throws {Error} When restrictAccessToCwd is true and path would resolve outside the provided cwd
|
|
268
280
|
*/
|
|
269
281
|
getAbsolutePathWithCwd(filePath: string, cwd: string): string;
|
|
270
282
|
/**
|
|
@@ -276,4 +288,4 @@ declare class FileEntryCache {
|
|
|
276
288
|
renameCacheKeys(oldPath: string, newPath: string): void;
|
|
277
289
|
}
|
|
278
290
|
|
|
279
|
-
export { type AnalyzedFiles, type FileDescriptor, type FileDescriptorMeta, FileEntryCache, type FileEntryCacheOptions, type GetFileDescriptorOptions, type ILogger, create, createFromFile, FileEntryDefault as default };
|
|
291
|
+
export { type AnalyzedFiles, type CreateOptions, type FileDescriptor, type FileDescriptorMeta, FileEntryCache, type FileEntryCacheOptions, type GetFileDescriptorOptions, type ILogger, create, createFromFile, FileEntryDefault as default };
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import f from"crypto";import l from"fs";import c from"path";import{createFromFile as
|
|
1
|
+
import f from"crypto";import l from"fs";import c from"path";import{createFromFile as b,FlatCache as m}from"flat-cache";function y(n,e){let s=c.basename(n),r=c.dirname(n);return p(s,r,e)}function p(n,e,s){let r={...s,cache:{cacheId:n,cacheDir:e}},t=new u(r);if(e){let i=`${e}/${n}`;l.existsSync(i)&&(t.cache=b(i,r.cache))}return t}var g=class{static create=p;static createFromFile=y},u=class{_cache=new m({useClone:!1});_useCheckSum=!1;_hashAlgorithm="md5";_cwd=process.cwd();_restrictAccessToCwd=!1;_logger;_useAbsolutePathAsKey=!1;constructor(e){e?.cache&&(this._cache=new m(e.cache)),e?.useCheckSum&&(this._useCheckSum=e.useCheckSum),e?.hashAlgorithm&&(this._hashAlgorithm=e.hashAlgorithm),e?.cwd&&(this._cwd=e.cwd),e?.restrictAccessToCwd!==void 0&&(this._restrictAccessToCwd=e.restrictAccessToCwd),e?.useAbsolutePathAsKey!==void 0&&(this._useAbsolutePathAsKey=e.useAbsolutePathAsKey),e?.logger&&(this._logger=e.logger)}get cache(){return this._cache}set cache(e){this._cache=e}get logger(){return this._logger}set logger(e){this._logger=e}get useCheckSum(){return this._useCheckSum}set useCheckSum(e){this._useCheckSum=e}get hashAlgorithm(){return this._hashAlgorithm}set hashAlgorithm(e){this._hashAlgorithm=e}get cwd(){return this._cwd}set cwd(e){this._cwd=e}get restrictAccessToCwd(){return this._restrictAccessToCwd}set restrictAccessToCwd(e){this._restrictAccessToCwd=e}get useAbsolutePathAsKey(){return this._useAbsolutePathAsKey}set useAbsolutePathAsKey(e){this._useAbsolutePathAsKey=e}getHash(e){return f.createHash(this._hashAlgorithm).update(e).digest("hex")}createFileKey(e){let s=e;return this._useAbsolutePathAsKey&&this.isRelativePath(e)&&(s=this.getAbsolutePathWithCwd(e,this._cwd)),s}isRelativePath(e){return!c.isAbsolute(e)}deleteCacheFile(){return this._cache.removeCacheFile()}destroy(){this._cache.destroy()}removeEntry(e){let s=this.createFileKey(e);this._cache.removeKey(s)}reconcile(){let{items:e}=this._cache;for(let s of e)this.getFileDescriptor(s.key).notFound&&this._cache.removeKey(s.key);this._cache.save()}hasFileChanged(e){let s=!1,r=this.getFileDescriptor(e);return(!r.err||!r.notFound)&&r.changed&&(s=!0),s}getFileDescriptor(e,s){this._logger?.debug({filePath:e,options:s},"Getting file descriptor");let r,t={key:this.createFileKey(e),changed:!1,meta:{}};this._logger?.trace({key:t.key},"Created file key");let i=this._cache.getKey(t.key);i?this._logger?.trace({metaCache:i},"Found cached meta"):this._logger?.trace("No cached meta found"),t.meta=i?{...i}:{};let o=this.getAbsolutePath(e);this._logger?.trace({absolutePath:o},"Resolved absolute path");let a=s?.useCheckSum??this._useCheckSum;this._logger?.debug({useCheckSum:a},"Using checksum setting");try{if(r=l.statSync(o),t.meta.size=r.size,t.meta.mtime=r.mtime.getTime(),this._logger?.trace({size:t.meta.size,mtime:t.meta.mtime},"Read file stats"),a){let h=l.readFileSync(o);t.meta.hash=this.getHash(h),this._logger?.trace({hash:t.meta.hash},"Calculated file hash")}}catch(h){this._logger?.error({filePath:e,error:h},"Error reading file"),this.removeEntry(e);let d=!1;return h.message.includes("ENOENT")&&(d=!0,this._logger?.debug({filePath:e},"File not found")),{key:t.key,err:h,notFound:d,meta:{}}}return i?(a===!1&&i?.mtime!==t.meta?.mtime&&(t.changed=!0,this._logger?.debug({filePath:e,oldMtime:i.mtime,newMtime:t.meta.mtime},"File changed: mtime differs")),i?.size!==t.meta?.size&&(t.changed=!0,this._logger?.debug({filePath:e,oldSize:i.size,newSize:t.meta.size},"File changed: size differs")),a&&i?.hash!==t.meta?.hash&&(t.changed=!0,this._logger?.debug({filePath:e,oldHash:i.hash,newHash:t.meta.hash},"File changed: hash differs")),this._cache.setKey(t.key,t.meta),t.changed?this._logger?.info({filePath:e},"File has changed"):this._logger?.debug({filePath:e},"File unchanged"),t):(t.changed=!0,this._cache.setKey(t.key,t.meta),this._logger?.debug({filePath:e},"File not in cache, marked as changed"),t)}normalizeEntries(e){let s=[];if(e){for(let t of e){let i=this.getFileDescriptor(t);s.push(i)}return s}let r=this.cache.keys();for(let t of r){let i=this.getFileDescriptor(t);!i.notFound&&!i.err&&s.push(i)}return s}analyzeFiles(e){let s={changedFiles:[],notFoundFiles:[],notChangedFiles:[]},r=this.normalizeEntries(e);for(let t of r)t.notFound?s.notFoundFiles.push(t.key):t.changed?s.changedFiles.push(t.key):s.notChangedFiles.push(t.key);return s}getUpdatedFiles(e){let s=[],r=this.normalizeEntries(e);for(let t of r)t.changed&&s.push(t.key);return s}getFileDescriptorsByPath(e){let s=[],r=this._cache.keys();for(let t of r)if(t.startsWith(e)){let i=this.getFileDescriptor(t);s.push(i)}return s}getAbsolutePath(e){if(this.isRelativePath(e)){let s=e.replace(/\0/g,""),r=c.resolve(this._cwd,s);if(this._restrictAccessToCwd){let t=c.normalize(r),i=c.normalize(this._cwd);if(!(t===i||t.startsWith(i+c.sep)))throw new Error(`Path traversal attempt blocked: "${e}" resolves outside of working directory "${this._cwd}"`)}return r}return e}getAbsolutePathWithCwd(e,s){if(this.isRelativePath(e)){let r=e.replace(/\0/g,""),t=c.resolve(s,r);if(this._restrictAccessToCwd){let i=c.normalize(t),o=c.normalize(s);if(!(i===o||i.startsWith(o+c.sep)))throw new Error(`Path traversal attempt blocked: "${e}" resolves outside of working directory "${s}"`)}return t}return e}renameCacheKeys(e,s){let r=this._cache.keys();for(let t of r)if(t.startsWith(e)){let i=t.replace(e,s),o=this._cache.getKey(t);this._cache.removeKey(t),this._cache.setKey(i,o)}}};export{u as FileEntryCache,p as create,y as createFromFile,g as default};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "file-entry-cache",
|
|
3
|
-
"version": "11.0.0
|
|
3
|
+
"version": "11.0.0",
|
|
4
4
|
"description": "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
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
],
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@biomejs/biome": "^2.2.5",
|
|
33
|
-
"@types/node": "^24.7.
|
|
33
|
+
"@types/node": "^24.7.2",
|
|
34
34
|
"@vitest/coverage-v8": "^3.2.4",
|
|
35
35
|
"pino": "^10.0.0",
|
|
36
36
|
"rimraf": "^6.0.1",
|