pnpm 7.9.1 → 7.9.2
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 +22 -7
- package/bin/pnpm.cjs +3 -0
- package/bin/pnpx.cjs +1 -15
- package/dist/node_modules/.modules.yaml +3 -3
- package/dist/node_modules/.pnpm/lock.yaml +76 -42
- package/dist/node_modules/@npmcli/fs/lib/common/owner-sync.js +96 -0
- package/dist/node_modules/@npmcli/fs/lib/common/owner.js +8 -4
- package/dist/node_modules/@npmcli/fs/lib/copy-file.js +3 -9
- package/dist/node_modules/@npmcli/fs/lib/fs.js +9 -3
- package/dist/node_modules/@npmcli/fs/lib/index.js +3 -1
- package/dist/node_modules/@npmcli/fs/lib/mkdir.js +19 -0
- package/dist/node_modules/@npmcli/fs/lib/mkdtemp.js +3 -8
- package/dist/node_modules/@npmcli/fs/lib/with-owner-sync.js +21 -0
- package/dist/node_modules/@npmcli/fs/lib/with-owner.js +21 -0
- package/dist/node_modules/@npmcli/fs/lib/with-temp-dir.js +4 -2
- package/dist/node_modules/@npmcli/fs/lib/write-file.js +3 -8
- package/dist/node_modules/@npmcli/fs/package.json +21 -9
- package/dist/node_modules/@npmcli/move-file/{index.js → lib/index.js} +50 -27
- package/dist/node_modules/@npmcli/move-file/package.json +20 -7
- package/dist/node_modules/@tootallnate/once/LICENSE +21 -0
- package/dist/node_modules/@tootallnate/once/dist/index.js +21 -36
- package/dist/node_modules/@tootallnate/once/dist/index.js.map +1 -1
- package/dist/node_modules/@tootallnate/once/dist/overloaded-parameters.js +3 -0
- package/dist/node_modules/@tootallnate/once/dist/overloaded-parameters.js.map +1 -0
- package/dist/node_modules/@tootallnate/once/dist/types.js +3 -0
- package/dist/node_modules/@tootallnate/once/dist/types.js.map +1 -0
- package/dist/node_modules/@tootallnate/once/package.json +22 -15
- package/dist/node_modules/cacache/lib/content/read.js +99 -102
- package/dist/node_modules/cacache/lib/content/rm.js +9 -8
- package/dist/node_modules/cacache/lib/content/write.js +67 -67
- package/dist/node_modules/cacache/lib/entry-index.js +128 -118
- package/dist/node_modules/cacache/{get.js → lib/get.js} +88 -100
- package/dist/node_modules/cacache/{index.js → lib/index.js} +5 -6
- package/dist/node_modules/cacache/lib/memoization.js +10 -11
- package/dist/node_modules/cacache/{put.js → lib/put.js} +23 -26
- package/dist/node_modules/cacache/{rm.js → lib/rm.js} +3 -3
- package/dist/node_modules/cacache/lib/util/fix-owner.js +41 -38
- package/dist/node_modules/cacache/lib/util/move-file.js +36 -47
- package/dist/node_modules/cacache/lib/util/tmp.js +5 -7
- package/dist/node_modules/cacache/lib/verify.js +160 -190
- package/dist/node_modules/cacache/node_modules/brace-expansion/.github/FUNDING.yml +2 -0
- package/dist/node_modules/cacache/node_modules/brace-expansion/LICENSE +21 -0
- package/dist/node_modules/cacache/node_modules/brace-expansion/index.js +203 -0
- package/dist/node_modules/cacache/node_modules/brace-expansion/package.json +46 -0
- package/dist/node_modules/cacache/node_modules/glob/LICENSE +15 -0
- package/dist/node_modules/cacache/node_modules/glob/common.js +240 -0
- package/dist/node_modules/cacache/node_modules/glob/glob.js +790 -0
- package/dist/node_modules/cacache/node_modules/glob/package.json +55 -0
- package/dist/node_modules/cacache/node_modules/glob/sync.js +486 -0
- package/dist/node_modules/cacache/node_modules/minimatch/LICENSE +15 -0
- package/dist/node_modules/cacache/node_modules/minimatch/lib/path.js +4 -0
- package/dist/node_modules/cacache/node_modules/minimatch/minimatch.js +906 -0
- package/dist/node_modules/cacache/node_modules/minimatch/package.json +32 -0
- package/dist/node_modules/cacache/package.json +34 -30
- package/dist/node_modules/http-proxy-agent/dist/agent.js +3 -3
- package/dist/node_modules/http-proxy-agent/dist/agent.js.map +1 -1
- package/dist/node_modules/http-proxy-agent/package.json +4 -4
- package/dist/node_modules/lru-cache/LICENSE +1 -1
- package/dist/node_modules/lru-cache/index.js +921 -247
- package/dist/node_modules/lru-cache/package.json +49 -9
- package/dist/node_modules/make-fetch-happen/LICENSE +1 -1
- package/dist/node_modules/make-fetch-happen/lib/agent.js +34 -14
- package/dist/node_modules/make-fetch-happen/lib/cache/entry.js +90 -106
- package/dist/node_modules/make-fetch-happen/lib/cache/errors.js +1 -0
- package/dist/node_modules/make-fetch-happen/lib/cache/index.js +10 -6
- package/dist/node_modules/make-fetch-happen/lib/cache/policy.js +21 -21
- package/dist/node_modules/make-fetch-happen/lib/dns.js +49 -0
- package/dist/node_modules/make-fetch-happen/lib/fetch.js +40 -22
- package/dist/node_modules/make-fetch-happen/lib/index.js +4 -3
- package/dist/node_modules/make-fetch-happen/lib/options.js +17 -9
- package/dist/node_modules/make-fetch-happen/lib/pipeline.js +41 -0
- package/dist/node_modules/make-fetch-happen/lib/remote.js +28 -9
- package/dist/node_modules/make-fetch-happen/package.json +36 -33
- package/dist/node_modules/minipass-fetch/lib/blob.js +4 -4
- package/dist/node_modules/minipass-fetch/lib/body.js +63 -49
- package/dist/node_modules/minipass-fetch/lib/fetch-error.js +2 -1
- package/dist/node_modules/minipass-fetch/lib/headers.js +38 -21
- package/dist/node_modules/minipass-fetch/lib/index.js +130 -106
- package/dist/node_modules/minipass-fetch/lib/request.js +46 -28
- package/dist/node_modules/minipass-fetch/lib/response.js +3 -2
- package/dist/node_modules/minipass-fetch/package.json +27 -14
- package/dist/node_modules/node-gyp/.github/workflows/release-please.yml +1 -1
- package/dist/node_modules/node-gyp/.github/workflows/tests.yml +16 -9
- package/dist/node_modules/node-gyp/.github/workflows/visual-studio.yml +16 -8
- package/dist/node_modules/node-gyp/lib/build.js +7 -0
- package/dist/node_modules/node-gyp/lib/configure.js +26 -1
- package/dist/node_modules/node-gyp/lib/create-config-gypi.js +2 -1
- package/dist/node_modules/node-gyp/lib/find-visualstudio.js +9 -8
- package/dist/node_modules/node-gyp/lib/node-gyp.js +4 -0
- package/dist/node_modules/node-gyp/package.json +4 -4
- package/dist/node_modules/semver/node_modules/lru-cache/LICENSE +15 -0
- package/dist/node_modules/semver/node_modules/lru-cache/index.js +334 -0
- package/dist/node_modules/semver/node_modules/lru-cache/package.json +34 -0
- package/dist/node_modules/socks-proxy-agent/dist/index.js +3 -3
- package/dist/node_modules/socks-proxy-agent/dist/index.js.map +1 -1
- package/dist/node_modules/socks-proxy-agent/package.json +2 -2
- package/dist/node_modules/ssri/{index.js → lib/index.js} +78 -24
- package/dist/node_modules/ssri/package.json +27 -16
- package/dist/pnpm.cjs +67042 -65886
- package/package.json +6 -6
- package/dist/node_modules/@npmcli/fs/lib/common/file-url-to-path/index.js +0 -17
- package/dist/node_modules/@npmcli/fs/lib/common/file-url-to-path/polyfill.js +0 -121
- package/dist/node_modules/@npmcli/fs/lib/mkdir/index.js +0 -32
- package/dist/node_modules/@npmcli/fs/lib/mkdir/polyfill.js +0 -81
- package/dist/node_modules/cacache/lib/util/disposer.js +0 -30
- package/dist/node_modules/cacache/ls.js +0 -6
- package/dist/node_modules/cacache/verify.js +0 -3
- package/dist/node_modules/minipass-fetch/index.js +0 -1
|
@@ -1,34 +1,74 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lru-cache",
|
|
3
3
|
"description": "A cache object that deletes the least-recently-used items.",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "7.14.0",
|
|
5
5
|
"author": "Isaac Z. Schlueter <i@izs.me>",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"mru",
|
|
8
8
|
"lru",
|
|
9
9
|
"cache"
|
|
10
10
|
],
|
|
11
|
+
"sideEffects": false,
|
|
11
12
|
"scripts": {
|
|
13
|
+
"build": "",
|
|
14
|
+
"size": "size-limit",
|
|
12
15
|
"test": "tap",
|
|
13
16
|
"snap": "tap",
|
|
14
17
|
"preversion": "npm test",
|
|
15
18
|
"postversion": "npm publish",
|
|
16
|
-
"prepublishOnly": "git push origin --follow-tags"
|
|
19
|
+
"prepublishOnly": "git push origin --follow-tags",
|
|
20
|
+
"format": "prettier --write ."
|
|
17
21
|
},
|
|
18
22
|
"main": "index.js",
|
|
19
23
|
"repository": "git://github.com/isaacs/node-lru-cache.git",
|
|
20
24
|
"devDependencies": {
|
|
25
|
+
"@size-limit/preset-small-lib": "^7.0.8",
|
|
26
|
+
"@types/node": "^17.0.31",
|
|
27
|
+
"@types/tap": "^15.0.6",
|
|
21
28
|
"benchmark": "^2.1.4",
|
|
22
|
-
"
|
|
29
|
+
"c8": "^7.11.2",
|
|
30
|
+
"clock-mock": "^1.0.6",
|
|
31
|
+
"eslint-config-prettier": "^8.5.0",
|
|
32
|
+
"prettier": "^2.6.2",
|
|
33
|
+
"size-limit": "^7.0.8",
|
|
34
|
+
"tap": "^16.0.1",
|
|
35
|
+
"ts-node": "^10.7.0",
|
|
36
|
+
"tslib": "^2.4.0",
|
|
37
|
+
"typescript": "^4.6.4"
|
|
23
38
|
},
|
|
24
39
|
"license": "ISC",
|
|
25
|
-
"dependencies": {
|
|
26
|
-
"yallist": "^4.0.0"
|
|
27
|
-
},
|
|
28
40
|
"files": [
|
|
29
|
-
"index.js"
|
|
41
|
+
"index.js",
|
|
42
|
+
"index.d.ts"
|
|
30
43
|
],
|
|
31
44
|
"engines": {
|
|
32
|
-
"node": ">=
|
|
33
|
-
}
|
|
45
|
+
"node": ">=12"
|
|
46
|
+
},
|
|
47
|
+
"prettier": {
|
|
48
|
+
"semi": false,
|
|
49
|
+
"printWidth": 70,
|
|
50
|
+
"tabWidth": 2,
|
|
51
|
+
"useTabs": false,
|
|
52
|
+
"singleQuote": true,
|
|
53
|
+
"jsxSingleQuote": false,
|
|
54
|
+
"bracketSameLine": true,
|
|
55
|
+
"arrowParens": "avoid",
|
|
56
|
+
"endOfLine": "lf"
|
|
57
|
+
},
|
|
58
|
+
"tap": {
|
|
59
|
+
"nyc-arg": [
|
|
60
|
+
"--include=index.js"
|
|
61
|
+
],
|
|
62
|
+
"node-arg": [
|
|
63
|
+
"--expose-gc",
|
|
64
|
+
"--require",
|
|
65
|
+
"ts-node/register"
|
|
66
|
+
],
|
|
67
|
+
"ts": false
|
|
68
|
+
},
|
|
69
|
+
"size-limit": [
|
|
70
|
+
{
|
|
71
|
+
"path": "./index.js"
|
|
72
|
+
}
|
|
73
|
+
]
|
|
34
74
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
const LRU = require('lru-cache')
|
|
3
3
|
const url = require('url')
|
|
4
4
|
const isLambda = require('is-lambda')
|
|
5
|
+
const dns = require('./dns.js')
|
|
5
6
|
|
|
6
7
|
const AGENT_CACHE = new LRU({ max: 50 })
|
|
7
8
|
const HttpAgent = require('agentkeepalive')
|
|
@@ -50,11 +51,13 @@ function getAgent (uri, opts) {
|
|
|
50
51
|
: isHttps ? require('https').globalAgent
|
|
51
52
|
: require('http').globalAgent
|
|
52
53
|
|
|
53
|
-
if (isLambda && !pxuri)
|
|
54
|
+
if (isLambda && !pxuri) {
|
|
54
55
|
return lambdaAgent
|
|
56
|
+
}
|
|
55
57
|
|
|
56
|
-
if (AGENT_CACHE.peek(key))
|
|
58
|
+
if (AGENT_CACHE.peek(key)) {
|
|
57
59
|
return AGENT_CACHE.get(key)
|
|
60
|
+
}
|
|
58
61
|
|
|
59
62
|
if (pxuri) {
|
|
60
63
|
const pxopts = isLambda ? {
|
|
@@ -74,10 +77,14 @@ function getAgent (uri, opts) {
|
|
|
74
77
|
localAddress: opts.localAddress,
|
|
75
78
|
rejectUnauthorized: opts.rejectUnauthorized,
|
|
76
79
|
timeout: agentTimeout,
|
|
80
|
+
freeSocketTimeout: 15000,
|
|
81
|
+
lookup: dns.getLookup(opts.dns),
|
|
77
82
|
}) : new HttpAgent({
|
|
78
83
|
maxSockets: agentMaxSockets,
|
|
79
84
|
localAddress: opts.localAddress,
|
|
80
85
|
timeout: agentTimeout,
|
|
86
|
+
freeSocketTimeout: 15000,
|
|
87
|
+
lookup: dns.getLookup(opts.dns),
|
|
81
88
|
})
|
|
82
89
|
AGENT_CACHE.set(key, agent)
|
|
83
90
|
return agent
|
|
@@ -86,16 +93,19 @@ function getAgent (uri, opts) {
|
|
|
86
93
|
function checkNoProxy (uri, opts) {
|
|
87
94
|
const host = new url.URL(uri).hostname.split('.').reverse()
|
|
88
95
|
let noproxy = (opts.noProxy || getProcessEnv('no_proxy'))
|
|
89
|
-
if (typeof noproxy === 'string')
|
|
90
|
-
noproxy = noproxy.split(
|
|
96
|
+
if (typeof noproxy === 'string') {
|
|
97
|
+
noproxy = noproxy.split(',').map(n => n.trim())
|
|
98
|
+
}
|
|
91
99
|
|
|
92
100
|
return noproxy && noproxy.some(no => {
|
|
93
101
|
const noParts = no.split('.').filter(x => x).reverse()
|
|
94
|
-
if (!noParts.length)
|
|
102
|
+
if (!noParts.length) {
|
|
95
103
|
return false
|
|
104
|
+
}
|
|
96
105
|
for (let i = 0; i < noParts.length; i++) {
|
|
97
|
-
if (host[i] !== noParts[i])
|
|
106
|
+
if (host[i] !== noParts[i]) {
|
|
98
107
|
return false
|
|
108
|
+
}
|
|
99
109
|
}
|
|
100
110
|
return true
|
|
101
111
|
})
|
|
@@ -104,8 +114,9 @@ function checkNoProxy (uri, opts) {
|
|
|
104
114
|
module.exports.getProcessEnv = getProcessEnv
|
|
105
115
|
|
|
106
116
|
function getProcessEnv (env) {
|
|
107
|
-
if (!env)
|
|
117
|
+
if (!env) {
|
|
108
118
|
return
|
|
119
|
+
}
|
|
109
120
|
|
|
110
121
|
let value
|
|
111
122
|
|
|
@@ -114,8 +125,9 @@ function getProcessEnv (env) {
|
|
|
114
125
|
value = process.env[e] ||
|
|
115
126
|
process.env[e.toUpperCase()] ||
|
|
116
127
|
process.env[e.toLowerCase()]
|
|
117
|
-
if (typeof value !== 'undefined')
|
|
128
|
+
if (typeof value !== 'undefined') {
|
|
118
129
|
break
|
|
130
|
+
}
|
|
119
131
|
}
|
|
120
132
|
}
|
|
121
133
|
|
|
@@ -141,8 +153,9 @@ function getProxyUri (uri, opts) {
|
|
|
141
153
|
protocol === 'http:' &&
|
|
142
154
|
getProcessEnv(['https_proxy', 'http_proxy', 'proxy'])
|
|
143
155
|
)
|
|
144
|
-
if (!proxy)
|
|
156
|
+
if (!proxy) {
|
|
145
157
|
return null
|
|
158
|
+
}
|
|
146
159
|
|
|
147
160
|
const parsedProxy = (typeof proxy === 'string') ? new url.URL(proxy) : proxy
|
|
148
161
|
|
|
@@ -158,9 +171,11 @@ const getPath = u => u.pathname + u.search + u.hash
|
|
|
158
171
|
|
|
159
172
|
const HttpProxyAgent = require('http-proxy-agent')
|
|
160
173
|
const HttpsProxyAgent = require('https-proxy-agent')
|
|
161
|
-
const SocksProxyAgent = require('socks-proxy-agent')
|
|
174
|
+
const { SocksProxyAgent } = require('socks-proxy-agent')
|
|
162
175
|
module.exports.getProxy = getProxy
|
|
163
176
|
function getProxy (proxyUrl, opts, isHttps) {
|
|
177
|
+
// our current proxy agents do not support an overridden dns lookup method, so will not
|
|
178
|
+
// benefit from the dns cache
|
|
164
179
|
const popts = {
|
|
165
180
|
host: proxyUrl.hostname,
|
|
166
181
|
port: proxyUrl.port,
|
|
@@ -177,16 +192,21 @@ function getProxy (proxyUrl, opts, isHttps) {
|
|
|
177
192
|
}
|
|
178
193
|
|
|
179
194
|
if (proxyUrl.protocol === 'http:' || proxyUrl.protocol === 'https:') {
|
|
180
|
-
if (!isHttps)
|
|
195
|
+
if (!isHttps) {
|
|
181
196
|
return new HttpProxyAgent(popts)
|
|
182
|
-
else
|
|
197
|
+
} else {
|
|
183
198
|
return new HttpsProxyAgent(popts)
|
|
184
|
-
|
|
199
|
+
}
|
|
200
|
+
} else if (proxyUrl.protocol.startsWith('socks')) {
|
|
201
|
+
// socks-proxy-agent uses hostname not host
|
|
202
|
+
popts.hostname = popts.host
|
|
203
|
+
delete popts.host
|
|
185
204
|
return new SocksProxyAgent(popts)
|
|
186
|
-
else {
|
|
205
|
+
} else {
|
|
187
206
|
throw Object.assign(
|
|
188
207
|
new Error(`unsupported proxy protocol: '${proxyUrl.protocol}'`),
|
|
189
208
|
{
|
|
209
|
+
code: 'EUNSUPPORTEDPROXY',
|
|
190
210
|
url: proxyUrl.href,
|
|
191
211
|
}
|
|
192
212
|
)
|
|
@@ -1,21 +1,16 @@
|
|
|
1
1
|
const { Request, Response } = require('minipass-fetch')
|
|
2
2
|
const Minipass = require('minipass')
|
|
3
|
-
const MinipassCollect = require('minipass-collect')
|
|
4
3
|
const MinipassFlush = require('minipass-flush')
|
|
5
|
-
const MinipassPipeline = require('minipass-pipeline')
|
|
6
4
|
const cacache = require('cacache')
|
|
7
5
|
const url = require('url')
|
|
8
6
|
|
|
7
|
+
const CachingMinipassPipeline = require('../pipeline.js')
|
|
9
8
|
const CachePolicy = require('./policy.js')
|
|
10
9
|
const cacheKey = require('./key.js')
|
|
11
10
|
const remote = require('../remote.js')
|
|
12
11
|
|
|
13
12
|
const hasOwnProperty = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop)
|
|
14
13
|
|
|
15
|
-
// maximum amount of data we will buffer into memory
|
|
16
|
-
// if we'll exceed this, we switch to streaming
|
|
17
|
-
const MAX_MEM_SIZE = 5 * 1024 * 1024 // 5MB
|
|
18
|
-
|
|
19
14
|
// allow list for request headers that will be written to the cache index
|
|
20
15
|
// note: we will also store any request headers
|
|
21
16
|
// that are named in a response's vary header
|
|
@@ -40,6 +35,7 @@ const KEEP_RESPONSE_HEADERS = [
|
|
|
40
35
|
'etag',
|
|
41
36
|
'expires',
|
|
42
37
|
'last-modified',
|
|
38
|
+
'link',
|
|
43
39
|
'location',
|
|
44
40
|
'pragma',
|
|
45
41
|
'vary',
|
|
@@ -52,23 +48,31 @@ const getMetadata = (request, response, options) => {
|
|
|
52
48
|
url: request.url,
|
|
53
49
|
reqHeaders: {},
|
|
54
50
|
resHeaders: {},
|
|
51
|
+
|
|
52
|
+
// options on which we must match the request and vary the response
|
|
53
|
+
options: {
|
|
54
|
+
compress: options.compress != null ? options.compress : request.compress,
|
|
55
|
+
},
|
|
55
56
|
}
|
|
56
57
|
|
|
57
58
|
// only save the status if it's not a 200 or 304
|
|
58
|
-
if (response.status !== 200 && response.status !== 304)
|
|
59
|
+
if (response.status !== 200 && response.status !== 304) {
|
|
59
60
|
metadata.status = response.status
|
|
61
|
+
}
|
|
60
62
|
|
|
61
63
|
for (const name of KEEP_REQUEST_HEADERS) {
|
|
62
|
-
if (request.headers.has(name))
|
|
64
|
+
if (request.headers.has(name)) {
|
|
63
65
|
metadata.reqHeaders[name] = request.headers.get(name)
|
|
66
|
+
}
|
|
64
67
|
}
|
|
65
68
|
|
|
66
69
|
// if the request's host header differs from the host in the url
|
|
67
70
|
// we need to keep it, otherwise it's just noise and we ignore it
|
|
68
71
|
const host = request.headers.get('host')
|
|
69
72
|
const parsedUrl = new url.URL(request.url)
|
|
70
|
-
if (host && parsedUrl.host !== host)
|
|
73
|
+
if (host && parsedUrl.host !== host) {
|
|
71
74
|
metadata.reqHeaders.host = host
|
|
75
|
+
}
|
|
72
76
|
|
|
73
77
|
// if the response has a vary header, make sure
|
|
74
78
|
// we store the relevant request headers too
|
|
@@ -82,25 +86,17 @@ const getMetadata = (request, response, options) => {
|
|
|
82
86
|
// copy any other request headers that will vary the response
|
|
83
87
|
const varyHeaders = vary.trim().toLowerCase().split(/\s*,\s*/)
|
|
84
88
|
for (const name of varyHeaders) {
|
|
85
|
-
|
|
86
|
-
if (name !== 'accept-encoding' && request.headers.has(name))
|
|
89
|
+
if (request.headers.has(name)) {
|
|
87
90
|
metadata.reqHeaders[name] = request.headers.get(name)
|
|
91
|
+
}
|
|
88
92
|
}
|
|
89
93
|
}
|
|
90
94
|
}
|
|
91
95
|
|
|
92
96
|
for (const name of KEEP_RESPONSE_HEADERS) {
|
|
93
|
-
if (response.headers.has(name))
|
|
97
|
+
if (response.headers.has(name)) {
|
|
94
98
|
metadata.resHeaders[name] = response.headers.get(name)
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
// we only store accept-encoding and content-encoding if the user
|
|
98
|
-
// has disabled automatic compression and decompression in minipass-fetch
|
|
99
|
-
// since if it's enabled (the default) then the content will have
|
|
100
|
-
// already been decompressed making the header a lie
|
|
101
|
-
if (options.compress === false) {
|
|
102
|
-
metadata.reqHeaders['accept-encoding'] = request.headers.get('accept-encoding')
|
|
103
|
-
metadata.resHeaders['content-encoding'] = response.headers.get('content-encoding')
|
|
99
|
+
}
|
|
104
100
|
}
|
|
105
101
|
|
|
106
102
|
return metadata
|
|
@@ -121,8 +117,9 @@ class CacheEntry {
|
|
|
121
117
|
// entry timestamp to determine staleness because cacache will update it
|
|
122
118
|
// when it verifies its data
|
|
123
119
|
this.entry.metadata.time = this.entry.metadata.time || this.entry.time
|
|
124
|
-
} else
|
|
120
|
+
} else {
|
|
125
121
|
this.key = cacheKey(request)
|
|
122
|
+
}
|
|
126
123
|
|
|
127
124
|
this.options = options
|
|
128
125
|
|
|
@@ -143,9 +140,17 @@ class CacheEntry {
|
|
|
143
140
|
return entryA.policy.satisfies(entryB.request)
|
|
144
141
|
}, {
|
|
145
142
|
validateEntry: (entry) => {
|
|
143
|
+
// clean out entries with a buggy content-encoding value
|
|
144
|
+
if (entry.metadata &&
|
|
145
|
+
entry.metadata.resHeaders &&
|
|
146
|
+
entry.metadata.resHeaders['content-encoding'] === null) {
|
|
147
|
+
return false
|
|
148
|
+
}
|
|
149
|
+
|
|
146
150
|
// if an integrity is null, it needs to have a status specified
|
|
147
|
-
if (entry.integrity === null)
|
|
151
|
+
if (entry.integrity === null) {
|
|
148
152
|
return !!(entry.metadata && entry.metadata.status)
|
|
153
|
+
}
|
|
149
154
|
|
|
150
155
|
return true
|
|
151
156
|
},
|
|
@@ -158,8 +163,9 @@ class CacheEntry {
|
|
|
158
163
|
// a cache mode of 'reload' means to behave as though we have no cache
|
|
159
164
|
// on the way to the network. return undefined to allow cacheFetch to
|
|
160
165
|
// create a brand new request no matter what.
|
|
161
|
-
if (options.cache === 'reload')
|
|
166
|
+
if (options.cache === 'reload') {
|
|
162
167
|
return
|
|
168
|
+
}
|
|
163
169
|
|
|
164
170
|
// find the specific entry that satisfies the request
|
|
165
171
|
let match
|
|
@@ -194,6 +200,7 @@ class CacheEntry {
|
|
|
194
200
|
this[_request] = new Request(this.entry.metadata.url, {
|
|
195
201
|
method: 'GET',
|
|
196
202
|
headers: this.entry.metadata.reqHeaders,
|
|
203
|
+
...this.entry.metadata.options,
|
|
197
204
|
})
|
|
198
205
|
}
|
|
199
206
|
|
|
@@ -235,19 +242,22 @@ class CacheEntry {
|
|
|
235
242
|
// if we got a status other than 200, 301, or 308,
|
|
236
243
|
// or the CachePolicy forbid storage, append the
|
|
237
244
|
// cache status header and return it untouched
|
|
238
|
-
if (
|
|
245
|
+
if (
|
|
246
|
+
this.request.method !== 'GET' ||
|
|
247
|
+
![200, 301, 308].includes(this.response.status) ||
|
|
248
|
+
!this.policy.storable()
|
|
249
|
+
) {
|
|
239
250
|
this.response.headers.set('x-local-cache-status', 'skip')
|
|
240
251
|
return this.response
|
|
241
252
|
}
|
|
242
253
|
|
|
243
254
|
const size = this.response.headers.get('content-length')
|
|
244
|
-
const fitsInMemory = !!size && Number(size) < MAX_MEM_SIZE
|
|
245
|
-
const shouldBuffer = this.options.memoize !== false && fitsInMemory
|
|
246
255
|
const cacheOpts = {
|
|
247
256
|
algorithms: this.options.algorithms,
|
|
248
257
|
metadata: getMetadata(this.request, this.response, this.options),
|
|
249
258
|
size,
|
|
250
|
-
|
|
259
|
+
integrity: this.options.integrity,
|
|
260
|
+
integrityEmitter: this.response.body.hasIntegrityEmitter && this.response.body,
|
|
251
261
|
}
|
|
252
262
|
|
|
253
263
|
let body = null
|
|
@@ -260,53 +270,35 @@ class CacheEntry {
|
|
|
260
270
|
cacheWriteReject = reject
|
|
261
271
|
})
|
|
262
272
|
|
|
263
|
-
body = new
|
|
273
|
+
body = new CachingMinipassPipeline({ events: ['integrity', 'size'] }, new MinipassFlush({
|
|
264
274
|
flush () {
|
|
265
275
|
return cacheWritePromise
|
|
266
276
|
},
|
|
267
277
|
}))
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
// if it does not fit in memory, create a tee stream and use
|
|
286
|
-
// that to pipe to both the cache and the user simultaneously
|
|
287
|
-
onResume = () => {
|
|
288
|
-
const tee = new Minipass()
|
|
289
|
-
const cacheStream = cacache.put.stream(this.options.cachePath, this.key, cacheOpts)
|
|
290
|
-
abortStream = cacheStream
|
|
291
|
-
tee.pipe(cacheStream)
|
|
292
|
-
// TODO if the cache write fails, log a warning but return the response anyway
|
|
293
|
-
cacheStream.promise().then(cacheWriteResolve, cacheWriteReject)
|
|
294
|
-
body.unshift(tee)
|
|
295
|
-
body.unshift(this.response.body)
|
|
296
|
-
}
|
|
278
|
+
// this is always true since if we aren't reusing the one from the remote fetch, we
|
|
279
|
+
// are using the one from cacache
|
|
280
|
+
body.hasIntegrityEmitter = true
|
|
281
|
+
|
|
282
|
+
const onResume = () => {
|
|
283
|
+
const tee = new Minipass()
|
|
284
|
+
const cacheStream = cacache.put.stream(this.options.cachePath, this.key, cacheOpts)
|
|
285
|
+
// re-emit the integrity and size events on our new response body so they can be reused
|
|
286
|
+
cacheStream.on('integrity', i => body.emit('integrity', i))
|
|
287
|
+
cacheStream.on('size', s => body.emit('size', s))
|
|
288
|
+
// stick a flag on here so downstream users will know if they can expect integrity events
|
|
289
|
+
tee.pipe(cacheStream)
|
|
290
|
+
// TODO if the cache write fails, log a warning but return the response anyway
|
|
291
|
+
// eslint-disable-next-line promise/catch-or-return
|
|
292
|
+
cacheStream.promise().then(cacheWriteResolve, cacheWriteReject)
|
|
293
|
+
body.unshift(tee)
|
|
294
|
+
body.unshift(this.response.body)
|
|
297
295
|
}
|
|
298
296
|
|
|
299
297
|
body.once('resume', onResume)
|
|
300
298
|
body.once('end', () => body.removeListener('resume', onResume))
|
|
301
|
-
|
|
302
|
-
// the abortStream will either be a MinipassCollect if we buffer
|
|
303
|
-
// or a cacache write stream, either way be sure to listen for
|
|
304
|
-
// errors from the actual response and avoid writing data that we
|
|
305
|
-
// know to be invalid to the cache
|
|
306
|
-
abortStream.destroy(err)
|
|
307
|
-
})
|
|
308
|
-
} else
|
|
299
|
+
} else {
|
|
309
300
|
await cacache.index.insert(this.options.cachePath, this.key, null, cacheOpts)
|
|
301
|
+
}
|
|
310
302
|
|
|
311
303
|
// note: we do not set the x-local-cache-hash header because we do not know
|
|
312
304
|
// the hash value until after the write to the cache completes, which doesn't
|
|
@@ -314,7 +306,7 @@ class CacheEntry {
|
|
|
314
306
|
// the header anyway
|
|
315
307
|
this.response.headers.set('x-local-cache', encodeURIComponent(this.options.cachePath))
|
|
316
308
|
this.response.headers.set('x-local-cache-key', encodeURIComponent(this.key))
|
|
317
|
-
this.response.headers.set('x-local-cache-mode',
|
|
309
|
+
this.response.headers.set('x-local-cache-mode', 'stream')
|
|
318
310
|
this.response.headers.set('x-local-cache-status', status)
|
|
319
311
|
this.response.headers.set('x-local-cache-time', new Date().toISOString())
|
|
320
312
|
const newResponse = new Response(body, {
|
|
@@ -329,9 +321,6 @@ class CacheEntry {
|
|
|
329
321
|
// use the cached data to create a response and return it
|
|
330
322
|
async respond (method, options, status) {
|
|
331
323
|
let response
|
|
332
|
-
const size = Number(this.response.headers.get('content-length'))
|
|
333
|
-
const fitsInMemory = !!size && size < MAX_MEM_SIZE
|
|
334
|
-
const shouldBuffer = this.options.memoize !== false && fitsInMemory
|
|
335
324
|
if (method === 'HEAD' || [301, 308].includes(this.response.status)) {
|
|
336
325
|
// if the request is a HEAD, or the response is a redirect,
|
|
337
326
|
// then the metadata in the entry already includes everything
|
|
@@ -341,54 +330,44 @@ class CacheEntry {
|
|
|
341
330
|
// we're responding with a full cached response, so create a body
|
|
342
331
|
// that reads from cacache and attach it to a new Response
|
|
343
332
|
const body = new Minipass()
|
|
344
|
-
const
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
if (err.code === 'ENOENT' || err.code === 'EINTEGRITY')
|
|
356
|
-
await CacheEntry.invalidate(this.request, this.options)
|
|
357
|
-
body.emit('error', err)
|
|
333
|
+
const headers = { ...this.policy.responseHeaders() }
|
|
334
|
+
const onResume = () => {
|
|
335
|
+
const cacheStream = cacache.get.stream.byDigest(
|
|
336
|
+
this.options.cachePath, this.entry.integrity, { memoize: this.options.memoize }
|
|
337
|
+
)
|
|
338
|
+
cacheStream.on('error', async (err) => {
|
|
339
|
+
cacheStream.pause()
|
|
340
|
+
if (err.code === 'EINTEGRITY') {
|
|
341
|
+
await cacache.rm.content(
|
|
342
|
+
this.options.cachePath, this.entry.integrity, { memoize: this.options.memoize }
|
|
343
|
+
)
|
|
358
344
|
}
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
cacheStream.
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
body.emit('error', err)
|
|
370
|
-
cacheStream.resume()
|
|
371
|
-
})
|
|
372
|
-
cacheStream.pipe(body)
|
|
373
|
-
}
|
|
345
|
+
if (err.code === 'ENOENT' || err.code === 'EINTEGRITY') {
|
|
346
|
+
await CacheEntry.invalidate(this.request, this.options)
|
|
347
|
+
}
|
|
348
|
+
body.emit('error', err)
|
|
349
|
+
cacheStream.resume()
|
|
350
|
+
})
|
|
351
|
+
// emit the integrity and size events based on our metadata so we're consistent
|
|
352
|
+
body.emit('integrity', this.entry.integrity)
|
|
353
|
+
body.emit('size', Number(headers['content-length']))
|
|
354
|
+
cacheStream.pipe(body)
|
|
374
355
|
}
|
|
375
356
|
|
|
376
357
|
body.once('resume', onResume)
|
|
377
|
-
body.once('end',
|
|
358
|
+
body.once('end', () => body.removeListener('resume', onResume))
|
|
378
359
|
response = new Response(body, {
|
|
379
360
|
url: this.entry.metadata.url,
|
|
380
361
|
counter: options.counter,
|
|
381
362
|
status: 200,
|
|
382
|
-
headers
|
|
383
|
-
...this.policy.responseHeaders(),
|
|
384
|
-
},
|
|
363
|
+
headers,
|
|
385
364
|
})
|
|
386
365
|
}
|
|
387
366
|
|
|
388
367
|
response.headers.set('x-local-cache', encodeURIComponent(this.options.cachePath))
|
|
389
368
|
response.headers.set('x-local-cache-hash', encodeURIComponent(this.entry.integrity))
|
|
390
369
|
response.headers.set('x-local-cache-key', encodeURIComponent(this.key))
|
|
391
|
-
response.headers.set('x-local-cache-mode',
|
|
370
|
+
response.headers.set('x-local-cache-mode', 'stream')
|
|
392
371
|
response.headers.set('x-local-cache-status', status)
|
|
393
372
|
response.headers.set('x-local-cache-time', new Date(this.entry.metadata.time).toUTCString())
|
|
394
373
|
return response
|
|
@@ -415,8 +394,9 @@ class CacheEntry {
|
|
|
415
394
|
// if the network fetch fails, return the stale
|
|
416
395
|
// cached response unless it has a cache-control
|
|
417
396
|
// of 'must-revalidate'
|
|
418
|
-
if (!this.policy.mustRevalidate)
|
|
397
|
+
if (!this.policy.mustRevalidate) {
|
|
419
398
|
return this.respond(request.method, options, 'stale')
|
|
399
|
+
}
|
|
420
400
|
|
|
421
401
|
throw err
|
|
422
402
|
}
|
|
@@ -429,8 +409,12 @@ class CacheEntry {
|
|
|
429
409
|
// in the old cache entry to the new one, if the new metadata does not already
|
|
430
410
|
// include that header
|
|
431
411
|
for (const name of KEEP_RESPONSE_HEADERS) {
|
|
432
|
-
if (
|
|
412
|
+
if (
|
|
413
|
+
!hasOwnProperty(metadata.resHeaders, name) &&
|
|
414
|
+
hasOwnProperty(this.entry.metadata.resHeaders, name)
|
|
415
|
+
) {
|
|
433
416
|
metadata.resHeaders[name] = this.entry.metadata.resHeaders[name]
|
|
417
|
+
}
|
|
434
418
|
}
|
|
435
419
|
|
|
436
420
|
try {
|
|
@@ -8,19 +8,21 @@ const cacheFetch = async (request, options) => {
|
|
|
8
8
|
const entry = await CacheEntry.find(request, options)
|
|
9
9
|
if (!entry) {
|
|
10
10
|
// no cached result, if the cache mode is 'only-if-cached' that's a failure
|
|
11
|
-
if (options.cache === 'only-if-cached')
|
|
11
|
+
if (options.cache === 'only-if-cached') {
|
|
12
12
|
throw new NotCachedError(request.url)
|
|
13
|
+
}
|
|
13
14
|
|
|
14
15
|
// otherwise, we make a request, store it and return it
|
|
15
16
|
const response = await remote(request, options)
|
|
16
|
-
const
|
|
17
|
-
return
|
|
17
|
+
const newEntry = new CacheEntry({ request, response, options })
|
|
18
|
+
return newEntry.store('miss')
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
// we have a cached response that satisfies this request, however if the cache
|
|
21
22
|
// mode is 'no-cache' then we send the revalidation request no matter what
|
|
22
|
-
if (options.cache === 'no-cache')
|
|
23
|
+
if (options.cache === 'no-cache') {
|
|
23
24
|
return entry.revalidate(request, options)
|
|
25
|
+
}
|
|
24
26
|
|
|
25
27
|
// if the cached entry is not stale, or if the cache mode is 'force-cache' or
|
|
26
28
|
// 'only-if-cached' we can respond with the cached entry. set the status
|
|
@@ -28,16 +30,18 @@ const cacheFetch = async (request, options) => {
|
|
|
28
30
|
const _needsRevalidation = entry.policy.needsRevalidation(request)
|
|
29
31
|
if (options.cache === 'force-cache' ||
|
|
30
32
|
options.cache === 'only-if-cached' ||
|
|
31
|
-
!_needsRevalidation)
|
|
33
|
+
!_needsRevalidation) {
|
|
32
34
|
return entry.respond(request.method, options, _needsRevalidation ? 'stale' : 'hit')
|
|
35
|
+
}
|
|
33
36
|
|
|
34
37
|
// if we got here, the cache entry is stale so revalidate it
|
|
35
38
|
return entry.revalidate(request, options)
|
|
36
39
|
}
|
|
37
40
|
|
|
38
41
|
cacheFetch.invalidate = async (request, options) => {
|
|
39
|
-
if (!options.cachePath)
|
|
42
|
+
if (!options.cachePath) {
|
|
40
43
|
return
|
|
44
|
+
}
|
|
41
45
|
|
|
42
46
|
return CacheEntry.invalidate(request, options)
|
|
43
47
|
}
|