11const fs = require ( "graceful-fs" ) ;
22const path = require ( "path" ) ;
3- const { create : FlatCacheCreate } = require ( "flat-cache" ) ;
43const { createHash } = require ( "crypto" ) ;
5- const debugUtil = require ( "debug " ) ;
4+ const { DateCompare } = require ( "@11ty/eleventy-utils " ) ;
65
6+ const FileCache = require ( "./FileCache.js" ) ;
77const Sources = require ( "./Sources.js" ) ;
8- const DirectoryManager = require ( "./DirectoryManager.js" ) ;
98
9+ const debugUtil = require ( "debug" ) ;
1010const debug = debugUtil ( "Eleventy:Fetch" ) ;
11- const debugAssets = debugUtil ( "Eleventy:Assets" ) ;
1211
1312class AssetCache {
1413 #source;
@@ -18,7 +17,6 @@ class AssetCache {
1817 #cacheDirectory;
1918 #cacheLocationDirty = false ;
2019 #directoryManager;
21- #rawContents = { }
2220
2321 constructor ( source , cacheDirectory , options = { } ) {
2422 if ( ! Sources . isValidSource ( source ) ) {
@@ -173,10 +171,12 @@ class AssetCache {
173171
174172 get cache ( ) {
175173 if ( ! this . #cache || this . #cacheLocationDirty) {
176- let cache = FlatCacheCreate ( {
177- cacheId : this . cacheFilename ,
178- cacheDir : this . rootDir ,
174+ let cache = new FileCache ( this . cacheFilename , {
175+ dir : this . rootDir ,
176+ source : this . source ,
179177 } ) ;
178+ cache . setDryRun ( this . options . dryRun ) ;
179+ cache . setDirectoryManager ( this . #directoryManager) ;
180180
181181 this . #cache = cache ;
182182 this . #cacheLocationDirty = false ;
@@ -185,181 +185,58 @@ class AssetCache {
185185 }
186186
187187 getDurationMs ( duration = "0s" ) {
188- let durationUnits = duration . slice ( - 1 ) ;
189- let durationMultiplier ;
190- if ( durationUnits === "s" ) {
191- durationMultiplier = 1 ;
192- } else if ( durationUnits === "m" ) {
193- durationMultiplier = 60 ;
194- } else if ( durationUnits === "h" ) {
195- durationMultiplier = 60 * 60 ;
196- } else if ( durationUnits === "d" ) {
197- durationMultiplier = 60 * 60 * 24 ;
198- } else if ( durationUnits === "w" ) {
199- durationMultiplier = 60 * 60 * 24 * 7 ;
200- } else if ( durationUnits === "y" ) {
201- durationMultiplier = 60 * 60 * 24 * 365 ;
202- }
203-
204- let durationValue = parseInt ( duration . slice ( 0 , duration . length - 1 ) , 10 ) ;
205- return durationValue * durationMultiplier * 1000 ;
206- }
207-
208- getCachedContentsPath ( type = "buffer" ) {
209- if ( type === "xml" ) {
210- type = "text" ;
211- } else if ( type === "parsed-xml" ) {
212- type = "json" ;
213- }
214-
215- return `${ this . cachePath } .${ type } ` ;
188+ return DateCompare . getDurationMs ( duration ) ;
216189 }
217190
218191 setDirectoryManager ( manager ) {
219192 this . #directoryManager = manager ;
220193 }
221194
222- ensureDir ( ) {
223- if ( this . options . dryRun ) {
224- return ;
225- }
226-
227- if ( ! this . #directoryManager) {
228- // standalone fallback (for tests)
229- this . #directoryManager = new DirectoryManager ( ) ;
230- }
231-
232- this . #directoryManager. create ( this . cacheDirectory ) ;
233- }
234-
235195 async save ( contents , type = "buffer" , metadata = { } ) {
236196 if ( ! contents ) {
237197 throw new Error ( "save(contents) expects contents (was falsy)" ) ;
238198 }
239199
240- this . cache . set ( this . hash , {
241- cachedAt : Date . now ( ) ,
242- type : type ,
243- metadata,
244- } ) ;
245-
246- let contentPath = this . getCachedContentsPath ( type ) ;
247-
248- if ( type === "json" || type === "parsed-xml" ) {
249- contents = JSON . stringify ( contents ) ;
250- }
251-
252- this . #rawContents[ type ] = contents ;
253-
254- if ( this . options . dryRun ) {
255- debug ( `Dry run writing ${ contentPath } ` ) ;
256- return ;
257- }
258-
259- this . ensureDir ( ) ;
260-
261- debugAssets ( "[11ty/eleventy-fetch] Writing %o from %o" , contentPath , this . source ) ;
262-
263- // the contents must exist before the cache metadata are saved below
264- fs . writeFileSync ( contentPath , contents ) ;
265- debug ( `Writing ${ contentPath } ` ) ;
200+ this . cache . set ( type , contents , metadata ) ;
266201
202+ // Dry-run handled downstream
267203 this . cache . save ( ) ;
268204 }
269205
270- async #getCachedContents( type ) {
271- let contentPath = this . getCachedContentsPath ( type ) ;
272-
273- debug ( `Fetching from cache ${ contentPath } ` ) ;
274-
275- if ( this . source ) {
276- debugAssets ( "[11ty/eleventy-fetch] Reading via %o" , this . source ) ;
277- } else {
278- debugAssets ( "[11ty/eleventy-fetch] Reading %o" , contentPath ) ;
279- }
280-
281- if ( type === "json" || type === "parsed-xml" ) {
282- return require ( contentPath ) ;
283- }
284-
285- return fs . readFileSync ( contentPath , type !== "buffer" ? "utf8" : null ) ;
286- }
287-
288- async getCachedContents ( type ) {
289- if ( ! this . #rawContents[ type ] ) {
290- this . #rawContents[ type ] = this . #getCachedContents( type ) ;
291- }
292-
293- // already saved on this instance in-memory
294- return this . #rawContents[ type ] ;
295- }
296-
297- _backwardsCompatibilityGetCachedValue ( type ) {
298- if ( type === "json" ) {
299- return this . cachedObject . contents ;
300- } else if ( type === "text" ) {
301- return this . cachedObject . contents . toString ( ) ;
302- }
303-
304- // buffer
305- return Buffer . from ( this . cachedObject . contents ) ;
206+ getCachedContents ( ) {
207+ return this . cache . getContents ( ) ;
306208 }
307209
308- async getCachedValue ( ) {
309- let type = this . cachedObject . type ;
310-
311- // backwards compat with old caches
312- if ( this . cachedObject . contents ) {
313- return this . _backwardsCompatibilityGetCachedValue ( type ) ;
314- }
315-
210+ getCachedValue ( ) {
316211 if ( this . options . returnType === "response" ) {
317212 return {
318213 ...this . cachedObject . metadata ?. response ,
319- body : await this . getCachedContents ( type ) ,
214+ body : this . getCachedContents ( ) ,
320215 cache : "hit" ,
321216 }
322217 }
323218
324- // promise
325- return this . getCachedContents ( type ) ;
219+ return this . getCachedContents ( ) ;
326220 }
327221
328222 getCachedTimestamp ( ) {
329223 return this . cachedObject ?. cachedAt ;
330224 }
331225
332226 isCacheValid ( duration = this . duration ) {
333- if ( ! this . cachedObject ) {
334- // not cached
227+ if ( ! this . cachedObject || ! this . cachedObject ?. cachedAt ) {
335228 return false ;
336229 }
337230
338- // in the cache and no duration
339- if ( ! duration || duration === "*" ) {
340- // no duration specified (plugin default is 1d, but if this is falsy assume infinite)
341- // "*" is infinite duration
342- return true ;
343- }
344-
345- debug ( "Cache check for: %o %o (duration: %o)" , this . hash , this . source , duration ) ;
346- debug ( "Cache object: %o" , this . cachedObject ) ;
347-
348- let compareDuration = this . getDurationMs ( duration ) ;
349- let expiration = this . cachedObject . cachedAt + compareDuration ;
350- let expirationRelative = Math . abs ( Date . now ( ) - expiration ) ;
351-
352- if ( expiration > Date . now ( ) ) {
353- debug ( "Cache okay, expires in %o s (%o)" , expirationRelative / 1000 , new Date ( expiration ) ) ;
354- return true ;
231+ if ( DateCompare . isTimestampWithinDuration ( this . cachedObject ?. cachedAt , duration ) ) {
232+ return this . cache . hasContents ( ) ; // check file system to make files haven’t been purged.
355233 }
356234
357- debug ( "Cache expired %o s ago (%o)" , expirationRelative / 1000 , new Date ( expiration ) ) ;
358235 return false ;
359236 }
360237
361238 get cachedObject ( ) {
362- return this . cache . get ( this . hash ) ;
239+ return this . cache . get ( ) ;
363240 }
364241
365242 // Deprecated
@@ -382,17 +259,18 @@ class AssetCache {
382259 }
383260
384261 // for testing
385- hasCacheFiles ( ) {
386- return fs . existsSync ( this . cachePath ) || fs . existsSync ( this . getCachedContentsPath ( ) ) ;
262+ hasAnyCacheFiles ( ) {
263+ for ( let p of this . cache . getFilePaths ( ) ) {
264+ if ( fs . existsSync ( p ) ) {
265+ return true ;
266+ }
267+ }
268+ return false ;
387269 }
388270
389271 // for testing
390272 async destroy ( ) {
391- let paths = [ ] ;
392- paths . push ( this . cachePath ) ;
393- paths . push ( this . getCachedContentsPath ( "json" ) ) ;
394- paths . push ( this . getCachedContentsPath ( "text" ) ) ;
395- paths . push ( this . getCachedContentsPath ( "buffer" ) ) ;
273+ let paths = this . cache . getFilePaths ( ) ;
396274
397275 await Promise . all ( paths . map ( path => {
398276 if ( fs . existsSync ( path ) ) {
0 commit comments