schnee effeckt und fehler Korektur
This commit is contained in:
21
node_modules/cacheable-request/LICENSE
generated
vendored
Normal file
21
node_modules/cacheable-request/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 Luke Childs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
190
node_modules/cacheable-request/README.md
generated
vendored
Normal file
190
node_modules/cacheable-request/README.md
generated
vendored
Normal file
@@ -0,0 +1,190 @@
|
||||
# cacheable-request
|
||||
|
||||
> Wrap native HTTP requests with RFC compliant cache support
|
||||
|
||||
[](https://travis-ci.org/lukechilds/cacheable-request)
|
||||
[](https://coveralls.io/github/lukechilds/cacheable-request?branch=master)
|
||||
[](https://www.npmjs.com/package/cacheable-request)
|
||||
[](https://www.npmjs.com/package/cacheable-request)
|
||||
|
||||
[RFC 7234](http://httpwg.org/specs/rfc7234.html) compliant HTTP caching for native Node.js HTTP/HTTPS requests. Caching works out of the box in memory or is easily pluggable with a wide range of storage adapters.
|
||||
|
||||
**Note:** This is a low level wrapper around the core HTTP modules, it's not a high level request library.
|
||||
|
||||
## Features
|
||||
|
||||
- Only stores cacheable responses as defined by RFC 7234
|
||||
- Fresh cache entries are served directly from cache
|
||||
- Stale cache entries are revalidated with `If-None-Match`/`If-Modified-Since` headers
|
||||
- 304 responses from revalidation requests use cached body
|
||||
- Updates `Age` header on cached responses
|
||||
- Can completely bypass cache on a per request basis
|
||||
- In memory cache by default
|
||||
- Official support for Redis, MongoDB, SQLite, PostgreSQL and MySQL storage adapters
|
||||
- Easily plug in your own or third-party storage adapters
|
||||
- If DB connection fails, cache is automatically bypassed ([disabled by default](#optsautomaticfailover))
|
||||
- Adds cache support to any existing HTTP code with minimal changes
|
||||
- Uses [http-cache-semantics](https://github.com/pornel/http-cache-semantics) internally for HTTP RFC 7234 compliance
|
||||
|
||||
## Install
|
||||
|
||||
```shell
|
||||
npm install --save cacheable-request
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const http = require('http');
|
||||
const CacheableRequest = require('cacheable-request');
|
||||
|
||||
// Then instead of
|
||||
const req = http.request('http://example.com', cb);
|
||||
req.end();
|
||||
|
||||
// You can do
|
||||
const cacheableRequest = new CacheableRequest(http.request);
|
||||
const cacheReq = cacheableRequest('http://example.com', cb);
|
||||
cacheReq.on('request', req => req.end());
|
||||
// Future requests to 'example.com' will be returned from cache if still valid
|
||||
|
||||
// You pass in any other http.request API compatible method to be wrapped with cache support:
|
||||
const cacheableRequest = new CacheableRequest(https.request);
|
||||
const cacheableRequest = new CacheableRequest(electron.net);
|
||||
```
|
||||
|
||||
## Storage Adapters
|
||||
|
||||
`cacheable-request` uses [Keyv](https://github.com/lukechilds/keyv) to support a wide range of storage adapters.
|
||||
|
||||
For example, to use Redis as a cache backend, you just need to install the official Redis Keyv storage adapter:
|
||||
|
||||
```
|
||||
npm install --save @keyv/redis
|
||||
```
|
||||
|
||||
And then you can pass `CacheableRequest` your connection string:
|
||||
|
||||
```js
|
||||
const cacheableRequest = new CacheableRequest(http.request, 'redis://user:pass@localhost:6379');
|
||||
```
|
||||
|
||||
[View all official Keyv storage adapters.](https://github.com/lukechilds/keyv#official-storage-adapters)
|
||||
|
||||
Keyv also supports anything that follows the Map API so it's easy to write your own storage adapter or use a third-party solution.
|
||||
|
||||
e.g The following are all valid storage adapters
|
||||
|
||||
```js
|
||||
const storageAdapter = new Map();
|
||||
// or
|
||||
const storageAdapter = require('./my-storage-adapter');
|
||||
// or
|
||||
const QuickLRU = require('quick-lru');
|
||||
const storageAdapter = new QuickLRU({ maxSize: 1000 });
|
||||
|
||||
const cacheableRequest = new CacheableRequest(http.request, storageAdapter);
|
||||
```
|
||||
|
||||
View the [Keyv docs](https://github.com/lukechilds/keyv) for more information on how to use storage adapters.
|
||||
|
||||
## API
|
||||
|
||||
### new cacheableRequest(request, [storageAdapter])
|
||||
|
||||
Returns the provided request function wrapped with cache support.
|
||||
|
||||
#### request
|
||||
|
||||
Type: `function`
|
||||
|
||||
Request function to wrap with cache support. Should be [`http.request`](https://nodejs.org/api/http.html#http_http_request_options_callback) or a similar API compatible request function.
|
||||
|
||||
#### storageAdapter
|
||||
|
||||
Type: `Keyv storage adapter`<br>
|
||||
Default: `new Map()`
|
||||
|
||||
A [Keyv](https://github.com/lukechilds/keyv) storage adapter instance, or connection string if using with an official Keyv storage adapter.
|
||||
|
||||
### Instance
|
||||
|
||||
#### cacheableRequest(opts, [cb])
|
||||
|
||||
Returns an event emitter.
|
||||
|
||||
##### opts
|
||||
|
||||
Type: `object`, `string`
|
||||
|
||||
Any of the default request functions options plus:
|
||||
|
||||
###### opts.cache
|
||||
|
||||
Type: `boolean`<br>
|
||||
Default: `true`
|
||||
|
||||
If the cache should be used. Setting this to false will completely bypass the cache for the current request.
|
||||
|
||||
###### opts.strictTtl
|
||||
|
||||
Type: `boolean`<br>
|
||||
Default: `false`
|
||||
|
||||
If set to `false`, after a cached resource's TTL expires it is kept in the cache and will be revalidated on the next request with `If-None-Match`/`If-Modified-Since` headers.
|
||||
|
||||
If set to `true` once a cached resource has expired it is deleted and will have to be re-requested.
|
||||
|
||||
###### opts.automaticFailover
|
||||
|
||||
Type: `boolean`<br>
|
||||
Default: `false`
|
||||
|
||||
When set to `true`, if the DB connection fails we will automatically fallback to a network request. DB errors will still be emitted to notify you of the problem even though the request callback may succeed.
|
||||
|
||||
##### cb
|
||||
|
||||
Type: `function`
|
||||
|
||||
The callback function which will receive the response as an argument.
|
||||
|
||||
The response can be either a [Node.js HTTP response stream](https://nodejs.org/api/http.html#http_class_http_incomingmessage) or a [responselike object](https://github.com/lukechilds/responselike). The response will also have a `fromCache` property set with a boolean value.
|
||||
|
||||
##### .on('request', request)
|
||||
|
||||
`request` event to get the request object of the request.
|
||||
|
||||
**Note:** This event will only fire if an HTTP request is actually made, not when a response is retrieved from cache. However, you should always handle the `request` event to end the request and handle any potential request errors.
|
||||
|
||||
##### .on('response', response)
|
||||
|
||||
`response` event to get the response object from the HTTP request or cache.
|
||||
|
||||
##### .on('error', error)
|
||||
|
||||
`error` event emitted in case of an error with the cache.
|
||||
|
||||
Errors emitted here will be an instance of `CacheableRequest.RequestError` or `CacheableRequest.CacheError`. You will only ever receive a `RequestError` if the request function throws (normally caused by invalid user input). Normal request errors should be handled inside the `request` event.
|
||||
|
||||
To properly handle all error scenarios you should use the following pattern:
|
||||
|
||||
```js
|
||||
cacheableRequest('example.com', cb)
|
||||
.on('error', err => {
|
||||
if (err instanceof CacheableRequest.CacheError) {
|
||||
handleCacheError(err); // Cache error
|
||||
} else if (err instanceof CacheableRequest.RequestError) {
|
||||
handleRequestError(err); // Request function thrown
|
||||
}
|
||||
})
|
||||
.on('request', req => {
|
||||
req.on('error', handleRequestError); // Request error emitted
|
||||
req.end();
|
||||
});
|
||||
```
|
||||
|
||||
**Note:** Database connection errors are emitted here, however `cacheable-request` will attempt to re-request the resource and bypass the cache on a connection error. Therefore a database connection error doesn't necessarily mean the request won't be fulfilled.
|
||||
|
||||
## License
|
||||
|
||||
MIT © Luke Childs
|
||||
51
node_modules/cacheable-request/node_modules/get-stream/buffer-stream.js
generated
vendored
Normal file
51
node_modules/cacheable-request/node_modules/get-stream/buffer-stream.js
generated
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
'use strict';
|
||||
const PassThrough = require('stream').PassThrough;
|
||||
|
||||
module.exports = opts => {
|
||||
opts = Object.assign({}, opts);
|
||||
|
||||
const array = opts.array;
|
||||
let encoding = opts.encoding;
|
||||
const buffer = encoding === 'buffer';
|
||||
let objectMode = false;
|
||||
|
||||
if (array) {
|
||||
objectMode = !(encoding || buffer);
|
||||
} else {
|
||||
encoding = encoding || 'utf8';
|
||||
}
|
||||
|
||||
if (buffer) {
|
||||
encoding = null;
|
||||
}
|
||||
|
||||
let len = 0;
|
||||
const ret = [];
|
||||
const stream = new PassThrough({objectMode});
|
||||
|
||||
if (encoding) {
|
||||
stream.setEncoding(encoding);
|
||||
}
|
||||
|
||||
stream.on('data', chunk => {
|
||||
ret.push(chunk);
|
||||
|
||||
if (objectMode) {
|
||||
len = ret.length;
|
||||
} else {
|
||||
len += chunk.length;
|
||||
}
|
||||
});
|
||||
|
||||
stream.getBufferedValue = () => {
|
||||
if (array) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return buffer ? Buffer.concat(ret, len) : ret.join('');
|
||||
};
|
||||
|
||||
stream.getBufferedLength = () => len;
|
||||
|
||||
return stream;
|
||||
};
|
||||
51
node_modules/cacheable-request/node_modules/get-stream/index.js
generated
vendored
Normal file
51
node_modules/cacheable-request/node_modules/get-stream/index.js
generated
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
'use strict';
|
||||
const bufferStream = require('./buffer-stream');
|
||||
|
||||
function getStream(inputStream, opts) {
|
||||
if (!inputStream) {
|
||||
return Promise.reject(new Error('Expected a stream'));
|
||||
}
|
||||
|
||||
opts = Object.assign({maxBuffer: Infinity}, opts);
|
||||
|
||||
const maxBuffer = opts.maxBuffer;
|
||||
let stream;
|
||||
let clean;
|
||||
|
||||
const p = new Promise((resolve, reject) => {
|
||||
const error = err => {
|
||||
if (err) { // null check
|
||||
err.bufferedData = stream.getBufferedValue();
|
||||
}
|
||||
|
||||
reject(err);
|
||||
};
|
||||
|
||||
stream = bufferStream(opts);
|
||||
inputStream.once('error', error);
|
||||
inputStream.pipe(stream);
|
||||
|
||||
stream.on('data', () => {
|
||||
if (stream.getBufferedLength() > maxBuffer) {
|
||||
reject(new Error('maxBuffer exceeded'));
|
||||
}
|
||||
});
|
||||
stream.once('error', error);
|
||||
stream.on('end', resolve);
|
||||
|
||||
clean = () => {
|
||||
// some streams doesn't implement the `stream.Readable` interface correctly
|
||||
if (inputStream.unpipe) {
|
||||
inputStream.unpipe(stream);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
p.then(clean, clean);
|
||||
|
||||
return p.then(() => stream.getBufferedValue());
|
||||
}
|
||||
|
||||
module.exports = getStream;
|
||||
module.exports.buffer = (stream, opts) => getStream(stream, Object.assign({}, opts, {encoding: 'buffer'}));
|
||||
module.exports.array = (stream, opts) => getStream(stream, Object.assign({}, opts, {array: true}));
|
||||
21
node_modules/cacheable-request/node_modules/get-stream/license
generated
vendored
Normal file
21
node_modules/cacheable-request/node_modules/get-stream/license
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
48
node_modules/cacheable-request/node_modules/get-stream/package.json
generated
vendored
Normal file
48
node_modules/cacheable-request/node_modules/get-stream/package.json
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"name": "get-stream",
|
||||
"version": "3.0.0",
|
||||
"description": "Get a stream as a string, buffer, or array",
|
||||
"license": "MIT",
|
||||
"repository": "sindresorhus/get-stream",
|
||||
"author": {
|
||||
"name": "Sindre Sorhus",
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"url": "sindresorhus.com"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "xo && ava"
|
||||
},
|
||||
"files": [
|
||||
"index.js",
|
||||
"buffer-stream.js"
|
||||
],
|
||||
"keywords": [
|
||||
"get",
|
||||
"stream",
|
||||
"promise",
|
||||
"concat",
|
||||
"string",
|
||||
"str",
|
||||
"text",
|
||||
"buffer",
|
||||
"read",
|
||||
"data",
|
||||
"consume",
|
||||
"readable",
|
||||
"readablestream",
|
||||
"array",
|
||||
"object",
|
||||
"obj"
|
||||
],
|
||||
"devDependencies": {
|
||||
"ava": "*",
|
||||
"into-stream": "^3.0.0",
|
||||
"xo": "*"
|
||||
},
|
||||
"xo": {
|
||||
"esnext": true
|
||||
}
|
||||
}
|
||||
117
node_modules/cacheable-request/node_modules/get-stream/readme.md
generated
vendored
Normal file
117
node_modules/cacheable-request/node_modules/get-stream/readme.md
generated
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
# get-stream [](https://travis-ci.org/sindresorhus/get-stream)
|
||||
|
||||
> Get a stream as a string, buffer, or array
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install --save get-stream
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const fs = require('fs');
|
||||
const getStream = require('get-stream');
|
||||
const stream = fs.createReadStream('unicorn.txt');
|
||||
|
||||
getStream(stream).then(str => {
|
||||
console.log(str);
|
||||
/*
|
||||
,,))))))));,
|
||||
__)))))))))))))),
|
||||
\|/ -\(((((''''((((((((.
|
||||
-*-==//////(('' . `)))))),
|
||||
/|\ ))| o ;-. '((((( ,(,
|
||||
( `| / ) ;))))' ,_))^;(~
|
||||
| | | ,))((((_ _____------~~~-. %,;(;(>';'~
|
||||
o_); ; )))(((` ~---~ `:: \ %%~~)(v;(`('~
|
||||
; ''''```` `: `:::|\,__,%% );`'; ~
|
||||
| _ ) / `:|`----' `-'
|
||||
______/\/~ | / /
|
||||
/~;;.____/;;' / ___--,-( `;;;/
|
||||
/ // _;______;'------~~~~~ /;;/\ /
|
||||
// | | / ; \;;,\
|
||||
(<_ | ; /',/-----' _>
|
||||
\_| ||_ //~;~~~~~~~~~
|
||||
`\_| (,~~
|
||||
\~\
|
||||
~~
|
||||
*/
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
## API
|
||||
|
||||
The methods returns a promise that resolves when the `end` event fires on the stream, indicating that there is no more data to be read. The stream is switched to flowing mode.
|
||||
|
||||
### getStream(stream, [options])
|
||||
|
||||
Get the `stream` as a string.
|
||||
|
||||
#### options
|
||||
|
||||
##### encoding
|
||||
|
||||
Type: `string`<br>
|
||||
Default: `utf8`
|
||||
|
||||
[Encoding](https://nodejs.org/api/buffer.html#buffer_buffer) of the incoming stream.
|
||||
|
||||
##### maxBuffer
|
||||
|
||||
Type: `number`<br>
|
||||
Default: `Infinity`
|
||||
|
||||
Maximum length of the returned string. If it exceeds this value before the stream ends, the promise will be rejected.
|
||||
|
||||
### getStream.buffer(stream, [options])
|
||||
|
||||
Get the `stream` as a buffer.
|
||||
|
||||
It honors the `maxBuffer` option as above, but it refers to byte length rather than string length.
|
||||
|
||||
### getStream.array(stream, [options])
|
||||
|
||||
Get the `stream` as an array of values.
|
||||
|
||||
It honors both the `maxBuffer` and `encoding` options. The behavior changes slightly based on the encoding chosen:
|
||||
|
||||
- When `encoding` is unset, it assumes an [object mode stream](https://nodesource.com/blog/understanding-object-streams/) and collects values emitted from `stream` unmodified. In this case `maxBuffer` refers to the number of items in the array (not the sum of their sizes).
|
||||
|
||||
- When `encoding` is set to `buffer`, it collects an array of buffers. `maxBuffer` refers to the summed byte lengths of every buffer in the array.
|
||||
|
||||
- When `encoding` is set to anything else, it collects an array of strings. `maxBuffer` refers to the summed character lengths of every string in the array.
|
||||
|
||||
|
||||
## Errors
|
||||
|
||||
If the input stream emits an `error` event, the promise will be rejected with the error. The buffered data will be attached to the `bufferedData` property of the error.
|
||||
|
||||
```js
|
||||
getStream(streamThatErrorsAtTheEnd('unicorn'))
|
||||
.catch(err => {
|
||||
console.log(err.bufferedData);
|
||||
//=> 'unicorn'
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
## FAQ
|
||||
|
||||
### How is this different from [`concat-stream`](https://github.com/maxogden/concat-stream)?
|
||||
|
||||
This module accepts a stream instead of being one and returns a promise instead of using a callback. The API is simpler and it only supports returning a string, buffer, or array. It doesn't have a fragile type inference. You explicitly choose what you want. And it doesn't depend on the huge `readable-stream` package.
|
||||
|
||||
|
||||
## Related
|
||||
|
||||
- [get-stdin](https://github.com/sindresorhus/get-stdin) - Get stdin as a string or buffer
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Sindre Sorhus](https://sindresorhus.com)
|
||||
11
node_modules/cacheable-request/node_modules/lowercase-keys/index.js
generated
vendored
Normal file
11
node_modules/cacheable-request/node_modules/lowercase-keys/index.js
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
'use strict';
|
||||
module.exports = function (obj) {
|
||||
var ret = {};
|
||||
var keys = Object.keys(Object(obj));
|
||||
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
ret[keys[i].toLowerCase()] = obj[keys[i]];
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
35
node_modules/cacheable-request/node_modules/lowercase-keys/package.json
generated
vendored
Normal file
35
node_modules/cacheable-request/node_modules/lowercase-keys/package.json
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "lowercase-keys",
|
||||
"version": "1.0.0",
|
||||
"description": "Lowercase the keys of an object",
|
||||
"license": "MIT",
|
||||
"repository": "sindresorhus/lowercase-keys",
|
||||
"author": {
|
||||
"name": "Sindre Sorhus",
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"url": "sindresorhus.com"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "node test.js"
|
||||
},
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"keywords": [
|
||||
"object",
|
||||
"assign",
|
||||
"extend",
|
||||
"properties",
|
||||
"lowercase",
|
||||
"lower-case",
|
||||
"case",
|
||||
"keys",
|
||||
"key"
|
||||
],
|
||||
"devDependencies": {
|
||||
"ava": "0.0.4"
|
||||
}
|
||||
}
|
||||
33
node_modules/cacheable-request/node_modules/lowercase-keys/readme.md
generated
vendored
Normal file
33
node_modules/cacheable-request/node_modules/lowercase-keys/readme.md
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
# lowercase-keys [](https://travis-ci.org/sindresorhus/lowercase-keys)
|
||||
|
||||
> Lowercase the keys of an object
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install --save lowercase-keys
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
var lowercaseKeys = require('lowercase-keys');
|
||||
|
||||
lowercaseKeys({FOO: true, bAr: false});
|
||||
//=> {foo: true, bar: false}
|
||||
```
|
||||
|
||||
|
||||
## API
|
||||
|
||||
### lowercaseKeys(object)
|
||||
|
||||
Lowercases the keys and returns a new object.
|
||||
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Sindre Sorhus](http://sindresorhus.com)
|
||||
57
node_modules/cacheable-request/package.json
generated
vendored
Normal file
57
node_modules/cacheable-request/package.json
generated
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"name": "cacheable-request",
|
||||
"version": "2.1.4",
|
||||
"description": "Wrap native HTTP requests with RFC compliant cache support",
|
||||
"main": "src/index.js",
|
||||
"scripts": {
|
||||
"test": "xo && nyc ava",
|
||||
"coverage": "nyc report --reporter=text-lcov | coveralls"
|
||||
},
|
||||
"xo": {
|
||||
"extends": "xo-lukechilds"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/lukechilds/cacheable-request.git"
|
||||
},
|
||||
"keywords": [
|
||||
"HTTP",
|
||||
"HTTPS",
|
||||
"cache",
|
||||
"caching",
|
||||
"layer",
|
||||
"cacheable",
|
||||
"RFC 7234",
|
||||
"RFC",
|
||||
"7234",
|
||||
"compliant"
|
||||
],
|
||||
"author": "Luke Childs <lukechilds123@gmail.com> (http://lukechilds.co.uk)",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/lukechilds/cacheable-request/issues"
|
||||
},
|
||||
"homepage": "https://github.com/lukechilds/cacheable-request",
|
||||
"dependencies": {
|
||||
"clone-response": "1.0.2",
|
||||
"get-stream": "3.0.0",
|
||||
"http-cache-semantics": "3.8.1",
|
||||
"keyv": "3.0.0",
|
||||
"lowercase-keys": "1.0.0",
|
||||
"normalize-url": "2.0.1",
|
||||
"responselike": "1.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@keyv/sqlite": "^1.2.6",
|
||||
"ava": "^0.24.0",
|
||||
"coveralls": "^3.0.0",
|
||||
"create-test-server": "^2.0.0",
|
||||
"delay": "^2.0.0",
|
||||
"eslint-config-xo-lukechilds": "^1.0.0",
|
||||
"nyc": "^11.0.2",
|
||||
"pify": "^3.0.0",
|
||||
"sqlite3": "^3.1.9",
|
||||
"this": "^1.0.2",
|
||||
"xo": "^0.19.0"
|
||||
}
|
||||
}
|
||||
155
node_modules/cacheable-request/src/index.js
generated
vendored
Normal file
155
node_modules/cacheable-request/src/index.js
generated
vendored
Normal file
@@ -0,0 +1,155 @@
|
||||
'use strict';
|
||||
|
||||
const EventEmitter = require('events');
|
||||
const urlLib = require('url');
|
||||
const normalizeUrl = require('normalize-url');
|
||||
const getStream = require('get-stream');
|
||||
const CachePolicy = require('http-cache-semantics');
|
||||
const Response = require('responselike');
|
||||
const lowercaseKeys = require('lowercase-keys');
|
||||
const cloneResponse = require('clone-response');
|
||||
const Keyv = require('keyv');
|
||||
|
||||
class CacheableRequest {
|
||||
constructor(request, cacheAdapter) {
|
||||
if (typeof request !== 'function') {
|
||||
throw new TypeError('Parameter `request` must be a function');
|
||||
}
|
||||
|
||||
this.cache = new Keyv({
|
||||
uri: typeof cacheAdapter === 'string' && cacheAdapter,
|
||||
store: typeof cacheAdapter !== 'string' && cacheAdapter,
|
||||
namespace: 'cacheable-request'
|
||||
});
|
||||
|
||||
return this.createCacheableRequest(request);
|
||||
}
|
||||
|
||||
createCacheableRequest(request) {
|
||||
return (opts, cb) => {
|
||||
if (typeof opts === 'string') {
|
||||
opts = urlLib.parse(opts);
|
||||
}
|
||||
opts = Object.assign({
|
||||
headers: {},
|
||||
method: 'GET',
|
||||
cache: true,
|
||||
strictTtl: false,
|
||||
automaticFailover: false
|
||||
}, opts);
|
||||
opts.headers = lowercaseKeys(opts.headers);
|
||||
|
||||
const ee = new EventEmitter();
|
||||
const url = normalizeUrl(urlLib.format(opts));
|
||||
const key = `${opts.method}:${url}`;
|
||||
let revalidate = false;
|
||||
let madeRequest = false;
|
||||
|
||||
const makeRequest = opts => {
|
||||
madeRequest = true;
|
||||
const handler = response => {
|
||||
if (revalidate) {
|
||||
const revalidatedPolicy = CachePolicy.fromObject(revalidate.cachePolicy).revalidatedPolicy(opts, response);
|
||||
if (!revalidatedPolicy.modified) {
|
||||
const headers = revalidatedPolicy.policy.responseHeaders();
|
||||
response = new Response(response.statusCode, headers, revalidate.body, revalidate.url);
|
||||
response.cachePolicy = revalidatedPolicy.policy;
|
||||
response.fromCache = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!response.fromCache) {
|
||||
response.cachePolicy = new CachePolicy(opts, response);
|
||||
response.fromCache = false;
|
||||
}
|
||||
|
||||
let clonedResponse;
|
||||
if (opts.cache && response.cachePolicy.storable()) {
|
||||
clonedResponse = cloneResponse(response);
|
||||
getStream.buffer(response)
|
||||
.then(body => {
|
||||
const value = {
|
||||
cachePolicy: response.cachePolicy.toObject(),
|
||||
url: response.url,
|
||||
statusCode: response.fromCache ? revalidate.statusCode : response.statusCode,
|
||||
body
|
||||
};
|
||||
const ttl = opts.strictTtl ? response.cachePolicy.timeToLive() : undefined;
|
||||
return this.cache.set(key, value, ttl);
|
||||
})
|
||||
.catch(err => ee.emit('error', new CacheableRequest.CacheError(err)));
|
||||
} else if (opts.cache && revalidate) {
|
||||
this.cache.delete(key)
|
||||
.catch(err => ee.emit('error', new CacheableRequest.CacheError(err)));
|
||||
}
|
||||
|
||||
ee.emit('response', clonedResponse || response);
|
||||
if (typeof cb === 'function') {
|
||||
cb(clonedResponse || response);
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
const req = request(opts, handler);
|
||||
ee.emit('request', req);
|
||||
} catch (err) {
|
||||
ee.emit('error', new CacheableRequest.RequestError(err));
|
||||
}
|
||||
};
|
||||
|
||||
const get = opts => Promise.resolve()
|
||||
.then(() => opts.cache ? this.cache.get(key) : undefined)
|
||||
.then(cacheEntry => {
|
||||
if (typeof cacheEntry === 'undefined') {
|
||||
return makeRequest(opts);
|
||||
}
|
||||
|
||||
const policy = CachePolicy.fromObject(cacheEntry.cachePolicy);
|
||||
if (policy.satisfiesWithoutRevalidation(opts)) {
|
||||
const headers = policy.responseHeaders();
|
||||
const response = new Response(cacheEntry.statusCode, headers, cacheEntry.body, cacheEntry.url);
|
||||
response.cachePolicy = policy;
|
||||
response.fromCache = true;
|
||||
|
||||
ee.emit('response', response);
|
||||
if (typeof cb === 'function') {
|
||||
cb(response);
|
||||
}
|
||||
} else {
|
||||
revalidate = cacheEntry;
|
||||
opts.headers = policy.revalidationHeaders(opts);
|
||||
makeRequest(opts);
|
||||
}
|
||||
});
|
||||
|
||||
this.cache.on('error', err => ee.emit('error', new CacheableRequest.CacheError(err)));
|
||||
|
||||
get(opts).catch(err => {
|
||||
if (opts.automaticFailover && !madeRequest) {
|
||||
makeRequest(opts);
|
||||
}
|
||||
ee.emit('error', new CacheableRequest.CacheError(err));
|
||||
});
|
||||
|
||||
return ee;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
CacheableRequest.RequestError = class extends Error {
|
||||
constructor(err) {
|
||||
super(err.message);
|
||||
this.name = 'RequestError';
|
||||
Object.assign(this, err);
|
||||
}
|
||||
};
|
||||
|
||||
CacheableRequest.CacheError = class extends Error {
|
||||
constructor(err) {
|
||||
super(err.message);
|
||||
this.name = 'CacheError';
|
||||
Object.assign(this, err);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = CacheableRequest;
|
||||
Reference in New Issue
Block a user