st 3.0.2 → 3.0.3
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/.claude/settings.local.json +12 -0
- package/README.md +3 -3
- package/package.json +2 -2
- package/st.js +192 -188
- package/test/no-cache.js +5 -5
package/README.md
CHANGED
|
@@ -129,7 +129,7 @@ const mount = st({
|
|
|
129
129
|
},
|
|
130
130
|
|
|
131
131
|
content: {
|
|
132
|
-
|
|
132
|
+
maxSize: 1024*1024*64, // how much memory to use on caching contents
|
|
133
133
|
maxAge: 1000 * 60 * 10, // how long to cache contents for
|
|
134
134
|
// if `false` does not set cache control headers
|
|
135
135
|
cacheControl: 'public, max-age=600' // to set an explicit cache-control
|
|
@@ -137,12 +137,12 @@ const mount = st({
|
|
|
137
137
|
},
|
|
138
138
|
|
|
139
139
|
index: { // irrelevant if not using index:true
|
|
140
|
-
|
|
140
|
+
maxSize: 1024 * 8, // how many bytes of autoindex html to cache
|
|
141
141
|
maxAge: 1000 * 60 * 10, // how long to store it for
|
|
142
142
|
},
|
|
143
143
|
|
|
144
144
|
readdir: { // irrelevant if not using index:true
|
|
145
|
-
|
|
145
|
+
maxSize: 1000, // how many dir entries to cache
|
|
146
146
|
maxAge: 1000 * 60 * 10, // how long to cache them for
|
|
147
147
|
}
|
|
148
148
|
},
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "st",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.3",
|
|
4
4
|
"description": "A module for serving static files. Does etags, caching, etc.",
|
|
5
5
|
"main": "st.js",
|
|
6
6
|
"bin": "bin/server.js",
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"
|
|
8
|
+
"lru-cache": "^11.1.0",
|
|
9
9
|
"bl": "^6.1.0",
|
|
10
10
|
"fd": "^0.0.3",
|
|
11
11
|
"mime": "^3.0.0",
|
package/st.js
CHANGED
|
@@ -9,7 +9,7 @@ try {
|
|
|
9
9
|
const zlib = require('zlib')
|
|
10
10
|
const Neg = require('negotiator')
|
|
11
11
|
const http = require('http')
|
|
12
|
-
const
|
|
12
|
+
const { LRUCache } = require('lru-cache')
|
|
13
13
|
const FD = require('fd')
|
|
14
14
|
const bl = require('bl')
|
|
15
15
|
const { STATUS_CODES } = http
|
|
@@ -17,26 +17,31 @@ const { STATUS_CODES } = http
|
|
|
17
17
|
const defaultCacheOptions = {
|
|
18
18
|
fd: {
|
|
19
19
|
max: 1000,
|
|
20
|
-
maxAge: 1000 * 60 * 60
|
|
20
|
+
maxAge: 1000 * 60 * 60,
|
|
21
|
+
ignoreFetchAbort: true
|
|
21
22
|
},
|
|
22
23
|
stat: {
|
|
23
24
|
max: 5000,
|
|
24
|
-
maxAge: 1000 * 60
|
|
25
|
+
maxAge: 1000 * 60,
|
|
26
|
+
ignoreFetchAbort: true
|
|
25
27
|
},
|
|
26
28
|
content: {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
maxAge: 1000 * 60 * 10
|
|
29
|
+
maxSize: 1024 * 1024 * 64,
|
|
30
|
+
sizeCalculation: (n) => n.length,
|
|
31
|
+
maxAge: 1000 * 60 * 10,
|
|
32
|
+
ignoreFetchAbort: true
|
|
30
33
|
},
|
|
31
34
|
index: {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
maxAge: 1000 * 60 * 10
|
|
35
|
+
maxSize: 1024 * 8,
|
|
36
|
+
sizeCalculation: (n) => n.length,
|
|
37
|
+
maxAge: 1000 * 60 * 10,
|
|
38
|
+
ignoreFetchAbort: true
|
|
35
39
|
},
|
|
36
40
|
readdir: {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
maxAge: 1000 * 60 * 10
|
|
41
|
+
maxSize: 1000,
|
|
42
|
+
sizeCalculation: (n) => Object.keys(n).length,
|
|
43
|
+
maxAge: 1000 * 60 * 10,
|
|
44
|
+
ignoreFetchAbort: true
|
|
40
45
|
}
|
|
41
46
|
}
|
|
42
47
|
|
|
@@ -44,8 +49,8 @@ const defaultCacheOptions = {
|
|
|
44
49
|
// everything is really big. kind of a kludge, but easiest way
|
|
45
50
|
// to get it done
|
|
46
51
|
const none = {
|
|
47
|
-
|
|
48
|
-
|
|
52
|
+
maxSize: 1,
|
|
53
|
+
sizeCalculation: () => Number.MAX_SAFE_INTEGER
|
|
49
54
|
}
|
|
50
55
|
|
|
51
56
|
const noCaching = {
|
|
@@ -124,11 +129,11 @@ class Mount {
|
|
|
124
129
|
// cache basically everything
|
|
125
130
|
const c = this.getCacheOptions(opt)
|
|
126
131
|
this.cache = {
|
|
127
|
-
fd:
|
|
128
|
-
stat:
|
|
129
|
-
index:
|
|
130
|
-
readdir:
|
|
131
|
-
content:
|
|
132
|
+
fd: new LRUCache(c.fd),
|
|
133
|
+
stat: new LRUCache(c.stat),
|
|
134
|
+
index: new LRUCache(c.index),
|
|
135
|
+
readdir: new LRUCache(c.readdir),
|
|
136
|
+
content: new LRUCache(c.content)
|
|
132
137
|
}
|
|
133
138
|
|
|
134
139
|
this._cacheControl =
|
|
@@ -158,7 +163,7 @@ class Mount {
|
|
|
158
163
|
const d = defaultCacheOptions
|
|
159
164
|
|
|
160
165
|
// should really only ever set max and maxAge here.
|
|
161
|
-
//
|
|
166
|
+
// fetchMethod and fd disposal is important to control.
|
|
162
167
|
const c = {
|
|
163
168
|
fd: set('fd'),
|
|
164
169
|
stat: set('stat'),
|
|
@@ -167,13 +172,14 @@ class Mount {
|
|
|
167
172
|
content: set('content')
|
|
168
173
|
}
|
|
169
174
|
|
|
170
|
-
c.fd.dispose = this.fdman.close
|
|
171
|
-
c.fd.
|
|
175
|
+
c.fd.dispose = (key) => this.fdman.close(key)
|
|
176
|
+
c.fd.fetchMethod = (key) => new Promise((resolve, reject) => this.fdman.open(key, (err, fd) => err ? reject(err) : resolve(fd)))
|
|
177
|
+
|
|
178
|
+
c.stat.fetchMethod = (key) => new Promise((resolve, reject) => this._loadStat(key, (err, fd) => err ? reject(err) : resolve(fd)))
|
|
179
|
+
c.index.fetchMethod = (key) => new Promise((resolve, reject) => this._loadIndex(key, (err, fd) => err ? reject(err) : resolve(fd)))
|
|
180
|
+
c.readdir.fetchMethod = (key) => new Promise((resolve, reject) => this._loadReaddir(key, (err, fd) => err ? reject(err) : resolve(fd)))
|
|
181
|
+
c.content.fetchMethod = (key) => new Promise((resolve, reject) => this._loadContent(key, (err, fd) => err ? reject(err) : resolve(fd)))
|
|
172
182
|
|
|
173
|
-
c.stat.load = this._loadStat.bind(this)
|
|
174
|
-
c.index.load = this._loadIndex.bind(this)
|
|
175
|
-
c.readdir.load = this._loadReaddir.bind(this)
|
|
176
|
-
c.content.load = this._loadContent.bind(this)
|
|
177
183
|
return c
|
|
178
184
|
}
|
|
179
185
|
|
|
@@ -202,7 +208,7 @@ class Mount {
|
|
|
202
208
|
u = decoded
|
|
203
209
|
}
|
|
204
210
|
} catch (e) {
|
|
205
|
-
|
|
211
|
+
// if decodeURIComponent failed, we weren't given a valid URL to begin with.
|
|
206
212
|
return false
|
|
207
213
|
}
|
|
208
214
|
|
|
@@ -216,10 +222,12 @@ class Mount {
|
|
|
216
222
|
|
|
217
223
|
// get a path from a url
|
|
218
224
|
getPath (u) {
|
|
219
|
-
//
|
|
220
|
-
//
|
|
221
|
-
|
|
222
|
-
|
|
225
|
+
// Normalize paths by removing trailing slashes
|
|
226
|
+
// This ensures consistent paths for directory content rendering
|
|
227
|
+
while (u.length > 0 && u[u.length - 1] === '/') {
|
|
228
|
+
u = u.slice(0, -1)
|
|
229
|
+
}
|
|
230
|
+
return path.join(this.path, u)
|
|
223
231
|
}
|
|
224
232
|
|
|
225
233
|
// get a url from a path
|
|
@@ -267,80 +275,82 @@ class Mount {
|
|
|
267
275
|
const p = this.getPath(req.sturl)
|
|
268
276
|
|
|
269
277
|
// now we have a path. check for the fd.
|
|
270
|
-
this.cache.fd.
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
278
|
+
this.cache.fd.fetch(p).then(
|
|
279
|
+
(fd) => {
|
|
280
|
+
// we may be about to use this, so don't let it be closed by cache purge
|
|
281
|
+
this.fdman.checkout(p, fd)
|
|
282
|
+
// a safe end() function that can be called multiple times but
|
|
283
|
+
// only perform a single checkin
|
|
284
|
+
const end = this.fdman.checkinfn(p, fd)
|
|
285
|
+
|
|
286
|
+
this.cache.stat.fetch(fd + ':' + p).then(
|
|
287
|
+
(stat) => {
|
|
288
|
+
const isDirectory = stat.isDirectory()
|
|
289
|
+
|
|
290
|
+
if (isDirectory) {
|
|
291
|
+
end() // we won't need this fd for a directory in any case
|
|
292
|
+
if (next && this.opt.passthrough === true && this._index === false) {
|
|
293
|
+
// this is done before if-modified-since and if-non-match checks so
|
|
294
|
+
// cached modified and etag values won't return 304's if we've since
|
|
295
|
+
// switched to !index. See Issue #51.
|
|
296
|
+
return next()
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
let ims = req.headers['if-modified-since']
|
|
301
|
+
if (ims) {
|
|
302
|
+
ims = new Date(ims).getTime()
|
|
303
|
+
}
|
|
304
|
+
if (ims && ims >= stat.mtime.getTime()) {
|
|
305
|
+
res.statusCode = 304
|
|
306
|
+
res.end()
|
|
307
|
+
return end()
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
const etag = getEtag(stat)
|
|
311
|
+
if (req.headers['if-none-match'] === etag) {
|
|
312
|
+
res.statusCode = 304
|
|
313
|
+
res.end()
|
|
314
|
+
return end()
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// only set headers once we're sure we'll be serving this request
|
|
318
|
+
if (!res.getHeader('cache-control') && this._cacheControl) {
|
|
319
|
+
res.setHeader('cache-control', this._cacheControl)
|
|
320
|
+
}
|
|
321
|
+
res.setHeader('last-modified', stat.mtime.toUTCString())
|
|
322
|
+
res.setHeader('etag', etag)
|
|
323
|
+
|
|
324
|
+
if (this.opt.cors) {
|
|
325
|
+
res.setHeader('Access-Control-Allow-Origin', '*')
|
|
326
|
+
res.setHeader('Access-Control-Allow-Headers',
|
|
327
|
+
'Origin, X-Requested-With, Content-Type, Accept, Range')
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
return isDirectory
|
|
331
|
+
? this.index(p, req, res)
|
|
332
|
+
: this.file(p, fd, stat, etag, req, res, end)
|
|
333
|
+
},
|
|
334
|
+
(er) => {
|
|
335
|
+
if (next && this.opt.passthrough === true && this._index === false) {
|
|
336
|
+
return next()
|
|
337
|
+
}
|
|
338
|
+
end()
|
|
339
|
+
return this.error(er, res)
|
|
340
|
+
}
|
|
341
|
+
)
|
|
342
|
+
},
|
|
343
|
+
(er) => {
|
|
344
|
+
// inability to open is some kind of error, probably 404
|
|
345
|
+
// if we're in passthrough, AND got a next function, we can
|
|
346
|
+
// fall through to that. otherwise, we already returned true,
|
|
347
|
+
// send an error.
|
|
276
348
|
if (this.opt.passthrough === true && er.code === 'ENOENT' && next) {
|
|
277
349
|
return next()
|
|
278
350
|
}
|
|
279
351
|
return this.error(er, res)
|
|
280
352
|
}
|
|
281
|
-
|
|
282
|
-
// we may be about to use this, so don't let it be closed by cache purge
|
|
283
|
-
this.fdman.checkout(p, fd)
|
|
284
|
-
// a safe end() function that can be called multiple times but
|
|
285
|
-
// only perform a single checkin
|
|
286
|
-
const end = this.fdman.checkinfn(p, fd)
|
|
287
|
-
|
|
288
|
-
this.cache.stat.get(fd + ':' + p, (er, stat) => {
|
|
289
|
-
if (er) {
|
|
290
|
-
if (next && this.opt.passthrough === true && this._index === false) {
|
|
291
|
-
return next()
|
|
292
|
-
}
|
|
293
|
-
end()
|
|
294
|
-
return this.error(er, res)
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
const isDirectory = stat.isDirectory()
|
|
298
|
-
|
|
299
|
-
if (isDirectory) {
|
|
300
|
-
end() // we won't need this fd for a directory in any case
|
|
301
|
-
if (next && this.opt.passthrough === true && this._index === false) {
|
|
302
|
-
// this is done before if-modified-since and if-non-match checks so
|
|
303
|
-
// cached modified and etag values won't return 304's if we've since
|
|
304
|
-
// switched to !index. See Issue #51.
|
|
305
|
-
return next()
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
let ims = req.headers['if-modified-since']
|
|
310
|
-
if (ims) {
|
|
311
|
-
ims = new Date(ims).getTime()
|
|
312
|
-
}
|
|
313
|
-
if (ims && ims >= stat.mtime.getTime()) {
|
|
314
|
-
res.statusCode = 304
|
|
315
|
-
res.end()
|
|
316
|
-
return end()
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
const etag = getEtag(stat)
|
|
320
|
-
if (req.headers['if-none-match'] === etag) {
|
|
321
|
-
res.statusCode = 304
|
|
322
|
-
res.end()
|
|
323
|
-
return end()
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
// only set headers once we're sure we'll be serving this request
|
|
327
|
-
if (!res.getHeader('cache-control') && this._cacheControl) {
|
|
328
|
-
res.setHeader('cache-control', this._cacheControl)
|
|
329
|
-
}
|
|
330
|
-
res.setHeader('last-modified', stat.mtime.toUTCString())
|
|
331
|
-
res.setHeader('etag', etag)
|
|
332
|
-
|
|
333
|
-
if (this.opt.cors) {
|
|
334
|
-
res.setHeader('Access-Control-Allow-Origin', '*')
|
|
335
|
-
res.setHeader('Access-Control-Allow-Headers',
|
|
336
|
-
'Origin, X-Requested-With, Content-Type, Accept, Range')
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
return isDirectory
|
|
340
|
-
? this.index(p, req, res)
|
|
341
|
-
: this.file(p, fd, stat, etag, req, res, end)
|
|
342
|
-
})
|
|
343
|
-
})
|
|
353
|
+
)
|
|
344
354
|
|
|
345
355
|
return true
|
|
346
356
|
}
|
|
@@ -385,16 +395,15 @@ class Mount {
|
|
|
385
395
|
return
|
|
386
396
|
}
|
|
387
397
|
|
|
388
|
-
this.cache.index.
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
})
|
|
398
|
+
this.cache.index.fetch(p).then(
|
|
399
|
+
(html) => {
|
|
400
|
+
res.statusCode = 200
|
|
401
|
+
res.setHeader('content-type', 'text/html')
|
|
402
|
+
res.setHeader('content-length', html.length)
|
|
403
|
+
res.end(html)
|
|
404
|
+
},
|
|
405
|
+
(er) => this.error(er, res)
|
|
406
|
+
)
|
|
398
407
|
}
|
|
399
408
|
|
|
400
409
|
file (p, fd, stat, etag, req, res, end) {
|
|
@@ -418,23 +427,19 @@ class Mount {
|
|
|
418
427
|
const key = stat.size + ':' + etag
|
|
419
428
|
const gz = this.opt.gzip !== false && getGz(p, req)
|
|
420
429
|
|
|
421
|
-
this.cache.content.get(key
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
res.setHeader('content-length', content.length)
|
|
435
|
-
res.end(content)
|
|
436
|
-
}
|
|
437
|
-
})
|
|
430
|
+
const content = this.cache.content.get(key)
|
|
431
|
+
res.statusCode = 200
|
|
432
|
+
if (this.opt.cachedHeader) {
|
|
433
|
+
res.setHeader('x-from-cache', 'true')
|
|
434
|
+
}
|
|
435
|
+
if (gz && content.gz) {
|
|
436
|
+
res.setHeader('content-encoding', 'gzip')
|
|
437
|
+
res.setHeader('content-length', content.gz.length)
|
|
438
|
+
res.end(content.gz)
|
|
439
|
+
} else {
|
|
440
|
+
res.setHeader('content-length', content.length)
|
|
441
|
+
res.end(content)
|
|
442
|
+
}
|
|
438
443
|
}
|
|
439
444
|
|
|
440
445
|
streamFile (p, fd, stat, etag, req, res, end) {
|
|
@@ -445,7 +450,7 @@ class Mount {
|
|
|
445
450
|
// gzip only if not explicitly turned off or client doesn't accept it
|
|
446
451
|
const gzOpt = this.opt.gzip !== false
|
|
447
452
|
const gz = gzOpt && getGz(p, req)
|
|
448
|
-
const cachable = this.cache.content.
|
|
453
|
+
const cachable = this.cache.content.maxSize > stat.size
|
|
449
454
|
let gzstr
|
|
450
455
|
|
|
451
456
|
// need a gzipped version for the cache, so do it regardless of what the client wants
|
|
@@ -530,57 +535,56 @@ class Mount {
|
|
|
530
535
|
'<h1>Index of ' + t + '</h1>' +
|
|
531
536
|
'<hr><pre><a href="../">../</a>\n'
|
|
532
537
|
|
|
533
|
-
this.cache.readdir.
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
538
|
+
this.cache.readdir.fetch(p).then(
|
|
539
|
+
(data) => {
|
|
540
|
+
let nameLen = 0
|
|
541
|
+
let sizeLen = 0
|
|
537
542
|
|
|
538
|
-
|
|
539
|
-
|
|
543
|
+
Object.keys(data).map((f) => {
|
|
544
|
+
const d = data[f]
|
|
540
545
|
|
|
541
|
-
|
|
542
|
-
|
|
546
|
+
let name = f
|
|
547
|
+
.replace(/"/g, '"')
|
|
548
|
+
.replace(/</g, '<')
|
|
549
|
+
.replace(/>/g, '>')
|
|
550
|
+
.replace(/'/g, ''')
|
|
543
551
|
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
.replace(
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
const namePad = new Array(8 + nameLen - line[3].length).join(' ')
|
|
575
|
-
const sizePad = new Array(8 + sizeLen - ('' + line[2]).length).join(' ')
|
|
576
|
-
str += line[0] + namePad +
|
|
577
|
-
line[1].toISOString() +
|
|
578
|
-
sizePad + line[2] + '\n'
|
|
579
|
-
})
|
|
552
|
+
if (d.size === '-') {
|
|
553
|
+
name += '/'
|
|
554
|
+
}
|
|
555
|
+
const showName = name.replace(/^(.{40}).{3,}$/, '$1..>')
|
|
556
|
+
const linkName = encodeURIComponent(name)
|
|
557
|
+
.replace(/%2e/ig, '.') // Encoded dots are dots
|
|
558
|
+
.replace(/%2f|%5c/ig, '/') // encoded slashes are /
|
|
559
|
+
.replace(/[/\\]/g, '/') // back slashes are slashes
|
|
560
|
+
|
|
561
|
+
nameLen = Math.max(nameLen, showName.length)
|
|
562
|
+
sizeLen = Math.max(sizeLen, ('' + d.size).length)
|
|
563
|
+
return ['<a href="' + linkName + '">' + showName + '</a>',
|
|
564
|
+
d.mtime, d.size, showName]
|
|
565
|
+
}).sort((a, b) => {
|
|
566
|
+
return a[2] === '-' && b[2] !== '-' // dirs first
|
|
567
|
+
? -1
|
|
568
|
+
: a[2] !== '-' && b[2] === '-'
|
|
569
|
+
? 1
|
|
570
|
+
: a[0].toLowerCase() < b[0].toLowerCase() // then alpha
|
|
571
|
+
? -1
|
|
572
|
+
: a[0].toLowerCase() > b[0].toLowerCase()
|
|
573
|
+
? 1
|
|
574
|
+
: 0
|
|
575
|
+
}).forEach((line) => {
|
|
576
|
+
const namePad = new Array(8 + nameLen - line[3].length).join(' ')
|
|
577
|
+
const sizePad = new Array(8 + sizeLen - ('' + line[2]).length).join(' ')
|
|
578
|
+
str += line[0] + namePad +
|
|
579
|
+
line[1].toISOString() +
|
|
580
|
+
sizePad + line[2] + '\n'
|
|
581
|
+
})
|
|
580
582
|
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
583
|
+
str += '</pre><hr></body></html>'
|
|
584
|
+
cb(null, Buffer.from(str))
|
|
585
|
+
},
|
|
586
|
+
(er) => cb(er)
|
|
587
|
+
)
|
|
584
588
|
}
|
|
585
589
|
|
|
586
590
|
_loadReaddir (p, cb) {
|
|
@@ -601,16 +605,16 @@ class Mount {
|
|
|
601
605
|
data = {}
|
|
602
606
|
files.forEach((file) => {
|
|
603
607
|
const pf = path.join(p, file)
|
|
604
|
-
this.cache.stat.
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
608
|
+
this.cache.stat.fetch(pf).then(
|
|
609
|
+
(stat) => {
|
|
610
|
+
if (stat.isDirectory()) {
|
|
611
|
+
stat.size = '-'
|
|
612
|
+
}
|
|
613
|
+
data[file] = stat
|
|
614
|
+
next()
|
|
615
|
+
},
|
|
616
|
+
(er) => cb(er)
|
|
617
|
+
)
|
|
614
618
|
})
|
|
615
619
|
})
|
|
616
620
|
|
|
@@ -639,11 +643,11 @@ class Mount {
|
|
|
639
643
|
}
|
|
640
644
|
}
|
|
641
645
|
|
|
642
|
-
_loadContent () {
|
|
646
|
+
_loadContent (_, cb) {
|
|
643
647
|
// this function should never be called.
|
|
644
648
|
// we check if the thing is in the cache, and if not, stream it in
|
|
645
|
-
// manually. this.cache.content.
|
|
646
|
-
|
|
649
|
+
// manually. this.cache.content.fetch() should not ever happen.
|
|
650
|
+
return cb(new Error('This should never happen'))
|
|
647
651
|
}
|
|
648
652
|
}
|
|
649
653
|
|
package/test/no-cache.js
CHANGED
|
@@ -10,10 +10,10 @@ const { test } = require('tap')
|
|
|
10
10
|
// additional tests to ensure that it's actually not caching.
|
|
11
11
|
|
|
12
12
|
test('all caches should be empty', (t) => {
|
|
13
|
-
t.same(mount._this.cache.fd.
|
|
14
|
-
t.same(mount._this.cache.stat.
|
|
15
|
-
t.same(mount._this.cache.index.
|
|
16
|
-
t.same(mount._this.cache.readdir.
|
|
17
|
-
t.same(mount._this.cache.content.
|
|
13
|
+
t.same(mount._this.cache.fd.dump(), [])
|
|
14
|
+
t.same(mount._this.cache.stat.dump(), [])
|
|
15
|
+
t.same(mount._this.cache.index.dump(), [])
|
|
16
|
+
t.same(mount._this.cache.readdir.dump(), [])
|
|
17
|
+
t.same(mount._this.cache.content.dump(), [])
|
|
18
18
|
t.end()
|
|
19
19
|
})
|