forked from friendica/friendica-addons
[advancedcontentfilter] Removed yet more JS/PHP Composer files
- Removed vendor/npm-asset - Removed vendor/slim/slim-skeleton
This commit is contained in:
parent
1e77af90ad
commit
6112160888
323 changed files with 1 additions and 41410 deletions
|
|
@ -20,12 +20,6 @@
|
|||
"config": {
|
||||
"optimize-autoloader": true,
|
||||
"autoloader-suffix": "AdvancedContentFilterAddon",
|
||||
"preferred-install": "dist",
|
||||
"fxp-asset": {
|
||||
"installer-paths": {
|
||||
"npm-asset-library": "vendor/asset",
|
||||
"bower-asset-library": "vendor/asset"
|
||||
}
|
||||
}
|
||||
"preferred-install": "dist"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,21 +0,0 @@
|
|||
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.
|
||||
|
|
@ -1,190 +0,0 @@
|
|||
# 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
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
{
|
||||
"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"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,155 +0,0 @@
|
|||
'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;
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
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.
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
# clone-response
|
||||
|
||||
> Clone a Node.js HTTP response stream
|
||||
|
||||
[](https://travis-ci.org/lukechilds/clone-response)
|
||||
[](https://coveralls.io/github/lukechilds/clone-response?branch=master)
|
||||
[](https://www.npmjs.com/package/clone-response)
|
||||
[](https://www.npmjs.com/package/clone-response)
|
||||
|
||||
Returns a new stream and copies over all properties and methods from the original response giving you a complete duplicate.
|
||||
|
||||
This is useful in situations where you need to consume the response stream but also want to pass an unconsumed stream somewhere else to be consumed later.
|
||||
|
||||
## Install
|
||||
|
||||
```shell
|
||||
npm install --save clone-response
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const http = require('http');
|
||||
const cloneResponse = require('clone-response');
|
||||
|
||||
http.get('http://example.com', response => {
|
||||
const clonedResponse = cloneResponse(response);
|
||||
response.pipe(process.stdout);
|
||||
|
||||
setImmediate(() => {
|
||||
// The response stream has already been consumed by the time this executes,
|
||||
// however the cloned response stream is still available.
|
||||
doSomethingWithResponse(clonedResponse);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
Please bear in mind that the process of cloning a stream consumes it. However, you can consume a stream multiple times in the same tick, therefore allowing you to create multiple clones. e.g:
|
||||
|
||||
```js
|
||||
const clone1 = cloneResponse(response);
|
||||
const clone2 = cloneResponse(response);
|
||||
// response can still be consumed in this tick but cannot be consumed if passed
|
||||
// into any async callbacks. clone1 and clone2 can be passed around and be
|
||||
// consumed in the future.
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### cloneResponse(response)
|
||||
|
||||
Returns a clone of the passed in response.
|
||||
|
||||
#### response
|
||||
|
||||
Type: `stream`
|
||||
|
||||
A [Node.js HTTP response stream](https://nodejs.org/api/http.html#http_class_http_incomingmessage) to clone.
|
||||
|
||||
## License
|
||||
|
||||
MIT © Luke Childs
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
{
|
||||
"name": "clone-response",
|
||||
"version": "1.0.2",
|
||||
"description": "Clone a Node.js HTTP response stream",
|
||||
"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/clone-response.git"
|
||||
},
|
||||
"keywords": [
|
||||
"clone",
|
||||
"duplicate",
|
||||
"copy",
|
||||
"response",
|
||||
"HTTP",
|
||||
"stream"
|
||||
],
|
||||
"author": "Luke Childs <lukechilds123@gmail.com> (http://lukechilds.co.uk)",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/lukechilds/clone-response/issues"
|
||||
},
|
||||
"homepage": "https://github.com/lukechilds/clone-response",
|
||||
"dependencies": {
|
||||
"mimic-response": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"ava": "^0.22.0",
|
||||
"coveralls": "^2.13.1",
|
||||
"create-test-server": "^2.0.1",
|
||||
"eslint-config-xo-lukechilds": "^1.0.0",
|
||||
"get-stream": "^3.0.0",
|
||||
"nyc": "^11.0.2",
|
||||
"pify": "^3.0.0",
|
||||
"xo": "^0.19.0"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
const PassThrough = require('stream').PassThrough;
|
||||
const mimicResponse = require('mimic-response');
|
||||
|
||||
const cloneResponse = response => {
|
||||
if (!(response && response.pipe)) {
|
||||
throw new TypeError('Parameter `response` must be a response stream.');
|
||||
}
|
||||
|
||||
const clone = new PassThrough();
|
||||
mimicResponse(response, clone);
|
||||
|
||||
return response.pipe(clone);
|
||||
};
|
||||
|
||||
module.exports = cloneResponse;
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
Copyright Node.js contributors. All rights reserved.
|
||||
|
||||
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.
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
# core-util-is
|
||||
|
||||
The `util.is*` functions introduced in Node v0.12.
|
||||
|
|
@ -1,604 +0,0 @@
|
|||
diff --git a/lib/util.js b/lib/util.js
|
||||
index a03e874..9074e8e 100644
|
||||
--- a/lib/util.js
|
||||
+++ b/lib/util.js
|
||||
@@ -19,430 +19,6 @@
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
-var formatRegExp = /%[sdj%]/g;
|
||||
-exports.format = function(f) {
|
||||
- if (!isString(f)) {
|
||||
- var objects = [];
|
||||
- for (var i = 0; i < arguments.length; i++) {
|
||||
- objects.push(inspect(arguments[i]));
|
||||
- }
|
||||
- return objects.join(' ');
|
||||
- }
|
||||
-
|
||||
- var i = 1;
|
||||
- var args = arguments;
|
||||
- var len = args.length;
|
||||
- var str = String(f).replace(formatRegExp, function(x) {
|
||||
- if (x === '%%') return '%';
|
||||
- if (i >= len) return x;
|
||||
- switch (x) {
|
||||
- case '%s': return String(args[i++]);
|
||||
- case '%d': return Number(args[i++]);
|
||||
- case '%j':
|
||||
- try {
|
||||
- return JSON.stringify(args[i++]);
|
||||
- } catch (_) {
|
||||
- return '[Circular]';
|
||||
- }
|
||||
- default:
|
||||
- return x;
|
||||
- }
|
||||
- });
|
||||
- for (var x = args[i]; i < len; x = args[++i]) {
|
||||
- if (isNull(x) || !isObject(x)) {
|
||||
- str += ' ' + x;
|
||||
- } else {
|
||||
- str += ' ' + inspect(x);
|
||||
- }
|
||||
- }
|
||||
- return str;
|
||||
-};
|
||||
-
|
||||
-
|
||||
-// Mark that a method should not be used.
|
||||
-// Returns a modified function which warns once by default.
|
||||
-// If --no-deprecation is set, then it is a no-op.
|
||||
-exports.deprecate = function(fn, msg) {
|
||||
- // Allow for deprecating things in the process of starting up.
|
||||
- if (isUndefined(global.process)) {
|
||||
- return function() {
|
||||
- return exports.deprecate(fn, msg).apply(this, arguments);
|
||||
- };
|
||||
- }
|
||||
-
|
||||
- if (process.noDeprecation === true) {
|
||||
- return fn;
|
||||
- }
|
||||
-
|
||||
- var warned = false;
|
||||
- function deprecated() {
|
||||
- if (!warned) {
|
||||
- if (process.throwDeprecation) {
|
||||
- throw new Error(msg);
|
||||
- } else if (process.traceDeprecation) {
|
||||
- console.trace(msg);
|
||||
- } else {
|
||||
- console.error(msg);
|
||||
- }
|
||||
- warned = true;
|
||||
- }
|
||||
- return fn.apply(this, arguments);
|
||||
- }
|
||||
-
|
||||
- return deprecated;
|
||||
-};
|
||||
-
|
||||
-
|
||||
-var debugs = {};
|
||||
-var debugEnviron;
|
||||
-exports.debuglog = function(set) {
|
||||
- if (isUndefined(debugEnviron))
|
||||
- debugEnviron = process.env.NODE_DEBUG || '';
|
||||
- set = set.toUpperCase();
|
||||
- if (!debugs[set]) {
|
||||
- if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
|
||||
- var pid = process.pid;
|
||||
- debugs[set] = function() {
|
||||
- var msg = exports.format.apply(exports, arguments);
|
||||
- console.error('%s %d: %s', set, pid, msg);
|
||||
- };
|
||||
- } else {
|
||||
- debugs[set] = function() {};
|
||||
- }
|
||||
- }
|
||||
- return debugs[set];
|
||||
-};
|
||||
-
|
||||
-
|
||||
-/**
|
||||
- * Echos the value of a value. Trys to print the value out
|
||||
- * in the best way possible given the different types.
|
||||
- *
|
||||
- * @param {Object} obj The object to print out.
|
||||
- * @param {Object} opts Optional options object that alters the output.
|
||||
- */
|
||||
-/* legacy: obj, showHidden, depth, colors*/
|
||||
-function inspect(obj, opts) {
|
||||
- // default options
|
||||
- var ctx = {
|
||||
- seen: [],
|
||||
- stylize: stylizeNoColor
|
||||
- };
|
||||
- // legacy...
|
||||
- if (arguments.length >= 3) ctx.depth = arguments[2];
|
||||
- if (arguments.length >= 4) ctx.colors = arguments[3];
|
||||
- if (isBoolean(opts)) {
|
||||
- // legacy...
|
||||
- ctx.showHidden = opts;
|
||||
- } else if (opts) {
|
||||
- // got an "options" object
|
||||
- exports._extend(ctx, opts);
|
||||
- }
|
||||
- // set default options
|
||||
- if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
|
||||
- if (isUndefined(ctx.depth)) ctx.depth = 2;
|
||||
- if (isUndefined(ctx.colors)) ctx.colors = false;
|
||||
- if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
|
||||
- if (ctx.colors) ctx.stylize = stylizeWithColor;
|
||||
- return formatValue(ctx, obj, ctx.depth);
|
||||
-}
|
||||
-exports.inspect = inspect;
|
||||
-
|
||||
-
|
||||
-// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
|
||||
-inspect.colors = {
|
||||
- 'bold' : [1, 22],
|
||||
- 'italic' : [3, 23],
|
||||
- 'underline' : [4, 24],
|
||||
- 'inverse' : [7, 27],
|
||||
- 'white' : [37, 39],
|
||||
- 'grey' : [90, 39],
|
||||
- 'black' : [30, 39],
|
||||
- 'blue' : [34, 39],
|
||||
- 'cyan' : [36, 39],
|
||||
- 'green' : [32, 39],
|
||||
- 'magenta' : [35, 39],
|
||||
- 'red' : [31, 39],
|
||||
- 'yellow' : [33, 39]
|
||||
-};
|
||||
-
|
||||
-// Don't use 'blue' not visible on cmd.exe
|
||||
-inspect.styles = {
|
||||
- 'special': 'cyan',
|
||||
- 'number': 'yellow',
|
||||
- 'boolean': 'yellow',
|
||||
- 'undefined': 'grey',
|
||||
- 'null': 'bold',
|
||||
- 'string': 'green',
|
||||
- 'date': 'magenta',
|
||||
- // "name": intentionally not styling
|
||||
- 'regexp': 'red'
|
||||
-};
|
||||
-
|
||||
-
|
||||
-function stylizeWithColor(str, styleType) {
|
||||
- var style = inspect.styles[styleType];
|
||||
-
|
||||
- if (style) {
|
||||
- return '\u001b[' + inspect.colors[style][0] + 'm' + str +
|
||||
- '\u001b[' + inspect.colors[style][1] + 'm';
|
||||
- } else {
|
||||
- return str;
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-
|
||||
-function stylizeNoColor(str, styleType) {
|
||||
- return str;
|
||||
-}
|
||||
-
|
||||
-
|
||||
-function arrayToHash(array) {
|
||||
- var hash = {};
|
||||
-
|
||||
- array.forEach(function(val, idx) {
|
||||
- hash[val] = true;
|
||||
- });
|
||||
-
|
||||
- return hash;
|
||||
-}
|
||||
-
|
||||
-
|
||||
-function formatValue(ctx, value, recurseTimes) {
|
||||
- // Provide a hook for user-specified inspect functions.
|
||||
- // Check that value is an object with an inspect function on it
|
||||
- if (ctx.customInspect &&
|
||||
- value &&
|
||||
- isFunction(value.inspect) &&
|
||||
- // Filter out the util module, it's inspect function is special
|
||||
- value.inspect !== exports.inspect &&
|
||||
- // Also filter out any prototype objects using the circular check.
|
||||
- !(value.constructor && value.constructor.prototype === value)) {
|
||||
- var ret = value.inspect(recurseTimes, ctx);
|
||||
- if (!isString(ret)) {
|
||||
- ret = formatValue(ctx, ret, recurseTimes);
|
||||
- }
|
||||
- return ret;
|
||||
- }
|
||||
-
|
||||
- // Primitive types cannot have properties
|
||||
- var primitive = formatPrimitive(ctx, value);
|
||||
- if (primitive) {
|
||||
- return primitive;
|
||||
- }
|
||||
-
|
||||
- // Look up the keys of the object.
|
||||
- var keys = Object.keys(value);
|
||||
- var visibleKeys = arrayToHash(keys);
|
||||
-
|
||||
- if (ctx.showHidden) {
|
||||
- keys = Object.getOwnPropertyNames(value);
|
||||
- }
|
||||
-
|
||||
- // Some type of object without properties can be shortcutted.
|
||||
- if (keys.length === 0) {
|
||||
- if (isFunction(value)) {
|
||||
- var name = value.name ? ': ' + value.name : '';
|
||||
- return ctx.stylize('[Function' + name + ']', 'special');
|
||||
- }
|
||||
- if (isRegExp(value)) {
|
||||
- return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
|
||||
- }
|
||||
- if (isDate(value)) {
|
||||
- return ctx.stylize(Date.prototype.toString.call(value), 'date');
|
||||
- }
|
||||
- if (isError(value)) {
|
||||
- return formatError(value);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- var base = '', array = false, braces = ['{', '}'];
|
||||
-
|
||||
- // Make Array say that they are Array
|
||||
- if (isArray(value)) {
|
||||
- array = true;
|
||||
- braces = ['[', ']'];
|
||||
- }
|
||||
-
|
||||
- // Make functions say that they are functions
|
||||
- if (isFunction(value)) {
|
||||
- var n = value.name ? ': ' + value.name : '';
|
||||
- base = ' [Function' + n + ']';
|
||||
- }
|
||||
-
|
||||
- // Make RegExps say that they are RegExps
|
||||
- if (isRegExp(value)) {
|
||||
- base = ' ' + RegExp.prototype.toString.call(value);
|
||||
- }
|
||||
-
|
||||
- // Make dates with properties first say the date
|
||||
- if (isDate(value)) {
|
||||
- base = ' ' + Date.prototype.toUTCString.call(value);
|
||||
- }
|
||||
-
|
||||
- // Make error with message first say the error
|
||||
- if (isError(value)) {
|
||||
- base = ' ' + formatError(value);
|
||||
- }
|
||||
-
|
||||
- if (keys.length === 0 && (!array || value.length == 0)) {
|
||||
- return braces[0] + base + braces[1];
|
||||
- }
|
||||
-
|
||||
- if (recurseTimes < 0) {
|
||||
- if (isRegExp(value)) {
|
||||
- return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
|
||||
- } else {
|
||||
- return ctx.stylize('[Object]', 'special');
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- ctx.seen.push(value);
|
||||
-
|
||||
- var output;
|
||||
- if (array) {
|
||||
- output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
|
||||
- } else {
|
||||
- output = keys.map(function(key) {
|
||||
- return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
|
||||
- });
|
||||
- }
|
||||
-
|
||||
- ctx.seen.pop();
|
||||
-
|
||||
- return reduceToSingleString(output, base, braces);
|
||||
-}
|
||||
-
|
||||
-
|
||||
-function formatPrimitive(ctx, value) {
|
||||
- if (isUndefined(value))
|
||||
- return ctx.stylize('undefined', 'undefined');
|
||||
- if (isString(value)) {
|
||||
- var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
|
||||
- .replace(/'/g, "\\'")
|
||||
- .replace(/\\"/g, '"') + '\'';
|
||||
- return ctx.stylize(simple, 'string');
|
||||
- }
|
||||
- if (isNumber(value)) {
|
||||
- // Format -0 as '-0'. Strict equality won't distinguish 0 from -0,
|
||||
- // so instead we use the fact that 1 / -0 < 0 whereas 1 / 0 > 0 .
|
||||
- if (value === 0 && 1 / value < 0)
|
||||
- return ctx.stylize('-0', 'number');
|
||||
- return ctx.stylize('' + value, 'number');
|
||||
- }
|
||||
- if (isBoolean(value))
|
||||
- return ctx.stylize('' + value, 'boolean');
|
||||
- // For some reason typeof null is "object", so special case here.
|
||||
- if (isNull(value))
|
||||
- return ctx.stylize('null', 'null');
|
||||
-}
|
||||
-
|
||||
-
|
||||
-function formatError(value) {
|
||||
- return '[' + Error.prototype.toString.call(value) + ']';
|
||||
-}
|
||||
-
|
||||
-
|
||||
-function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
|
||||
- var output = [];
|
||||
- for (var i = 0, l = value.length; i < l; ++i) {
|
||||
- if (hasOwnProperty(value, String(i))) {
|
||||
- output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
|
||||
- String(i), true));
|
||||
- } else {
|
||||
- output.push('');
|
||||
- }
|
||||
- }
|
||||
- keys.forEach(function(key) {
|
||||
- if (!key.match(/^\d+$/)) {
|
||||
- output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
|
||||
- key, true));
|
||||
- }
|
||||
- });
|
||||
- return output;
|
||||
-}
|
||||
-
|
||||
-
|
||||
-function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
|
||||
- var name, str, desc;
|
||||
- desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
|
||||
- if (desc.get) {
|
||||
- if (desc.set) {
|
||||
- str = ctx.stylize('[Getter/Setter]', 'special');
|
||||
- } else {
|
||||
- str = ctx.stylize('[Getter]', 'special');
|
||||
- }
|
||||
- } else {
|
||||
- if (desc.set) {
|
||||
- str = ctx.stylize('[Setter]', 'special');
|
||||
- }
|
||||
- }
|
||||
- if (!hasOwnProperty(visibleKeys, key)) {
|
||||
- name = '[' + key + ']';
|
||||
- }
|
||||
- if (!str) {
|
||||
- if (ctx.seen.indexOf(desc.value) < 0) {
|
||||
- if (isNull(recurseTimes)) {
|
||||
- str = formatValue(ctx, desc.value, null);
|
||||
- } else {
|
||||
- str = formatValue(ctx, desc.value, recurseTimes - 1);
|
||||
- }
|
||||
- if (str.indexOf('\n') > -1) {
|
||||
- if (array) {
|
||||
- str = str.split('\n').map(function(line) {
|
||||
- return ' ' + line;
|
||||
- }).join('\n').substr(2);
|
||||
- } else {
|
||||
- str = '\n' + str.split('\n').map(function(line) {
|
||||
- return ' ' + line;
|
||||
- }).join('\n');
|
||||
- }
|
||||
- }
|
||||
- } else {
|
||||
- str = ctx.stylize('[Circular]', 'special');
|
||||
- }
|
||||
- }
|
||||
- if (isUndefined(name)) {
|
||||
- if (array && key.match(/^\d+$/)) {
|
||||
- return str;
|
||||
- }
|
||||
- name = JSON.stringify('' + key);
|
||||
- if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
|
||||
- name = name.substr(1, name.length - 2);
|
||||
- name = ctx.stylize(name, 'name');
|
||||
- } else {
|
||||
- name = name.replace(/'/g, "\\'")
|
||||
- .replace(/\\"/g, '"')
|
||||
- .replace(/(^"|"$)/g, "'");
|
||||
- name = ctx.stylize(name, 'string');
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- return name + ': ' + str;
|
||||
-}
|
||||
-
|
||||
-
|
||||
-function reduceToSingleString(output, base, braces) {
|
||||
- var numLinesEst = 0;
|
||||
- var length = output.reduce(function(prev, cur) {
|
||||
- numLinesEst++;
|
||||
- if (cur.indexOf('\n') >= 0) numLinesEst++;
|
||||
- return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
|
||||
- }, 0);
|
||||
-
|
||||
- if (length > 60) {
|
||||
- return braces[0] +
|
||||
- (base === '' ? '' : base + '\n ') +
|
||||
- ' ' +
|
||||
- output.join(',\n ') +
|
||||
- ' ' +
|
||||
- braces[1];
|
||||
- }
|
||||
-
|
||||
- return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
|
||||
-}
|
||||
-
|
||||
-
|
||||
// NOTE: These type checking functions intentionally don't use `instanceof`
|
||||
// because it is fragile and can be easily faked with `Object.create()`.
|
||||
function isArray(ar) {
|
||||
@@ -522,166 +98,10 @@ function isPrimitive(arg) {
|
||||
exports.isPrimitive = isPrimitive;
|
||||
|
||||
function isBuffer(arg) {
|
||||
- return arg instanceof Buffer;
|
||||
+ return Buffer.isBuffer(arg);
|
||||
}
|
||||
exports.isBuffer = isBuffer;
|
||||
|
||||
function objectToString(o) {
|
||||
return Object.prototype.toString.call(o);
|
||||
-}
|
||||
-
|
||||
-
|
||||
-function pad(n) {
|
||||
- return n < 10 ? '0' + n.toString(10) : n.toString(10);
|
||||
-}
|
||||
-
|
||||
-
|
||||
-var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
|
||||
- 'Oct', 'Nov', 'Dec'];
|
||||
-
|
||||
-// 26 Feb 16:19:34
|
||||
-function timestamp() {
|
||||
- var d = new Date();
|
||||
- var time = [pad(d.getHours()),
|
||||
- pad(d.getMinutes()),
|
||||
- pad(d.getSeconds())].join(':');
|
||||
- return [d.getDate(), months[d.getMonth()], time].join(' ');
|
||||
-}
|
||||
-
|
||||
-
|
||||
-// log is just a thin wrapper to console.log that prepends a timestamp
|
||||
-exports.log = function() {
|
||||
- console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
|
||||
-};
|
||||
-
|
||||
-
|
||||
-/**
|
||||
- * Inherit the prototype methods from one constructor into another.
|
||||
- *
|
||||
- * The Function.prototype.inherits from lang.js rewritten as a standalone
|
||||
- * function (not on Function.prototype). NOTE: If this file is to be loaded
|
||||
- * during bootstrapping this function needs to be rewritten using some native
|
||||
- * functions as prototype setup using normal JavaScript does not work as
|
||||
- * expected during bootstrapping (see mirror.js in r114903).
|
||||
- *
|
||||
- * @param {function} ctor Constructor function which needs to inherit the
|
||||
- * prototype.
|
||||
- * @param {function} superCtor Constructor function to inherit prototype from.
|
||||
- */
|
||||
-exports.inherits = function(ctor, superCtor) {
|
||||
- ctor.super_ = superCtor;
|
||||
- ctor.prototype = Object.create(superCtor.prototype, {
|
||||
- constructor: {
|
||||
- value: ctor,
|
||||
- enumerable: false,
|
||||
- writable: true,
|
||||
- configurable: true
|
||||
- }
|
||||
- });
|
||||
-};
|
||||
-
|
||||
-exports._extend = function(origin, add) {
|
||||
- // Don't do anything if add isn't an object
|
||||
- if (!add || !isObject(add)) return origin;
|
||||
-
|
||||
- var keys = Object.keys(add);
|
||||
- var i = keys.length;
|
||||
- while (i--) {
|
||||
- origin[keys[i]] = add[keys[i]];
|
||||
- }
|
||||
- return origin;
|
||||
-};
|
||||
-
|
||||
-function hasOwnProperty(obj, prop) {
|
||||
- return Object.prototype.hasOwnProperty.call(obj, prop);
|
||||
-}
|
||||
-
|
||||
-
|
||||
-// Deprecated old stuff.
|
||||
-
|
||||
-exports.p = exports.deprecate(function() {
|
||||
- for (var i = 0, len = arguments.length; i < len; ++i) {
|
||||
- console.error(exports.inspect(arguments[i]));
|
||||
- }
|
||||
-}, 'util.p: Use console.error() instead');
|
||||
-
|
||||
-
|
||||
-exports.exec = exports.deprecate(function() {
|
||||
- return require('child_process').exec.apply(this, arguments);
|
||||
-}, 'util.exec is now called `child_process.exec`.');
|
||||
-
|
||||
-
|
||||
-exports.print = exports.deprecate(function() {
|
||||
- for (var i = 0, len = arguments.length; i < len; ++i) {
|
||||
- process.stdout.write(String(arguments[i]));
|
||||
- }
|
||||
-}, 'util.print: Use console.log instead');
|
||||
-
|
||||
-
|
||||
-exports.puts = exports.deprecate(function() {
|
||||
- for (var i = 0, len = arguments.length; i < len; ++i) {
|
||||
- process.stdout.write(arguments[i] + '\n');
|
||||
- }
|
||||
-}, 'util.puts: Use console.log instead');
|
||||
-
|
||||
-
|
||||
-exports.debug = exports.deprecate(function(x) {
|
||||
- process.stderr.write('DEBUG: ' + x + '\n');
|
||||
-}, 'util.debug: Use console.error instead');
|
||||
-
|
||||
-
|
||||
-exports.error = exports.deprecate(function(x) {
|
||||
- for (var i = 0, len = arguments.length; i < len; ++i) {
|
||||
- process.stderr.write(arguments[i] + '\n');
|
||||
- }
|
||||
-}, 'util.error: Use console.error instead');
|
||||
-
|
||||
-
|
||||
-exports.pump = exports.deprecate(function(readStream, writeStream, callback) {
|
||||
- var callbackCalled = false;
|
||||
-
|
||||
- function call(a, b, c) {
|
||||
- if (callback && !callbackCalled) {
|
||||
- callback(a, b, c);
|
||||
- callbackCalled = true;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- readStream.addListener('data', function(chunk) {
|
||||
- if (writeStream.write(chunk) === false) readStream.pause();
|
||||
- });
|
||||
-
|
||||
- writeStream.addListener('drain', function() {
|
||||
- readStream.resume();
|
||||
- });
|
||||
-
|
||||
- readStream.addListener('end', function() {
|
||||
- writeStream.end();
|
||||
- });
|
||||
-
|
||||
- readStream.addListener('close', function() {
|
||||
- call();
|
||||
- });
|
||||
-
|
||||
- readStream.addListener('error', function(err) {
|
||||
- writeStream.end();
|
||||
- call(err);
|
||||
- });
|
||||
-
|
||||
- writeStream.addListener('error', function(err) {
|
||||
- readStream.destroy();
|
||||
- call(err);
|
||||
- });
|
||||
-}, 'util.pump(): Use readableStream.pipe() instead');
|
||||
-
|
||||
-
|
||||
-var uv;
|
||||
-exports._errnoException = function(err, syscall) {
|
||||
- if (isUndefined(uv)) uv = process.binding('uv');
|
||||
- var errname = uv.errname(err);
|
||||
- var e = new Error(syscall + ' ' + errname);
|
||||
- e.code = errname;
|
||||
- e.errno = errname;
|
||||
- e.syscall = syscall;
|
||||
- return e;
|
||||
-};
|
||||
+}
|
||||
|
|
@ -1,107 +0,0 @@
|
|||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// 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.
|
||||
|
||||
// NOTE: These type checking functions intentionally don't use `instanceof`
|
||||
// because it is fragile and can be easily faked with `Object.create()`.
|
||||
|
||||
function isArray(arg) {
|
||||
if (Array.isArray) {
|
||||
return Array.isArray(arg);
|
||||
}
|
||||
return objectToString(arg) === '[object Array]';
|
||||
}
|
||||
exports.isArray = isArray;
|
||||
|
||||
function isBoolean(arg) {
|
||||
return typeof arg === 'boolean';
|
||||
}
|
||||
exports.isBoolean = isBoolean;
|
||||
|
||||
function isNull(arg) {
|
||||
return arg === null;
|
||||
}
|
||||
exports.isNull = isNull;
|
||||
|
||||
function isNullOrUndefined(arg) {
|
||||
return arg == null;
|
||||
}
|
||||
exports.isNullOrUndefined = isNullOrUndefined;
|
||||
|
||||
function isNumber(arg) {
|
||||
return typeof arg === 'number';
|
||||
}
|
||||
exports.isNumber = isNumber;
|
||||
|
||||
function isString(arg) {
|
||||
return typeof arg === 'string';
|
||||
}
|
||||
exports.isString = isString;
|
||||
|
||||
function isSymbol(arg) {
|
||||
return typeof arg === 'symbol';
|
||||
}
|
||||
exports.isSymbol = isSymbol;
|
||||
|
||||
function isUndefined(arg) {
|
||||
return arg === void 0;
|
||||
}
|
||||
exports.isUndefined = isUndefined;
|
||||
|
||||
function isRegExp(re) {
|
||||
return objectToString(re) === '[object RegExp]';
|
||||
}
|
||||
exports.isRegExp = isRegExp;
|
||||
|
||||
function isObject(arg) {
|
||||
return typeof arg === 'object' && arg !== null;
|
||||
}
|
||||
exports.isObject = isObject;
|
||||
|
||||
function isDate(d) {
|
||||
return objectToString(d) === '[object Date]';
|
||||
}
|
||||
exports.isDate = isDate;
|
||||
|
||||
function isError(e) {
|
||||
return (objectToString(e) === '[object Error]' || e instanceof Error);
|
||||
}
|
||||
exports.isError = isError;
|
||||
|
||||
function isFunction(arg) {
|
||||
return typeof arg === 'function';
|
||||
}
|
||||
exports.isFunction = isFunction;
|
||||
|
||||
function isPrimitive(arg) {
|
||||
return arg === null ||
|
||||
typeof arg === 'boolean' ||
|
||||
typeof arg === 'number' ||
|
||||
typeof arg === 'string' ||
|
||||
typeof arg === 'symbol' || // ES6 symbol
|
||||
typeof arg === 'undefined';
|
||||
}
|
||||
exports.isPrimitive = isPrimitive;
|
||||
|
||||
exports.isBuffer = Buffer.isBuffer;
|
||||
|
||||
function objectToString(o) {
|
||||
return Object.prototype.toString.call(o);
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
{
|
||||
"name": "core-util-is",
|
||||
"version": "1.0.2",
|
||||
"description": "The `util.is*` functions introduced in Node v0.12.",
|
||||
"main": "lib/util.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/isaacs/core-util-is"
|
||||
},
|
||||
"keywords": [
|
||||
"util",
|
||||
"isBuffer",
|
||||
"isArray",
|
||||
"isNumber",
|
||||
"isString",
|
||||
"isRegExp",
|
||||
"isThis",
|
||||
"isThat",
|
||||
"polyfill"
|
||||
],
|
||||
"author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/isaacs/core-util-is/issues"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "tap test.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"tap": "^2.3.0"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
var assert = require('tap');
|
||||
|
||||
var t = require('./lib/util');
|
||||
|
||||
assert.equal(t.isArray([]), true);
|
||||
assert.equal(t.isArray({}), false);
|
||||
|
||||
assert.equal(t.isBoolean(null), false);
|
||||
assert.equal(t.isBoolean(true), true);
|
||||
assert.equal(t.isBoolean(false), true);
|
||||
|
||||
assert.equal(t.isNull(null), true);
|
||||
assert.equal(t.isNull(undefined), false);
|
||||
assert.equal(t.isNull(false), false);
|
||||
assert.equal(t.isNull(), false);
|
||||
|
||||
assert.equal(t.isNullOrUndefined(null), true);
|
||||
assert.equal(t.isNullOrUndefined(undefined), true);
|
||||
assert.equal(t.isNullOrUndefined(false), false);
|
||||
assert.equal(t.isNullOrUndefined(), true);
|
||||
|
||||
assert.equal(t.isNumber(null), false);
|
||||
assert.equal(t.isNumber('1'), false);
|
||||
assert.equal(t.isNumber(1), true);
|
||||
|
||||
assert.equal(t.isString(null), false);
|
||||
assert.equal(t.isString('1'), true);
|
||||
assert.equal(t.isString(1), false);
|
||||
|
||||
assert.equal(t.isSymbol(null), false);
|
||||
assert.equal(t.isSymbol('1'), false);
|
||||
assert.equal(t.isSymbol(1), false);
|
||||
assert.equal(t.isSymbol(Symbol()), true);
|
||||
|
||||
assert.equal(t.isUndefined(null), false);
|
||||
assert.equal(t.isUndefined(undefined), true);
|
||||
assert.equal(t.isUndefined(false), false);
|
||||
assert.equal(t.isUndefined(), true);
|
||||
|
||||
assert.equal(t.isRegExp(null), false);
|
||||
assert.equal(t.isRegExp('1'), false);
|
||||
assert.equal(t.isRegExp(new RegExp()), true);
|
||||
|
||||
assert.equal(t.isObject({}), true);
|
||||
assert.equal(t.isObject([]), true);
|
||||
assert.equal(t.isObject(new RegExp()), true);
|
||||
assert.equal(t.isObject(new Date()), true);
|
||||
|
||||
assert.equal(t.isDate(null), false);
|
||||
assert.equal(t.isDate('1'), false);
|
||||
assert.equal(t.isDate(new Date()), true);
|
||||
|
||||
assert.equal(t.isError(null), false);
|
||||
assert.equal(t.isError({ err: true }), false);
|
||||
assert.equal(t.isError(new Error()), true);
|
||||
|
||||
assert.equal(t.isFunction(null), false);
|
||||
assert.equal(t.isFunction({ }), false);
|
||||
assert.equal(t.isFunction(function() {}), true);
|
||||
|
||||
assert.equal(t.isPrimitive(null), true);
|
||||
assert.equal(t.isPrimitive(''), true);
|
||||
assert.equal(t.isPrimitive(0), true);
|
||||
assert.equal(t.isPrimitive(new Date()), false);
|
||||
|
||||
assert.equal(t.isBuffer(null), false);
|
||||
assert.equal(t.isBuffer({}), false);
|
||||
assert.equal(t.isBuffer(new Buffer(0)), true);
|
||||
|
|
@ -1,94 +0,0 @@
|
|||
'use strict';
|
||||
var token = '%[a-f0-9]{2}';
|
||||
var singleMatcher = new RegExp(token, 'gi');
|
||||
var multiMatcher = new RegExp('(' + token + ')+', 'gi');
|
||||
|
||||
function decodeComponents(components, split) {
|
||||
try {
|
||||
// Try to decode the entire string first
|
||||
return decodeURIComponent(components.join(''));
|
||||
} catch (err) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
if (components.length === 1) {
|
||||
return components;
|
||||
}
|
||||
|
||||
split = split || 1;
|
||||
|
||||
// Split the array in 2 parts
|
||||
var left = components.slice(0, split);
|
||||
var right = components.slice(split);
|
||||
|
||||
return Array.prototype.concat.call([], decodeComponents(left), decodeComponents(right));
|
||||
}
|
||||
|
||||
function decode(input) {
|
||||
try {
|
||||
return decodeURIComponent(input);
|
||||
} catch (err) {
|
||||
var tokens = input.match(singleMatcher);
|
||||
|
||||
for (var i = 1; i < tokens.length; i++) {
|
||||
input = decodeComponents(tokens, i).join('');
|
||||
|
||||
tokens = input.match(singleMatcher);
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
}
|
||||
|
||||
function customDecodeURIComponent(input) {
|
||||
// Keep track of all the replacements and prefill the map with the `BOM`
|
||||
var replaceMap = {
|
||||
'%FE%FF': '\uFFFD\uFFFD',
|
||||
'%FF%FE': '\uFFFD\uFFFD'
|
||||
};
|
||||
|
||||
var match = multiMatcher.exec(input);
|
||||
while (match) {
|
||||
try {
|
||||
// Decode as big chunks as possible
|
||||
replaceMap[match[0]] = decodeURIComponent(match[0]);
|
||||
} catch (err) {
|
||||
var result = decode(match[0]);
|
||||
|
||||
if (result !== match[0]) {
|
||||
replaceMap[match[0]] = result;
|
||||
}
|
||||
}
|
||||
|
||||
match = multiMatcher.exec(input);
|
||||
}
|
||||
|
||||
// Add `%C2` at the end of the map to make sure it does not replace the combinator before everything else
|
||||
replaceMap['%C2'] = '\uFFFD';
|
||||
|
||||
var entries = Object.keys(replaceMap);
|
||||
|
||||
for (var i = 0; i < entries.length; i++) {
|
||||
// Replace all decoded components
|
||||
var key = entries[i];
|
||||
input = input.replace(new RegExp(key, 'g'), replaceMap[key]);
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
module.exports = function (encodedURI) {
|
||||
if (typeof encodedURI !== 'string') {
|
||||
throw new TypeError('Expected `encodedURI` to be of type `string`, got `' + typeof encodedURI + '`');
|
||||
}
|
||||
|
||||
try {
|
||||
encodedURI = encodedURI.replace(/\+/g, ' ');
|
||||
|
||||
// Try the built in decoder first
|
||||
return decodeURIComponent(encodedURI);
|
||||
} catch (err) {
|
||||
// Fallback to a more advanced decoder
|
||||
return customDecodeURIComponent(encodedURI);
|
||||
}
|
||||
};
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) Sam Verschueren <sam.verschueren@gmail.com> (github.com/SamVerschueren)
|
||||
|
||||
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.
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
{
|
||||
"name": "decode-uri-component",
|
||||
"version": "0.2.0",
|
||||
"description": "A better decodeURIComponent",
|
||||
"license": "MIT",
|
||||
"repository": "SamVerschueren/decode-uri-component",
|
||||
"author": {
|
||||
"name": "Sam Verschueren",
|
||||
"email": "sam.verschueren@gmail.com",
|
||||
"url": "github.com/SamVerschueren"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "xo && nyc ava",
|
||||
"coveralls": "nyc report --reporter=text-lcov | coveralls"
|
||||
},
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"keywords": [
|
||||
"decode",
|
||||
"uri",
|
||||
"component",
|
||||
"decodeuricomponent",
|
||||
"components",
|
||||
"decoder",
|
||||
"url"
|
||||
],
|
||||
"devDependencies": {
|
||||
"ava": "^0.17.0",
|
||||
"coveralls": "^2.13.1",
|
||||
"nyc": "^10.3.2",
|
||||
"xo": "^0.16.0"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
# decode-uri-component
|
||||
|
||||
[](https://travis-ci.org/SamVerschueren/decode-uri-component) [](https://coveralls.io/github/SamVerschueren/decode-uri-component?branch=master)
|
||||
|
||||
> A better [decodeURIComponent](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent)
|
||||
|
||||
|
||||
## Why?
|
||||
|
||||
- Decodes `+` to a space.
|
||||
- Converts the [BOM](https://en.wikipedia.org/wiki/Byte_order_mark) to a [replacement character](https://en.wikipedia.org/wiki/Specials_(Unicode_block)#Replacement_character) `<60>`.
|
||||
- Does not throw with invalid encoded input.
|
||||
- Decodes as much of the string as possible.
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install --save decode-uri-component
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const decodeUriComponent = require('decode-uri-component');
|
||||
|
||||
decodeUriComponent('%25');
|
||||
//=> '%'
|
||||
|
||||
decodeUriComponent('%');
|
||||
//=> '%'
|
||||
|
||||
decodeUriComponent('st%C3%A5le');
|
||||
//=> 'ståle'
|
||||
|
||||
decodeUriComponent('%st%C3%A5le%');
|
||||
//=> '%ståle%'
|
||||
|
||||
decodeUriComponent('%%7Bst%C3%A5le%7D%');
|
||||
//=> '%{ståle}%'
|
||||
|
||||
decodeUriComponent('%7B%ab%%7C%de%%7D');
|
||||
//=> '{%ab%|%de%}'
|
||||
|
||||
decodeUriComponent('%FE%FF');
|
||||
//=> '\uFFFD\uFFFD'
|
||||
|
||||
decodeUriComponent('%C2');
|
||||
//=> '\uFFFD'
|
||||
|
||||
decodeUriComponent('%C2%B5');
|
||||
//=> 'µ'
|
||||
```
|
||||
|
||||
|
||||
## API
|
||||
|
||||
### decodeUriComponent(encodedURI)
|
||||
|
||||
#### encodedURI
|
||||
|
||||
Type: `string`
|
||||
|
||||
An encoded component of a Uniform Resource Identifier.
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Sam Verschueren](https://github.com/SamVerschueren)
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
'use strict';
|
||||
const PassThrough = require('stream').PassThrough;
|
||||
const zlib = require('zlib');
|
||||
const mimicResponse = require('mimic-response');
|
||||
|
||||
module.exports = response => {
|
||||
// TODO: Use Array#includes when targeting Node.js 6
|
||||
if (['gzip', 'deflate'].indexOf(response.headers['content-encoding']) === -1) {
|
||||
return response;
|
||||
}
|
||||
|
||||
const unzip = zlib.createUnzip();
|
||||
const stream = new PassThrough();
|
||||
|
||||
mimicResponse(response, stream);
|
||||
|
||||
unzip.on('error', err => {
|
||||
if (err.code === 'Z_BUF_ERROR') {
|
||||
stream.end();
|
||||
return;
|
||||
}
|
||||
|
||||
stream.emit('error', err);
|
||||
});
|
||||
|
||||
response.pipe(unzip).pipe(stream);
|
||||
|
||||
return stream;
|
||||
};
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
`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.
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
{
|
||||
"name": "decompress-response",
|
||||
"version": "3.3.0",
|
||||
"description": "Decompress a HTTP response if needed",
|
||||
"license": "MIT",
|
||||
"repository": "sindresorhus/decompress-response",
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "Sindre Sorhus",
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"url": "sindresorhus.com"
|
||||
},
|
||||
{
|
||||
"name": "Vsevolod Strukchinsky",
|
||||
"email": "floatdrop@gmail.com",
|
||||
"url": "github.com/floatdrop"
|
||||
}
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "xo && ava"
|
||||
},
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"keywords": [
|
||||
"decompress",
|
||||
"response",
|
||||
"http",
|
||||
"https",
|
||||
"zlib",
|
||||
"gzip",
|
||||
"zip",
|
||||
"deflate",
|
||||
"unzip",
|
||||
"ungzip",
|
||||
"incoming",
|
||||
"message",
|
||||
"stream",
|
||||
"compressed"
|
||||
],
|
||||
"dependencies": {
|
||||
"mimic-response": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"ava": "*",
|
||||
"get-stream": "^3.0.0",
|
||||
"pify": "^3.0.0",
|
||||
"xo": "*"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
# decompress-response [](https://travis-ci.org/sindresorhus/decompress-response)
|
||||
|
||||
> Decompress a HTTP response if needed
|
||||
|
||||
Decompresses the [response](https://nodejs.org/api/http.html#http_class_http_incomingmessage) from [`http.request`](https://nodejs.org/api/http.html#http_http_request_options_callback) if it's gzipped or deflated, otherwise just passes it through.
|
||||
|
||||
Used by [`got`](https://github.com/sindresorhus/got).
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install decompress-response
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const http = require('http');
|
||||
const decompressResponse = require('decompress-response');
|
||||
|
||||
http.get('http://sindresorhus.com', response => {
|
||||
response = decompressResponse(response);
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Sindre Sorhus](https://sindresorhus.com)
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
Copyright (c) 2013, Deoxxa Development
|
||||
======================================
|
||||
All rights reserved.
|
||||
--------------------
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of Deoxxa Development nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY DEOXXA DEVELOPMENT ''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL DEOXXA DEVELOPMENT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
# duplexer3 [](https://travis-ci.org/floatdrop/duplexer3) [](https://coveralls.io/github/floatdrop/duplexer3?branch=master)
|
||||
|
||||
Like [duplexer2](https://github.com/deoxxa/duplexer2) but using Streams3 without readable-stream dependency
|
||||
|
||||
```javascript
|
||||
var stream = require("stream");
|
||||
|
||||
var duplexer3 = require("duplexer3");
|
||||
|
||||
var writable = new stream.Writable({objectMode: true}),
|
||||
readable = new stream.Readable({objectMode: true});
|
||||
|
||||
writable._write = function _write(input, encoding, done) {
|
||||
if (readable.push(input)) {
|
||||
return done();
|
||||
} else {
|
||||
readable.once("drain", done);
|
||||
}
|
||||
};
|
||||
|
||||
readable._read = function _read(n) {
|
||||
// no-op
|
||||
};
|
||||
|
||||
// simulate the readable thing closing after a bit
|
||||
writable.once("finish", function() {
|
||||
setTimeout(function() {
|
||||
readable.push(null);
|
||||
}, 500);
|
||||
});
|
||||
|
||||
var duplex = duplexer3(writable, readable);
|
||||
|
||||
duplex.on("data", function(e) {
|
||||
console.log("got data", JSON.stringify(e));
|
||||
});
|
||||
|
||||
duplex.on("finish", function() {
|
||||
console.log("got finish event");
|
||||
});
|
||||
|
||||
duplex.on("end", function() {
|
||||
console.log("got end event");
|
||||
});
|
||||
|
||||
duplex.write("oh, hi there", function() {
|
||||
console.log("finished writing");
|
||||
});
|
||||
|
||||
duplex.end(function() {
|
||||
console.log("finished ending");
|
||||
});
|
||||
```
|
||||
|
||||
```
|
||||
got data "oh, hi there"
|
||||
finished writing
|
||||
got finish event
|
||||
finished ending
|
||||
got end event
|
||||
```
|
||||
|
||||
## Overview
|
||||
|
||||
This is a reimplementation of [duplexer](https://www.npmjs.com/package/duplexer) using the
|
||||
Streams3 API which is standard in Node as of v4. Everything largely
|
||||
works the same.
|
||||
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
[Available via `npm`](https://docs.npmjs.com/cli/install):
|
||||
|
||||
```
|
||||
$ npm i duplexer3
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### duplexer3
|
||||
|
||||
Creates a new `DuplexWrapper` object, which is the actual class that implements
|
||||
most of the fun stuff. All that fun stuff is hidden. DON'T LOOK.
|
||||
|
||||
```javascript
|
||||
duplexer3([options], writable, readable)
|
||||
```
|
||||
|
||||
```javascript
|
||||
const duplex = duplexer3(new stream.Writable(), new stream.Readable());
|
||||
```
|
||||
|
||||
Arguments
|
||||
|
||||
* __options__ - an object specifying the regular `stream.Duplex` options, as
|
||||
well as the properties described below.
|
||||
* __writable__ - a writable stream
|
||||
* __readable__ - a readable stream
|
||||
|
||||
Options
|
||||
|
||||
* __bubbleErrors__ - a boolean value that specifies whether to bubble errors
|
||||
from the underlying readable/writable streams. Default is `true`.
|
||||
|
||||
|
||||
## License
|
||||
|
||||
3-clause BSD. [A copy](./LICENSE) is included with the source.
|
||||
|
||||
## Contact
|
||||
|
||||
* GitHub ([deoxxa](http://github.com/deoxxa))
|
||||
* Twitter ([@deoxxa](http://twitter.com/deoxxa))
|
||||
* Email ([deoxxa@fknsrs.biz](mailto:deoxxa@fknsrs.biz))
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
var stream = require("stream");
|
||||
|
||||
function DuplexWrapper(options, writable, readable) {
|
||||
if (typeof readable === "undefined") {
|
||||
readable = writable;
|
||||
writable = options;
|
||||
options = null;
|
||||
}
|
||||
|
||||
stream.Duplex.call(this, options);
|
||||
|
||||
if (typeof readable.read !== "function") {
|
||||
readable = (new stream.Readable(options)).wrap(readable);
|
||||
}
|
||||
|
||||
this._writable = writable;
|
||||
this._readable = readable;
|
||||
this._waiting = false;
|
||||
|
||||
var self = this;
|
||||
|
||||
writable.once("finish", function() {
|
||||
self.end();
|
||||
});
|
||||
|
||||
this.once("finish", function() {
|
||||
writable.end();
|
||||
});
|
||||
|
||||
readable.on("readable", function() {
|
||||
if (self._waiting) {
|
||||
self._waiting = false;
|
||||
self._read();
|
||||
}
|
||||
});
|
||||
|
||||
readable.once("end", function() {
|
||||
self.push(null);
|
||||
});
|
||||
|
||||
if (!options || typeof options.bubbleErrors === "undefined" || options.bubbleErrors) {
|
||||
writable.on("error", function(err) {
|
||||
self.emit("error", err);
|
||||
});
|
||||
|
||||
readable.on("error", function(err) {
|
||||
self.emit("error", err);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
DuplexWrapper.prototype = Object.create(stream.Duplex.prototype, {constructor: {value: DuplexWrapper}});
|
||||
|
||||
DuplexWrapper.prototype._write = function _write(input, encoding, done) {
|
||||
this._writable.write(input, encoding, done);
|
||||
};
|
||||
|
||||
DuplexWrapper.prototype._read = function _read() {
|
||||
var buf;
|
||||
var reads = 0;
|
||||
while ((buf = this._readable.read()) !== null) {
|
||||
this.push(buf);
|
||||
reads++;
|
||||
}
|
||||
if (reads === 0) {
|
||||
this._waiting = true;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = function duplex2(options, writable, readable) {
|
||||
return new DuplexWrapper(options, writable, readable);
|
||||
};
|
||||
|
||||
module.exports.DuplexWrapper = DuplexWrapper;
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
{
|
||||
"name": "duplexer3",
|
||||
"version": "0.1.4",
|
||||
"description": "Like duplexer but using streams3",
|
||||
"engine": {
|
||||
"node": ">=4"
|
||||
},
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"scripts": {
|
||||
"test": "mocha -R tap"
|
||||
},
|
||||
"repository": "floatdrop/duplexer3",
|
||||
"keywords": [
|
||||
"duplex",
|
||||
"duplexer",
|
||||
"stream",
|
||||
"stream3",
|
||||
"join",
|
||||
"combine"
|
||||
],
|
||||
"author": "Conrad Pankoff <deoxxa@fknsrs.biz> (http://www.fknsrs.biz/)",
|
||||
"license": "BSD-3-Clause",
|
||||
"devDependencies": {
|
||||
"mocha": "^2.2.5"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
language: node_js
|
||||
before_install:
|
||||
- npm install -g npm
|
||||
node_js:
|
||||
- "0.8"
|
||||
- "0.10"
|
||||
- "0.12"
|
||||
- "iojs"
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
## The MIT License (MIT) ##
|
||||
|
||||
Copyright (c) 2014 Hugh Kennedy
|
||||
|
||||
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.
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
# from2 [](https://flattr.com/submit/auto?user_id=hughskennedy&url=http://github.com/hughsk/from2&title=from2&description=hughsk/from2%20on%20GitHub&language=en_GB&tags=flattr,github,javascript&category=software)[](http://github.com/hughsk/stability-badges) #
|
||||
|
||||
`from2` is a high-level module for creating readable streams that properly handle backpressure.
|
||||
|
||||
Convience wrapper for
|
||||
[readable-stream](http://github.com/isaacs/readable-stream)'s `ReadableStream`
|
||||
base class, with an API lifted from
|
||||
[from](http://github.com/dominictarr/from) and
|
||||
[through2](http://github.com/rvagg/through2).
|
||||
|
||||
## Usage ##
|
||||
|
||||
[](https://nodei.co/npm/from2)
|
||||
|
||||
### `stream = from2([opts], read)` ###
|
||||
|
||||
Where `opts` are the options to pass on to the `ReadableStream` constructor,
|
||||
and `read(size, next)` is called when data is requested from the stream.
|
||||
|
||||
* `size` is the recommended amount of data (in bytes) to retrieve.
|
||||
* `next(err)` should be called when you're ready to emit more data.
|
||||
|
||||
For example, here's a readable stream that emits the contents of a given
|
||||
string:
|
||||
|
||||
``` javascript
|
||||
var from = require('from2')
|
||||
|
||||
function fromString(string) {
|
||||
return from(function(size, next) {
|
||||
// if there's no more content
|
||||
// left in the string, close the stream.
|
||||
if (string.length <= 0) return next(null, null)
|
||||
|
||||
// Pull in a new chunk of text,
|
||||
// removing it from the string.
|
||||
var chunk = string.slice(0, size)
|
||||
string = string.slice(size)
|
||||
|
||||
// Emit "chunk" from the stream.
|
||||
next(null, chunk)
|
||||
})
|
||||
}
|
||||
|
||||
// pipe "hello world" out
|
||||
// to stdout.
|
||||
fromString('hello world').pipe(process.stdout)
|
||||
```
|
||||
|
||||
### `stream = from2.obj([opts], read)` ###
|
||||
|
||||
Shorthand for `from2({ objectMode: true }, read)`.
|
||||
|
||||
### `createStream = from2.ctor([opts], read)` ###
|
||||
|
||||
If you're creating similar streams in quick succession you can improve
|
||||
performance by generating a stream **constructor** that you can reuse instead
|
||||
of creating one-off streams on each call.
|
||||
|
||||
Takes the same options as `from2`, instead returning a constructor which you
|
||||
can use to create new streams.
|
||||
|
||||
### See Also
|
||||
|
||||
- [from2-array](https://github.com/binocarlos/from2-array) - Create a from2 stream based on an array of source values.
|
||||
- [from2-string](https://github.com/yoshuawuyts/from2-string) - Create a stream from a string. Sugary wrapper around from2.
|
||||
|
||||
## License ##
|
||||
|
||||
MIT. See [LICENSE.md](http://github.com/hughsk/from2/blob/master/LICENSE.md) for details.
|
||||
|
|
@ -1,103 +0,0 @@
|
|||
var Readable = require('readable-stream').Readable
|
||||
var inherits = require('inherits')
|
||||
|
||||
module.exports = from2
|
||||
|
||||
from2.ctor = ctor
|
||||
from2.obj = obj
|
||||
|
||||
var Proto = ctor()
|
||||
|
||||
function toFunction(list) {
|
||||
list = list.slice()
|
||||
return function (_, cb) {
|
||||
var err = null
|
||||
var item = list.length ? list.shift() : null
|
||||
if (item instanceof Error) {
|
||||
err = item
|
||||
item = null
|
||||
}
|
||||
|
||||
cb(err, item)
|
||||
}
|
||||
}
|
||||
|
||||
function from2(opts, read) {
|
||||
if (typeof opts !== 'object' || Array.isArray(opts)) {
|
||||
read = opts
|
||||
opts = {}
|
||||
}
|
||||
|
||||
var rs = new Proto(opts)
|
||||
rs._from = Array.isArray(read) ? toFunction(read) : (read || noop)
|
||||
return rs
|
||||
}
|
||||
|
||||
function ctor(opts, read) {
|
||||
if (typeof opts === 'function') {
|
||||
read = opts
|
||||
opts = {}
|
||||
}
|
||||
|
||||
opts = defaults(opts)
|
||||
|
||||
inherits(Class, Readable)
|
||||
function Class(override) {
|
||||
if (!(this instanceof Class)) return new Class(override)
|
||||
this._reading = false
|
||||
this._callback = check
|
||||
this.destroyed = false
|
||||
Readable.call(this, override || opts)
|
||||
|
||||
var self = this
|
||||
var hwm = this._readableState.highWaterMark
|
||||
|
||||
function check(err, data) {
|
||||
if (self.destroyed) return
|
||||
if (err) return self.destroy(err)
|
||||
if (data === null) return self.push(null)
|
||||
self._reading = false
|
||||
if (self.push(data)) self._read(hwm)
|
||||
}
|
||||
}
|
||||
|
||||
Class.prototype._from = read || noop
|
||||
Class.prototype._read = function(size) {
|
||||
if (this._reading || this.destroyed) return
|
||||
this._reading = true
|
||||
this._from(size, this._callback)
|
||||
}
|
||||
|
||||
Class.prototype.destroy = function(err) {
|
||||
if (this.destroyed) return
|
||||
this.destroyed = true
|
||||
|
||||
var self = this
|
||||
process.nextTick(function() {
|
||||
if (err) self.emit('error', err)
|
||||
self.emit('close')
|
||||
})
|
||||
}
|
||||
|
||||
return Class
|
||||
}
|
||||
|
||||
function obj(opts, read) {
|
||||
if (typeof opts === 'function' || Array.isArray(opts)) {
|
||||
read = opts
|
||||
opts = {}
|
||||
}
|
||||
|
||||
opts = defaults(opts)
|
||||
opts.objectMode = true
|
||||
opts.highWaterMark = 16
|
||||
|
||||
return from2(opts, read)
|
||||
}
|
||||
|
||||
function noop () {}
|
||||
|
||||
function defaults(opts) {
|
||||
opts = opts || {}
|
||||
return opts
|
||||
}
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
{
|
||||
"name": "from2",
|
||||
"description": "Convenience wrapper for ReadableStream, with an API lifted from \"from\" and \"through2\"",
|
||||
"version": "2.3.0",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "node test"
|
||||
},
|
||||
"dependencies": {
|
||||
"inherits": "^2.0.1",
|
||||
"readable-stream": "^2.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"tape": "^4.0.0"
|
||||
},
|
||||
"author": "Hugh Kennedy <hughskennedy@gmail.com> (http://hughsk.io/)",
|
||||
"contributors": [
|
||||
"Mathias Buus <mathiasbuus@gmail.com>"
|
||||
],
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/hughsk/from2"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/hughsk/from2/issues"
|
||||
},
|
||||
"homepage": "https://github.com/hughsk/from2",
|
||||
"keywords": [
|
||||
"from",
|
||||
"stream",
|
||||
"readable",
|
||||
"pull",
|
||||
"convenience",
|
||||
"wrapper"
|
||||
]
|
||||
}
|
||||
123
advancedcontentfilter/vendor/npm-asset/from2/test.js
vendored
123
advancedcontentfilter/vendor/npm-asset/from2/test.js
vendored
|
|
@ -1,123 +0,0 @@
|
|||
var test = require('tape')
|
||||
var path = require('path')
|
||||
var from = require('./')
|
||||
var fs = require('fs')
|
||||
|
||||
var tmp = path.resolve(
|
||||
__dirname, 'tmp.txt'
|
||||
)
|
||||
|
||||
function fromString(string) {
|
||||
return from(function(size, next) {
|
||||
if (string.length <= 0) return next(null, null)
|
||||
var chunk = string.slice(0, size)
|
||||
string = string.slice(size)
|
||||
next(null, chunk)
|
||||
})
|
||||
}
|
||||
|
||||
test('from2', function(t) {
|
||||
var contents = fs.readFileSync(__filename, 'utf8')
|
||||
var stream = fromString(contents)
|
||||
|
||||
stream
|
||||
.pipe(fs.createWriteStream(tmp))
|
||||
.on('close', function() {
|
||||
t.equal(fs.readFileSync(tmp, 'utf8'), contents)
|
||||
fs.unlinkSync(tmp)
|
||||
t.end()
|
||||
})
|
||||
})
|
||||
|
||||
test('old mode', function(t) {
|
||||
var contents = fs.readFileSync(__filename, 'utf8')
|
||||
var stream = fromString(contents)
|
||||
var buffer = ''
|
||||
|
||||
stream.on('data', function(data) {
|
||||
buffer += data
|
||||
}).on('end', function() {
|
||||
t.equal(buffer, contents)
|
||||
t.end()
|
||||
})
|
||||
})
|
||||
|
||||
test('destroy', function(t) {
|
||||
var stream = from(function(size, next) {
|
||||
process.nextTick(function() {
|
||||
next(null, 'no')
|
||||
})
|
||||
})
|
||||
|
||||
stream.on('data', function(data) {
|
||||
t.ok(false)
|
||||
}).on('close', function() {
|
||||
t.ok(true)
|
||||
t.end()
|
||||
})
|
||||
|
||||
stream.destroy()
|
||||
})
|
||||
|
||||
test('arrays', function (t) {
|
||||
var input = ['a', 'b', 'c']
|
||||
var stream = from(input)
|
||||
var output = []
|
||||
stream.on('data', function (letter) {
|
||||
output.push(letter.toString())
|
||||
})
|
||||
stream.on('end', function () {
|
||||
t.deepEqual(input, output)
|
||||
t.end()
|
||||
})
|
||||
})
|
||||
|
||||
test('obj arrays', function (t) {
|
||||
var input = [{foo:'a'}, {foo:'b'}, {foo:'c'}]
|
||||
var stream = from.obj(input)
|
||||
var output = []
|
||||
stream.on('data', function (letter) {
|
||||
output.push(letter)
|
||||
})
|
||||
stream.on('end', function () {
|
||||
t.deepEqual(input, output)
|
||||
t.end()
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
test('arrays can emit errors', function (t) {
|
||||
var input = ['a', 'b', new Error('ooops'), 'c']
|
||||
var stream = from(input)
|
||||
var output = []
|
||||
stream.on('data', function (letter) {
|
||||
output.push(letter.toString())
|
||||
})
|
||||
stream.on('error', function(e){
|
||||
t.deepEqual(['a', 'b'], output)
|
||||
t.equal('ooops', e.message)
|
||||
t.end()
|
||||
})
|
||||
stream.on('end', function () {
|
||||
t.fail('the stream should have errored')
|
||||
})
|
||||
})
|
||||
|
||||
test('obj arrays can emit errors', function (t) {
|
||||
var input = [{foo:'a'}, {foo:'b'}, new Error('ooops'), {foo:'c'}]
|
||||
var stream = from.obj(input)
|
||||
var output = []
|
||||
stream.on('data', function (letter) {
|
||||
output.push(letter)
|
||||
})
|
||||
stream.on('error', function(e){
|
||||
t.deepEqual([{foo:'a'}, {foo:'b'}], output)
|
||||
t.equal('ooops', e.message)
|
||||
t.end()
|
||||
})
|
||||
stream.on('end', function () {
|
||||
t.fail('the stream should have errored')
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
'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;
|
||||
};
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
'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}));
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
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.
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
{
|
||||
"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
|
||||
}
|
||||
}
|
||||
|
|
@ -1,117 +0,0 @@
|
|||
# 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)
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
'use strict';
|
||||
const urlLib = require('url');
|
||||
const http = require('http');
|
||||
const PCancelable = require('p-cancelable');
|
||||
const is = require('@sindresorhus/is');
|
||||
|
||||
class GotError extends Error {
|
||||
constructor(message, error, opts) {
|
||||
super(message);
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
this.name = 'GotError';
|
||||
|
||||
if (!is.undefined(error.code)) {
|
||||
this.code = error.code;
|
||||
}
|
||||
|
||||
Object.assign(this, {
|
||||
host: opts.host,
|
||||
hostname: opts.hostname,
|
||||
method: opts.method,
|
||||
path: opts.path,
|
||||
protocol: opts.protocol,
|
||||
url: opts.href
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.GotError = GotError;
|
||||
|
||||
module.exports.CacheError = class extends GotError {
|
||||
constructor(error, opts) {
|
||||
super(error.message, error, opts);
|
||||
this.name = 'CacheError';
|
||||
}
|
||||
};
|
||||
|
||||
module.exports.RequestError = class extends GotError {
|
||||
constructor(error, opts) {
|
||||
super(error.message, error, opts);
|
||||
this.name = 'RequestError';
|
||||
}
|
||||
};
|
||||
|
||||
module.exports.ReadError = class extends GotError {
|
||||
constructor(error, opts) {
|
||||
super(error.message, error, opts);
|
||||
this.name = 'ReadError';
|
||||
}
|
||||
};
|
||||
|
||||
module.exports.ParseError = class extends GotError {
|
||||
constructor(error, statusCode, opts, data) {
|
||||
super(`${error.message} in "${urlLib.format(opts)}": \n${data.slice(0, 77)}...`, error, opts);
|
||||
this.name = 'ParseError';
|
||||
this.statusCode = statusCode;
|
||||
this.statusMessage = http.STATUS_CODES[this.statusCode];
|
||||
}
|
||||
};
|
||||
|
||||
module.exports.HTTPError = class extends GotError {
|
||||
constructor(statusCode, statusMessage, headers, opts) {
|
||||
if (statusMessage) {
|
||||
statusMessage = statusMessage.replace(/\r?\n/g, ' ').trim();
|
||||
} else {
|
||||
statusMessage = http.STATUS_CODES[statusCode];
|
||||
}
|
||||
super(`Response code ${statusCode} (${statusMessage})`, {}, opts);
|
||||
this.name = 'HTTPError';
|
||||
this.statusCode = statusCode;
|
||||
this.statusMessage = statusMessage;
|
||||
this.headers = headers;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports.MaxRedirectsError = class extends GotError {
|
||||
constructor(statusCode, redirectUrls, opts) {
|
||||
super('Redirected 10 times. Aborting.', {}, opts);
|
||||
this.name = 'MaxRedirectsError';
|
||||
this.statusCode = statusCode;
|
||||
this.statusMessage = http.STATUS_CODES[this.statusCode];
|
||||
this.redirectUrls = redirectUrls;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports.UnsupportedProtocolError = class extends GotError {
|
||||
constructor(opts) {
|
||||
super(`Unsupported protocol "${opts.protocol}"`, {}, opts);
|
||||
this.name = 'UnsupportedProtocolError';
|
||||
}
|
||||
};
|
||||
|
||||
module.exports.CancelError = PCancelable.CancelError;
|
||||
661
advancedcontentfilter/vendor/npm-asset/got/index.js
vendored
661
advancedcontentfilter/vendor/npm-asset/got/index.js
vendored
|
|
@ -1,661 +0,0 @@
|
|||
'use strict';
|
||||
const EventEmitter = require('events');
|
||||
const http = require('http');
|
||||
const https = require('https');
|
||||
const PassThrough = require('stream').PassThrough;
|
||||
const Transform = require('stream').Transform;
|
||||
const urlLib = require('url');
|
||||
const fs = require('fs');
|
||||
const querystring = require('querystring');
|
||||
const CacheableRequest = require('cacheable-request');
|
||||
const duplexer3 = require('duplexer3');
|
||||
const intoStream = require('into-stream');
|
||||
const is = require('@sindresorhus/is');
|
||||
const getStream = require('get-stream');
|
||||
const timedOut = require('timed-out');
|
||||
const urlParseLax = require('url-parse-lax');
|
||||
const urlToOptions = require('url-to-options');
|
||||
const lowercaseKeys = require('lowercase-keys');
|
||||
const decompressResponse = require('decompress-response');
|
||||
const mimicResponse = require('mimic-response');
|
||||
const isRetryAllowed = require('is-retry-allowed');
|
||||
const isURL = require('isurl');
|
||||
const PCancelable = require('p-cancelable');
|
||||
const pTimeout = require('p-timeout');
|
||||
const pify = require('pify');
|
||||
const Buffer = require('safe-buffer').Buffer;
|
||||
const pkg = require('./package.json');
|
||||
const errors = require('./errors');
|
||||
|
||||
const getMethodRedirectCodes = new Set([300, 301, 302, 303, 304, 305, 307, 308]);
|
||||
const allMethodRedirectCodes = new Set([300, 303, 307, 308]);
|
||||
|
||||
const isFormData = body => is.nodeStream(body) && is.function(body.getBoundary);
|
||||
|
||||
const getBodySize = opts => {
|
||||
const body = opts.body;
|
||||
|
||||
if (opts.headers['content-length']) {
|
||||
return Number(opts.headers['content-length']);
|
||||
}
|
||||
|
||||
if (!body && !opts.stream) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (is.string(body)) {
|
||||
return Buffer.byteLength(body);
|
||||
}
|
||||
|
||||
if (isFormData(body)) {
|
||||
return pify(body.getLength.bind(body))();
|
||||
}
|
||||
|
||||
if (body instanceof fs.ReadStream) {
|
||||
return pify(fs.stat)(body.path).then(stat => stat.size);
|
||||
}
|
||||
|
||||
if (is.nodeStream(body) && is.buffer(body._buffer)) {
|
||||
return body._buffer.length;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
function requestAsEventEmitter(opts) {
|
||||
opts = opts || {};
|
||||
|
||||
const ee = new EventEmitter();
|
||||
const requestUrl = opts.href || urlLib.resolve(urlLib.format(opts), opts.path);
|
||||
const redirects = [];
|
||||
const agents = is.object(opts.agent) ? opts.agent : null;
|
||||
let retryCount = 0;
|
||||
let redirectUrl;
|
||||
let uploadBodySize;
|
||||
let uploaded = 0;
|
||||
|
||||
const get = opts => {
|
||||
if (opts.protocol !== 'http:' && opts.protocol !== 'https:') {
|
||||
ee.emit('error', new got.UnsupportedProtocolError(opts));
|
||||
return;
|
||||
}
|
||||
|
||||
let fn = opts.protocol === 'https:' ? https : http;
|
||||
|
||||
if (agents) {
|
||||
const protocolName = opts.protocol === 'https:' ? 'https' : 'http';
|
||||
opts.agent = agents[protocolName] || opts.agent;
|
||||
}
|
||||
|
||||
if (opts.useElectronNet && process.versions.electron) {
|
||||
const electron = require('electron');
|
||||
fn = electron.net || electron.remote.net;
|
||||
}
|
||||
|
||||
let progressInterval;
|
||||
|
||||
const cacheableRequest = new CacheableRequest(fn.request, opts.cache);
|
||||
const cacheReq = cacheableRequest(opts, res => {
|
||||
clearInterval(progressInterval);
|
||||
|
||||
ee.emit('uploadProgress', {
|
||||
percent: 1,
|
||||
transferred: uploaded,
|
||||
total: uploadBodySize
|
||||
});
|
||||
|
||||
const statusCode = res.statusCode;
|
||||
|
||||
res.url = redirectUrl || requestUrl;
|
||||
res.requestUrl = requestUrl;
|
||||
|
||||
const followRedirect = opts.followRedirect && 'location' in res.headers;
|
||||
const redirectGet = followRedirect && getMethodRedirectCodes.has(statusCode);
|
||||
const redirectAll = followRedirect && allMethodRedirectCodes.has(statusCode);
|
||||
|
||||
if (redirectAll || (redirectGet && (opts.method === 'GET' || opts.method === 'HEAD'))) {
|
||||
res.resume();
|
||||
|
||||
if (statusCode === 303) {
|
||||
// Server responded with "see other", indicating that the resource exists at another location,
|
||||
// and the client should request it from that location via GET or HEAD.
|
||||
opts.method = 'GET';
|
||||
}
|
||||
|
||||
if (redirects.length >= 10) {
|
||||
ee.emit('error', new got.MaxRedirectsError(statusCode, redirects, opts), null, res);
|
||||
return;
|
||||
}
|
||||
|
||||
const bufferString = Buffer.from(res.headers.location, 'binary').toString();
|
||||
|
||||
redirectUrl = urlLib.resolve(urlLib.format(opts), bufferString);
|
||||
|
||||
redirects.push(redirectUrl);
|
||||
|
||||
const redirectOpts = Object.assign({}, opts, urlLib.parse(redirectUrl));
|
||||
|
||||
ee.emit('redirect', res, redirectOpts);
|
||||
|
||||
get(redirectOpts);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
setImmediate(() => {
|
||||
try {
|
||||
getResponse(res, opts, ee, redirects);
|
||||
} catch (e) {
|
||||
ee.emit('error', e);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
cacheReq.on('error', err => {
|
||||
if (err instanceof CacheableRequest.RequestError) {
|
||||
ee.emit('error', new got.RequestError(err, opts));
|
||||
} else {
|
||||
ee.emit('error', new got.CacheError(err, opts));
|
||||
}
|
||||
});
|
||||
|
||||
cacheReq.once('request', req => {
|
||||
let aborted = false;
|
||||
req.once('abort', _ => {
|
||||
aborted = true;
|
||||
});
|
||||
|
||||
req.once('error', err => {
|
||||
clearInterval(progressInterval);
|
||||
|
||||
if (aborted) {
|
||||
return;
|
||||
}
|
||||
|
||||
const backoff = opts.retries(++retryCount, err);
|
||||
|
||||
if (backoff) {
|
||||
setTimeout(get, backoff, opts);
|
||||
return;
|
||||
}
|
||||
|
||||
ee.emit('error', new got.RequestError(err, opts));
|
||||
});
|
||||
|
||||
ee.once('request', req => {
|
||||
ee.emit('uploadProgress', {
|
||||
percent: 0,
|
||||
transferred: 0,
|
||||
total: uploadBodySize
|
||||
});
|
||||
|
||||
const socket = req.connection;
|
||||
if (socket) {
|
||||
// `._connecting` was the old property which was made public in node v6.1.0
|
||||
const isConnecting = socket.connecting === undefined ? socket._connecting : socket.connecting;
|
||||
|
||||
const onSocketConnect = () => {
|
||||
const uploadEventFrequency = 150;
|
||||
|
||||
progressInterval = setInterval(() => {
|
||||
const lastUploaded = uploaded;
|
||||
const headersSize = Buffer.byteLength(req._header);
|
||||
uploaded = socket.bytesWritten - headersSize;
|
||||
|
||||
// Prevent the known issue of `bytesWritten` being larger than body size
|
||||
if (uploadBodySize && uploaded > uploadBodySize) {
|
||||
uploaded = uploadBodySize;
|
||||
}
|
||||
|
||||
// Don't emit events with unchanged progress and
|
||||
// prevent last event from being emitted, because
|
||||
// it's emitted when `response` is emitted
|
||||
if (uploaded === lastUploaded || uploaded === uploadBodySize) {
|
||||
return;
|
||||
}
|
||||
|
||||
ee.emit('uploadProgress', {
|
||||
percent: uploadBodySize ? uploaded / uploadBodySize : 0,
|
||||
transferred: uploaded,
|
||||
total: uploadBodySize
|
||||
});
|
||||
}, uploadEventFrequency);
|
||||
};
|
||||
|
||||
// Only subscribe to 'connect' event if we're actually connecting a new
|
||||
// socket, otherwise if we're already connected (because this is a
|
||||
// keep-alive connection) do not bother. This is important since we won't
|
||||
// get a 'connect' event for an already connected socket.
|
||||
if (isConnecting) {
|
||||
socket.once('connect', onSocketConnect);
|
||||
} else {
|
||||
onSocketConnect();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (opts.gotTimeout) {
|
||||
clearInterval(progressInterval);
|
||||
timedOut(req, opts.gotTimeout);
|
||||
}
|
||||
|
||||
setImmediate(() => {
|
||||
ee.emit('request', req);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
setImmediate(() => {
|
||||
Promise.resolve(getBodySize(opts))
|
||||
.then(size => {
|
||||
uploadBodySize = size;
|
||||
get(opts);
|
||||
})
|
||||
.catch(err => {
|
||||
ee.emit('error', err);
|
||||
});
|
||||
});
|
||||
|
||||
return ee;
|
||||
}
|
||||
|
||||
function getResponse(res, opts, ee, redirects) {
|
||||
const downloadBodySize = Number(res.headers['content-length']) || null;
|
||||
let downloaded = 0;
|
||||
|
||||
const progressStream = new Transform({
|
||||
transform(chunk, encoding, callback) {
|
||||
downloaded += chunk.length;
|
||||
|
||||
const percent = downloadBodySize ? downloaded / downloadBodySize : 0;
|
||||
|
||||
// Let flush() be responsible for emitting the last event
|
||||
if (percent < 1) {
|
||||
ee.emit('downloadProgress', {
|
||||
percent,
|
||||
transferred: downloaded,
|
||||
total: downloadBodySize
|
||||
});
|
||||
}
|
||||
|
||||
callback(null, chunk);
|
||||
},
|
||||
|
||||
flush(callback) {
|
||||
ee.emit('downloadProgress', {
|
||||
percent: 1,
|
||||
transferred: downloaded,
|
||||
total: downloadBodySize
|
||||
});
|
||||
|
||||
callback();
|
||||
}
|
||||
});
|
||||
|
||||
mimicResponse(res, progressStream);
|
||||
progressStream.redirectUrls = redirects;
|
||||
|
||||
const response = opts.decompress === true &&
|
||||
is.function(decompressResponse) &&
|
||||
opts.method !== 'HEAD' ? decompressResponse(progressStream) : progressStream;
|
||||
|
||||
if (!opts.decompress && ['gzip', 'deflate'].indexOf(res.headers['content-encoding']) !== -1) {
|
||||
opts.encoding = null;
|
||||
}
|
||||
|
||||
ee.emit('response', response);
|
||||
|
||||
ee.emit('downloadProgress', {
|
||||
percent: 0,
|
||||
transferred: 0,
|
||||
total: downloadBodySize
|
||||
});
|
||||
|
||||
res.pipe(progressStream);
|
||||
}
|
||||
|
||||
function asPromise(opts) {
|
||||
const timeoutFn = requestPromise => opts.gotTimeout && opts.gotTimeout.request ?
|
||||
pTimeout(requestPromise, opts.gotTimeout.request, new got.RequestError({message: 'Request timed out', code: 'ETIMEDOUT'}, opts)) :
|
||||
requestPromise;
|
||||
|
||||
const proxy = new EventEmitter();
|
||||
|
||||
const cancelable = new PCancelable((resolve, reject, onCancel) => {
|
||||
const ee = requestAsEventEmitter(opts);
|
||||
let cancelOnRequest = false;
|
||||
|
||||
onCancel(() => {
|
||||
cancelOnRequest = true;
|
||||
});
|
||||
|
||||
ee.on('request', req => {
|
||||
if (cancelOnRequest) {
|
||||
req.abort();
|
||||
}
|
||||
|
||||
onCancel(() => {
|
||||
req.abort();
|
||||
});
|
||||
|
||||
if (is.nodeStream(opts.body)) {
|
||||
opts.body.pipe(req);
|
||||
opts.body = undefined;
|
||||
return;
|
||||
}
|
||||
|
||||
req.end(opts.body);
|
||||
});
|
||||
|
||||
ee.on('response', res => {
|
||||
const stream = is.null(opts.encoding) ? getStream.buffer(res) : getStream(res, opts);
|
||||
|
||||
stream
|
||||
.catch(err => reject(new got.ReadError(err, opts)))
|
||||
.then(data => {
|
||||
const statusCode = res.statusCode;
|
||||
const limitStatusCode = opts.followRedirect ? 299 : 399;
|
||||
|
||||
res.body = data;
|
||||
|
||||
if (opts.json && res.body) {
|
||||
try {
|
||||
res.body = JSON.parse(res.body);
|
||||
} catch (err) {
|
||||
if (statusCode >= 200 && statusCode < 300) {
|
||||
throw new got.ParseError(err, statusCode, opts, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (opts.throwHttpErrors && statusCode !== 304 && (statusCode < 200 || statusCode > limitStatusCode)) {
|
||||
throw new got.HTTPError(statusCode, res.statusMessage, res.headers, opts);
|
||||
}
|
||||
|
||||
resolve(res);
|
||||
})
|
||||
.catch(err => {
|
||||
Object.defineProperty(err, 'response', {value: res});
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
|
||||
ee.once('error', reject);
|
||||
ee.on('redirect', proxy.emit.bind(proxy, 'redirect'));
|
||||
ee.on('uploadProgress', proxy.emit.bind(proxy, 'uploadProgress'));
|
||||
ee.on('downloadProgress', proxy.emit.bind(proxy, 'downloadProgress'));
|
||||
});
|
||||
|
||||
// Preserve backwards-compatibility
|
||||
// TODO: Remove this in the next major version
|
||||
Object.defineProperty(cancelable, 'canceled', {
|
||||
get() {
|
||||
return cancelable.isCanceled;
|
||||
}
|
||||
});
|
||||
|
||||
const promise = timeoutFn(cancelable);
|
||||
|
||||
promise.cancel = cancelable.cancel.bind(cancelable);
|
||||
|
||||
promise.on = (name, fn) => {
|
||||
proxy.on(name, fn);
|
||||
return promise;
|
||||
};
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
function asStream(opts) {
|
||||
opts.stream = true;
|
||||
|
||||
const input = new PassThrough();
|
||||
const output = new PassThrough();
|
||||
const proxy = duplexer3(input, output);
|
||||
let timeout;
|
||||
|
||||
if (opts.gotTimeout && opts.gotTimeout.request) {
|
||||
timeout = setTimeout(() => {
|
||||
proxy.emit('error', new got.RequestError({message: 'Request timed out', code: 'ETIMEDOUT'}, opts));
|
||||
}, opts.gotTimeout.request);
|
||||
}
|
||||
|
||||
if (opts.json) {
|
||||
throw new Error('Got can not be used as a stream when the `json` option is used');
|
||||
}
|
||||
|
||||
if (opts.body) {
|
||||
proxy.write = () => {
|
||||
throw new Error('Got\'s stream is not writable when the `body` option is used');
|
||||
};
|
||||
}
|
||||
|
||||
const ee = requestAsEventEmitter(opts);
|
||||
|
||||
ee.on('request', req => {
|
||||
proxy.emit('request', req);
|
||||
|
||||
if (is.nodeStream(opts.body)) {
|
||||
opts.body.pipe(req);
|
||||
return;
|
||||
}
|
||||
|
||||
if (opts.body) {
|
||||
req.end(opts.body);
|
||||
return;
|
||||
}
|
||||
|
||||
if (opts.method === 'POST' || opts.method === 'PUT' || opts.method === 'PATCH') {
|
||||
input.pipe(req);
|
||||
return;
|
||||
}
|
||||
|
||||
req.end();
|
||||
});
|
||||
|
||||
ee.on('response', res => {
|
||||
clearTimeout(timeout);
|
||||
|
||||
const statusCode = res.statusCode;
|
||||
|
||||
res.on('error', err => {
|
||||
proxy.emit('error', new got.ReadError(err, opts));
|
||||
});
|
||||
|
||||
res.pipe(output);
|
||||
|
||||
if (opts.throwHttpErrors && statusCode !== 304 && (statusCode < 200 || statusCode > 299)) {
|
||||
proxy.emit('error', new got.HTTPError(statusCode, res.statusMessage, res.headers, opts), null, res);
|
||||
return;
|
||||
}
|
||||
|
||||
proxy.emit('response', res);
|
||||
});
|
||||
|
||||
ee.on('error', proxy.emit.bind(proxy, 'error'));
|
||||
ee.on('redirect', proxy.emit.bind(proxy, 'redirect'));
|
||||
ee.on('uploadProgress', proxy.emit.bind(proxy, 'uploadProgress'));
|
||||
ee.on('downloadProgress', proxy.emit.bind(proxy, 'downloadProgress'));
|
||||
|
||||
return proxy;
|
||||
}
|
||||
|
||||
function normalizeArguments(url, opts) {
|
||||
if (!is.string(url) && !is.object(url)) {
|
||||
throw new TypeError(`Parameter \`url\` must be a string or object, not ${is(url)}`);
|
||||
} else if (is.string(url)) {
|
||||
url = url.replace(/^unix:/, 'http://$&');
|
||||
|
||||
try {
|
||||
decodeURI(url);
|
||||
} catch (err) {
|
||||
throw new Error('Parameter `url` must contain valid UTF-8 character sequences');
|
||||
}
|
||||
|
||||
url = urlParseLax(url);
|
||||
if (url.auth) {
|
||||
throw new Error('Basic authentication must be done with the `auth` option');
|
||||
}
|
||||
} else if (isURL.lenient(url)) {
|
||||
url = urlToOptions(url);
|
||||
}
|
||||
|
||||
opts = Object.assign(
|
||||
{
|
||||
path: '',
|
||||
retries: 2,
|
||||
cache: false,
|
||||
decompress: true,
|
||||
useElectronNet: false,
|
||||
throwHttpErrors: true
|
||||
},
|
||||
url,
|
||||
{
|
||||
protocol: url.protocol || 'http:' // Override both null/undefined with default protocol
|
||||
},
|
||||
opts
|
||||
);
|
||||
|
||||
const headers = lowercaseKeys(opts.headers);
|
||||
for (const key of Object.keys(headers)) {
|
||||
if (is.nullOrUndefined(headers[key])) {
|
||||
delete headers[key];
|
||||
}
|
||||
}
|
||||
|
||||
opts.headers = Object.assign({
|
||||
'user-agent': `${pkg.name}/${pkg.version} (https://github.com/sindresorhus/got)`
|
||||
}, headers);
|
||||
|
||||
if (opts.decompress) {
|
||||
opts.headers['accept-encoding'] = 'gzip,deflate';
|
||||
}
|
||||
|
||||
const query = opts.query;
|
||||
|
||||
if (query) {
|
||||
if (!is.string(query)) {
|
||||
opts.query = querystring.stringify(query);
|
||||
}
|
||||
|
||||
opts.path = `${opts.path.split('?')[0]}?${opts.query}`;
|
||||
delete opts.query;
|
||||
}
|
||||
|
||||
if (opts.json && is.undefined(opts.headers.accept)) {
|
||||
opts.headers.accept = 'application/json';
|
||||
}
|
||||
|
||||
const body = opts.body;
|
||||
if (is.nullOrUndefined(body)) {
|
||||
opts.method = (opts.method || 'GET').toUpperCase();
|
||||
} else {
|
||||
const headers = opts.headers;
|
||||
if (!is.nodeStream(body) && !is.string(body) && !is.buffer(body) && !(opts.form || opts.json)) {
|
||||
throw new TypeError('The `body` option must be a stream.Readable, string, Buffer or plain Object');
|
||||
}
|
||||
|
||||
const canBodyBeStringified = is.plainObject(body) || is.array(body);
|
||||
if ((opts.form || opts.json) && !canBodyBeStringified) {
|
||||
throw new TypeError('The `body` option must be a plain Object or Array when the `form` or `json` option is used');
|
||||
}
|
||||
|
||||
if (isFormData(body)) {
|
||||
// Special case for https://github.com/form-data/form-data
|
||||
headers['content-type'] = headers['content-type'] || `multipart/form-data; boundary=${body.getBoundary()}`;
|
||||
} else if (opts.form && canBodyBeStringified) {
|
||||
headers['content-type'] = headers['content-type'] || 'application/x-www-form-urlencoded';
|
||||
opts.body = querystring.stringify(body);
|
||||
} else if (opts.json && canBodyBeStringified) {
|
||||
headers['content-type'] = headers['content-type'] || 'application/json';
|
||||
opts.body = JSON.stringify(body);
|
||||
}
|
||||
|
||||
if (is.undefined(headers['content-length']) && is.undefined(headers['transfer-encoding']) && !is.nodeStream(body)) {
|
||||
const length = is.string(opts.body) ? Buffer.byteLength(opts.body) : opts.body.length;
|
||||
headers['content-length'] = length;
|
||||
}
|
||||
|
||||
// Convert buffer to stream to receive upload progress events
|
||||
// see https://github.com/sindresorhus/got/pull/322
|
||||
if (is.buffer(body)) {
|
||||
opts.body = intoStream(body);
|
||||
opts.body._buffer = body;
|
||||
}
|
||||
|
||||
opts.method = (opts.method || 'POST').toUpperCase();
|
||||
}
|
||||
|
||||
if (opts.hostname === 'unix') {
|
||||
const matches = /(.+?):(.+)/.exec(opts.path);
|
||||
|
||||
if (matches) {
|
||||
opts.socketPath = matches[1];
|
||||
opts.path = matches[2];
|
||||
opts.host = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is.function(opts.retries)) {
|
||||
const retries = opts.retries;
|
||||
|
||||
opts.retries = (iter, err) => {
|
||||
if (iter > retries || !isRetryAllowed(err)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const noise = Math.random() * 100;
|
||||
|
||||
return ((1 << iter) * 1000) + noise;
|
||||
};
|
||||
}
|
||||
|
||||
if (is.undefined(opts.followRedirect)) {
|
||||
opts.followRedirect = true;
|
||||
}
|
||||
|
||||
if (opts.timeout) {
|
||||
if (is.number(opts.timeout)) {
|
||||
opts.gotTimeout = {request: opts.timeout};
|
||||
} else {
|
||||
opts.gotTimeout = opts.timeout;
|
||||
}
|
||||
delete opts.timeout;
|
||||
}
|
||||
|
||||
return opts;
|
||||
}
|
||||
|
||||
function got(url, opts) {
|
||||
try {
|
||||
const normalizedArgs = normalizeArguments(url, opts);
|
||||
|
||||
if (normalizedArgs.stream) {
|
||||
return asStream(normalizedArgs);
|
||||
}
|
||||
|
||||
return asPromise(normalizedArgs);
|
||||
} catch (err) {
|
||||
return Promise.reject(err);
|
||||
}
|
||||
}
|
||||
|
||||
got.stream = (url, opts) => asStream(normalizeArguments(url, opts));
|
||||
|
||||
const methods = [
|
||||
'get',
|
||||
'post',
|
||||
'put',
|
||||
'patch',
|
||||
'head',
|
||||
'delete'
|
||||
];
|
||||
|
||||
for (const method of methods) {
|
||||
got[method] = (url, opts) => got(url, Object.assign({}, opts, {method}));
|
||||
got.stream[method] = (url, opts) => got.stream(url, Object.assign({}, opts, {method}));
|
||||
}
|
||||
|
||||
Object.assign(got, errors);
|
||||
|
||||
module.exports = got;
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
MIT License
|
||||
|
||||
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.
|
||||
|
|
@ -1,95 +0,0 @@
|
|||
{
|
||||
"name": "got",
|
||||
"version": "8.3.0",
|
||||
"description": "Simplified HTTP requests",
|
||||
"license": "MIT",
|
||||
"repository": "sindresorhus/got",
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "Sindre Sorhus",
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"url": "sindresorhus.com"
|
||||
},
|
||||
{
|
||||
"name": "Vsevolod Strukchinsky",
|
||||
"email": "floatdrop@gmail.com",
|
||||
"url": "github.com/floatdrop"
|
||||
},
|
||||
{
|
||||
"name": "Alexander Tesfamichael",
|
||||
"email": "alex.tesfamichael@gmail.com",
|
||||
"url": "alextes.me"
|
||||
}
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "xo && nyc ava",
|
||||
"coveralls": "nyc report --reporter=text-lcov | coveralls"
|
||||
},
|
||||
"files": [
|
||||
"index.js",
|
||||
"errors.js"
|
||||
],
|
||||
"keywords": [
|
||||
"http",
|
||||
"https",
|
||||
"get",
|
||||
"got",
|
||||
"url",
|
||||
"uri",
|
||||
"request",
|
||||
"util",
|
||||
"utility",
|
||||
"simple",
|
||||
"curl",
|
||||
"wget",
|
||||
"fetch",
|
||||
"net",
|
||||
"network",
|
||||
"electron"
|
||||
],
|
||||
"dependencies": {
|
||||
"@sindresorhus/is": "^0.7.0",
|
||||
"cacheable-request": "^2.1.1",
|
||||
"decompress-response": "^3.3.0",
|
||||
"duplexer3": "^0.1.4",
|
||||
"get-stream": "^3.0.0",
|
||||
"into-stream": "^3.1.0",
|
||||
"is-retry-allowed": "^1.1.0",
|
||||
"isurl": "^1.0.0-alpha5",
|
||||
"lowercase-keys": "^1.0.0",
|
||||
"mimic-response": "^1.0.0",
|
||||
"p-cancelable": "^0.4.0",
|
||||
"p-timeout": "^2.0.1",
|
||||
"pify": "^3.0.0",
|
||||
"safe-buffer": "^5.1.1",
|
||||
"timed-out": "^4.0.1",
|
||||
"url-parse-lax": "^3.0.0",
|
||||
"url-to-options": "^1.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"ava": "^0.25.0",
|
||||
"coveralls": "^3.0.0",
|
||||
"form-data": "^2.1.1",
|
||||
"get-port": "^3.0.0",
|
||||
"nyc": "^11.0.2",
|
||||
"p-event": "^1.3.0",
|
||||
"pem": "^1.4.4",
|
||||
"proxyquire": "^1.8.0",
|
||||
"sinon": "^4.0.0",
|
||||
"slow-stream": "0.0.4",
|
||||
"tempfile": "^2.0.0",
|
||||
"tempy": "^0.2.1",
|
||||
"universal-url": "1.0.0-alpha",
|
||||
"xo": "^0.20.0"
|
||||
},
|
||||
"ava": {
|
||||
"concurrency": 4
|
||||
},
|
||||
"browser": {
|
||||
"decompress-response": false,
|
||||
"electron": false
|
||||
}
|
||||
}
|
||||
650
advancedcontentfilter/vendor/npm-asset/got/readme.md
vendored
650
advancedcontentfilter/vendor/npm-asset/got/readme.md
vendored
|
|
@ -1,650 +0,0 @@
|
|||
<div align="center">
|
||||
<br>
|
||||
<br>
|
||||
<img width="360" src="https://rawgit.com/sindresorhus/got/master/media/logo.svg" alt="got">
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<p align="center">Huge thanks to <a href="https://moxy.studio"><img src="https://sindresorhus.com/assets/thanks/moxy-logo.svg" width="150"></a> for sponsoring me!
|
||||
</p>
|
||||
<br>
|
||||
<br>
|
||||
</div>
|
||||
|
||||
> Simplified HTTP requests
|
||||
|
||||
[](https://travis-ci.org/sindresorhus/got) [](https://coveralls.io/github/sindresorhus/got?branch=master) [](https://npmjs.com/got)
|
||||
|
||||
A nicer interface to the built-in [`http`](http://nodejs.org/api/http.html) module.
|
||||
|
||||
Created because [`request`](https://github.com/request/request) is bloated *(several megabytes!)*.
|
||||
|
||||
|
||||
## Highlights
|
||||
|
||||
- [Promise & stream API](#api)
|
||||
- [Request cancelation](#aborting-the-request)
|
||||
- [RFC compliant caching](#cache-adapters)
|
||||
- [Follows redirects](#followredirect)
|
||||
- [Retries on network failure](#retries)
|
||||
- [Progress events](#onuploadprogress-progress)
|
||||
- [Handles gzip/deflate](#decompress)
|
||||
- [Timeout handling](#timeout)
|
||||
- [Errors with metadata](#errors)
|
||||
- [JSON mode](#json)
|
||||
- [WHATWG URL support](#url)
|
||||
- [Electron support](#useelectronnet)
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install got
|
||||
```
|
||||
|
||||
<a href="https://www.patreon.com/sindresorhus">
|
||||
<img src="https://c5.patreon.com/external/logo/become_a_patron_button@2x.png" width="160">
|
||||
</a>
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const got = require('got');
|
||||
|
||||
(async () => {
|
||||
try {
|
||||
const response = await got('sindresorhus.com');
|
||||
console.log(response.body);
|
||||
//=> '<!doctype html> ...'
|
||||
} catch (error) {
|
||||
console.log(error.response.body);
|
||||
//=> 'Internal server error ...'
|
||||
}
|
||||
})();
|
||||
```
|
||||
|
||||
###### Streams
|
||||
|
||||
```js
|
||||
const fs = require('fs');
|
||||
const got = require('got');
|
||||
|
||||
got.stream('sindresorhus.com').pipe(fs.createWriteStream('index.html'));
|
||||
|
||||
// For POST, PUT, and PATCH methods `got.stream` returns a `stream.Writable`
|
||||
fs.createReadStream('index.html').pipe(got.stream.post('sindresorhus.com'));
|
||||
```
|
||||
|
||||
|
||||
### API
|
||||
|
||||
It's a `GET` request by default, but can be changed by using different methods or in the `options`.
|
||||
|
||||
#### got(url, [options])
|
||||
|
||||
Returns a Promise for a `response` object with a `body` property, a `url` property with the request URL or the final URL after redirects, and a `requestUrl` property with the original request URL.
|
||||
|
||||
The response object will normally be a [Node.js HTTP response stream](https://nodejs.org/api/http.html#http_class_http_incomingmessage), however if returned from the cache it will be a [responselike object](https://github.com/lukechilds/responselike) which behaves in the same way.
|
||||
|
||||
The response will also have a `fromCache` property set with a boolean value.
|
||||
|
||||
##### url
|
||||
|
||||
Type: `string` `Object`
|
||||
|
||||
The URL to request as simple string, a [`http.request` options](https://nodejs.org/api/http.html#http_http_request_options_callback), or a [WHATWG `URL`](https://nodejs.org/api/url.html#url_class_url).
|
||||
|
||||
Properties from `options` will override properties in the parsed `url`.
|
||||
|
||||
If no protocol is specified, it will default to `https`.
|
||||
|
||||
##### options
|
||||
|
||||
Type: `Object`
|
||||
|
||||
Any of the [`http.request`](http://nodejs.org/api/http.html#http_http_request_options_callback) options.
|
||||
|
||||
###### stream
|
||||
|
||||
Type: `boolean`<br>
|
||||
Default: `false`
|
||||
|
||||
Returns a `Stream` instead of a `Promise`. This is equivalent to calling `got.stream(url, [options])`.
|
||||
|
||||
###### body
|
||||
|
||||
Type: `string` `Buffer` `stream.Readable`
|
||||
|
||||
*This is mutually exclusive with stream mode.*
|
||||
|
||||
Body that will be sent with a `POST` request.
|
||||
|
||||
If present in `options` and `options.method` is not set, `options.method` will be set to `POST`.
|
||||
|
||||
If `content-length` or `transfer-encoding` is not set in `options.headers` and `body` is a string or buffer, `content-length` will be set to the body length.
|
||||
|
||||
###### encoding
|
||||
|
||||
Type: `string` `null`<br>
|
||||
Default: `'utf8'`
|
||||
|
||||
[Encoding](https://nodejs.org/api/buffer.html#buffer_buffers_and_character_encodings) to be used on `setEncoding` of the response data. If `null`, the body is returned as a [`Buffer`](https://nodejs.org/api/buffer.html) (binary data).
|
||||
|
||||
###### form
|
||||
|
||||
Type: `boolean`<br>
|
||||
Default: `false`
|
||||
|
||||
*This is mutually exclusive with stream mode.*
|
||||
|
||||
If set to `true` and `Content-Type` header is not set, it will be set to `application/x-www-form-urlencoded`.
|
||||
|
||||
`body` must be a plain object or array and will be stringified.
|
||||
|
||||
###### json
|
||||
|
||||
Type: `boolean`<br>
|
||||
Default: `false`
|
||||
|
||||
*This is mutually exclusive with stream mode.*
|
||||
|
||||
If set to `true` and `Content-Type` header is not set, it will be set to `application/json`.
|
||||
|
||||
Parse response body with `JSON.parse` and set `accept` header to `application/json`. If used in conjunction with the `form` option, the `body` will the stringified as querystring and the response parsed as JSON.
|
||||
|
||||
`body` must be a plain object or array and will be stringified.
|
||||
|
||||
###### query
|
||||
|
||||
Type: `string` `Object`<br>
|
||||
|
||||
Query string object that will be added to the request URL. This will override the query string in `url`.
|
||||
|
||||
###### timeout
|
||||
|
||||
Type: `number` `Object`
|
||||
|
||||
Milliseconds to wait for the server to end the response before aborting request with `ETIMEDOUT` error.
|
||||
|
||||
This also accepts an object with separate `connect`, `socket`, and `request` fields for connection, socket, and entire request timeouts.
|
||||
|
||||
###### retries
|
||||
|
||||
Type: `number` `Function`<br>
|
||||
Default: `2`
|
||||
|
||||
Number of request retries when network errors happens. Delays between retries counts with function `1000 * Math.pow(2, retry) + Math.random() * 100`, where `retry` is attempt number (starts from 0).
|
||||
|
||||
Option accepts `function` with `retry` and `error` arguments. Function must return delay in milliseconds (`0` return value cancels retry).
|
||||
|
||||
**Note:** if `retries` is `number`, `ENOTFOUND` and `ENETUNREACH` error will not be retried (see full list in [`is-retry-allowed`](https://github.com/floatdrop/is-retry-allowed/blob/master/index.js#L12) module).
|
||||
|
||||
###### followRedirect
|
||||
|
||||
Type: `boolean`<br>
|
||||
Default: `true`
|
||||
|
||||
Defines if redirect responses should be followed automatically.
|
||||
|
||||
Note that if a `303` is sent by the server in response to any request type (`POST`, `DELETE`, etc.), got will automatically
|
||||
request the resource pointed to in the location header via `GET`. This is in accordance with [the spec](https://tools.ietf.org/html/rfc7231#section-6.4.4).
|
||||
|
||||
###### decompress
|
||||
|
||||
Type: `boolean`<br>
|
||||
Default: `true`
|
||||
|
||||
Decompress the response automatically.
|
||||
|
||||
If this is disabled, a compressed response is returned as a `Buffer`. This may be useful if you want to handle decompression yourself or stream the raw compressed data.
|
||||
|
||||
###### cache
|
||||
|
||||
Type: `Object`<br>
|
||||
Default: `false`
|
||||
|
||||
[Cache adapter instance](#cache-adapters) for storing cached data.
|
||||
|
||||
###### useElectronNet
|
||||
|
||||
Type: `boolean`<br>
|
||||
Default: `false`
|
||||
|
||||
When used in Electron, Got will use [`electron.net`](https://electronjs.org/docs/api/net/) instead of the Node.js `http` module. According to the Electron docs, it should be fully compatible, but it's not entirely. See [#315](https://github.com/sindresorhus/got/issues/315).
|
||||
|
||||
###### throwHttpErrors
|
||||
|
||||
Type: `boolean`<br>
|
||||
Default: `true`
|
||||
|
||||
Determines if a `got.HTTPError` is thrown for error responses (non-2xx status codes).
|
||||
|
||||
If this is disabled, requests that encounter an error status code will be resolved with the `response` instead of throwing. This may be useful if you are checking for resource availability and are expecting error responses.
|
||||
|
||||
#### Streams
|
||||
|
||||
#### got.stream(url, [options])
|
||||
|
||||
`stream` method will return Duplex stream with additional events:
|
||||
|
||||
##### .on('request', request)
|
||||
|
||||
`request` event to get the request object of the request.
|
||||
|
||||
**Tip**: You can use `request` event to abort request:
|
||||
|
||||
```js
|
||||
got.stream('github.com')
|
||||
.on('request', req => setTimeout(() => req.abort(), 50));
|
||||
```
|
||||
|
||||
##### .on('response', response)
|
||||
|
||||
`response` event to get the response object of the final request.
|
||||
|
||||
##### .on('redirect', response, nextOptions)
|
||||
|
||||
`redirect` event to get the response object of a redirect. The second argument is options for the next request to the redirect location.
|
||||
|
||||
##### .on('uploadProgress', progress)
|
||||
##### .on('downloadProgress', progress)
|
||||
|
||||
Progress events for uploading (sending request) and downloading (receiving response). The `progress` argument is an object like:
|
||||
|
||||
```js
|
||||
{
|
||||
percent: 0.1,
|
||||
transferred: 1024,
|
||||
total: 10240
|
||||
}
|
||||
```
|
||||
|
||||
If it's not possible to retrieve the body size (can happen when streaming), `total` will be `null`.
|
||||
|
||||
**Note**: Progress events can also be used with promises.
|
||||
|
||||
```js
|
||||
(async () => {
|
||||
const response = await got('sindresorhus.com')
|
||||
.on('downloadProgress', progress => {
|
||||
// Report download progress
|
||||
})
|
||||
.on('uploadProgress', progress => {
|
||||
// Report upload progress
|
||||
});
|
||||
|
||||
console.log(response);
|
||||
})();
|
||||
```
|
||||
|
||||
##### .on('error', error, body, response)
|
||||
|
||||
`error` event emitted in case of protocol error (like `ENOTFOUND` etc.) or status error (4xx or 5xx). The second argument is the body of the server response in case of status error. The third argument is response object.
|
||||
|
||||
#### got.get(url, [options])
|
||||
#### got.post(url, [options])
|
||||
#### got.put(url, [options])
|
||||
#### got.patch(url, [options])
|
||||
#### got.head(url, [options])
|
||||
#### got.delete(url, [options])
|
||||
|
||||
Sets `options.method` to the method name and makes a request.
|
||||
|
||||
|
||||
## Errors
|
||||
|
||||
Each error contains (if available) `statusCode`, `statusMessage`, `host`, `hostname`, `method`, `path`, `protocol` and `url` properties to make debugging easier.
|
||||
|
||||
In Promise mode, the `response` is attached to the error.
|
||||
|
||||
#### got.CacheError
|
||||
|
||||
When a cache method fails, for example if the database goes down, or there's a filesystem error.
|
||||
|
||||
#### got.RequestError
|
||||
|
||||
When a request fails. Contains a `code` property with error class code, like `ECONNREFUSED`.
|
||||
|
||||
#### got.ReadError
|
||||
|
||||
When reading from response stream fails.
|
||||
|
||||
#### got.ParseError
|
||||
|
||||
When `json` option is enabled, server response code is 2xx, and `JSON.parse` fails.
|
||||
|
||||
#### got.HTTPError
|
||||
|
||||
When server response code is not 2xx. Includes `statusCode`, `statusMessage`, and `redirectUrls` properties.
|
||||
|
||||
#### got.MaxRedirectsError
|
||||
|
||||
When server redirects you more than 10 times. Includes a `redirectUrls` property, which is an array of the URLs Got was redirected to before giving up.
|
||||
|
||||
#### got.UnsupportedProtocolError
|
||||
|
||||
When given an unsupported protocol.
|
||||
|
||||
#### got.CancelError
|
||||
|
||||
When the request is aborted with `.cancel()`.
|
||||
|
||||
|
||||
## Aborting the request
|
||||
|
||||
The promise returned by Got has a [`.cancel()`](https://github.com/sindresorhus/p-cancelable) method which, when called, aborts the request.
|
||||
|
||||
```js
|
||||
(async () => {
|
||||
const request = got(url, options);
|
||||
|
||||
…
|
||||
|
||||
// In another part of the code
|
||||
if (something) {
|
||||
request.cancel();
|
||||
}
|
||||
|
||||
…
|
||||
|
||||
try {
|
||||
await request;
|
||||
} catch (error) {
|
||||
if (request.isCanceled) { // Or `error instanceof got.CancelError`
|
||||
// Handle cancelation
|
||||
}
|
||||
|
||||
// Handle other errors
|
||||
}
|
||||
})();
|
||||
```
|
||||
|
||||
<a name="cache-adapters"></a>
|
||||
## Cache
|
||||
|
||||
Got implements [RFC 7234](http://httpwg.org/specs/rfc7234.html) compliant HTTP caching which works out of the box in memory or is easily pluggable with a wide range of storage adapters. Fresh cache entries are served directly from cache and stale cache entries are revalidated with `If-None-Match`/`If-Modified-Since` headers. You can read more about the underlying cache behaviour in the `cacheable-request` [documentation](https://github.com/lukechilds/cacheable-request).
|
||||
|
||||
You can use the JavaScript `Map` type as an in memory cache:
|
||||
|
||||
```js
|
||||
const got = require('got');
|
||||
const map = new Map();
|
||||
|
||||
(async () => {
|
||||
let response = await got('sindresorhus.com', {cache: map});
|
||||
console.log(response.fromCache);
|
||||
//=> false
|
||||
|
||||
response = await got('sindresorhus.com', {cache: map});
|
||||
console.log(response.fromCache);
|
||||
//=> true
|
||||
})();
|
||||
```
|
||||
|
||||
Got uses [Keyv](https://github.com/lukechilds/keyv) internally to support a wide range of storage adapters. For something more scalable you could use an [official Keyv storage adapter](https://github.com/lukechilds/keyv#official-storage-adapters):
|
||||
|
||||
```
|
||||
$ npm install @keyv/redis
|
||||
```
|
||||
|
||||
```js
|
||||
const got = require('got');
|
||||
const KeyvRedis = require('@keyv/redis');
|
||||
|
||||
const redis = new KeyvRedis('redis://user:pass@localhost:6379');
|
||||
|
||||
got('sindresorhus.com', {cache: redis});
|
||||
```
|
||||
|
||||
Got supports anything that follows the Map API, so it's easy to write your own storage adapter or use a third-party solution.
|
||||
|
||||
For example, 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});
|
||||
|
||||
got('sindresorhus.com', {cache: storageAdapter});
|
||||
```
|
||||
|
||||
View the [Keyv docs](https://github.com/lukechilds/keyv) for more information on how to use storage adapters.
|
||||
|
||||
|
||||
## Proxies
|
||||
|
||||
You can use the [`tunnel`](https://github.com/koichik/node-tunnel) module with the `agent` option to work with proxies:
|
||||
|
||||
```js
|
||||
const got = require('got');
|
||||
const tunnel = require('tunnel');
|
||||
|
||||
got('sindresorhus.com', {
|
||||
agent: tunnel.httpOverHttp({
|
||||
proxy: {
|
||||
host: 'localhost'
|
||||
}
|
||||
})
|
||||
});
|
||||
```
|
||||
|
||||
If you require different agents for different protocols, you can pass a map of agents to the `agent` option. This is necessary because a request to one protocol might redirect to another. In such a scenario, `got` will switch over to the right protocol agent for you.
|
||||
|
||||
```js
|
||||
const got = require('got');
|
||||
const HttpAgent = require('agentkeepalive');
|
||||
const HttpsAgent = HttpAgent.HttpsAgent;
|
||||
|
||||
got('sindresorhus.com', {
|
||||
agent: {
|
||||
http: new HttpAgent(),
|
||||
https: new HttpsAgent()
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
## Cookies
|
||||
|
||||
You can use the [`cookie`](https://github.com/jshttp/cookie) module to include cookies in a request:
|
||||
|
||||
```js
|
||||
const got = require('got');
|
||||
const cookie = require('cookie');
|
||||
|
||||
got('google.com', {
|
||||
headers: {
|
||||
cookie: cookie.serialize('foo', 'bar')
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
## Form data
|
||||
|
||||
You can use the [`form-data`](https://github.com/form-data/form-data) module to create POST request with form data:
|
||||
|
||||
```js
|
||||
const fs = require('fs');
|
||||
const got = require('got');
|
||||
const FormData = require('form-data');
|
||||
const form = new FormData();
|
||||
|
||||
form.append('my_file', fs.createReadStream('/foo/bar.jpg'));
|
||||
|
||||
got.post('google.com', {
|
||||
body: form
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
## OAuth
|
||||
|
||||
You can use the [`oauth-1.0a`](https://github.com/ddo/oauth-1.0a) module to create a signed OAuth request:
|
||||
|
||||
```js
|
||||
const got = require('got');
|
||||
const crypto = require('crypto');
|
||||
const OAuth = require('oauth-1.0a');
|
||||
|
||||
const oauth = OAuth({
|
||||
consumer: {
|
||||
key: process.env.CONSUMER_KEY,
|
||||
secret: process.env.CONSUMER_SECRET
|
||||
},
|
||||
signature_method: 'HMAC-SHA1',
|
||||
hash_function: (baseString, key) => crypto.createHmac('sha1', key).update(baseString).digest('base64')
|
||||
});
|
||||
|
||||
const token = {
|
||||
key: process.env.ACCESS_TOKEN,
|
||||
secret: process.env.ACCESS_TOKEN_SECRET
|
||||
};
|
||||
|
||||
const url = 'https://api.twitter.com/1.1/statuses/home_timeline.json';
|
||||
|
||||
got(url, {
|
||||
headers: oauth.toHeader(oauth.authorize({url, method: 'GET'}, token)),
|
||||
json: true
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
## Unix Domain Sockets
|
||||
|
||||
Requests can also be sent via [unix domain sockets](http://serverfault.com/questions/124517/whats-the-difference-between-unix-socket-and-tcp-ip-socket). Use the following URL scheme: `PROTOCOL://unix:SOCKET:PATH`.
|
||||
|
||||
- `PROTOCOL` - `http` or `https` *(optional)*
|
||||
- `SOCKET` - absolute path to a unix domain socket, e.g. `/var/run/docker.sock`
|
||||
- `PATH` - request path, e.g. `/v2/keys`
|
||||
|
||||
```js
|
||||
got('http://unix:/var/run/docker.sock:/containers/json');
|
||||
|
||||
// or without protocol (http by default)
|
||||
got('unix:/var/run/docker.sock:/containers/json');
|
||||
```
|
||||
|
||||
## AWS
|
||||
|
||||
Requests to AWS services need to have their headers signed. This can be accomplished by using the [`aws4`](https://www.npmjs.com/package/aws4) package. This is an example for querying an ["Elasticsearch Service"](https://aws.amazon.com/elasticsearch-service/) host with a signed request.
|
||||
|
||||
```js
|
||||
const url = require('url');
|
||||
const AWS = require('aws-sdk');
|
||||
const aws4 = require('aws4');
|
||||
const got = require('got');
|
||||
const config = require('./config');
|
||||
|
||||
// Reads keys from the environment or `~/.aws/credentials`. Could be a plain object.
|
||||
const awsConfig = new AWS.Config({ region: config.region });
|
||||
|
||||
function request(uri, options) {
|
||||
const awsOpts = {
|
||||
region: awsConfig.region,
|
||||
headers: {
|
||||
accept: 'application/json',
|
||||
'content-type': 'application/json'
|
||||
},
|
||||
method: 'GET',
|
||||
json: true
|
||||
};
|
||||
|
||||
// We need to parse the URL before passing it to `got` so `aws4` can sign the request
|
||||
const opts = Object.assign(url.parse(uri), awsOpts, options);
|
||||
aws4.sign(opts, awsConfig.credentials);
|
||||
|
||||
return got(opts);
|
||||
}
|
||||
|
||||
request(`https://${config.host}/production/users/1`);
|
||||
|
||||
request(`https://${config.host}/production/`, {
|
||||
// All usual `got` options
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
## Testing
|
||||
|
||||
You can test your requests by using the [`nock`](https://github.com/node-nock/nock) module to mock an endpoint:
|
||||
|
||||
```js
|
||||
const got = require('got');
|
||||
const nock = require('nock');
|
||||
|
||||
nock('https://sindresorhus.com')
|
||||
.get('/')
|
||||
.reply(200, 'Hello world!');
|
||||
|
||||
(async () => {
|
||||
const response = await got('sindresorhus.com');
|
||||
console.log(response.body);
|
||||
//=> 'Hello world!'
|
||||
})();
|
||||
```
|
||||
|
||||
If you need real integration tests you can use [`create-test-server`](https://github.com/lukechilds/create-test-server):
|
||||
|
||||
```js
|
||||
const got = require('got');
|
||||
const createTestServer = require('create-test-server');
|
||||
|
||||
(async () => {
|
||||
const server = await createTestServer();
|
||||
server.get('/', 'Hello world!');
|
||||
|
||||
const response = await got(server.url);
|
||||
console.log(response.body);
|
||||
//=> 'Hello world!'
|
||||
|
||||
await server.close();
|
||||
})();
|
||||
```
|
||||
|
||||
|
||||
## Tips
|
||||
|
||||
### User Agent
|
||||
|
||||
It's a good idea to set the `'user-agent'` header so the provider can more easily see how their resource is used. By default, it's the URL to this repo.
|
||||
|
||||
```js
|
||||
const got = require('got');
|
||||
const pkg = require('./package.json');
|
||||
|
||||
got('sindresorhus.com', {
|
||||
headers: {
|
||||
'user-agent': `my-module/${pkg.version} (https://github.com/username/my-module)`
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### 304 Responses
|
||||
|
||||
Bear in mind, if you send an `if-modified-since` header and receive a `304 Not Modified` response, the body will be empty. It's your responsibility to cache and retrieve the body contents.
|
||||
|
||||
|
||||
## Related
|
||||
|
||||
- [gh-got](https://github.com/sindresorhus/gh-got) - Got convenience wrapper to interact with the GitHub API
|
||||
- [gl-got](https://github.com/singapore/gl-got) - Got convenience wrapper to interact with the GitLab API
|
||||
- [travis-got](https://github.com/samverschueren/travis-got) - Got convenience wrapper to interact with the Travis API
|
||||
- [graphql-got](https://github.com/kevva/graphql-got) - Got convenience wrapper to interact with GraphQL
|
||||
- [GotQL](https://github.com/khaosdoctor/gotql) - Got convenience wrapper to interact with GraphQL using JSON-parsed queries instead of strings
|
||||
|
||||
|
||||
## Created by
|
||||
|
||||
[](https://sindresorhus.com) | [](https://github.com/floatdrop) | [](https://github.com/AlexTes) | [](https://github.com/lukechilds)
|
||||
---|---|---|---
|
||||
[Sindre Sorhus](https://sindresorhus.com) | [Vsevolod Strukchinsky](https://github.com/floatdrop) | [Alexander Tesfamichael](https://alextes.me) | [Luke Childs](https://github.com/lukechilds)
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
# This file is for unifying the coding style for different editors and IDEs
|
||||
# editorconfig.org
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
# every file
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_size = 2
|
||||
indent_style = space
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
# 4 space indentation
|
||||
[*.py]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
# Tab indentation (no size specified)
|
||||
[Makefile]
|
||||
indent_style = tab
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
|
@ -1 +0,0 @@
|
|||
lib/*
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"root": true,
|
||||
"extends": [
|
||||
"@xotic750/eslint-config-standard-x"
|
||||
]
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
lts/*
|
||||
|
|
@ -1,111 +0,0 @@
|
|||
sudo: false
|
||||
language: node_js
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- /^greenkeeper/.*$/
|
||||
notifications:
|
||||
email: false
|
||||
node_js:
|
||||
- "9.6"
|
||||
- "9.5"
|
||||
- "9.4"
|
||||
- "9.3"
|
||||
- "9.2"
|
||||
- "9.1"
|
||||
- "9.0"
|
||||
- "8.9"
|
||||
- "8.8"
|
||||
- "8.7"
|
||||
- "8.6"
|
||||
- "8.5"
|
||||
- "8.4"
|
||||
- "8.3"
|
||||
- "8.2"
|
||||
- "8.1"
|
||||
- "8.0"
|
||||
- "7.10"
|
||||
- "7.9"
|
||||
- "7.8"
|
||||
- "7.7"
|
||||
- "7.6"
|
||||
- "7.5"
|
||||
- "7.4"
|
||||
- "7.3"
|
||||
- "7.2"
|
||||
- "7.1"
|
||||
- "7.0"
|
||||
- "6.11"
|
||||
- "6.10"
|
||||
- "6.9"
|
||||
- "6.8"
|
||||
- "6.7"
|
||||
- "6.6"
|
||||
- "6.5"
|
||||
- "6.4"
|
||||
- "6.3"
|
||||
- "6.2"
|
||||
- "6.1"
|
||||
- "6.0"
|
||||
- "5.12"
|
||||
- "5.11"
|
||||
- "5.10"
|
||||
- "5.9"
|
||||
- "5.8"
|
||||
- "5.7"
|
||||
- "5.6"
|
||||
- "5.5"
|
||||
- "5.4"
|
||||
- "5.3"
|
||||
- "5.2"
|
||||
- "5.1"
|
||||
- "5.0"
|
||||
- "4.8"
|
||||
- "4.7"
|
||||
- "4.6"
|
||||
- "4.5"
|
||||
- "4.4"
|
||||
- "4.3"
|
||||
- "4.2"
|
||||
- "4.1"
|
||||
- "4.0"
|
||||
- "iojs-v3.3"
|
||||
- "iojs-v3.2"
|
||||
- "iojs-v3.1"
|
||||
- "iojs-v3.0"
|
||||
- "iojs-v2.5"
|
||||
- "iojs-v2.4"
|
||||
- "iojs-v2.3"
|
||||
- "iojs-v2.2"
|
||||
- "iojs-v2.1"
|
||||
- "iojs-v2.0"
|
||||
- "iojs-v1.8"
|
||||
- "iojs-v1.7"
|
||||
- "iojs-v1.6"
|
||||
- "iojs-v1.5"
|
||||
- "iojs-v1.4"
|
||||
- "iojs-v1.3"
|
||||
- "iojs-v1.2"
|
||||
- "iojs-v1.1"
|
||||
- "iojs-v1.0"
|
||||
- "0.12"
|
||||
- "0.11"
|
||||
- "0.10"
|
||||
- "0.9"
|
||||
- "0.8"
|
||||
- "0.6"
|
||||
- "0.4"
|
||||
before_install:
|
||||
- 'if [ "${TRAVIS_NODE_VERSION}" = "0.6" ]; then npm install -g npm@1.3 ; elif [ "${TRAVIS_NODE_VERSION}" != "0.9" ]; then case "$(npm --version)" in 1.*) npm install -g npm@1.4.28 ;; 2.*) npm install -g npm@2 ; esac ; fi'
|
||||
- 'if [ "${TRAVIS_NODE_VERSION}" != "0.6" ] && [ "${TRAVIS_NODE_VERSION}" != "0.9" ]; then if [ "${TRAVIS_NODE_VERSION%${TRAVIS_NODE_VERSION#[0-9]}}" = "0" ] || [ "${TRAVIS_NODE_VERSION:0:4}" = "iojs" ]; then npm install -g npm@4.5; elif [[ "${TRAVIS_NODE_VERSION%${TRAVIS_NODE_VERSION#[0-9]}}" =~ ^[4-5]+$ ]]; then npm install -g npm@5.3; else npm install -g npm; fi; fi'
|
||||
install:
|
||||
- 'if [ "${TRAVIS_NODE_VERSION}" = "0.6" ]; then nvm install 0.8 && npm install -g npm@1.3 && npm install -g npm@1.4.28 && npm install -g npm@2 && npm install && nvm use --delete-prefix "${TRAVIS_NODE_VERSION}"; else npm install; fi;'
|
||||
script:
|
||||
- 'npm test'
|
||||
matrix:
|
||||
fast_finish: true
|
||||
allow_failures:
|
||||
- node_js: "0.11"
|
||||
- node_js: "0.9"
|
||||
- node_js: "0.6"
|
||||
- node_js: "0.4"
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
{
|
||||
"warnings": false,
|
||||
"parse": {},
|
||||
"compress": {
|
||||
"keep_fnames": true
|
||||
},
|
||||
"mangle": false,
|
||||
"output": {
|
||||
"ascii_only": true,
|
||||
"beautify": false,
|
||||
"comments": "some"
|
||||
},
|
||||
"sourceMap": {},
|
||||
"nameCache": null,
|
||||
"toplevel": false,
|
||||
"ie8": true
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
https://opensource.org/licenses/MIT
|
||||
|
||||
Copyright (c) 2015-present Graham Fairweather.
|
||||
|
||||
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.
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
<a href="https://travis-ci.org/Xotic750/has-symbol-support-x"
|
||||
title="Travis status">
|
||||
<img
|
||||
src="https://travis-ci.org/Xotic750/has-symbol-support-x.svg?branch=master"
|
||||
alt="Travis status" height="18"/>
|
||||
</a>
|
||||
<a href="https://david-dm.org/Xotic750/has-symbol-support-x"
|
||||
title="Dependency status">
|
||||
<img src="https://david-dm.org/Xotic750/has-symbol-support-x.svg"
|
||||
alt="Dependency status" height="18"/>
|
||||
</a>
|
||||
<a href="https://david-dm.org/Xotic750/has-symbol-support-x#info=devDependencies"
|
||||
title="devDependency status">
|
||||
<img src="https://david-dm.org/Xotic750/has-symbol-support-x/dev-status.svg"
|
||||
alt="devDependency status" height="18"/>
|
||||
</a>
|
||||
<a href="https://badge.fury.io/js/has-symbol-support-x" title="npm version">
|
||||
<img src="https://badge.fury.io/js/has-symbol-support-x.svg"
|
||||
alt="npm version" height="18"/>
|
||||
</a>
|
||||
<a name="module_has-symbol-support-x"></a>
|
||||
|
||||
## has-symbol-support-x
|
||||
Tests if ES6 Symbol is supported.
|
||||
|
||||
**Version**: 1.4.2
|
||||
**Author**: Xotic750 <Xotic750@gmail.com>
|
||||
**License**: [MIT](<https://opensource.org/licenses/MIT>)
|
||||
**Copyright**: Xotic750
|
||||
<a name="exp_module_has-symbol-support-x--module.exports"></a>
|
||||
|
||||
### `module.exports` : <code>boolean</code> ⏏
|
||||
Indicates if `Symbol`exists and creates the correct type.
|
||||
`true`, if it exists and creates the correct type, otherwise `false`.
|
||||
|
||||
**Kind**: Exported member
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
<a href="https://travis-ci.org/Xotic750/@{PACKAGE-NAME}"
|
||||
title="Travis status">
|
||||
<img
|
||||
src="https://travis-ci.org/Xotic750/@{PACKAGE-NAME}.svg?branch=master"
|
||||
alt="Travis status" height="18"/>
|
||||
</a>
|
||||
<a href="https://david-dm.org/Xotic750/@{PACKAGE-NAME}"
|
||||
title="Dependency status">
|
||||
<img src="https://david-dm.org/Xotic750/@{PACKAGE-NAME}.svg"
|
||||
alt="Dependency status" height="18"/>
|
||||
</a>
|
||||
<a href="https://david-dm.org/Xotic750/@{PACKAGE-NAME}#info=devDependencies"
|
||||
title="devDependency status">
|
||||
<img src="https://david-dm.org/Xotic750/@{PACKAGE-NAME}/dev-status.svg"
|
||||
alt="devDependency status" height="18"/>
|
||||
</a>
|
||||
<a href="https://badge.fury.io/js/@{PACKAGE-NAME}" title="npm version">
|
||||
<img src="https://badge.fury.io/js/@{PACKAGE-NAME}.svg"
|
||||
alt="npm version" height="18"/>
|
||||
</a>
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
/**
|
||||
* @file Tests if ES6 Symbol is supported.
|
||||
* @version 1.4.2
|
||||
* @author Xotic750 <Xotic750@gmail.com>
|
||||
* @copyright Xotic750
|
||||
* @license {@link <https://opensource.org/licenses/MIT> MIT}
|
||||
* @module has-symbol-support-x
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Indicates if `Symbol`exists and creates the correct type.
|
||||
* `true`, if it exists and creates the correct type, otherwise `false`.
|
||||
*
|
||||
* @type boolean
|
||||
*/
|
||||
module.exports = typeof Symbol === 'function' && typeof Symbol('') === 'symbol';
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.returnExports = f()}})(function(){var define,module,exports;return (function(){function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s}return e})()({1:[function(_dereq_,module,exports){
|
||||
/**
|
||||
* @file Tests if ES6 Symbol is supported.
|
||||
* @version 1.4.2
|
||||
* @author Xotic750 <Xotic750@gmail.com>
|
||||
* @copyright Xotic750
|
||||
* @license {@link <https://opensource.org/licenses/MIT> MIT}
|
||||
* @module has-symbol-support-x
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Indicates if `Symbol`exists and creates the correct type.
|
||||
* `true`, if it exists and creates the correct type, otherwise `false`.
|
||||
*
|
||||
* @type boolean
|
||||
*/
|
||||
module.exports = typeof Symbol === 'function' && typeof Symbol('') === 'symbol';
|
||||
|
||||
},{}]},{},[1])(1)
|
||||
});
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
!function(f){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=f();else if("function"==typeof define&&define.amd)define([],f);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).returnExports=f()}}(function(){return function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a="function"==typeof require&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n||e)},l,l.exports,e,t,n,r)}return n[o].exports}for(var i="function"==typeof require&&require,o=0;o<r.length;o++)s(r[o]);return s}({1:[function(_dereq_,module,exports){
|
||||
/**
|
||||
* @file Tests if ES6 Symbol is supported.
|
||||
* @version 1.4.2
|
||||
* @author Xotic750 <Xotic750@gmail.com>
|
||||
* @copyright Xotic750
|
||||
* @license {@link <https://opensource.org/licenses/MIT> MIT}
|
||||
* @module has-symbol-support-x
|
||||
*/
|
||||
"use strict";module.exports="function"==typeof Symbol&&"symbol"==typeof Symbol("")},{}]},{},[1])(1)});
|
||||
|
|
@ -1 +0,0 @@
|
|||
{"version":3,"sources":["lib/has-symbol-support-x.js"],"names":["f","exports","module","define","amd","window","global","self","this","returnExports","e","t","n","r","s","o","u","a","require","i","Error","code","l","call","length","1","_dereq_","Symbol"],"mappings":"CAAA,SAAUA,GAAG,GAAoB,iBAAVC,SAAoC,oBAATC,OAAsBA,OAAOD,QAAQD,SAAS,GAAmB,mBAATG,QAAqBA,OAAOC,IAAKD,UAAUH,OAAO,EAA0B,oBAATK,OAAwBA,OAA+B,oBAATC,OAAwBA,OAA6B,oBAAPC,KAAsBA,KAAYC,MAAOC,cAAgBT,KAAlU,CAAyU,WAAqC,OAAmB,SAASU,EAAEC,EAAEC,EAAEC,GAAG,SAASC,EAAEC,EAAEC,GAAG,IAAIJ,EAAEG,GAAG,CAAC,IAAIJ,EAAEI,GAAG,CAAC,IAAIE,EAAkB,mBAATC,SAAqBA,QAAQ,IAAIF,GAAGC,EAAE,OAAOA,EAAEF,GAAE,GAAI,GAAGI,EAAE,OAAOA,EAAEJ,GAAE,GAAI,IAAIf,EAAE,IAAIoB,MAAM,uBAAuBL,EAAE,KAAK,MAAMf,EAAEqB,KAAK,mBAAmBrB,EAAE,IAAIsB,EAAEV,EAAEG,IAAId,YAAYU,EAAEI,GAAG,GAAGQ,KAAKD,EAAErB,QAAQ,SAASS,GAAG,IAAIE,EAAED,EAAEI,GAAG,GAAGL,GAAG,OAAOI,EAAEF,GAAIF,IAAIY,EAAEA,EAAErB,QAAQS,EAAEC,EAAEC,EAAEC,GAAG,OAAOD,EAAEG,GAAGd,QAAkD,IAA1C,IAAIkB,EAAkB,mBAATD,SAAqBA,QAAgBH,EAAE,EAAEA,EAAEF,EAAEW,OAAOT,IAAID,EAAED,EAAEE,IAAI,OAAOD,EAAlc,EAAkdW,GAAG,SAASC,QAAQxB,OAAOD;;;;;;;;;AAUl2B,aAQAC,OAAOD,QAA4B,mBAAX0B,QAA+C,iBAAfA,OAAO,cAEpD,GApB0W,CAoBtW"}
|
||||
|
|
@ -1,86 +0,0 @@
|
|||
{
|
||||
"name": "has-symbol-support-x",
|
||||
"version": "1.4.2",
|
||||
"description": "Tests if ES6 Symbol is supported.",
|
||||
"homepage": "https://github.com/Xotic750/has-symbol-support-x",
|
||||
"author": {
|
||||
"name": "Graham Fairweather",
|
||||
"email": "xotic750@gmail.com"
|
||||
},
|
||||
"copyright": "Copyright (c) 2015-present",
|
||||
"keywords": [
|
||||
"ES6",
|
||||
"hasSymbolSupport",
|
||||
"module",
|
||||
"javascript",
|
||||
"nodejs",
|
||||
"browser"
|
||||
],
|
||||
"main": "index.js",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Xotic750/has-symbol-support-x.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/Xotic750/has-symbol-support-x/issues"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"@xotic750/eslint-config-standard-x": "^3.1.1",
|
||||
"ajv": "^6.1.1",
|
||||
"browserify": "^16.1.0",
|
||||
"browserify-derequire": "^0.9.4",
|
||||
"cross-env": "^5.1.3",
|
||||
"es5-shim": "^4.5.10",
|
||||
"es6-shim": "^0.35.3",
|
||||
"es7-shim": "^6.0.0",
|
||||
"eslint": "^4.18.1",
|
||||
"eslint-plugin-compat": "^2.2.0",
|
||||
"eslint-plugin-css-modules": "^2.7.5",
|
||||
"eslint-plugin-eslint-comments": "^2.0.2",
|
||||
"eslint-plugin-jsdoc": "^3.5.0",
|
||||
"eslint-plugin-json": "^1.2.0",
|
||||
"eslint-plugin-no-use-extend-native": "^0.3.12",
|
||||
"husky": "^0.13.4",
|
||||
"jasmine-node": "^1.14.5",
|
||||
"jsdoc-to-markdown": "^4.0.1",
|
||||
"json3": "^3.3.2",
|
||||
"make-jasmine-spec-runner-html": "^1.3.0",
|
||||
"ncp": "^2.0.0",
|
||||
"nodemon": "^1.15.1",
|
||||
"nsp": "^3.2.1",
|
||||
"parallelshell": "^3.0.2",
|
||||
"replace-x": "^1.5.0",
|
||||
"rimraf": "^2.6.2",
|
||||
"serve": "^6.4.11",
|
||||
"uglify-js": "^3.3.12"
|
||||
},
|
||||
"scripts": {
|
||||
"clean": "rimraf README.md lib/*",
|
||||
"clean:jasmine": "rimraf tests/index.html tests/run.js",
|
||||
"clean:all": "npm run clean:jasmine && npm run clean",
|
||||
"build": "npm run clean && npm run lint && npm run browserify && npm run uglify && npm run docs && npm test && npm run security",
|
||||
"build:jasmine": "npm run clean:jasmine && make-jasmine-spec-runner-html",
|
||||
"build:setver": "replace-x \" @version .*\" \" @version $(node -p -e \"require('./package.json').version\")\" index.js",
|
||||
"build:name": "replace-x \" @module .*\" \" @module $(node -p -e \"require('./package.json').name\")\" index.js",
|
||||
"build:description": "replace-x \" @file .*\" \" @file $(node -p -e \"require('./package.json').description\")\" index.js",
|
||||
"build:replace": "npm run build:setver && npm run build:name && npm run build:description",
|
||||
"production": "npm run clean:all && npm run build:jasmine && npm run build:replace && npm run build",
|
||||
"start": "parallelshell \"serve\" \"nodemon --watch index.js --exec 'npm run build'\"",
|
||||
"docs:name": "replace-x \"@{PACKAGE-NAME}\" \"$(node -p -e \"require('./package.json').name\")\" README.md",
|
||||
"docs:badges": "ncp badges.html README.md && npm run docs:name",
|
||||
"docs": "npm run docs:badges && jsdoc2md --name-format --example-lang js index.js >> README.md",
|
||||
"lint": "eslint *.js tests/spec/*.js",
|
||||
"lint-fix": "npm run lint -- --fix",
|
||||
"security": "nsp check",
|
||||
"test": "jasmine-node --matchall tests/spec/",
|
||||
"browserify": "browserify -p browserify-derequire -e index.js -o lib/has-symbol-support-x.js -u 'crypto' -s returnExports",
|
||||
"uglify": "uglifyjs lib/has-symbol-support-x.js -o lib/has-symbol-support-x.min.js --config-file .uglifyjsrc.json",
|
||||
"precommit": "npm run production",
|
||||
"prepush": "npm run production"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Jasmine Spec Runner: has-symbol-support-x</title>
|
||||
|
||||
<link rel="icon" href="http://jasmine.github.io/images/jasmine.ico" sizes="16x16">
|
||||
<link rel="icon" href="http://jasmine.github.io//images/jasmine_32x32.ico" sizes="32x32">
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/jasmine/1.3.1/jasmine.min.css">
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.5.10/es5-shim.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.5.10/es5-sham.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/json3/3.3.2/json3.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/es6-shim/0.35.3/es6-shim.js"></script>
|
||||
<script type="text/javascript" src="https://wzrd.in/standalone/es7-shim@latest"></script>
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/1.3.1/jasmine.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/1.3.1/jasmine-html.min.js"></script>
|
||||
|
||||
<!-- include helper files here... -->
|
||||
|
||||
<!-- include source files here... -->
|
||||
<script src="../lib/has-symbol-support-x.min.js"></script>
|
||||
|
||||
<!-- include spec files here... -->
|
||||
<script src="spec/test.js"></script>
|
||||
|
||||
<!-- run the tests -->
|
||||
<script src="./run.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
/* global window, jasmine */
|
||||
/* eslint strict: 0 */
|
||||
(function () {
|
||||
var jasmineEnv = jasmine.getEnv();
|
||||
jasmineEnv.updateInterval = 1000;
|
||||
|
||||
var trivialReporter = new jasmine.TrivialReporter();
|
||||
|
||||
jasmineEnv.addReporter(trivialReporter);
|
||||
|
||||
jasmineEnv.specFilter = function (spec) {
|
||||
return trivialReporter.specFilter(spec);
|
||||
};
|
||||
|
||||
var currentWindowOnload = window.onload;
|
||||
var execJasmine = function () {
|
||||
jasmineEnv.execute();
|
||||
};
|
||||
window.onload = function () {
|
||||
if (currentWindowOnload) {
|
||||
currentWindowOnload();
|
||||
}
|
||||
execJasmine();
|
||||
};
|
||||
}());
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
var hasSymbolSupport;
|
||||
if (typeof module === 'object' && module.exports) {
|
||||
require('es5-shim');
|
||||
require('es5-shim/es5-sham');
|
||||
if (typeof JSON === 'undefined') {
|
||||
JSON = {};
|
||||
}
|
||||
require('json3').runInContext(null, JSON);
|
||||
require('es6-shim');
|
||||
var es7 = require('es7-shim');
|
||||
Object.keys(es7).forEach(function (key) {
|
||||
var obj = es7[key];
|
||||
if (typeof obj.shim === 'function') {
|
||||
obj.shim();
|
||||
}
|
||||
});
|
||||
hasSymbolSupport = require('../../index.js');
|
||||
} else {
|
||||
hasSymbolSupport = returnExports;
|
||||
}
|
||||
|
||||
describe('Basic tests', function () {
|
||||
it('results should match', function () {
|
||||
var expected = typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol';
|
||||
expect(hasSymbolSupport).toBe(expected);
|
||||
});
|
||||
});
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
# This file is for unifying the coding style for different editors and IDEs
|
||||
# editorconfig.org
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
# every file
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_size = 2
|
||||
indent_style = space
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
# 4 space indentation
|
||||
[*.py]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
# Tab indentation (no size specified)
|
||||
[Makefile]
|
||||
indent_style = tab
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
|
@ -1 +0,0 @@
|
|||
lib/*
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"root": true,
|
||||
"extends": [
|
||||
"@xotic750/eslint-config-standard-x"
|
||||
]
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
lts/*
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
sudo: false
|
||||
language: node_js
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- /^greenkeeper/.*$/
|
||||
notifications:
|
||||
email: false
|
||||
node_js:
|
||||
- "8.4"
|
||||
- "8.3"
|
||||
- "8.2"
|
||||
- "8.1"
|
||||
- "8.0"
|
||||
- "7.10"
|
||||
- "7.9"
|
||||
- "7.8"
|
||||
- "7.7"
|
||||
- "7.6"
|
||||
- "7.5"
|
||||
- "7.4"
|
||||
- "7.3"
|
||||
- "7.2"
|
||||
- "7.1"
|
||||
- "7.0"
|
||||
- "6.9"
|
||||
- "6.8"
|
||||
- "6.7"
|
||||
- "6.6"
|
||||
- "6.5"
|
||||
- "6.4"
|
||||
- "6.3"
|
||||
- "6.2"
|
||||
- "6.1"
|
||||
- "6.0"
|
||||
- "5.12"
|
||||
- "5.11"
|
||||
- "5.10"
|
||||
- "5.9"
|
||||
- "5.8"
|
||||
- "5.7"
|
||||
- "5.6"
|
||||
- "5.5"
|
||||
- "5.4"
|
||||
- "5.3"
|
||||
- "5.2"
|
||||
- "5.1"
|
||||
- "5.0"
|
||||
- "4.4"
|
||||
- "4.3"
|
||||
- "4.2"
|
||||
- "4.1"
|
||||
- "4.0"
|
||||
- "iojs-v3.3"
|
||||
- "iojs-v3.2"
|
||||
- "iojs-v3.1"
|
||||
- "iojs-v3.0"
|
||||
- "iojs-v2.5"
|
||||
- "iojs-v2.4"
|
||||
- "iojs-v2.3"
|
||||
- "iojs-v2.2"
|
||||
- "iojs-v2.1"
|
||||
- "iojs-v2.0"
|
||||
- "iojs-v1.8"
|
||||
- "iojs-v1.7"
|
||||
- "iojs-v1.6"
|
||||
- "iojs-v1.5"
|
||||
- "iojs-v1.4"
|
||||
- "iojs-v1.3"
|
||||
- "iojs-v1.2"
|
||||
- "iojs-v1.1"
|
||||
- "iojs-v1.0"
|
||||
- "0.12"
|
||||
- "0.11"
|
||||
- "0.10"
|
||||
- "0.9"
|
||||
- "0.8"
|
||||
- "0.6"
|
||||
- "0.4"
|
||||
before_install:
|
||||
- 'if [ "${TRAVIS_NODE_VERSION}" = "0.6" ]; then npm install -g npm@1.3 ; elif [ "${TRAVIS_NODE_VERSION}" != "0.9" ]; then case "$(npm --version)" in 1.*) npm install -g npm@1.4.28 ;; 2.*) npm install -g npm@2 ;; esac ; fi'
|
||||
- 'if [ "${TRAVIS_NODE_VERSION%${TRAVIS_NODE_VERSION#[0-9]}}" = "0" ] || [ "${TRAVIS_NODE_VERSION:0:4}" = "iojs" ]; then npm install -g npm@4.5 ; elif [ "${TRAVIS_NODE_VERSION}" != "0.6" ] && [ "${TRAVIS_NODE_VERSION}" != "0.9" ]; then npm install -g npm; fi'
|
||||
install:
|
||||
- 'if [ "${TRAVIS_NODE_VERSION}" = "0.6" ]; then nvm install 0.8 && npm install -g npm@1.3 && npm install -g npm@1.4.28 && npm install -g npm@2 && npm install && nvm use --delete-prefix "${TRAVIS_NODE_VERSION}"; else npm install; fi;'
|
||||
script:
|
||||
- 'npm test'
|
||||
matrix:
|
||||
fast_finish: true
|
||||
allow_failures:
|
||||
- node_js: "0.11"
|
||||
- node_js: "0.9"
|
||||
- node_js: "0.6"
|
||||
- node_js: "0.4"
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
{
|
||||
"warnings": false,
|
||||
"parse": {},
|
||||
"compress": {
|
||||
"keep_fnames": true
|
||||
},
|
||||
"mangle": false,
|
||||
"output": {
|
||||
"ascii_only": true,
|
||||
"beautify": false,
|
||||
"comments": "some"
|
||||
},
|
||||
"sourceMap": {},
|
||||
"nameCache": null,
|
||||
"toplevel": false,
|
||||
"ie8": true
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
https://opensource.org/licenses/MIT
|
||||
|
||||
Copyright (c) 2015-2017 Graham Fairweather.
|
||||
|
||||
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.
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
<a href="https://travis-ci.org/Xotic750/has-to-string-tag-x"
|
||||
title="Travis status">
|
||||
<img
|
||||
src="https://travis-ci.org/Xotic750/has-to-string-tag-x.svg?branch=master"
|
||||
alt="Travis status" height="18"/>
|
||||
</a>
|
||||
<a href="https://david-dm.org/Xotic750/has-to-string-tag-x"
|
||||
title="Dependency status">
|
||||
<img src="https://david-dm.org/Xotic750/has-to-string-tag-x.svg"
|
||||
alt="Dependency status" height="18"/>
|
||||
</a>
|
||||
<a href="https://david-dm.org/Xotic750/has-to-string-tag-x#info=devDependencies"
|
||||
title="devDependency status">
|
||||
<img src="https://david-dm.org/Xotic750/has-to-string-tag-x/dev-status.svg"
|
||||
alt="devDependency status" height="18"/>
|
||||
</a>
|
||||
<a href="https://badge.fury.io/js/has-to-string-tag-x" title="npm version">
|
||||
<img src="https://badge.fury.io/js/has-to-string-tag-x.svg"
|
||||
alt="npm version" height="18"/>
|
||||
</a>
|
||||
<a name="module_has-to-string-tag-x"></a>
|
||||
|
||||
## has-to-string-tag-x
|
||||
Tests if ES6 @@toStringTag is supported.
|
||||
|
||||
**See**: [26.3.1 @@toStringTag](http://www.ecma-international.org/ecma-262/6.0/#sec-@@tostringtag)
|
||||
**Version**: 1.4.1
|
||||
**Author**: Xotic750 <Xotic750@gmail.com>
|
||||
**License**: [MIT](<https://opensource.org/licenses/MIT>)
|
||||
**Copyright**: Xotic750
|
||||
<a name="exp_module_has-to-string-tag-x--module.exports"></a>
|
||||
|
||||
### `module.exports` : <code>boolean</code> ⏏
|
||||
Indicates if `Symbol.toStringTag`exists and is the correct type.
|
||||
`true`, if it exists and is the correct type, otherwise `false`.
|
||||
|
||||
**Kind**: Exported member
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
<a href="https://travis-ci.org/Xotic750/@{PACKAGE-NAME}"
|
||||
title="Travis status">
|
||||
<img
|
||||
src="https://travis-ci.org/Xotic750/@{PACKAGE-NAME}.svg?branch=master"
|
||||
alt="Travis status" height="18"/>
|
||||
</a>
|
||||
<a href="https://david-dm.org/Xotic750/@{PACKAGE-NAME}"
|
||||
title="Dependency status">
|
||||
<img src="https://david-dm.org/Xotic750/@{PACKAGE-NAME}.svg"
|
||||
alt="Dependency status" height="18"/>
|
||||
</a>
|
||||
<a href="https://david-dm.org/Xotic750/@{PACKAGE-NAME}#info=devDependencies"
|
||||
title="devDependency status">
|
||||
<img src="https://david-dm.org/Xotic750/@{PACKAGE-NAME}/dev-status.svg"
|
||||
alt="devDependency status" height="18"/>
|
||||
</a>
|
||||
<a href="https://badge.fury.io/js/@{PACKAGE-NAME}" title="npm version">
|
||||
<img src="https://badge.fury.io/js/@{PACKAGE-NAME}.svg"
|
||||
alt="npm version" height="18"/>
|
||||
</a>
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
/**
|
||||
* @file Tests if ES6 @@toStringTag is supported.
|
||||
* @see {@link http://www.ecma-international.org/ecma-262/6.0/#sec-@@tostringtag|26.3.1 @@toStringTag}
|
||||
* @version 1.4.1
|
||||
* @author Xotic750 <Xotic750@gmail.com>
|
||||
* @copyright Xotic750
|
||||
* @license {@link <https://opensource.org/licenses/MIT> MIT}
|
||||
* @module has-to-string-tag-x
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Indicates if `Symbol.toStringTag`exists and is the correct type.
|
||||
* `true`, if it exists and is the correct type, otherwise `false`.
|
||||
*
|
||||
* @type boolean
|
||||
*/
|
||||
module.exports = require('has-symbol-support-x') && typeof Symbol.toStringTag === 'symbol';
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.returnExports = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
|
||||
/**
|
||||
* @file Tests if ES6 @@toStringTag is supported.
|
||||
* @see {@link http://www.ecma-international.org/ecma-262/6.0/#sec-@@tostringtag|26.3.1 @@toStringTag}
|
||||
* @version 1.4.1
|
||||
* @author Xotic750 <Xotic750@gmail.com>
|
||||
* @copyright Xotic750
|
||||
* @license {@link <https://opensource.org/licenses/MIT> MIT}
|
||||
* @module has-to-string-tag-x
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Indicates if `Symbol.toStringTag`exists and is the correct type.
|
||||
* `true`, if it exists and is the correct type, otherwise `false`.
|
||||
*
|
||||
* @type boolean
|
||||
*/
|
||||
module.exports = _dereq_('has-symbol-support-x') && typeof Symbol.toStringTag === 'symbol';
|
||||
|
||||
},{"has-symbol-support-x":2}],2:[function(_dereq_,module,exports){
|
||||
/**
|
||||
* @file Tests if ES6 Symbol is supported.
|
||||
* @version 1.4.1
|
||||
* @author Xotic750 <Xotic750@gmail.com>
|
||||
* @copyright Xotic750
|
||||
* @license {@link <https://opensource.org/licenses/MIT> MIT}
|
||||
* @module has-symbol-support-x
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Indicates if `Symbol`exists and creates the correct type.
|
||||
* `true`, if it exists and creates the correct type, otherwise `false`.
|
||||
*
|
||||
* @type boolean
|
||||
*/
|
||||
module.exports = typeof Symbol === 'function' && typeof Symbol('') === 'symbol';
|
||||
|
||||
},{}]},{},[1])(1)
|
||||
});
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
!function(f){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=f();else if("function"==typeof define&&define.amd)define([],f);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).returnExports=f()}}(function(){return function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a="function"==typeof require&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n||e)},l,l.exports,e,t,n,r)}return n[o].exports}for(var i="function"==typeof require&&require,o=0;o<r.length;o++)s(r[o]);return s}({1:[function(_dereq_,module,exports){/**
|
||||
* @file Tests if ES6 @@toStringTag is supported.
|
||||
* @see {@link http://www.ecma-international.org/ecma-262/6.0/#sec-@@tostringtag|26.3.1 @@toStringTag}
|
||||
* @version 1.4.1
|
||||
* @author Xotic750 <Xotic750@gmail.com>
|
||||
* @copyright Xotic750
|
||||
* @license {@link <https://opensource.org/licenses/MIT> MIT}
|
||||
* @module has-to-string-tag-x
|
||||
*/
|
||||
"use strict";module.exports=_dereq_("has-symbol-support-x")&&"symbol"==typeof Symbol.toStringTag},{"has-symbol-support-x":2}],2:[function(_dereq_,module,exports){/**
|
||||
* @file Tests if ES6 Symbol is supported.
|
||||
* @version 1.4.1
|
||||
* @author Xotic750 <Xotic750@gmail.com>
|
||||
* @copyright Xotic750
|
||||
* @license {@link <https://opensource.org/licenses/MIT> MIT}
|
||||
* @module has-symbol-support-x
|
||||
*/
|
||||
"use strict";module.exports="function"==typeof Symbol&&"symbol"==typeof Symbol("")},{}]},{},[1])(1)});
|
||||
|
|
@ -1 +0,0 @@
|
|||
{"version":3,"sources":["lib/has-to-string-tag-x.js"],"names":["f","exports","module","define","amd","window","global","self","this","returnExports","e","t","n","r","s","o","u","a","require","i","Error","code","l","call","length","1","_dereq_","Symbol","toStringTag","has-symbol-support-x","2"],"mappings":"CAAA,SAAUA,GAAG,GAAoB,iBAAVC,SAAoC,oBAATC,OAAsBA,OAAOD,QAAQD,SAAS,GAAmB,mBAATG,QAAqBA,OAAOC,IAAKD,UAAUH,OAAO,EAA0B,oBAATK,OAAwBA,OAA+B,oBAATC,OAAwBA,OAA6B,oBAAPC,KAAsBA,KAAYC,MAAOC,cAAgBT,KAAlU,CAAyU,WAAqC,OAAO,SAAUU,EAAEC,EAAEC,EAAEC,GAAG,SAASC,EAAEC,EAAEC,GAAG,IAAIJ,EAAEG,GAAG,CAAC,IAAIJ,EAAEI,GAAG,CAAC,IAAIE,EAAkB,mBAATC,SAAqBA,QAAQ,IAAIF,GAAGC,EAAE,OAAOA,EAAEF,GAAE,GAAI,GAAGI,EAAE,OAAOA,EAAEJ,GAAE,GAAI,IAAIf,EAAE,IAAIoB,MAAM,uBAAuBL,EAAE,KAAK,MAAMf,EAAEqB,KAAK,mBAAmBrB,EAAE,IAAIsB,EAAEV,EAAEG,IAAId,YAAYU,EAAEI,GAAG,GAAGQ,KAAKD,EAAErB,QAAQ,SAASS,GAAG,IAAIE,EAAED,EAAEI,GAAG,GAAGL,GAAG,OAAOI,EAAEF,GAAIF,IAAIY,EAAEA,EAAErB,QAAQS,EAAEC,EAAEC,EAAEC,GAAG,OAAOD,EAAEG,GAAGd,QAAkD,IAAI,IAA1CkB,EAAkB,mBAATD,SAAqBA,QAAgBH,EAAE,EAAEA,EAAEF,EAAEW,OAAOT,IAAID,EAAED,EAAEE,IAAI,OAAOD,EAAvb,EAA4bW,GAAG,SAASC,QAAQxB,OAAOD;;;;;;;;;AAW50B,aAQAC,OAAOD,QAAUyB,QAAQ,yBAAyD,iBAAvBC,OAAOC,cAE/DC,uBAAuB,IAAIC,GAAG,SAASJ,QAAQxB,OAAOD;;;;;;;;AAUzD,aAQAC,OAAOD,QAA4B,mBAAX0B,QAA+C,iBAAfA,OAAO,cAEpD,IAAI"}
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
{
|
||||
"name": "has-to-string-tag-x",
|
||||
"version": "1.4.1",
|
||||
"description": "Tests if ES6 @@toStringTag is supported.",
|
||||
"homepage": "https://github.com/Xotic750/has-to-string-tag-x",
|
||||
"author": {
|
||||
"name": "Graham Fairweather",
|
||||
"email": "xotic750@gmail.com"
|
||||
},
|
||||
"copyright": "Copyright (c) 2015-2017",
|
||||
"keywords": [
|
||||
"ES6",
|
||||
"hasToStringTag",
|
||||
"module",
|
||||
"javascript",
|
||||
"nodejs",
|
||||
"browser"
|
||||
],
|
||||
"main": "index.js",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Xotic750/has-to-string-tag-x.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/Xotic750/has-to-string-tag-x/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"has-symbol-support-x": "^1.4.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@xotic750/eslint-config-standard-x": "^2.2.1",
|
||||
"browserify": "^14.4.0",
|
||||
"browserify-derequire": "^0.9.4",
|
||||
"cross-env": "^5.0.1",
|
||||
"es5-shim": "^4.5.9",
|
||||
"es6-shim": "^0.35.3",
|
||||
"es7-shim": "^6.0.0",
|
||||
"eslint": "^4.2.0",
|
||||
"eslint-plugin-compat": "^1.0.4",
|
||||
"eslint-plugin-css-modules": "^2.7.2",
|
||||
"eslint-plugin-eslint-comments": "^1.0.2",
|
||||
"eslint-plugin-jsdoc": "^3.1.1",
|
||||
"eslint-plugin-json": "^1.2.0",
|
||||
"eslint-plugin-no-use-extend-native": "^0.3.12",
|
||||
"husky": "^0.13.4",
|
||||
"jasmine-node": "^1.14.5",
|
||||
"jsdoc-to-markdown": "^3.0.0",
|
||||
"json3": "^3.3.2",
|
||||
"make-jasmine-spec-runner-html": "^1.3.0",
|
||||
"ncp": "^2.0.0",
|
||||
"nodemon": "^1.11.0",
|
||||
"nsp": "^2.6.3",
|
||||
"parallelshell": "^3.0.1",
|
||||
"replace-x": "^1.5.0",
|
||||
"rimraf": "^2.6.1",
|
||||
"serve": "^6.0.2",
|
||||
"uglify-js": "^3.0.24"
|
||||
},
|
||||
"scripts": {
|
||||
"clean": "rimraf README.md lib/*",
|
||||
"clean:jasmine": "rimraf tests/index.html tests/run.js",
|
||||
"clean:all": "npm run clean:jasmine && npm run clean",
|
||||
"build": "npm run clean && npm run lint && npm run browserify && npm run uglify && npm run docs && npm test && npm run security",
|
||||
"build:jasmine": "npm run clean:jasmine && make-jasmine-spec-runner-html",
|
||||
"build:setver": "replace-x \" @version .*\" \" @version $(node -p -e \"require('./package.json').version\")\" index.js",
|
||||
"build:name": "replace-x \" @module .*\" \" @module $(node -p -e \"require('./package.json').name\")\" index.js",
|
||||
"build:description": "replace-x \" @file .*\" \" @file $(node -p -e \"require('./package.json').description\")\" index.js",
|
||||
"build:replace": "npm run build:setver && npm run build:name && npm run build:description",
|
||||
"production": "npm run clean:all && npm run build:jasmine && npm run build:replace && npm run build",
|
||||
"start": "parallelshell \"serve\" \"nodemon --watch index.js --exec 'npm run build'\"",
|
||||
"docs:name": "replace-x \"@{PACKAGE-NAME}\" \"$(node -p -e \"require('./package.json').name\")\" README.md",
|
||||
"docs:badges": "ncp badges.html README.md && npm run docs:name",
|
||||
"docs": "npm run docs:badges && jsdoc2md --name-format --example-lang js index.js >> README.md",
|
||||
"lint": "eslint *.js tests/spec/*.js",
|
||||
"lint-fix": "npm run lint -- --fix",
|
||||
"security": "nsp check",
|
||||
"test": "jasmine-node --matchall tests/spec/",
|
||||
"browserify": "browserify -p browserify-derequire -e index.js -o lib/has-to-string-tag-x.js -u 'crypto' -s returnExports",
|
||||
"uglify": "uglifyjs lib/has-to-string-tag-x.js -o lib/has-to-string-tag-x.min.js --config-file .uglifyjsrc.json",
|
||||
"precommit": "npm run production",
|
||||
"prepush": "npm run production"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,177 +0,0 @@
|
|||
# Can I cache this? [](https://travis-ci.org/pornel/http-cache-semantics)
|
||||
|
||||
`CachePolicy` tells when responses can be reused from a cache, taking into account [HTTP RFC 7234](http://httpwg.org/specs/rfc7234.html) rules for user agents and shared caches. It's aware of many tricky details such as the `Vary` header, proxy revalidation, and authenticated responses.
|
||||
|
||||
## Usage
|
||||
|
||||
Cacheability of an HTTP response depends on how it was requested, so both `request` and `response` are required to create the policy.
|
||||
|
||||
```js
|
||||
const policy = new CachePolicy(request, response, options);
|
||||
|
||||
if (!policy.storable()) {
|
||||
// throw the response away, it's not usable at all
|
||||
return;
|
||||
}
|
||||
|
||||
// Cache the data AND the policy object in your cache
|
||||
// (this is pseudocode, roll your own cache (lru-cache package works))
|
||||
letsPretendThisIsSomeCache.set(request.url, {policy, response}, policy.timeToLive());
|
||||
```
|
||||
|
||||
```js
|
||||
// And later, when you receive a new request:
|
||||
const {policy, response} = letsPretendThisIsSomeCache.get(newRequest.url);
|
||||
|
||||
// It's not enough that it exists in the cache, it has to match the new request, too:
|
||||
if (policy && policy.satisfiesWithoutRevalidation(newRequest)) {
|
||||
// OK, the previous response can be used to respond to the `newRequest`.
|
||||
// Response headers have to be updated, e.g. to add Age and remove uncacheable headers.
|
||||
response.headers = policy.responseHeaders();
|
||||
return response;
|
||||
}
|
||||
```
|
||||
|
||||
It may be surprising, but it's not enough for an HTTP response to be [fresh](#yo-fresh) to satisfy a request. It may need to match request headers specified in `Vary`. Even a matching fresh response may still not be usable if the new request restricted cacheability, etc.
|
||||
|
||||
The key method is `satisfiesWithoutRevalidation(newRequest)`, which checks whether the `newRequest` is compatible with the original request and whether all caching conditions are met.
|
||||
|
||||
### Constructor options
|
||||
|
||||
Request and response must have a `headers` property with all header names in lower case. `url`, `status` and `method` are optional (defaults are any URL, status `200`, and `GET` method).
|
||||
|
||||
```js
|
||||
const request = {
|
||||
url: '/',
|
||||
method: 'GET',
|
||||
headers: {
|
||||
accept: '*/*',
|
||||
},
|
||||
};
|
||||
|
||||
const response = {
|
||||
status: 200,
|
||||
headers: {
|
||||
'cache-control': 'public, max-age=7234',
|
||||
},
|
||||
};
|
||||
|
||||
const options = {
|
||||
shared: true,
|
||||
cacheHeuristic: 0.1,
|
||||
immutableMinTimeToLive: 24*3600*1000, // 24h
|
||||
ignoreCargoCult: false,
|
||||
};
|
||||
```
|
||||
|
||||
If `options.shared` is `true` (default), then the response is evaluated from a perspective of a shared cache (i.e. `private` is not cacheable and `s-maxage` is respected). If `options.shared` is `false`, then the response is evaluated from a perspective of a single-user cache (i.e. `private` is cacheable and `s-maxage` is ignored).
|
||||
|
||||
`options.cacheHeuristic` is a fraction of response's age that is used as a fallback cache duration. The default is 0.1 (10%), e.g. if a file hasn't been modified for 100 days, it'll be cached for 100*0.1 = 10 days.
|
||||
|
||||
`options.immutableMinTimeToLive` is a number of milliseconds to assume as the default time to cache responses with `Cache-Control: immutable`. Note that [per RFC](http://httpwg.org/http-extensions/immutable.html) these can become stale, so `max-age` still overrides the default.
|
||||
|
||||
If `options.ignoreCargoCult` is true, common anti-cache directives will be completely ignored if the non-standard `pre-check` and `post-check` directives are present. These two useless directives are most commonly found in bad StackOverflow answers and PHP's "session limiter" defaults.
|
||||
|
||||
### `storable()`
|
||||
|
||||
Returns `true` if the response can be stored in a cache. If it's `false` then you MUST NOT store either the request or the response.
|
||||
|
||||
### `satisfiesWithoutRevalidation(newRequest)`
|
||||
|
||||
This is the most important method. Use this method to check whether the cached response is still fresh in the context of the new request.
|
||||
|
||||
If it returns `true`, then the given `request` matches the original response this cache policy has been created with, and the response can be reused without contacting the server. Note that the old response can't be returned without being updated, see `responseHeaders()`.
|
||||
|
||||
If it returns `false`, then the response may not be matching at all (e.g. it's for a different URL or method), or may require to be refreshed first (see `revalidationHeaders()`).
|
||||
|
||||
### `responseHeaders()`
|
||||
|
||||
Returns updated, filtered set of response headers to return to clients receiving the cached response. This function is necessary, because proxies MUST always remove hop-by-hop headers (such as `TE` and `Connection`) and update response's `Age` to avoid doubling cache time.
|
||||
|
||||
```js
|
||||
cachedResponse.headers = cachePolicy.responseHeaders(cachedResponse);
|
||||
```
|
||||
|
||||
### `timeToLive()`
|
||||
|
||||
Returns approximate time in *milliseconds* until the response becomes stale (i.e. not fresh).
|
||||
|
||||
After that time (when `timeToLive() <= 0`) the response might not be usable without revalidation. However, there are exceptions, e.g. a client can explicitly allow stale responses, so always check with `satisfiesWithoutRevalidation()`.
|
||||
|
||||
### `toObject()`/`fromObject(json)`
|
||||
|
||||
Chances are you'll want to store the `CachePolicy` object along with the cached response. `obj = policy.toObject()` gives a plain JSON-serializable object. `policy = CachePolicy.fromObject(obj)` creates an instance from it.
|
||||
|
||||
### Refreshing stale cache (revalidation)
|
||||
|
||||
When a cached response has expired, it can be made fresh again by making a request to the origin server. The server may respond with status 304 (Not Modified) without sending the response body again, saving bandwidth.
|
||||
|
||||
The following methods help perform the update efficiently and correctly.
|
||||
|
||||
#### `revalidationHeaders(newRequest)`
|
||||
|
||||
Returns updated, filtered set of request headers to send to the origin server to check if the cached response can be reused. These headers allow the origin server to return status 304 indicating the response is still fresh. All headers unrelated to caching are passed through as-is.
|
||||
|
||||
Use this method when updating cache from the origin server.
|
||||
|
||||
```js
|
||||
updateRequest.headers = cachePolicy.revalidationHeaders(updateRequest);
|
||||
```
|
||||
|
||||
#### `revalidatedPolicy(revalidationRequest, revalidationResponse)`
|
||||
|
||||
Use this method to update the cache after receiving a new response from the origin server. It returns an object with two keys:
|
||||
|
||||
* `policy` — A new `CachePolicy` with HTTP headers updated from `revalidationResponse`. You can always replace the old cached `CachePolicy` with the new one.
|
||||
* `modified` — Boolean indicating whether the response body has changed.
|
||||
* If `false`, then a valid 304 Not Modified response has been received, and you can reuse the old cached response body.
|
||||
* If `true`, you should use new response's body (if present), or make another request to the origin server without any conditional headers (i.e. don't use `revalidationHeaders()` this time) to get the new resource.
|
||||
|
||||
```js
|
||||
// When serving requests from cache:
|
||||
const {oldPolicy, oldResponse} = letsPretendThisIsSomeCache.get(newRequest.url);
|
||||
|
||||
if (!oldPolicy.satisfiesWithoutRevalidation(newRequest)) {
|
||||
// Change the request to ask the origin server if the cached response can be used
|
||||
newRequest.headers = oldPolicy.revalidationHeaders(newRequest);
|
||||
|
||||
// Send request to the origin server. The server may respond with status 304
|
||||
const newResponse = await makeRequest(newResponse);
|
||||
|
||||
// Create updated policy and combined response from the old and new data
|
||||
const {policy, modified} = oldPolicy.revalidatedPolicy(newRequest, newResponse);
|
||||
const response = modified ? newResponse : oldResponse;
|
||||
|
||||
// Update the cache with the newer/fresher response
|
||||
letsPretendThisIsSomeCache.set(newRequest.url, {policy, response}, policy.timeToLive());
|
||||
|
||||
// And proceed returning cached response as usual
|
||||
response.headers = policy.responseHeaders();
|
||||
return response;
|
||||
}
|
||||
```
|
||||
|
||||
# Yo, FRESH
|
||||
|
||||

|
||||
|
||||
## Used by
|
||||
|
||||
* [ImageOptim API](https://imageoptim.com/api), [make-fetch-happen](https://github.com/zkat/make-fetch-happen), [cacheable-request](https://www.npmjs.com/package/cacheable-request), [npm/registry-fetch](https://github.com/npm/registry-fetch), [etc.](https://github.com/pornel/http-cache-semantics/network/dependents)
|
||||
|
||||
## Implemented
|
||||
|
||||
* `Cache-Control` response header with all the quirks.
|
||||
* `Expires` with check for bad clocks.
|
||||
* `Pragma` response header.
|
||||
* `Age` response header.
|
||||
* `Vary` response header.
|
||||
* Default cacheability of statuses and methods.
|
||||
* Requests for stale data.
|
||||
* Filtering of hop-by-hop headers.
|
||||
* Basic revalidation request
|
||||
|
||||
## Unimplemented
|
||||
|
||||
* Merging of range requests, If-Range (but correctly supports them as non-cacheable)
|
||||
* Revalidation of multiple representations
|
||||
|
|
@ -1,559 +0,0 @@
|
|||
'use strict';
|
||||
// rfc7231 6.1
|
||||
|
||||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||||
|
||||
var statusCodeCacheableByDefault = [200, 203, 204, 206, 300, 301, 404, 405, 410, 414, 501];
|
||||
|
||||
// This implementation does not understand partial responses (206)
|
||||
var understoodStatuses = [200, 203, 204, 300, 301, 302, 303, 307, 308, 404, 405, 410, 414, 501];
|
||||
|
||||
var hopByHopHeaders = { 'connection': true, 'keep-alive': true, 'proxy-authenticate': true, 'proxy-authorization': true, 'te': true, 'trailer': true, 'transfer-encoding': true, 'upgrade': true };
|
||||
var excludedFromRevalidationUpdate = {
|
||||
// Since the old body is reused, it doesn't make sense to change properties of the body
|
||||
'content-length': true, 'content-encoding': true, 'transfer-encoding': true,
|
||||
'content-range': true
|
||||
};
|
||||
|
||||
function parseCacheControl(header) {
|
||||
var cc = {};
|
||||
if (!header) return cc;
|
||||
|
||||
// TODO: When there is more than one value present for a given directive (e.g., two Expires header fields, multiple Cache-Control: max-age directives),
|
||||
// the directive's value is considered invalid. Caches are encouraged to consider responses that have invalid freshness information to be stale
|
||||
var parts = header.trim().split(/\s*,\s*/); // TODO: lame parsing
|
||||
for (var _iterator = parts, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
|
||||
var _ref;
|
||||
|
||||
if (_isArray) {
|
||||
if (_i >= _iterator.length) break;
|
||||
_ref = _iterator[_i++];
|
||||
} else {
|
||||
_i = _iterator.next();
|
||||
if (_i.done) break;
|
||||
_ref = _i.value;
|
||||
}
|
||||
|
||||
var part = _ref;
|
||||
|
||||
var _part$split = part.split(/\s*=\s*/, 2),
|
||||
k = _part$split[0],
|
||||
v = _part$split[1];
|
||||
|
||||
cc[k] = v === undefined ? true : v.replace(/^"|"$/g, ''); // TODO: lame unquoting
|
||||
}
|
||||
|
||||
return cc;
|
||||
}
|
||||
|
||||
function formatCacheControl(cc) {
|
||||
var parts = [];
|
||||
for (var k in cc) {
|
||||
var v = cc[k];
|
||||
parts.push(v === true ? k : k + '=' + v);
|
||||
}
|
||||
if (!parts.length) {
|
||||
return undefined;
|
||||
}
|
||||
return parts.join(', ');
|
||||
}
|
||||
|
||||
module.exports = function () {
|
||||
function CachePolicy(req, res) {
|
||||
var _ref2 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {},
|
||||
shared = _ref2.shared,
|
||||
cacheHeuristic = _ref2.cacheHeuristic,
|
||||
immutableMinTimeToLive = _ref2.immutableMinTimeToLive,
|
||||
ignoreCargoCult = _ref2.ignoreCargoCult,
|
||||
_fromObject = _ref2._fromObject;
|
||||
|
||||
_classCallCheck(this, CachePolicy);
|
||||
|
||||
if (_fromObject) {
|
||||
this._fromObject(_fromObject);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!res || !res.headers) {
|
||||
throw Error("Response headers missing");
|
||||
}
|
||||
this._assertRequestHasHeaders(req);
|
||||
|
||||
this._responseTime = this.now();
|
||||
this._isShared = shared !== false;
|
||||
this._cacheHeuristic = undefined !== cacheHeuristic ? cacheHeuristic : 0.1; // 10% matches IE
|
||||
this._immutableMinTtl = undefined !== immutableMinTimeToLive ? immutableMinTimeToLive : 24 * 3600 * 1000;
|
||||
|
||||
this._status = 'status' in res ? res.status : 200;
|
||||
this._resHeaders = res.headers;
|
||||
this._rescc = parseCacheControl(res.headers['cache-control']);
|
||||
this._method = 'method' in req ? req.method : 'GET';
|
||||
this._url = req.url;
|
||||
this._host = req.headers.host;
|
||||
this._noAuthorization = !req.headers.authorization;
|
||||
this._reqHeaders = res.headers.vary ? req.headers : null; // Don't keep all request headers if they won't be used
|
||||
this._reqcc = parseCacheControl(req.headers['cache-control']);
|
||||
|
||||
// Assume that if someone uses legacy, non-standard uncecessary options they don't understand caching,
|
||||
// so there's no point stricly adhering to the blindly copy&pasted directives.
|
||||
if (ignoreCargoCult && "pre-check" in this._rescc && "post-check" in this._rescc) {
|
||||
delete this._rescc['pre-check'];
|
||||
delete this._rescc['post-check'];
|
||||
delete this._rescc['no-cache'];
|
||||
delete this._rescc['no-store'];
|
||||
delete this._rescc['must-revalidate'];
|
||||
this._resHeaders = Object.assign({}, this._resHeaders, { 'cache-control': formatCacheControl(this._rescc) });
|
||||
delete this._resHeaders.expires;
|
||||
delete this._resHeaders.pragma;
|
||||
}
|
||||
|
||||
// When the Cache-Control header field is not present in a request, caches MUST consider the no-cache request pragma-directive
|
||||
// as having the same effect as if "Cache-Control: no-cache" were present (see Section 5.2.1).
|
||||
if (!res.headers['cache-control'] && /no-cache/.test(res.headers.pragma)) {
|
||||
this._rescc['no-cache'] = true;
|
||||
}
|
||||
}
|
||||
|
||||
CachePolicy.prototype.now = function now() {
|
||||
return Date.now();
|
||||
};
|
||||
|
||||
CachePolicy.prototype.storable = function storable() {
|
||||
// The "no-store" request directive indicates that a cache MUST NOT store any part of either this request or any response to it.
|
||||
return !!(!this._reqcc['no-store'] && (
|
||||
// A cache MUST NOT store a response to any request, unless:
|
||||
// The request method is understood by the cache and defined as being cacheable, and
|
||||
'GET' === this._method || 'HEAD' === this._method || 'POST' === this._method && this._hasExplicitExpiration()) &&
|
||||
// the response status code is understood by the cache, and
|
||||
understoodStatuses.indexOf(this._status) !== -1 &&
|
||||
// the "no-store" cache directive does not appear in request or response header fields, and
|
||||
!this._rescc['no-store'] && (
|
||||
// the "private" response directive does not appear in the response, if the cache is shared, and
|
||||
!this._isShared || !this._rescc.private) && (
|
||||
// the Authorization header field does not appear in the request, if the cache is shared,
|
||||
!this._isShared || this._noAuthorization || this._allowsStoringAuthenticated()) && (
|
||||
// the response either:
|
||||
|
||||
// contains an Expires header field, or
|
||||
this._resHeaders.expires ||
|
||||
// contains a max-age response directive, or
|
||||
// contains a s-maxage response directive and the cache is shared, or
|
||||
// contains a public response directive.
|
||||
this._rescc.public || this._rescc['max-age'] || this._rescc['s-maxage'] ||
|
||||
// has a status code that is defined as cacheable by default
|
||||
statusCodeCacheableByDefault.indexOf(this._status) !== -1));
|
||||
};
|
||||
|
||||
CachePolicy.prototype._hasExplicitExpiration = function _hasExplicitExpiration() {
|
||||
// 4.2.1 Calculating Freshness Lifetime
|
||||
return this._isShared && this._rescc['s-maxage'] || this._rescc['max-age'] || this._resHeaders.expires;
|
||||
};
|
||||
|
||||
CachePolicy.prototype._assertRequestHasHeaders = function _assertRequestHasHeaders(req) {
|
||||
if (!req || !req.headers) {
|
||||
throw Error("Request headers missing");
|
||||
}
|
||||
};
|
||||
|
||||
CachePolicy.prototype.satisfiesWithoutRevalidation = function satisfiesWithoutRevalidation(req) {
|
||||
this._assertRequestHasHeaders(req);
|
||||
|
||||
// When presented with a request, a cache MUST NOT reuse a stored response, unless:
|
||||
// the presented request does not contain the no-cache pragma (Section 5.4), nor the no-cache cache directive,
|
||||
// unless the stored response is successfully validated (Section 4.3), and
|
||||
var requestCC = parseCacheControl(req.headers['cache-control']);
|
||||
if (requestCC['no-cache'] || /no-cache/.test(req.headers.pragma)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (requestCC['max-age'] && this.age() > requestCC['max-age']) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (requestCC['min-fresh'] && this.timeToLive() < 1000 * requestCC['min-fresh']) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// the stored response is either:
|
||||
// fresh, or allowed to be served stale
|
||||
if (this.stale()) {
|
||||
var allowsStale = requestCC['max-stale'] && !this._rescc['must-revalidate'] && (true === requestCC['max-stale'] || requestCC['max-stale'] > this.age() - this.maxAge());
|
||||
if (!allowsStale) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return this._requestMatches(req, false);
|
||||
};
|
||||
|
||||
CachePolicy.prototype._requestMatches = function _requestMatches(req, allowHeadMethod) {
|
||||
// The presented effective request URI and that of the stored response match, and
|
||||
return (!this._url || this._url === req.url) && this._host === req.headers.host && (
|
||||
// the request method associated with the stored response allows it to be used for the presented request, and
|
||||
!req.method || this._method === req.method || allowHeadMethod && 'HEAD' === req.method) &&
|
||||
// selecting header fields nominated by the stored response (if any) match those presented, and
|
||||
this._varyMatches(req);
|
||||
};
|
||||
|
||||
CachePolicy.prototype._allowsStoringAuthenticated = function _allowsStoringAuthenticated() {
|
||||
// following Cache-Control response directives (Section 5.2.2) have such an effect: must-revalidate, public, and s-maxage.
|
||||
return this._rescc['must-revalidate'] || this._rescc.public || this._rescc['s-maxage'];
|
||||
};
|
||||
|
||||
CachePolicy.prototype._varyMatches = function _varyMatches(req) {
|
||||
if (!this._resHeaders.vary) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// A Vary header field-value of "*" always fails to match
|
||||
if (this._resHeaders.vary === '*') {
|
||||
return false;
|
||||
}
|
||||
|
||||
var fields = this._resHeaders.vary.trim().toLowerCase().split(/\s*,\s*/);
|
||||
for (var _iterator2 = fields, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) {
|
||||
var _ref3;
|
||||
|
||||
if (_isArray2) {
|
||||
if (_i2 >= _iterator2.length) break;
|
||||
_ref3 = _iterator2[_i2++];
|
||||
} else {
|
||||
_i2 = _iterator2.next();
|
||||
if (_i2.done) break;
|
||||
_ref3 = _i2.value;
|
||||
}
|
||||
|
||||
var name = _ref3;
|
||||
|
||||
if (req.headers[name] !== this._reqHeaders[name]) return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
CachePolicy.prototype._copyWithoutHopByHopHeaders = function _copyWithoutHopByHopHeaders(inHeaders) {
|
||||
var headers = {};
|
||||
for (var name in inHeaders) {
|
||||
if (hopByHopHeaders[name]) continue;
|
||||
headers[name] = inHeaders[name];
|
||||
}
|
||||
// 9.1. Connection
|
||||
if (inHeaders.connection) {
|
||||
var tokens = inHeaders.connection.trim().split(/\s*,\s*/);
|
||||
for (var _iterator3 = tokens, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) {
|
||||
var _ref4;
|
||||
|
||||
if (_isArray3) {
|
||||
if (_i3 >= _iterator3.length) break;
|
||||
_ref4 = _iterator3[_i3++];
|
||||
} else {
|
||||
_i3 = _iterator3.next();
|
||||
if (_i3.done) break;
|
||||
_ref4 = _i3.value;
|
||||
}
|
||||
|
||||
var _name = _ref4;
|
||||
|
||||
delete headers[_name];
|
||||
}
|
||||
}
|
||||
if (headers.warning) {
|
||||
var warnings = headers.warning.split(/,/).filter(function (warning) {
|
||||
return !/^\s*1[0-9][0-9]/.test(warning);
|
||||
});
|
||||
if (!warnings.length) {
|
||||
delete headers.warning;
|
||||
} else {
|
||||
headers.warning = warnings.join(',').trim();
|
||||
}
|
||||
}
|
||||
return headers;
|
||||
};
|
||||
|
||||
CachePolicy.prototype.responseHeaders = function responseHeaders() {
|
||||
var headers = this._copyWithoutHopByHopHeaders(this._resHeaders);
|
||||
var age = this.age();
|
||||
|
||||
// A cache SHOULD generate 113 warning if it heuristically chose a freshness
|
||||
// lifetime greater than 24 hours and the response's age is greater than 24 hours.
|
||||
if (age > 3600 * 24 && !this._hasExplicitExpiration() && this.maxAge() > 3600 * 24) {
|
||||
headers.warning = (headers.warning ? `${headers.warning}, ` : '') + '113 - "rfc7234 5.5.4"';
|
||||
}
|
||||
headers.age = `${Math.round(age)}`;
|
||||
return headers;
|
||||
};
|
||||
|
||||
/**
|
||||
* Value of the Date response header or current time if Date was demed invalid
|
||||
* @return timestamp
|
||||
*/
|
||||
|
||||
|
||||
CachePolicy.prototype.date = function date() {
|
||||
var dateValue = Date.parse(this._resHeaders.date);
|
||||
var maxClockDrift = 8 * 3600 * 1000;
|
||||
if (Number.isNaN(dateValue) || dateValue < this._responseTime - maxClockDrift || dateValue > this._responseTime + maxClockDrift) {
|
||||
return this._responseTime;
|
||||
}
|
||||
return dateValue;
|
||||
};
|
||||
|
||||
/**
|
||||
* Value of the Age header, in seconds, updated for the current time.
|
||||
* May be fractional.
|
||||
*
|
||||
* @return Number
|
||||
*/
|
||||
|
||||
|
||||
CachePolicy.prototype.age = function age() {
|
||||
var age = Math.max(0, (this._responseTime - this.date()) / 1000);
|
||||
if (this._resHeaders.age) {
|
||||
var ageValue = this._ageValue();
|
||||
if (ageValue > age) age = ageValue;
|
||||
}
|
||||
|
||||
var residentTime = (this.now() - this._responseTime) / 1000;
|
||||
return age + residentTime;
|
||||
};
|
||||
|
||||
CachePolicy.prototype._ageValue = function _ageValue() {
|
||||
var ageValue = parseInt(this._resHeaders.age);
|
||||
return isFinite(ageValue) ? ageValue : 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Value of applicable max-age (or heuristic equivalent) in seconds. This counts since response's `Date`.
|
||||
*
|
||||
* For an up-to-date value, see `timeToLive()`.
|
||||
*
|
||||
* @return Number
|
||||
*/
|
||||
|
||||
|
||||
CachePolicy.prototype.maxAge = function maxAge() {
|
||||
if (!this.storable() || this._rescc['no-cache']) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Shared responses with cookies are cacheable according to the RFC, but IMHO it'd be unwise to do so by default
|
||||
// so this implementation requires explicit opt-in via public header
|
||||
if (this._isShared && this._resHeaders['set-cookie'] && !this._rescc.public && !this._rescc.immutable) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (this._resHeaders.vary === '*') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (this._isShared) {
|
||||
if (this._rescc['proxy-revalidate']) {
|
||||
return 0;
|
||||
}
|
||||
// if a response includes the s-maxage directive, a shared cache recipient MUST ignore the Expires field.
|
||||
if (this._rescc['s-maxage']) {
|
||||
return parseInt(this._rescc['s-maxage'], 10);
|
||||
}
|
||||
}
|
||||
|
||||
// If a response includes a Cache-Control field with the max-age directive, a recipient MUST ignore the Expires field.
|
||||
if (this._rescc['max-age']) {
|
||||
return parseInt(this._rescc['max-age'], 10);
|
||||
}
|
||||
|
||||
var defaultMinTtl = this._rescc.immutable ? this._immutableMinTtl : 0;
|
||||
|
||||
var dateValue = this.date();
|
||||
if (this._resHeaders.expires) {
|
||||
var expires = Date.parse(this._resHeaders.expires);
|
||||
// A cache recipient MUST interpret invalid date formats, especially the value "0", as representing a time in the past (i.e., "already expired").
|
||||
if (Number.isNaN(expires) || expires < dateValue) {
|
||||
return 0;
|
||||
}
|
||||
return Math.max(defaultMinTtl, (expires - dateValue) / 1000);
|
||||
}
|
||||
|
||||
if (this._resHeaders['last-modified']) {
|
||||
var lastModified = Date.parse(this._resHeaders['last-modified']);
|
||||
if (isFinite(lastModified) && dateValue > lastModified) {
|
||||
return Math.max(defaultMinTtl, (dateValue - lastModified) / 1000 * this._cacheHeuristic);
|
||||
}
|
||||
}
|
||||
|
||||
return defaultMinTtl;
|
||||
};
|
||||
|
||||
CachePolicy.prototype.timeToLive = function timeToLive() {
|
||||
return Math.max(0, this.maxAge() - this.age()) * 1000;
|
||||
};
|
||||
|
||||
CachePolicy.prototype.stale = function stale() {
|
||||
return this.maxAge() <= this.age();
|
||||
};
|
||||
|
||||
CachePolicy.fromObject = function fromObject(obj) {
|
||||
return new this(undefined, undefined, { _fromObject: obj });
|
||||
};
|
||||
|
||||
CachePolicy.prototype._fromObject = function _fromObject(obj) {
|
||||
if (this._responseTime) throw Error("Reinitialized");
|
||||
if (!obj || obj.v !== 1) throw Error("Invalid serialization");
|
||||
|
||||
this._responseTime = obj.t;
|
||||
this._isShared = obj.sh;
|
||||
this._cacheHeuristic = obj.ch;
|
||||
this._immutableMinTtl = obj.imm !== undefined ? obj.imm : 24 * 3600 * 1000;
|
||||
this._status = obj.st;
|
||||
this._resHeaders = obj.resh;
|
||||
this._rescc = obj.rescc;
|
||||
this._method = obj.m;
|
||||
this._url = obj.u;
|
||||
this._host = obj.h;
|
||||
this._noAuthorization = obj.a;
|
||||
this._reqHeaders = obj.reqh;
|
||||
this._reqcc = obj.reqcc;
|
||||
};
|
||||
|
||||
CachePolicy.prototype.toObject = function toObject() {
|
||||
return {
|
||||
v: 1,
|
||||
t: this._responseTime,
|
||||
sh: this._isShared,
|
||||
ch: this._cacheHeuristic,
|
||||
imm: this._immutableMinTtl,
|
||||
st: this._status,
|
||||
resh: this._resHeaders,
|
||||
rescc: this._rescc,
|
||||
m: this._method,
|
||||
u: this._url,
|
||||
h: this._host,
|
||||
a: this._noAuthorization,
|
||||
reqh: this._reqHeaders,
|
||||
reqcc: this._reqcc
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Headers for sending to the origin server to revalidate stale response.
|
||||
* Allows server to return 304 to allow reuse of the previous response.
|
||||
*
|
||||
* Hop by hop headers are always stripped.
|
||||
* Revalidation headers may be added or removed, depending on request.
|
||||
*/
|
||||
|
||||
|
||||
CachePolicy.prototype.revalidationHeaders = function revalidationHeaders(incomingReq) {
|
||||
this._assertRequestHasHeaders(incomingReq);
|
||||
var headers = this._copyWithoutHopByHopHeaders(incomingReq.headers);
|
||||
|
||||
// This implementation does not understand range requests
|
||||
delete headers['if-range'];
|
||||
|
||||
if (!this._requestMatches(incomingReq, true) || !this.storable()) {
|
||||
// revalidation allowed via HEAD
|
||||
// not for the same resource, or wasn't allowed to be cached anyway
|
||||
delete headers['if-none-match'];
|
||||
delete headers['if-modified-since'];
|
||||
return headers;
|
||||
}
|
||||
|
||||
/* MUST send that entity-tag in any cache validation request (using If-Match or If-None-Match) if an entity-tag has been provided by the origin server. */
|
||||
if (this._resHeaders.etag) {
|
||||
headers['if-none-match'] = headers['if-none-match'] ? `${headers['if-none-match']}, ${this._resHeaders.etag}` : this._resHeaders.etag;
|
||||
}
|
||||
|
||||
// Clients MAY issue simple (non-subrange) GET requests with either weak validators or strong validators. Clients MUST NOT use weak validators in other forms of request.
|
||||
var forbidsWeakValidators = headers['accept-ranges'] || headers['if-match'] || headers['if-unmodified-since'] || this._method && this._method != 'GET';
|
||||
|
||||
/* SHOULD send the Last-Modified value in non-subrange cache validation requests (using If-Modified-Since) if only a Last-Modified value has been provided by the origin server.
|
||||
Note: This implementation does not understand partial responses (206) */
|
||||
if (forbidsWeakValidators) {
|
||||
delete headers['if-modified-since'];
|
||||
|
||||
if (headers['if-none-match']) {
|
||||
var etags = headers['if-none-match'].split(/,/).filter(function (etag) {
|
||||
return !/^\s*W\//.test(etag);
|
||||
});
|
||||
if (!etags.length) {
|
||||
delete headers['if-none-match'];
|
||||
} else {
|
||||
headers['if-none-match'] = etags.join(',').trim();
|
||||
}
|
||||
}
|
||||
} else if (this._resHeaders['last-modified'] && !headers['if-modified-since']) {
|
||||
headers['if-modified-since'] = this._resHeaders['last-modified'];
|
||||
}
|
||||
|
||||
return headers;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates new CachePolicy with information combined from the previews response,
|
||||
* and the new revalidation response.
|
||||
*
|
||||
* Returns {policy, modified} where modified is a boolean indicating
|
||||
* whether the response body has been modified, and old cached body can't be used.
|
||||
*
|
||||
* @return {Object} {policy: CachePolicy, modified: Boolean}
|
||||
*/
|
||||
|
||||
|
||||
CachePolicy.prototype.revalidatedPolicy = function revalidatedPolicy(request, response) {
|
||||
this._assertRequestHasHeaders(request);
|
||||
if (!response || !response.headers) {
|
||||
throw Error("Response headers missing");
|
||||
}
|
||||
|
||||
// These aren't going to be supported exactly, since one CachePolicy object
|
||||
// doesn't know about all the other cached objects.
|
||||
var matches = false;
|
||||
if (response.status !== undefined && response.status != 304) {
|
||||
matches = false;
|
||||
} else if (response.headers.etag && !/^\s*W\//.test(response.headers.etag)) {
|
||||
// "All of the stored responses with the same strong validator are selected.
|
||||
// If none of the stored responses contain the same strong validator,
|
||||
// then the cache MUST NOT use the new response to update any stored responses."
|
||||
matches = this._resHeaders.etag && this._resHeaders.etag.replace(/^\s*W\//, '') === response.headers.etag;
|
||||
} else if (this._resHeaders.etag && response.headers.etag) {
|
||||
// "If the new response contains a weak validator and that validator corresponds
|
||||
// to one of the cache's stored responses,
|
||||
// then the most recent of those matching stored responses is selected for update."
|
||||
matches = this._resHeaders.etag.replace(/^\s*W\//, '') === response.headers.etag.replace(/^\s*W\//, '');
|
||||
} else if (this._resHeaders['last-modified']) {
|
||||
matches = this._resHeaders['last-modified'] === response.headers['last-modified'];
|
||||
} else {
|
||||
// If the new response does not include any form of validator (such as in the case where
|
||||
// a client generates an If-Modified-Since request from a source other than the Last-Modified
|
||||
// response header field), and there is only one stored response, and that stored response also
|
||||
// lacks a validator, then that stored response is selected for update.
|
||||
if (!this._resHeaders.etag && !this._resHeaders['last-modified'] && !response.headers.etag && !response.headers['last-modified']) {
|
||||
matches = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!matches) {
|
||||
return {
|
||||
policy: new this.constructor(request, response),
|
||||
modified: true
|
||||
};
|
||||
}
|
||||
|
||||
// use other header fields provided in the 304 (Not Modified) response to replace all instances
|
||||
// of the corresponding header fields in the stored response.
|
||||
var headers = {};
|
||||
for (var k in this._resHeaders) {
|
||||
headers[k] = k in response.headers && !excludedFromRevalidationUpdate[k] ? response.headers[k] : this._resHeaders[k];
|
||||
}
|
||||
|
||||
var newResponse = Object.assign({}, response, {
|
||||
status: this._status,
|
||||
method: this._method,
|
||||
headers
|
||||
});
|
||||
return {
|
||||
policy: new this.constructor(request, newResponse),
|
||||
modified: false
|
||||
};
|
||||
};
|
||||
|
||||
return CachePolicy;
|
||||
}();
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
{
|
||||
"name": "http-cache-semantics",
|
||||
"version": "3.8.1",
|
||||
"description": "Parses Cache-Control and other headers. Helps building correct HTTP caches and proxies",
|
||||
"repository": "https://github.com/pornel/http-cache-semantics.git",
|
||||
"main": "node4/index.js",
|
||||
"scripts": {
|
||||
"compile": "babel -d node4/ index.js; babel -d node4/test test",
|
||||
"prepublish": "npm run compile",
|
||||
"test": "npm run compile; mocha node4/test"
|
||||
},
|
||||
"files": [
|
||||
"node4/index.js"
|
||||
],
|
||||
"author": "Kornel Lesiński <kornel@geekhood.net> (https://kornel.ski/)",
|
||||
"license": "BSD-2-Clause",
|
||||
"devDependencies": {
|
||||
"babel-cli": "^6.24.1",
|
||||
"babel-preset-env": "^1.6.1",
|
||||
"mocha": "^3.4.2"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
The ISC License
|
||||
|
||||
Copyright (c) Isaac Z. Schlueter
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
Browser-friendly inheritance fully compatible with standard node.js
|
||||
[inherits](http://nodejs.org/api/util.html#util_util_inherits_constructor_superconstructor).
|
||||
|
||||
This package exports standard `inherits` from node.js `util` module in
|
||||
node environment, but also provides alternative browser-friendly
|
||||
implementation through [browser
|
||||
field](https://gist.github.com/shtylman/4339901). Alternative
|
||||
implementation is a literal copy of standard one located in standalone
|
||||
module to avoid requiring of `util`. It also has a shim for old
|
||||
browsers with no `Object.create` support.
|
||||
|
||||
While keeping you sure you are using standard `inherits`
|
||||
implementation in node.js environment, it allows bundlers such as
|
||||
[browserify](https://github.com/substack/node-browserify) to not
|
||||
include full `util` package to your client code if all you need is
|
||||
just `inherits` function. It worth, because browser shim for `util`
|
||||
package is large and `inherits` is often the single function you need
|
||||
from it.
|
||||
|
||||
It's recommended to use this package instead of
|
||||
`require('util').inherits` for any code that has chances to be used
|
||||
not only in node.js but in browser too.
|
||||
|
||||
## usage
|
||||
|
||||
```js
|
||||
var inherits = require('inherits');
|
||||
// then use exactly as the standard one
|
||||
```
|
||||
|
||||
## note on version ~1.0
|
||||
|
||||
Version ~1.0 had completely different motivation and is not compatible
|
||||
neither with 2.0 nor with standard node.js `inherits`.
|
||||
|
||||
If you are using version ~1.0 and planning to switch to ~2.0, be
|
||||
careful:
|
||||
|
||||
* new version uses `super_` instead of `super` for referencing
|
||||
superclass
|
||||
* new version overwrites current prototype while old one preserves any
|
||||
existing fields on it
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
try {
|
||||
var util = require('util');
|
||||
if (typeof util.inherits !== 'function') throw '';
|
||||
module.exports = util.inherits;
|
||||
} catch (e) {
|
||||
module.exports = require('./inherits_browser.js');
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
if (typeof Object.create === 'function') {
|
||||
// implementation from standard node.js 'util' module
|
||||
module.exports = function inherits(ctor, superCtor) {
|
||||
ctor.super_ = superCtor
|
||||
ctor.prototype = Object.create(superCtor.prototype, {
|
||||
constructor: {
|
||||
value: ctor,
|
||||
enumerable: false,
|
||||
writable: true,
|
||||
configurable: true
|
||||
}
|
||||
});
|
||||
};
|
||||
} else {
|
||||
// old school shim for old browsers
|
||||
module.exports = function inherits(ctor, superCtor) {
|
||||
ctor.super_ = superCtor
|
||||
var TempCtor = function () {}
|
||||
TempCtor.prototype = superCtor.prototype
|
||||
ctor.prototype = new TempCtor()
|
||||
ctor.prototype.constructor = ctor
|
||||
}
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
{
|
||||
"name": "inherits",
|
||||
"description": "Browser-friendly inheritance fully compatible with standard node.js inherits()",
|
||||
"version": "2.0.3",
|
||||
"keywords": [
|
||||
"inheritance",
|
||||
"class",
|
||||
"klass",
|
||||
"oop",
|
||||
"object-oriented",
|
||||
"inherits",
|
||||
"browser",
|
||||
"browserify"
|
||||
],
|
||||
"main": "./inherits.js",
|
||||
"browser": "./inherits_browser.js",
|
||||
"repository": "git://github.com/isaacs/inherits",
|
||||
"license": "ISC",
|
||||
"scripts": {
|
||||
"test": "node test"
|
||||
},
|
||||
"devDependencies": {
|
||||
"tap": "^7.1.0"
|
||||
},
|
||||
"files": [
|
||||
"inherits.js",
|
||||
"inherits_browser.js"
|
||||
]
|
||||
}
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
'use strict';
|
||||
const from = require('from2');
|
||||
const pIsPromise = require('p-is-promise');
|
||||
|
||||
module.exports = x => {
|
||||
if (Array.isArray(x)) {
|
||||
x = x.slice();
|
||||
}
|
||||
|
||||
let promise;
|
||||
let iterator;
|
||||
|
||||
prepare(x);
|
||||
|
||||
function prepare(value) {
|
||||
x = value;
|
||||
promise = pIsPromise(x) ? x : null;
|
||||
// we don't iterate on strings and buffers since slicing them is ~7x faster
|
||||
const shouldIterate = !promise && x[Symbol.iterator] && typeof x !== 'string' && !Buffer.isBuffer(x);
|
||||
iterator = shouldIterate ? x[Symbol.iterator]() : null;
|
||||
}
|
||||
|
||||
return from(function reader(size, cb) {
|
||||
if (promise) {
|
||||
promise.then(prepare).then(() => reader.call(this, size, cb), cb);
|
||||
return;
|
||||
}
|
||||
|
||||
if (iterator) {
|
||||
const obj = iterator.next();
|
||||
setImmediate(cb, null, obj.done ? null : obj.value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (x.length === 0) {
|
||||
setImmediate(cb, null, null);
|
||||
return;
|
||||
}
|
||||
|
||||
const chunk = x.slice(0, size);
|
||||
x = x.slice(size);
|
||||
|
||||
setImmediate(cb, null, chunk);
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.obj = x => {
|
||||
if (Array.isArray(x)) {
|
||||
x = x.slice();
|
||||
}
|
||||
|
||||
let promise;
|
||||
let iterator;
|
||||
|
||||
prepare(x);
|
||||
|
||||
function prepare(value) {
|
||||
x = value;
|
||||
promise = pIsPromise(x) ? x : null;
|
||||
iterator = !promise && x[Symbol.iterator] ? x[Symbol.iterator]() : null;
|
||||
}
|
||||
|
||||
return from.obj(function reader(size, cb) {
|
||||
if (promise) {
|
||||
promise.then(prepare).then(() => reader.call(this, size, cb), cb);
|
||||
return;
|
||||
}
|
||||
|
||||
if (iterator) {
|
||||
const obj = iterator.next();
|
||||
setImmediate(cb, null, obj.done ? null : obj.value);
|
||||
return;
|
||||
}
|
||||
|
||||
this.push(x);
|
||||
|
||||
setImmediate(cb, null, null);
|
||||
});
|
||||
};
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
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.
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
{
|
||||
"name": "into-stream",
|
||||
"version": "3.1.0",
|
||||
"description": "Convert a buffer/string/array/object/iterable/promise into a stream",
|
||||
"license": "MIT",
|
||||
"repository": "sindresorhus/into-stream",
|
||||
"author": {
|
||||
"name": "Sindre Sorhus",
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"url": "sindresorhus.com"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "xo && ava"
|
||||
},
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"keywords": [
|
||||
"stream",
|
||||
"buffer",
|
||||
"string",
|
||||
"object",
|
||||
"array",
|
||||
"iterable",
|
||||
"promise",
|
||||
"promises",
|
||||
"from",
|
||||
"into",
|
||||
"to",
|
||||
"transform",
|
||||
"convert",
|
||||
"readable",
|
||||
"pull",
|
||||
"gulpfriendly",
|
||||
"value",
|
||||
"str"
|
||||
],
|
||||
"dependencies": {
|
||||
"from2": "^2.1.1",
|
||||
"p-is-promise": "^1.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"ava": "*",
|
||||
"get-stream": "^3.0.0",
|
||||
"xo": "*"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
# into-stream [](https://travis-ci.org/sindresorhus/into-stream)
|
||||
|
||||
> Convert a buffer/string/array/object/iterable/promise into a stream
|
||||
|
||||
Correctly chunks up the input and handles backpressure.
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install --save into-stream
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const intoStream = require('into-stream');
|
||||
|
||||
intoStream('unicorn').pipe(process.stdout);
|
||||
//=> 'unicorn'
|
||||
```
|
||||
|
||||
|
||||
## API
|
||||
|
||||
### intoStream(input)
|
||||
|
||||
Type: `Buffer` `string` `Iterable<Buffer|string>` `Promise`<br>
|
||||
Returns: [Readable stream](https://nodejs.org/api/stream.html#stream_class_stream_readable)
|
||||
|
||||
Adheres to the requested chunk size, except for `array` where each element will be a chunk.
|
||||
|
||||
### intoStream.obj(input)
|
||||
|
||||
Type: `Object`, `Iterable<Object>` `Promise`<br>
|
||||
Returns: [Readable object stream](https://nodejs.org/api/stream.html#stream_object_mode)
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Sindre Sorhus](https://sindresorhus.com)
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
{
|
||||
"requireCurlyBraces": ["if", "else", "for", "while", "do", "try", "catch"],
|
||||
|
||||
"requireSpaceAfterKeywords": ["if", "else", "for", "while", "do", "switch", "return", "try", "catch", "function"],
|
||||
|
||||
"disallowSpaceAfterKeywords": [],
|
||||
|
||||
"requireSpacesInAnonymousFunctionExpression": { "beforeOpeningRoundBrace": true, "beforeOpeningCurlyBrace": true },
|
||||
"requireSpacesInNamedFunctionExpression": { "beforeOpeningCurlyBrace": true },
|
||||
"disallowSpacesInNamedFunctionExpression": { "beforeOpeningRoundBrace": true },
|
||||
"requireSpacesInFunctionDeclaration": { "beforeOpeningCurlyBrace": true },
|
||||
"disallowSpacesInFunctionDeclaration": { "beforeOpeningRoundBrace": true },
|
||||
|
||||
"disallowSpacesInsideParentheses": true,
|
||||
|
||||
"disallowSpacesInsideArrayBrackets": true,
|
||||
|
||||
"disallowQuotedKeysInObjects": "allButReserved",
|
||||
|
||||
"disallowSpaceAfterObjectKeys": true,
|
||||
|
||||
"requireCommaBeforeLineBreak": true,
|
||||
|
||||
"disallowSpaceAfterPrefixUnaryOperators": ["++", "--", "+", "-", "~", "!"],
|
||||
"requireSpaceAfterPrefixUnaryOperators": [],
|
||||
|
||||
"disallowSpaceBeforePostfixUnaryOperators": ["++", "--"],
|
||||
"requireSpaceBeforePostfixUnaryOperators": [],
|
||||
|
||||
"disallowSpaceBeforeBinaryOperators": [],
|
||||
"requireSpaceBeforeBinaryOperators": ["+", "-", "/", "*", "=", "==", "===", "!=", "!=="],
|
||||
|
||||
"requireSpaceAfterBinaryOperators": ["+", "-", "/", "*", "=", "==", "===", "!=", "!=="],
|
||||
"disallowSpaceAfterBinaryOperators": [],
|
||||
|
||||
"disallowImplicitTypeConversion": ["binary", "string"],
|
||||
|
||||
"disallowKeywords": ["with", "eval"],
|
||||
|
||||
"validateLineBreaks": "LF",
|
||||
|
||||
"requireKeywordsOnNewLine": [],
|
||||
"disallowKeywordsOnNewLine": ["else"],
|
||||
|
||||
"requireLineFeedAtFileEnd": true,
|
||||
|
||||
"disallowTrailingWhitespace": true,
|
||||
|
||||
"excludeFiles": ["node_modules/**", "vendor/**"],
|
||||
|
||||
"disallowMultipleLineStrings": true,
|
||||
|
||||
"additionalRules": []
|
||||
}
|
||||
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
.DS_Store
|
||||
.monitor
|
||||
.*.swp
|
||||
.nodemonignore
|
||||
releases
|
||||
*.log
|
||||
*.err
|
||||
fleet.json
|
||||
public/browserify
|
||||
bin/*.json
|
||||
.bin
|
||||
build
|
||||
compile
|
||||
.lock-wscript
|
||||
node_modules
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
{
|
||||
"launchers": {
|
||||
"node": {
|
||||
"command": "node ./test"
|
||||
}
|
||||
},
|
||||
"src_files": [
|
||||
"./**/*.js"
|
||||
],
|
||||
"before_tests": "npm run build",
|
||||
"on_exit": "rm test/static/bundle.js",
|
||||
"test_page": "test/static/index.html",
|
||||
"launch_in_dev": ["node", "phantomjs"]
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
language: node_js
|
||||
node_js:
|
||||
- "0.11"
|
||||
- "0.10"
|
||||
- "0.9"
|
||||
- "0.8"
|
||||
- "0.6"
|
||||
- "0.4"
|
||||
before_install:
|
||||
- '[ "${TRAVIS_NODE_VERSION}" == "0.6" ] || npm install -g npm@~1.4.6'
|
||||
matrix:
|
||||
fast_finish: true
|
||||
allow_failures:
|
||||
- node_js: "0.11"
|
||||
- node_js: "0.9"
|
||||
- node_js: "0.6"
|
||||
- node_js: "0.4"
|
||||
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
Copyright (c) 2013 Colingo.
|
||||
|
||||
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.
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
# is-object <sup>[![Version Badge][12]][11]</sup>
|
||||
|
||||
[![build status][1]][2]
|
||||
[![dependency status][3]][4]
|
||||
[![dev dependency status][9]][10]
|
||||
[![License][license-image]][license-url]
|
||||
[![Downloads][downloads-image]][downloads-url]
|
||||
|
||||
[![npm badge][13]][11]
|
||||
|
||||
[![browser support][5]][6]
|
||||
|
||||
Checks whether a value is an object
|
||||
|
||||
Because `typeof null` is a troll.
|
||||
|
||||
## Example
|
||||
|
||||
```js
|
||||
var isObject = require('is-object');
|
||||
var assert = require('assert');
|
||||
|
||||
assert.equal(isObject(null), false);
|
||||
assert.equal(isObject({}), true);
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
`npm install is-object`
|
||||
|
||||
## Contributors
|
||||
|
||||
- [Raynos][7]
|
||||
- [Jordan Harband][8]
|
||||
|
||||
## MIT Licensed
|
||||
|
||||
[1]: https://secure.travis-ci.org/ljharb/is-object.svg
|
||||
[2]: http://travis-ci.org/ljharb/is-object
|
||||
[3]: http://david-dm.org/ljharb/is-object/status.svg
|
||||
[4]: http://david-dm.org/ljharb/is-object
|
||||
[5]: http://ci.testling.com/ljharb/is-object.svg
|
||||
[6]: http://ci.testling.com/ljharb/is-object
|
||||
[7]: https://github.com/Raynos
|
||||
[8]: https://github.com/ljharb
|
||||
[9]: https://david-dm.org/ljharb/is-object/dev-status.svg
|
||||
[10]: https://david-dm.org/ljharb/is-object#info=devDependencies
|
||||
[11]: https://npmjs.org/package/is-object
|
||||
[12]: http://vb.teelaun.ch/ljharb/is-object.svg
|
||||
[13]: https://nodei.co/npm/is-object.png?downloads=true&stars=true
|
||||
[license-image]: http://img.shields.io/npm/l/is-object.svg
|
||||
[license-url]: LICENSE
|
||||
[downloads-image]: http://img.shields.io/npm/dm/is-object.svg
|
||||
[downloads-url]: http://npm-stat.com/charts.html?package=is-object
|
||||
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
module.exports = function isObject(x) {
|
||||
return typeof x === "object" && x !== null;
|
||||
};
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
{
|
||||
"name": "is-object",
|
||||
"version": "1.0.1",
|
||||
"description": "Checks whether a value is an object",
|
||||
"keywords": [],
|
||||
"author": "Raynos <raynos2@gmail.com>",
|
||||
"repository": "git://github.com/ljharb/is-object.git",
|
||||
"main": "index",
|
||||
"homepage": "https://github.com/ljharb/is-object",
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Raynos"
|
||||
},
|
||||
{
|
||||
"name": "Jordan Harband",
|
||||
"url": "https://github.com/ljharb"
|
||||
}
|
||||
],
|
||||
"bugs": {
|
||||
"url": "https://github.com/ljharb/is-object/issues",
|
||||
"email": "ljharb@gmail.com"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"tape": "~2.14.0",
|
||||
"covert": "~1.0.0",
|
||||
"jscs": "~1.6.0"
|
||||
},
|
||||
"license": "MIT",
|
||||
"licenses": [
|
||||
{
|
||||
"type": "MIT",
|
||||
"url": "http://github.com/ljharb/is-object/raw/master/LICENSE"
|
||||
}
|
||||
],
|
||||
"scripts": {
|
||||
"test": "npm run lint && node test/index.js && npm run coverage-quiet",
|
||||
"coverage": "covert test/index.js",
|
||||
"coverage-quiet": "covert test/index.js --quiet",
|
||||
"lint": "jscs *.js */*.js"
|
||||
},
|
||||
"testling": {
|
||||
"files": "test/index.js",
|
||||
"browsers": [
|
||||
"ie/6..latest",
|
||||
"firefox/3..6",
|
||||
"firefox/16..latest",
|
||||
"firefox/nightly",
|
||||
"chrome/22..latest",
|
||||
"chrome/canary",
|
||||
"opera/10.0",
|
||||
"opera/11..latest",
|
||||
"opera/next",
|
||||
"safari/4..latest",
|
||||
"ipad/6.0..latest",
|
||||
"iphone/6.0..latest"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
var test = require('tape');
|
||||
|
||||
var isObject = require('../index');
|
||||
|
||||
test('returns true for objects', function (assert) {
|
||||
assert.equal(isObject({}), true);
|
||||
assert.equal(isObject([]), true);
|
||||
|
||||
assert.end();
|
||||
});
|
||||
|
||||
test('returns false for null', function (assert) {
|
||||
assert.equal(isObject(null), false);
|
||||
|
||||
assert.end();
|
||||
});
|
||||
|
||||
test('returns false for primitives', function (assert) {
|
||||
assert.equal(isObject(42), false);
|
||||
assert.equal(isObject('foo'), false);
|
||||
|
||||
assert.end();
|
||||
});
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
'use strict';
|
||||
var toString = Object.prototype.toString;
|
||||
|
||||
module.exports = function (x) {
|
||||
var prototype;
|
||||
return toString.call(x) === '[object Object]' && (prototype = Object.getPrototypeOf(x), prototype === null || prototype === Object.getPrototypeOf({}));
|
||||
};
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
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.
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
{
|
||||
"name": "is-plain-obj",
|
||||
"version": "1.1.0",
|
||||
"description": "Check if a value is a plain object",
|
||||
"license": "MIT",
|
||||
"repository": "sindresorhus/is-plain-obj",
|
||||
"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": [
|
||||
"obj",
|
||||
"object",
|
||||
"is",
|
||||
"check",
|
||||
"test",
|
||||
"type",
|
||||
"plain",
|
||||
"vanilla",
|
||||
"pure",
|
||||
"simple"
|
||||
],
|
||||
"devDependencies": {
|
||||
"ava": "0.0.4"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
# is-plain-obj [](https://travis-ci.org/sindresorhus/is-plain-obj)
|
||||
|
||||
> Check if a value is a plain object
|
||||
|
||||
An object is plain if it's created by either `{}`, `new Object()` or `Object.create(null)`.
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install --save is-plain-obj
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
var isPlainObj = require('is-plain-obj');
|
||||
|
||||
isPlainObj({foo: 'bar'});
|
||||
//=> true
|
||||
|
||||
isPlainObj([1, 2, 3]);
|
||||
//=> false
|
||||
```
|
||||
|
||||
|
||||
## Related
|
||||
|
||||
- [is-obj](https://github.com/sindresorhus/is-obj) - Check if a value is an object
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Sindre Sorhus](http://sindresorhus.com)
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
var WHITELIST = [
|
||||
'ETIMEDOUT',
|
||||
'ECONNRESET',
|
||||
'EADDRINUSE',
|
||||
'ESOCKETTIMEDOUT',
|
||||
'ECONNREFUSED',
|
||||
'EPIPE'
|
||||
];
|
||||
|
||||
var BLACKLIST = [
|
||||
'ENOTFOUND',
|
||||
'ENETUNREACH',
|
||||
|
||||
// SSL errors from https://github.com/nodejs/node/blob/ed3d8b13ee9a705d89f9e0397d9e96519e7e47ac/src/node_crypto.cc#L1950
|
||||
'UNABLE_TO_GET_ISSUER_CERT',
|
||||
'UNABLE_TO_GET_CRL',
|
||||
'UNABLE_TO_DECRYPT_CERT_SIGNATURE',
|
||||
'UNABLE_TO_DECRYPT_CRL_SIGNATURE',
|
||||
'UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY',
|
||||
'CERT_SIGNATURE_FAILURE',
|
||||
'CRL_SIGNATURE_FAILURE',
|
||||
'CERT_NOT_YET_VALID',
|
||||
'CERT_HAS_EXPIRED',
|
||||
'CRL_NOT_YET_VALID',
|
||||
'CRL_HAS_EXPIRED',
|
||||
'ERROR_IN_CERT_NOT_BEFORE_FIELD',
|
||||
'ERROR_IN_CERT_NOT_AFTER_FIELD',
|
||||
'ERROR_IN_CRL_LAST_UPDATE_FIELD',
|
||||
'ERROR_IN_CRL_NEXT_UPDATE_FIELD',
|
||||
'OUT_OF_MEM',
|
||||
'DEPTH_ZERO_SELF_SIGNED_CERT',
|
||||
'SELF_SIGNED_CERT_IN_CHAIN',
|
||||
'UNABLE_TO_GET_ISSUER_CERT_LOCALLY',
|
||||
'UNABLE_TO_VERIFY_LEAF_SIGNATURE',
|
||||
'CERT_CHAIN_TOO_LONG',
|
||||
'CERT_REVOKED',
|
||||
'INVALID_CA',
|
||||
'PATH_LENGTH_EXCEEDED',
|
||||
'INVALID_PURPOSE',
|
||||
'CERT_UNTRUSTED',
|
||||
'CERT_REJECTED'
|
||||
];
|
||||
|
||||
module.exports = function (err) {
|
||||
if (!err || !err.code) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (WHITELIST.indexOf(err.code) !== -1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (BLACKLIST.indexOf(err.code) !== -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) Vsevolod Strukchinsky <floatdrop@gmail.com> (github.com/floatdrop)
|
||||
|
||||
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.
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
{
|
||||
"name": "is-retry-allowed",
|
||||
"version": "1.1.0",
|
||||
"description": "My prime module",
|
||||
"license": "MIT",
|
||||
"repository": "floatdrop/is-retry-allowed",
|
||||
"author": {
|
||||
"name": "Vsevolod Strukchinsky",
|
||||
"email": "floatdrop@gmail.com",
|
||||
"url": "github.com/floatdrop"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "xo && ava"
|
||||
},
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"keywords": [
|
||||
""
|
||||
],
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"ava": "^0.8.0",
|
||||
"xo": "^0.12.1"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
# is-retry-allowed [](https://travis-ci.org/floatdrop/is-retry-allowed)
|
||||
|
||||
Is retry allowed for Error?
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install --save is-retry-allowed
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const isRetryAllowed = require('is-retry-allowed');
|
||||
|
||||
isRetryAllowed({code: 'ETIMEDOUT'});
|
||||
//=> true
|
||||
|
||||
isRetryAllowed({code: 'ENOTFOUND'});
|
||||
//=> false
|
||||
|
||||
isRetryAllowed({});
|
||||
//=> true
|
||||
```
|
||||
|
||||
|
||||
## API
|
||||
|
||||
### isRetryAllowed(error)
|
||||
|
||||
#### error
|
||||
|
||||
Type: `object`
|
||||
|
||||
Object with `code` property, which will be used to determine retry.
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Vsevolod Strukchinsky](http://github.com/floatdrop)
|
||||
|
|
@ -1 +0,0 @@
|
|||
node_modules
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
language: node_js
|
||||
node_js:
|
||||
- "0.8"
|
||||
- "0.10"
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
|
||||
test:
|
||||
@node_modules/.bin/tape test.js
|
||||
|
||||
.PHONY: test
|
||||
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
|
||||
# isarray
|
||||
|
||||
`Array#isArray` for older browsers.
|
||||
|
||||
[](http://travis-ci.org/juliangruber/isarray)
|
||||
[](https://www.npmjs.org/package/isarray)
|
||||
|
||||
[
|
||||
](https://ci.testling.com/juliangruber/isarray)
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
var isArray = require('isarray');
|
||||
|
||||
console.log(isArray([])); // => true
|
||||
console.log(isArray({})); // => false
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
With [npm](http://npmjs.org) do
|
||||
|
||||
```bash
|
||||
$ npm install isarray
|
||||
```
|
||||
|
||||
Then bundle for the browser with
|
||||
[browserify](https://github.com/substack/browserify).
|
||||
|
||||
With [component](http://component.io) do
|
||||
|
||||
```bash
|
||||
$ component install juliangruber/isarray
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
(MIT)
|
||||
|
||||
Copyright (c) 2013 Julian Gruber <julian@juliangruber.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.
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
{
|
||||
"name" : "isarray",
|
||||
"description" : "Array#isArray for older browsers",
|
||||
"version" : "0.0.1",
|
||||
"repository" : "juliangruber/isarray",
|
||||
"homepage": "https://github.com/juliangruber/isarray",
|
||||
"main" : "index.js",
|
||||
"scripts" : [
|
||||
"index.js"
|
||||
],
|
||||
"dependencies" : {},
|
||||
"keywords": ["browser","isarray","array"],
|
||||
"author": {
|
||||
"name": "Julian Gruber",
|
||||
"email": "mail@juliangruber.com",
|
||||
"url": "http://juliangruber.com"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
var toString = {}.toString;
|
||||
|
||||
module.exports = Array.isArray || function (arr) {
|
||||
return toString.call(arr) == '[object Array]';
|
||||
};
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
{
|
||||
"name": "isarray",
|
||||
"description": "Array#isArray for older browsers",
|
||||
"version": "1.0.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/juliangruber/isarray.git"
|
||||
},
|
||||
"homepage": "https://github.com/juliangruber/isarray",
|
||||
"main": "index.js",
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"tape": "~2.13.4"
|
||||
},
|
||||
"keywords": [
|
||||
"browser",
|
||||
"isarray",
|
||||
"array"
|
||||
],
|
||||
"author": {
|
||||
"name": "Julian Gruber",
|
||||
"email": "mail@juliangruber.com",
|
||||
"url": "http://juliangruber.com"
|
||||
},
|
||||
"license": "MIT",
|
||||
"testling": {
|
||||
"files": "test.js",
|
||||
"browsers": [
|
||||
"ie/8..latest",
|
||||
"firefox/17..latest",
|
||||
"firefox/nightly",
|
||||
"chrome/22..latest",
|
||||
"chrome/canary",
|
||||
"opera/12..latest",
|
||||
"opera/next",
|
||||
"safari/5.1..latest",
|
||||
"ipad/6.0..latest",
|
||||
"iphone/6.0..latest",
|
||||
"android-browser/4.2..latest"
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
"test": "tape test.js"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
var isArray = require('./');
|
||||
var test = require('tape');
|
||||
|
||||
test('is array', function(t){
|
||||
t.ok(isArray([]));
|
||||
t.notOk(isArray({}));
|
||||
t.notOk(isArray(null));
|
||||
t.notOk(isArray(false));
|
||||
|
||||
var obj = {};
|
||||
obj[0] = true;
|
||||
t.notOk(isArray(obj));
|
||||
|
||||
var arr = [];
|
||||
arr.foo = 'bar';
|
||||
t.ok(isArray(arr));
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2017 Steven Vachon
|
||||
|
||||
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.
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
# isurl [![NPM Version][npm-image]][npm-url] [![Build Status][travis-image]][travis-url]
|
||||
|
||||
> Checks whether a value is a WHATWG [`URL`](https://developer.mozilla.org/en/docs/Web/API/URL).
|
||||
|
||||
|
||||
Works cross-realm/iframe and despite @@toStringTag.
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
[Node.js](http://nodejs.org/) `>= 4` is required. To install, type this at the command line:
|
||||
```shell
|
||||
npm install isurl
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const isURL = require('isurl');
|
||||
|
||||
isURL('http://domain/'); //-> false
|
||||
isURL(new URL('http://domain/')); //-> true
|
||||
```
|
||||
|
||||
Optionally, acceptance can be extended to incomplete `URL` implementations that lack `searchParams` (which are common in many modern web browsers):
|
||||
```js
|
||||
const url = new URL('http://domain/?query');
|
||||
|
||||
console.log(url.searchParams); //-> undefined
|
||||
|
||||
isURL.lenient(url); //-> true
|
||||
```
|
||||
|
||||
|
||||
[npm-image]: https://img.shields.io/npm/v/isurl.svg
|
||||
[npm-url]: https://npmjs.org/package/isurl
|
||||
[travis-image]: https://img.shields.io/travis/stevenvachon/isurl.svg
|
||||
[travis-url]: https://travis-ci.org/stevenvachon/isurl
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
"use strict";
|
||||
const hasToStringTag = require("has-to-string-tag-x");
|
||||
const isObject = require("is-object");
|
||||
|
||||
const toString = Object.prototype.toString;
|
||||
const urlClass = "[object URL]";
|
||||
|
||||
const hash = "hash";
|
||||
const host = "host";
|
||||
const hostname = "hostname";
|
||||
const href = "href";
|
||||
const password = "password";
|
||||
const pathname = "pathname";
|
||||
const port = "port";
|
||||
const protocol = "protocol";
|
||||
const search = "search";
|
||||
const username = "username";
|
||||
|
||||
|
||||
|
||||
const isURL = (url, supportIncomplete/*=false*/) =>
|
||||
{
|
||||
if (!isObject(url)) return false;
|
||||
|
||||
// Native implementation in older browsers
|
||||
if (!hasToStringTag && toString.call(url) === urlClass) return true;
|
||||
|
||||
if (!(href in url)) return false;
|
||||
if (!(protocol in url)) return false;
|
||||
if (!(username in url)) return false;
|
||||
if (!(password in url)) return false;
|
||||
if (!(hostname in url)) return false;
|
||||
if (!(port in url)) return false;
|
||||
if (!(host in url)) return false;
|
||||
if (!(pathname in url)) return false;
|
||||
if (!(search in url)) return false;
|
||||
if (!(hash in url)) return false;
|
||||
|
||||
if (supportIncomplete !== true)
|
||||
{
|
||||
if (!isObject(url.searchParams)) return false;
|
||||
|
||||
// TODO :: write a separate isURLSearchParams ?
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
isURL.lenient = url =>
|
||||
{
|
||||
return isURL(url, true);
|
||||
};
|
||||
|
||||
|
||||
|
||||
module.exports = isURL;
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
{
|
||||
"name": "isurl",
|
||||
"description": "Checks whether a value is a WHATWG URL.",
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"author": "Steven Vachon <contact@svachon.com> (https://www.svachon.com/)",
|
||||
"repository": "stevenvachon/isurl",
|
||||
"dependencies": {
|
||||
"has-to-string-tag-x": "^1.2.0",
|
||||
"is-object": "^1.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"chai": "^4.0.2",
|
||||
"mocha": "^3.4.2",
|
||||
"semver": "^5.3.0",
|
||||
"universal-url": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "mocha test --check-leaks --bail"
|
||||
},
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"keywords": [
|
||||
"uri",
|
||||
"url",
|
||||
"whatwg"
|
||||
]
|
||||
}
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
node_modules
|
||||
node_modules/*
|
||||
npm_debug.log
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
language: node_js
|
||||
node_js:
|
||||
- '0.10'
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
Copyright (c) 2013 Dominic Tarr
|
||||
|
||||
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.
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
# json-buffer
|
||||
|
||||
JSON functions that can convert buffers!
|
||||
|
||||
[](http://travis-ci.org/dominictarr/json-buffer)
|
||||
|
||||
[](https://ci.testling.com/dominictarr/json-buffer)
|
||||
|
||||
JSON mangles buffers by converting to an array...
|
||||
which isn't helpful. json-buffers converts to base64 instead,
|
||||
and deconverts base64 to a buffer.
|
||||
|
||||
``` js
|
||||
var JSONB = require('json-buffer')
|
||||
var Buffer = require('buffer').Buffer
|
||||
|
||||
var str = JSONB.stringify(new Buffer('hello there!'))
|
||||
|
||||
console.log(JSONB.parse(str)) //GET a BUFFER back
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
//TODO: handle reviver/dehydrate function like normal
|
||||
//and handle indentation, like normal.
|
||||
//if anyone needs this... please send pull request.
|
||||
|
||||
exports.stringify = function stringify (o) {
|
||||
if('undefined' == typeof o) return o
|
||||
|
||||
if(o && Buffer.isBuffer(o))
|
||||
return JSON.stringify(':base64:' + o.toString('base64'))
|
||||
|
||||
if(o && o.toJSON)
|
||||
o = o.toJSON()
|
||||
|
||||
if(o && 'object' === typeof o) {
|
||||
var s = ''
|
||||
var array = Array.isArray(o)
|
||||
s = array ? '[' : '{'
|
||||
var first = true
|
||||
|
||||
for(var k in o) {
|
||||
var ignore = 'function' == typeof o[k] || (!array && 'undefined' === typeof o[k])
|
||||
if(Object.hasOwnProperty.call(o, k) && !ignore) {
|
||||
if(!first)
|
||||
s += ','
|
||||
first = false
|
||||
if (array) {
|
||||
if(o[k] == undefined)
|
||||
s += 'null'
|
||||
else
|
||||
s += stringify(o[k])
|
||||
} else if (o[k] !== void(0)) {
|
||||
s += stringify(k) + ':' + stringify(o[k])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s += array ? ']' : '}'
|
||||
|
||||
return s
|
||||
} else if ('string' === typeof o) {
|
||||
return JSON.stringify(/^:/.test(o) ? ':' + o : o)
|
||||
} else if ('undefined' === typeof o) {
|
||||
return 'null';
|
||||
} else
|
||||
return JSON.stringify(o)
|
||||
}
|
||||
|
||||
exports.parse = function (s) {
|
||||
return JSON.parse(s, function (key, value) {
|
||||
if('string' === typeof value) {
|
||||
if(/^:base64:/.test(value))
|
||||
return new Buffer(value.substring(8), 'base64')
|
||||
else
|
||||
return /^:/.test(value) ? value.substring(1) : value
|
||||
}
|
||||
return value
|
||||
})
|
||||
}
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
{
|
||||
"name": "json-buffer",
|
||||
"description": "JSON parse & stringify that supports binary via bops & base64",
|
||||
"version": "3.0.0",
|
||||
"homepage": "https://github.com/dominictarr/json-buffer",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/dominictarr/json-buffer.git"
|
||||
},
|
||||
"devDependencies": {
|
||||
"tape": "^4.6.3"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "set -e; for t in test/*.js; do node $t; done"
|
||||
},
|
||||
"author": "Dominic Tarr <dominic.tarr@gmail.com> (http://dominictarr.com)",
|
||||
"license": "MIT",
|
||||
"testling": {
|
||||
"files": "test/*.js",
|
||||
"browsers": [
|
||||
"ie/8..latest",
|
||||
"firefox/17..latest",
|
||||
"firefox/nightly",
|
||||
"chrome/22..latest",
|
||||
"chrome/canary",
|
||||
"opera/12..latest",
|
||||
"opera/next",
|
||||
"safari/5.1..latest",
|
||||
"ipad/6.0..latest",
|
||||
"iphone/6.0..latest",
|
||||
"android-browser/4.2..latest"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
|
||||
var test = require('tape')
|
||||
var _JSON = require('../')
|
||||
|
||||
function clone (o) {
|
||||
return JSON.parse(JSON.stringify(o))
|
||||
}
|
||||
|
||||
var examples = {
|
||||
simple: { foo: [], bar: {}, baz: new Buffer('some binary data') },
|
||||
just_buffer: new Buffer('JUST A BUFFER'),
|
||||
all_types: {
|
||||
string:'hello',
|
||||
number: 3145,
|
||||
null: null,
|
||||
object: {},
|
||||
array: [],
|
||||
boolean: true,
|
||||
boolean2: false
|
||||
},
|
||||
foo: new Buffer('foo'),
|
||||
foo2: new Buffer('foo2'),
|
||||
escape: {
|
||||
buffer: new Buffer('x'),
|
||||
string: _JSON.stringify(new Buffer('x'))
|
||||
},
|
||||
escape2: {
|
||||
buffer: new Buffer('x'),
|
||||
string: ':base64:'+ new Buffer('x').toString('base64')
|
||||
},
|
||||
undefined: {
|
||||
empty: undefined, test: true
|
||||
},
|
||||
undefined2: {
|
||||
first: 1, empty: undefined, test: true
|
||||
},
|
||||
undefinedArray: {
|
||||
array: [undefined, 1, 'two']
|
||||
},
|
||||
fn: {
|
||||
fn: function () {}
|
||||
},
|
||||
undefined: undefined
|
||||
}
|
||||
|
||||
for(k in examples)
|
||||
(function (value, k) {
|
||||
test(k, function (t) {
|
||||
var s = _JSON.stringify(value)
|
||||
console.log('parse', s)
|
||||
if(JSON.stringify(value) !== undefined) {
|
||||
console.log(s)
|
||||
var _value = _JSON.parse(s)
|
||||
t.deepEqual(clone(_value), clone(value))
|
||||
}
|
||||
else
|
||||
t.equal(s, undefined)
|
||||
t.end()
|
||||
})
|
||||
})(examples[k], k)
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
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.
|
||||
|
|
@ -1,243 +0,0 @@
|
|||
<h1 align="center">
|
||||
<img width="250" src="https://rawgit.com/lukechilds/keyv/master/media/logo.svg" alt="keyv">
|
||||
<br>
|
||||
<br>
|
||||
</h1>
|
||||
|
||||
> Simple key-value storage with support for multiple backends
|
||||
|
||||
[](https://travis-ci.org/lukechilds/keyv)
|
||||
[](https://coveralls.io/github/lukechilds/keyv?branch=master)
|
||||
[](https://www.npmjs.com/package/keyv)
|
||||
|
||||
Keyv provides a consistent interface for key-value storage across multiple backends via storage adapters. It supports TTL based expiry, making it suitable as a cache or a persistent key-value store.
|
||||
|
||||
## Features
|
||||
|
||||
There are a few existing modules similar to Keyv, however Keyv is different because it:
|
||||
|
||||
- Isn't bloated
|
||||
- Has a simple Promise based API
|
||||
- Suitable as a TTL based cache or persistent key-value store
|
||||
- [Easily embeddable](#add-cache-support-to-your-module) inside another module
|
||||
- Works with any storage that implements the [`Map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) API
|
||||
- Handles all JavaScript types (values can be `Buffer`/`null`/`undefined`)
|
||||
- Supports namespaces
|
||||
- Wide range of [**efficient, well tested**](#official-storage-adapters) storage adapters
|
||||
- Connection errors are passed through (db failures won't kill your app)
|
||||
- Supports the current active LTS version of Node.js or higher
|
||||
|
||||
## Usage
|
||||
|
||||
Install Keyv.
|
||||
|
||||
```
|
||||
npm install --save keyv
|
||||
```
|
||||
|
||||
By default everything is stored in memory, you can optionally also install a storage adapter.
|
||||
|
||||
```
|
||||
npm install --save @keyv/redis
|
||||
npm install --save @keyv/mongo
|
||||
npm install --save @keyv/sqlite
|
||||
npm install --save @keyv/postgres
|
||||
npm install --save @keyv/mysql
|
||||
```
|
||||
|
||||
Create a new Keyv instance, passing your connection string if applicable. Keyv will automatically load the correct storage adapter.
|
||||
|
||||
```js
|
||||
const Keyv = require('keyv');
|
||||
|
||||
// One of the following
|
||||
const keyv = new Keyv();
|
||||
const keyv = new Keyv('redis://user:pass@localhost:6379');
|
||||
const keyv = new Keyv('mongodb://user:pass@localhost:27017/dbname');
|
||||
const keyv = new Keyv('sqlite://path/to/database.sqlite');
|
||||
const keyv = new Keyv('postgresql://user:pass@localhost:5432/dbname');
|
||||
const keyv = new Keyv('mysql://user:pass@localhost:3306/dbname');
|
||||
|
||||
// Handle DB connection errors
|
||||
keyv.on('error' err => console.log('Connection Error', err));
|
||||
|
||||
await keyv.set('foo', 'expires in 1 second', 1000); // true
|
||||
await keyv.set('foo', 'never expires'); // true
|
||||
await keyv.get('foo'); // 'never expires'
|
||||
await keyv.delete('foo'); // true
|
||||
await keyv.clear(); // undefined
|
||||
```
|
||||
|
||||
### Namespaces
|
||||
|
||||
You can namespace your Keyv instance to avoid key collisions and allow you to clear only a certain namespace while using the same database.
|
||||
|
||||
```js
|
||||
const users = new Keyv('redis://user:pass@localhost:6379', { namespace: 'users' });
|
||||
const cache = new Keyv('redis://user:pass@localhost:6379', { namespace: 'cache' });
|
||||
|
||||
await users.set('foo', 'users'); // true
|
||||
await cache.set('foo', 'cache'); // true
|
||||
await users.get('foo'); // 'users'
|
||||
await cache.get('foo'); // 'cache'
|
||||
await users.clear(); // undefined
|
||||
await users.get('foo'); // undefined
|
||||
await cache.get('foo'); // 'cache'
|
||||
```
|
||||
|
||||
## Official Storage Adapters
|
||||
|
||||
The official storage adapters are covered by [over 150 integration tests](https://travis-ci.org/lukechilds/keyv/jobs/260418145) to guarantee consistent behaviour. They are lightweight, efficient wrappers over the DB clients making use of indexes and native TTLs where available.
|
||||
|
||||
Database | Adapter | Native TTL | Status
|
||||
---|---|---|---
|
||||
Redis | [@keyv/redis](https://github.com/lukechilds/keyv-redis) | Yes | [](https://travis-ci.org/lukechilds/keyv-redis) [](https://coveralls.io/github/lukechilds/keyv-redis?branch=master)
|
||||
MongoDB | [@keyv/mongo](https://github.com/lukechilds/keyv-mongo) | Yes | [](https://travis-ci.org/lukechilds/keyv-mongo) [](https://coveralls.io/github/lukechilds/keyv-mongo?branch=master)
|
||||
SQLite | [@keyv/sqlite](https://github.com/lukechilds/keyv-sqlite) | No | [](https://travis-ci.org/lukechilds/keyv-sqlite) [](https://coveralls.io/github/lukechilds/keyv-sqlite?branch=master)
|
||||
PostgreSQL | [@keyv/postgres](https://github.com/lukechilds/keyv-postgres) | No | [](https://travis-ci.org/lukechildskeyv-postgreskeyv) [](https://coveralls.io/github/lukechilds/keyv-postgres?branch=master)
|
||||
MySQL | [@keyv/mysql](https://github.com/lukechilds/keyv-mysql) | No | [](https://travis-ci.org/lukechilds/keyv-mysql) [](https://coveralls.io/github/lukechilds/keyv-mysql?branch=master)
|
||||
|
||||
## Third-party Storage Adapters
|
||||
|
||||
You can also use third-party storage adapters or build your own. Keyv will wrap these storage adapters in TTL functionality and handle complex types internally.
|
||||
|
||||
```js
|
||||
const Keyv = require('keyv');
|
||||
const myAdapter = require('./my-storage-adapter');
|
||||
|
||||
const keyv = new Keyv({ store: myAdapter });
|
||||
```
|
||||
|
||||
Any store that follows the [`Map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) api will work.
|
||||
|
||||
```js
|
||||
new Keyv({ store: new Map() });
|
||||
```
|
||||
|
||||
For example, [`quick-lru`](https://github.com/sindresorhus/quick-lru) is a completely unrelated module that implements the Map API.
|
||||
|
||||
```js
|
||||
const Keyv = require('keyv');
|
||||
const QuickLRU = require('quick-lru');
|
||||
|
||||
const lru = new QuickLRU({ maxSize: 1000 });
|
||||
const keyv = new Keyv({ store: lru });
|
||||
```
|
||||
|
||||
## Add Cache Support to your Module
|
||||
|
||||
Keyv is designed to be easily embedded into other modules to add cache support. The recommended pattern is to expose a `cache` option in your modules options which is passed through to Keyv. Caching will work in memory by default and users have the option to also install a Keyv storage adapter and pass in a connection string, or any other storage that implements the `Map` API.
|
||||
|
||||
You should also set a namespace for your module so you can safely call `.clear()` without clearing unrelated app data.
|
||||
|
||||
Inside your module:
|
||||
|
||||
```js
|
||||
class AwesomeModule {
|
||||
constructor(opts) {
|
||||
this.cache = new Keyv({
|
||||
uri: typeof opts.cache === 'string' && opts.cache,
|
||||
store: typeof opts.cache !== 'string' && opts.cache,
|
||||
namespace: 'awesome-module'
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Now it can be consumed like this:
|
||||
|
||||
```js
|
||||
const AwesomeModule = require('awesome-module');
|
||||
|
||||
// Caches stuff in memory by default
|
||||
const awesomeModule = new AwesomeModule();
|
||||
|
||||
// After npm install --save keyv-redis
|
||||
const awesomeModule = new AwesomeModule({ cache: 'redis://localhost' });
|
||||
|
||||
// Some third-party module that implements the Map API
|
||||
const awesomeModule = new AwesomeModule({ cache: some3rdPartyStore });
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### new Keyv([uri], [options])
|
||||
|
||||
Returns a new Keyv instance.
|
||||
|
||||
The Keyv instance is also an `EventEmitter` that will emit an `'error'` event if the storage adapter connection fails.
|
||||
|
||||
### uri
|
||||
|
||||
Type: `String`<br>
|
||||
Default: `undefined`
|
||||
|
||||
The connection string URI.
|
||||
|
||||
Merged into the options object as options.uri.
|
||||
|
||||
### options
|
||||
|
||||
Type: `Object`
|
||||
|
||||
The options object is also passed through to the storage adapter. Check your storage adapter docs for any extra options.
|
||||
|
||||
#### options.namespace
|
||||
|
||||
Type: `String`<br>
|
||||
Default: `'keyv'`
|
||||
|
||||
Namespace for the current instance.
|
||||
|
||||
#### options.ttl
|
||||
|
||||
Type: `Number`<br>
|
||||
Default: `undefined`
|
||||
|
||||
Default TTL. Can be overridden by specififying a TTL on `.set()`.
|
||||
|
||||
#### options.store
|
||||
|
||||
Type: `Storage adapter instance`<br>
|
||||
Default: `new Map()`
|
||||
|
||||
The storage adapter instance to be used by Keyv.
|
||||
|
||||
#### options.adapter
|
||||
|
||||
Type: `String`<br>
|
||||
Default: `undefined`
|
||||
|
||||
Specify an adapter to use. e.g `'redis'` or `'mongodb'`.
|
||||
|
||||
### Instance
|
||||
|
||||
Keys must always be strings. Values can be of any type.
|
||||
|
||||
#### .set(key, value, [ttl])
|
||||
|
||||
Set a value.
|
||||
|
||||
By default keys are persistent. You can set an expiry TTL in milliseconds.
|
||||
|
||||
Returns `true`.
|
||||
|
||||
#### .get(key)
|
||||
|
||||
Returns the value.
|
||||
|
||||
#### .delete(key)
|
||||
|
||||
Deletes an entry.
|
||||
|
||||
Returns `true` if the key existed, `false` if not.
|
||||
|
||||
#### .clear()
|
||||
|
||||
Delete all entries in the current namespace.
|
||||
|
||||
Returns `undefined`.
|
||||
|
||||
## License
|
||||
|
||||
MIT © Luke Childs
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
{
|
||||
"name": "keyv",
|
||||
"version": "3.0.0",
|
||||
"description": "Simple key-value storage with support for multiple backends",
|
||||
"main": "src/index.js",
|
||||
"scripts": {
|
||||
"test": "xo && nyc ava test/keyv.js",
|
||||
"test:full": "xo && nyc ava --serial",
|
||||
"coverage": "nyc report --reporter=text-lcov | coveralls"
|
||||
},
|
||||
"xo": {
|
||||
"extends": "xo-lukechilds"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/lukechilds/keyv.git"
|
||||
},
|
||||
"keywords": [
|
||||
"key",
|
||||
"value",
|
||||
"store",
|
||||
"cache",
|
||||
"ttl"
|
||||
],
|
||||
"author": "Luke Childs <lukechilds123@gmail.com> (http://lukechilds.co.uk)",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/lukechilds/keyv/issues"
|
||||
},
|
||||
"homepage": "https://github.com/lukechilds/keyv",
|
||||
"dependencies": {
|
||||
"json-buffer": "3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"ava": "^0.22.0",
|
||||
"coveralls": "^3.0.0",
|
||||
"eslint-config-xo-lukechilds": "^1.0.0",
|
||||
"@keyv/mongo": "*",
|
||||
"@keyv/mysql": "*",
|
||||
"@keyv/postgres": "*",
|
||||
"@keyv/redis": "*",
|
||||
"@keyv/sqlite": "*",
|
||||
"@keyv/test-suite": "*",
|
||||
"nyc": "^11.0.3",
|
||||
"this": "^1.0.2",
|
||||
"timekeeper": "^2.0.0",
|
||||
"xo": "^0.19.0"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,99 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
const EventEmitter = require('events');
|
||||
const JSONB = require('json-buffer');
|
||||
|
||||
const loadStore = opts => {
|
||||
const adapters = {
|
||||
redis: '@keyv/redis',
|
||||
mongodb: '@keyv/mongo',
|
||||
mongo: '@keyv/mongo',
|
||||
sqlite: '@keyv/sqlite',
|
||||
postgresql: '@keyv/postgres',
|
||||
postgres: '@keyv/postgres',
|
||||
mysql: '@keyv/mysql'
|
||||
};
|
||||
if (opts.adapter || opts.uri) {
|
||||
const adapter = opts.adapter || /^[^:]*/.exec(opts.uri)[0];
|
||||
return new (require(adapters[adapter]))(opts);
|
||||
}
|
||||
return new Map();
|
||||
};
|
||||
|
||||
class Keyv extends EventEmitter {
|
||||
constructor(uri, opts) {
|
||||
super();
|
||||
this.opts = Object.assign(
|
||||
{ namespace: 'keyv' },
|
||||
(typeof uri === 'string') ? { uri } : uri,
|
||||
opts
|
||||
);
|
||||
|
||||
if (!this.opts.store) {
|
||||
const adapterOpts = Object.assign({}, this.opts);
|
||||
this.opts.store = loadStore(adapterOpts);
|
||||
}
|
||||
|
||||
if (typeof this.opts.store.on === 'function') {
|
||||
this.opts.store.on('error', err => this.emit('error', err));
|
||||
}
|
||||
|
||||
this.opts.store.namespace = this.opts.namespace;
|
||||
}
|
||||
|
||||
_getKeyPrefix(key) {
|
||||
return `${this.opts.namespace}:${key}`;
|
||||
}
|
||||
|
||||
get(key) {
|
||||
key = this._getKeyPrefix(key);
|
||||
const store = this.opts.store;
|
||||
return Promise.resolve()
|
||||
.then(() => store.get(key))
|
||||
.then(data => {
|
||||
data = (typeof data === 'string') ? JSONB.parse(data) : data;
|
||||
if (data === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
if (typeof data.expires === 'number' && Date.now() > data.expires) {
|
||||
this.delete(key);
|
||||
return undefined;
|
||||
}
|
||||
return data.value;
|
||||
});
|
||||
}
|
||||
|
||||
set(key, value, ttl) {
|
||||
key = this._getKeyPrefix(key);
|
||||
if (typeof ttl === 'undefined') {
|
||||
ttl = this.opts.ttl;
|
||||
}
|
||||
if (ttl === 0) {
|
||||
ttl = undefined;
|
||||
}
|
||||
const store = this.opts.store;
|
||||
|
||||
return Promise.resolve()
|
||||
.then(() => {
|
||||
const expires = (typeof ttl === 'number') ? (Date.now() + ttl) : null;
|
||||
value = { value, expires };
|
||||
return store.set(key, JSONB.stringify(value), ttl);
|
||||
})
|
||||
.then(() => true);
|
||||
}
|
||||
|
||||
delete(key) {
|
||||
key = this._getKeyPrefix(key);
|
||||
const store = this.opts.store;
|
||||
return Promise.resolve()
|
||||
.then(() => store.delete(key));
|
||||
}
|
||||
|
||||
clear() {
|
||||
const store = this.opts.store;
|
||||
return Promise.resolve()
|
||||
.then(() => store.clear());
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Keyv;
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
'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;
|
||||
};
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
{
|
||||
"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"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
# 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)
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
// We define these manually to ensure they're always copied
|
||||
// even if they would move up the prototype chain
|
||||
// https://nodejs.org/api/http.html#http_class_http_incomingmessage
|
||||
const knownProps = [
|
||||
'destroy',
|
||||
'setTimeout',
|
||||
'socket',
|
||||
'headers',
|
||||
'trailers',
|
||||
'rawHeaders',
|
||||
'statusCode',
|
||||
'httpVersion',
|
||||
'httpVersionMinor',
|
||||
'httpVersionMajor',
|
||||
'rawTrailers',
|
||||
'statusMessage'
|
||||
];
|
||||
|
||||
module.exports = (fromStream, toStream) => {
|
||||
const toProps = Object.keys(toStream);
|
||||
const fromProps = new Set(Object.keys(fromStream).concat(knownProps));
|
||||
|
||||
for (const prop of fromProps) {
|
||||
// Don't overwrite existing properties
|
||||
if (toProps.indexOf(prop) !== -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
toStream[prop] = typeof fromStream[prop] === 'function' ? fromStream[prop].bind(fromStream) : fromStream[prop];
|
||||
}
|
||||
};
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
MIT License
|
||||
|
||||
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.
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
{
|
||||
"name": "mimic-response",
|
||||
"version": "1.0.0",
|
||||
"description": "Mimic a Node.js HTTP response stream",
|
||||
"license": "MIT",
|
||||
"repository": "sindresorhus/mimic-response",
|
||||
"author": {
|
||||
"name": "Sindre Sorhus",
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"url": "sindresorhus.com"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "xo && ava"
|
||||
},
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"keywords": [
|
||||
"mimic",
|
||||
"response",
|
||||
"stream",
|
||||
"http",
|
||||
"https",
|
||||
"request",
|
||||
"get",
|
||||
"core"
|
||||
],
|
||||
"devDependencies": {
|
||||
"ava": "*",
|
||||
"create-test-server": "^0.1.0",
|
||||
"pify": "^3.0.0",
|
||||
"xo": "*"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
# mimic-response [](https://travis-ci.org/sindresorhus/mimic-response)
|
||||
|
||||
> Mimic a [Node.js HTTP response stream](https://nodejs.org/api/http.html#http_class_http_incomingmessage)
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install mimic-response
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const stream = require('stream');
|
||||
const mimicResponse = require('mimic-response');
|
||||
|
||||
const responseStream = getHttpResponseStream();
|
||||
const myStream = new stream.PassThrough();
|
||||
|
||||
mimicResponse(responseStream, myStream);
|
||||
|
||||
console.log(myStream.statusCode);
|
||||
//=> 200
|
||||
```
|
||||
|
||||
|
||||
## API
|
||||
|
||||
### mimicResponse(from, to)
|
||||
|
||||
#### from
|
||||
|
||||
Type: `Stream`
|
||||
|
||||
[Node.js HTTP response stream.](https://nodejs.org/api/http.html#http_class_http_incomingmessage)
|
||||
|
||||
#### to
|
||||
|
||||
Type: `Stream`
|
||||
|
||||
Any stream.
|
||||
|
||||
|
||||
## Related
|
||||
|
||||
- [mimic-fn](https://github.com/sindresorhus/mimic-fn) - Make a function mimic another one
|
||||
- [clone-response](https://github.com/lukechilds/clone-response) - Clone a Node.js response stream
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Sindre Sorhus](https://sindresorhus.com)
|
||||
|
|
@ -1,163 +0,0 @@
|
|||
'use strict';
|
||||
const url = require('url');
|
||||
const punycode = require('punycode');
|
||||
const queryString = require('query-string');
|
||||
const prependHttp = require('prepend-http');
|
||||
const sortKeys = require('sort-keys');
|
||||
|
||||
const DEFAULT_PORTS = {
|
||||
'http:': 80,
|
||||
'https:': 443,
|
||||
'ftp:': 21
|
||||
};
|
||||
|
||||
// Protocols that always contain a `//`` bit
|
||||
const slashedProtocol = {
|
||||
http: true,
|
||||
https: true,
|
||||
ftp: true,
|
||||
gopher: true,
|
||||
file: true,
|
||||
'http:': true,
|
||||
'https:': true,
|
||||
'ftp:': true,
|
||||
'gopher:': true,
|
||||
'file:': true
|
||||
};
|
||||
|
||||
function testParameter(name, filters) {
|
||||
return filters.some(filter => filter instanceof RegExp ? filter.test(name) : filter === name);
|
||||
}
|
||||
|
||||
module.exports = (str, opts) => {
|
||||
opts = Object.assign({
|
||||
normalizeProtocol: true,
|
||||
normalizeHttps: false,
|
||||
stripFragment: true,
|
||||
stripWWW: true,
|
||||
removeQueryParameters: [/^utm_\w+/i],
|
||||
removeTrailingSlash: true,
|
||||
removeDirectoryIndex: false,
|
||||
sortQueryParameters: true
|
||||
}, opts);
|
||||
|
||||
if (typeof str !== 'string') {
|
||||
throw new TypeError('Expected a string');
|
||||
}
|
||||
|
||||
const hasRelativeProtocol = str.startsWith('//');
|
||||
|
||||
// Prepend protocol
|
||||
str = prependHttp(str.trim()).replace(/^\/\//, 'http://');
|
||||
|
||||
const urlObj = url.parse(str);
|
||||
|
||||
if (opts.normalizeHttps && urlObj.protocol === 'https:') {
|
||||
urlObj.protocol = 'http:';
|
||||
}
|
||||
|
||||
if (!urlObj.hostname && !urlObj.pathname) {
|
||||
throw new Error('Invalid URL');
|
||||
}
|
||||
|
||||
// Prevent these from being used by `url.format`
|
||||
delete urlObj.host;
|
||||
delete urlObj.query;
|
||||
|
||||
// Remove fragment
|
||||
if (opts.stripFragment) {
|
||||
delete urlObj.hash;
|
||||
}
|
||||
|
||||
// Remove default port
|
||||
const port = DEFAULT_PORTS[urlObj.protocol];
|
||||
if (Number(urlObj.port) === port) {
|
||||
delete urlObj.port;
|
||||
}
|
||||
|
||||
// Remove duplicate slashes
|
||||
if (urlObj.pathname) {
|
||||
urlObj.pathname = urlObj.pathname.replace(/\/{2,}/g, '/');
|
||||
}
|
||||
|
||||
// Decode URI octets
|
||||
if (urlObj.pathname) {
|
||||
urlObj.pathname = decodeURI(urlObj.pathname);
|
||||
}
|
||||
|
||||
// Remove directory index
|
||||
if (opts.removeDirectoryIndex === true) {
|
||||
opts.removeDirectoryIndex = [/^index\.[a-z]+$/];
|
||||
}
|
||||
|
||||
if (Array.isArray(opts.removeDirectoryIndex) && opts.removeDirectoryIndex.length > 0) {
|
||||
let pathComponents = urlObj.pathname.split('/');
|
||||
const lastComponent = pathComponents[pathComponents.length - 1];
|
||||
|
||||
if (testParameter(lastComponent, opts.removeDirectoryIndex)) {
|
||||
pathComponents = pathComponents.slice(0, pathComponents.length - 1);
|
||||
urlObj.pathname = pathComponents.slice(1).join('/') + '/';
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve relative paths, but only for slashed protocols
|
||||
if (slashedProtocol[urlObj.protocol]) {
|
||||
const domain = urlObj.protocol + '//' + urlObj.hostname;
|
||||
const relative = url.resolve(domain, urlObj.pathname);
|
||||
urlObj.pathname = relative.replace(domain, '');
|
||||
}
|
||||
|
||||
if (urlObj.hostname) {
|
||||
// IDN to Unicode
|
||||
urlObj.hostname = punycode.toUnicode(urlObj.hostname).toLowerCase();
|
||||
|
||||
// Remove trailing dot
|
||||
urlObj.hostname = urlObj.hostname.replace(/\.$/, '');
|
||||
|
||||
// Remove `www.`
|
||||
if (opts.stripWWW) {
|
||||
urlObj.hostname = urlObj.hostname.replace(/^www\./, '');
|
||||
}
|
||||
}
|
||||
|
||||
// Remove URL with empty query string
|
||||
if (urlObj.search === '?') {
|
||||
delete urlObj.search;
|
||||
}
|
||||
|
||||
const queryParameters = queryString.parse(urlObj.search);
|
||||
|
||||
// Remove query unwanted parameters
|
||||
if (Array.isArray(opts.removeQueryParameters)) {
|
||||
for (const key in queryParameters) {
|
||||
if (testParameter(key, opts.removeQueryParameters)) {
|
||||
delete queryParameters[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sort query parameters
|
||||
if (opts.sortQueryParameters) {
|
||||
urlObj.search = queryString.stringify(sortKeys(queryParameters));
|
||||
}
|
||||
|
||||
// Decode query parameters
|
||||
if (urlObj.search !== null) {
|
||||
urlObj.search = decodeURIComponent(urlObj.search);
|
||||
}
|
||||
|
||||
// Take advantage of many of the Node `url` normalizations
|
||||
str = url.format(urlObj);
|
||||
|
||||
// Remove ending `/`
|
||||
if (opts.removeTrailingSlash || urlObj.pathname === '/') {
|
||||
str = str.replace(/\/$/, '');
|
||||
}
|
||||
|
||||
// Restore relative protocol, if applicable
|
||||
if (hasRelativeProtocol && !opts.normalizeProtocol) {
|
||||
str = str.replace(/^http:\/\//, '//');
|
||||
}
|
||||
|
||||
return str;
|
||||
};
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
MIT License
|
||||
|
||||
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.
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
{
|
||||
"name": "normalize-url",
|
||||
"version": "2.0.1",
|
||||
"description": "Normalize a URL",
|
||||
"license": "MIT",
|
||||
"repository": "sindresorhus/normalize-url",
|
||||
"author": {
|
||||
"name": "Sindre Sorhus",
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"url": "sindresorhus.com"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "xo && ava"
|
||||
},
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"keywords": [
|
||||
"normalize",
|
||||
"url",
|
||||
"uri",
|
||||
"address",
|
||||
"string",
|
||||
"normalization",
|
||||
"normalisation",
|
||||
"query",
|
||||
"querystring",
|
||||
"unicode",
|
||||
"simplify",
|
||||
"strip",
|
||||
"trim",
|
||||
"canonical"
|
||||
],
|
||||
"dependencies": {
|
||||
"prepend-http": "^2.0.0",
|
||||
"query-string": "^5.0.1",
|
||||
"sort-keys": "^2.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"ava": "*",
|
||||
"xo": "*"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,172 +0,0 @@
|
|||
# normalize-url [](https://travis-ci.org/sindresorhus/normalize-url)
|
||||
|
||||
> [Normalize](https://en.wikipedia.org/wiki/URL_normalization) a URL
|
||||
|
||||
Useful when you need to display, store, deduplicate, sort, compare, etc, URLs.
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install normalize-url
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const normalizeUrl = require('normalize-url');
|
||||
|
||||
normalizeUrl('sindresorhus.com');
|
||||
//=> 'http://sindresorhus.com'
|
||||
|
||||
normalizeUrl('HTTP://xn--xample-hva.com:80/?b=bar&a=foo');
|
||||
//=> 'http://êxample.com/?a=foo&b=bar'
|
||||
```
|
||||
|
||||
|
||||
## API
|
||||
|
||||
### normalizeUrl(url, [options])
|
||||
|
||||
#### url
|
||||
|
||||
Type: `string`
|
||||
|
||||
URL to normalize.
|
||||
|
||||
#### options
|
||||
|
||||
Type: `Object`
|
||||
|
||||
##### normalizeProtocol
|
||||
|
||||
Type: `boolean`<br>
|
||||
Default: `true`
|
||||
|
||||
Prepend `http:` to the URL if it's protocol-relative.
|
||||
|
||||
```js
|
||||
normalizeUrl('//sindresorhus.com:80/');
|
||||
//=> 'http://sindresorhus.com'
|
||||
|
||||
normalizeUrl('//sindresorhus.com:80/', {normalizeProtocol: false});
|
||||
//=> '//sindresorhus.com'
|
||||
```
|
||||
|
||||
##### normalizeHttps
|
||||
|
||||
Type: `boolean`<br>
|
||||
Default: `false`
|
||||
|
||||
Normalize `https:` URLs to `http:`.
|
||||
|
||||
```js
|
||||
normalizeUrl('https://sindresorhus.com:80/');
|
||||
//=> 'https://sindresorhus.com'
|
||||
|
||||
normalizeUrl('https://sindresorhus.com:80/', {normalizeHttps: true});
|
||||
//=> 'http://sindresorhus.com'
|
||||
```
|
||||
|
||||
##### stripFragment
|
||||
|
||||
Type: `boolean`<br>
|
||||
Default: `true`
|
||||
|
||||
Remove the fragment at the end of the URL.
|
||||
|
||||
```js
|
||||
normalizeUrl('sindresorhus.com/about.html#contact');
|
||||
//=> 'http://sindresorhus.com/about.html'
|
||||
|
||||
normalizeUrl('sindresorhus.com/about.html#contact', {stripFragment: false});
|
||||
//=> 'http://sindresorhus.com/about.html#contact'
|
||||
```
|
||||
|
||||
##### stripWWW
|
||||
|
||||
Type: `boolean`<br>
|
||||
Default: `true`
|
||||
|
||||
Remove `www.` from the URL.
|
||||
|
||||
```js
|
||||
normalizeUrl('http://www.sindresorhus.com/about.html#contact');
|
||||
//=> 'http://sindresorhus.com/about.html#contact'
|
||||
|
||||
normalizeUrl('http://www.sindresorhus.com/about.html#contact', {stripWWW: false});
|
||||
//=> 'http://www.sindresorhus.com/about.html#contact'
|
||||
```
|
||||
|
||||
##### removeQueryParameters
|
||||
|
||||
Type: `Array<RegExp|string>`<br>
|
||||
Default: `[/^utm_\w+/i]`
|
||||
|
||||
Remove query parameters that matches any of the provided strings or regexes.
|
||||
|
||||
```js
|
||||
normalizeUrl('www.sindresorhus.com?foo=bar&ref=test_ref', {
|
||||
removeQueryParameters: ['ref']
|
||||
});
|
||||
//=> 'http://sindresorhus.com/?foo=bar'
|
||||
```
|
||||
|
||||
##### removeTrailingSlash
|
||||
|
||||
Type: `boolean`<br>
|
||||
Default: `true`
|
||||
|
||||
Remove trailing slash.
|
||||
|
||||
**Note:** Trailing slash is always removed if the URL doesn't have a pathname.
|
||||
|
||||
```js
|
||||
normalizeUrl('http://sindresorhus.com/redirect/');
|
||||
//=> 'http://sindresorhus.com/redirect'
|
||||
|
||||
normalizeUrl('http://sindresorhus.com/redirect/', {removeTrailingSlash: false});
|
||||
//=> 'http://sindresorhus.com/redirect/'
|
||||
|
||||
normalizeUrl('http://sindresorhus.com/', {removeTrailingSlash: false});
|
||||
//=> 'http://sindresorhus.com'
|
||||
```
|
||||
|
||||
##### removeDirectoryIndex
|
||||
|
||||
Type: `boolean` `Array<RegExp|string>`<br>
|
||||
Default: `false`
|
||||
|
||||
Remove the default directory index file from path that matches any of the provided strings or regexes. When `true`, the regex `/^index\.[a-z]+$/` is used.
|
||||
|
||||
```js
|
||||
normalizeUrl('www.sindresorhus.com/foo/default.php', {
|
||||
removeDirectoryIndex: [/^default\.[a-z]+$/]
|
||||
});
|
||||
//=> 'http://sindresorhus.com/foo'
|
||||
```
|
||||
|
||||
##### sortQueryParameters
|
||||
|
||||
Type: `boolean`<br>
|
||||
Default: `true`
|
||||
|
||||
Sort the query parameters alphabetically by key.
|
||||
|
||||
```js
|
||||
normalizeUrl('www.sindresorhus.com?b=two&a=one&c=three', {
|
||||
sortQueryParameters: false
|
||||
});
|
||||
//=> 'http://sindresorhus.com/?b=two&a=one&c=three'
|
||||
```
|
||||
|
||||
|
||||
## Related
|
||||
|
||||
- [compare-urls](https://github.com/sindresorhus/compare-urls) - Compare URLs by first normalizing them
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Sindre Sorhus](https://sindresorhus.com)
|
||||
|
|
@ -1,90 +0,0 @@
|
|||
/*
|
||||
object-assign
|
||||
(c) Sindre Sorhus
|
||||
@license MIT
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
/* eslint-disable no-unused-vars */
|
||||
var getOwnPropertySymbols = Object.getOwnPropertySymbols;
|
||||
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
||||
var propIsEnumerable = Object.prototype.propertyIsEnumerable;
|
||||
|
||||
function toObject(val) {
|
||||
if (val === null || val === undefined) {
|
||||
throw new TypeError('Object.assign cannot be called with null or undefined');
|
||||
}
|
||||
|
||||
return Object(val);
|
||||
}
|
||||
|
||||
function shouldUseNative() {
|
||||
try {
|
||||
if (!Object.assign) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Detect buggy property enumeration order in older V8 versions.
|
||||
|
||||
// https://bugs.chromium.org/p/v8/issues/detail?id=4118
|
||||
var test1 = new String('abc'); // eslint-disable-line no-new-wrappers
|
||||
test1[5] = 'de';
|
||||
if (Object.getOwnPropertyNames(test1)[0] === '5') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// https://bugs.chromium.org/p/v8/issues/detail?id=3056
|
||||
var test2 = {};
|
||||
for (var i = 0; i < 10; i++) {
|
||||
test2['_' + String.fromCharCode(i)] = i;
|
||||
}
|
||||
var order2 = Object.getOwnPropertyNames(test2).map(function (n) {
|
||||
return test2[n];
|
||||
});
|
||||
if (order2.join('') !== '0123456789') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// https://bugs.chromium.org/p/v8/issues/detail?id=3056
|
||||
var test3 = {};
|
||||
'abcdefghijklmnopqrst'.split('').forEach(function (letter) {
|
||||
test3[letter] = letter;
|
||||
});
|
||||
if (Object.keys(Object.assign({}, test3)).join('') !==
|
||||
'abcdefghijklmnopqrst') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (err) {
|
||||
// We don't expect any of the above to throw, but better to be safe.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = shouldUseNative() ? Object.assign : function (target, source) {
|
||||
var from;
|
||||
var to = toObject(target);
|
||||
var symbols;
|
||||
|
||||
for (var s = 1; s < arguments.length; s++) {
|
||||
from = Object(arguments[s]);
|
||||
|
||||
for (var key in from) {
|
||||
if (hasOwnProperty.call(from, key)) {
|
||||
to[key] = from[key];
|
||||
}
|
||||
}
|
||||
|
||||
if (getOwnPropertySymbols) {
|
||||
symbols = getOwnPropertySymbols(from);
|
||||
for (var i = 0; i < symbols.length; i++) {
|
||||
if (propIsEnumerable.call(from, symbols[i])) {
|
||||
to[symbols[i]] = from[symbols[i]];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return to;
|
||||
};
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
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.
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
{
|
||||
"name": "object-assign",
|
||||
"version": "4.1.1",
|
||||
"description": "ES2015 `Object.assign()` ponyfill",
|
||||
"license": "MIT",
|
||||
"repository": "sindresorhus/object-assign",
|
||||
"author": {
|
||||
"name": "Sindre Sorhus",
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"url": "sindresorhus.com"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "xo && ava",
|
||||
"bench": "matcha bench.js"
|
||||
},
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"keywords": [
|
||||
"object",
|
||||
"assign",
|
||||
"extend",
|
||||
"properties",
|
||||
"es2015",
|
||||
"ecmascript",
|
||||
"harmony",
|
||||
"ponyfill",
|
||||
"prollyfill",
|
||||
"polyfill",
|
||||
"shim",
|
||||
"browser"
|
||||
],
|
||||
"devDependencies": {
|
||||
"ava": "^0.16.0",
|
||||
"lodash": "^4.16.4",
|
||||
"matcha": "^0.7.0",
|
||||
"xo": "^0.16.0"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
# object-assign [](https://travis-ci.org/sindresorhus/object-assign)
|
||||
|
||||
> ES2015 [`Object.assign()`](http://www.2ality.com/2014/01/object-assign.html) [ponyfill](https://ponyfill.com)
|
||||
|
||||
|
||||
## Use the built-in
|
||||
|
||||
Node.js 4 and up, as well as every evergreen browser (Chrome, Edge, Firefox, Opera, Safari),
|
||||
support `Object.assign()` :tada:. If you target only those environments, then by all
|
||||
means, use `Object.assign()` instead of this package.
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install --save object-assign
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const objectAssign = require('object-assign');
|
||||
|
||||
objectAssign({foo: 0}, {bar: 1});
|
||||
//=> {foo: 0, bar: 1}
|
||||
|
||||
// multiple sources
|
||||
objectAssign({foo: 0}, {bar: 1}, {baz: 2});
|
||||
//=> {foo: 0, bar: 1, baz: 2}
|
||||
|
||||
// overwrites equal keys
|
||||
objectAssign({foo: 0}, {foo: 1}, {foo: 2});
|
||||
//=> {foo: 2}
|
||||
|
||||
// ignores null and undefined sources
|
||||
objectAssign({foo: 0}, null, {bar: 1}, undefined);
|
||||
//=> {foo: 0, bar: 1}
|
||||
```
|
||||
|
||||
|
||||
## API
|
||||
|
||||
### objectAssign(target, [source, ...])
|
||||
|
||||
Assigns enumerable own properties of `source` objects to the `target` object and returns the `target` object. Additional `source` objects will overwrite previous ones.
|
||||
|
||||
|
||||
## Resources
|
||||
|
||||
- [ES2015 spec - Object.assign](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.assign)
|
||||
|
||||
|
||||
## Related
|
||||
|
||||
- [deep-assign](https://github.com/sindresorhus/deep-assign) - Recursive `Object.assign()`
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Sindre Sorhus](https://sindresorhus.com)
|
||||
|
|
@ -1,88 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
class CancelError extends Error {
|
||||
constructor() {
|
||||
super('Promise was canceled');
|
||||
this.name = 'CancelError';
|
||||
}
|
||||
|
||||
get isCanceled() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class PCancelable {
|
||||
static fn(userFn) {
|
||||
return function () {
|
||||
const args = [].slice.apply(arguments);
|
||||
return new PCancelable((resolve, reject, onCancel) => {
|
||||
args.push(onCancel);
|
||||
userFn.apply(null, args).then(resolve, reject);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
constructor(executor) {
|
||||
this._cancelHandlers = [];
|
||||
this._isPending = true;
|
||||
this._isCanceled = false;
|
||||
|
||||
this._promise = new Promise((resolve, reject) => {
|
||||
this._reject = reject;
|
||||
|
||||
return executor(
|
||||
value => {
|
||||
this._isPending = false;
|
||||
resolve(value);
|
||||
},
|
||||
error => {
|
||||
this._isPending = false;
|
||||
reject(error);
|
||||
},
|
||||
handler => {
|
||||
this._cancelHandlers.push(handler);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
then(onFulfilled, onRejected) {
|
||||
return this._promise.then(onFulfilled, onRejected);
|
||||
}
|
||||
|
||||
catch(onRejected) {
|
||||
return this._promise.catch(onRejected);
|
||||
}
|
||||
|
||||
finally(onFinally) {
|
||||
return this._promise.finally(onFinally);
|
||||
}
|
||||
|
||||
cancel() {
|
||||
if (!this._isPending || this._isCanceled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._cancelHandlers.length > 0) {
|
||||
try {
|
||||
for (const handler of this._cancelHandlers) {
|
||||
handler();
|
||||
}
|
||||
} catch (err) {
|
||||
this._reject(err);
|
||||
}
|
||||
}
|
||||
|
||||
this._isCanceled = true;
|
||||
this._reject(new CancelError());
|
||||
}
|
||||
|
||||
get isCanceled() {
|
||||
return this._isCanceled;
|
||||
}
|
||||
}
|
||||
|
||||
Object.setPrototypeOf(PCancelable.prototype, Promise.prototype);
|
||||
|
||||
module.exports = PCancelable;
|
||||
module.exports.CancelError = CancelError;
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
MIT License
|
||||
|
||||
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.
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
{
|
||||
"name": "p-cancelable",
|
||||
"version": "0.4.1",
|
||||
"description": "Create a promise that can be canceled",
|
||||
"license": "MIT",
|
||||
"repository": "sindresorhus/p-cancelable",
|
||||
"author": {
|
||||
"name": "Sindre Sorhus",
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"url": "sindresorhus.com"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "xo && ava"
|
||||
},
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"keywords": [
|
||||
"promise",
|
||||
"cancelable",
|
||||
"cancel",
|
||||
"canceled",
|
||||
"canceling",
|
||||
"cancellable",
|
||||
"cancellation",
|
||||
"abort",
|
||||
"abortable",
|
||||
"aborting",
|
||||
"cleanup",
|
||||
"task",
|
||||
"token",
|
||||
"async",
|
||||
"function",
|
||||
"await",
|
||||
"promises",
|
||||
"bluebird"
|
||||
],
|
||||
"devDependencies": {
|
||||
"ava": "*",
|
||||
"delay": "^2.0.0",
|
||||
"promise.prototype.finally": "^3.1.0",
|
||||
"xo": "*"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,135 +0,0 @@
|
|||
# p-cancelable [](https://travis-ci.org/sindresorhus/p-cancelable)
|
||||
|
||||
> Create a promise that can be canceled
|
||||
|
||||
Useful for animation, loading resources, long-running async computations, async iteration, etc.
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install p-cancelable
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const PCancelable = require('p-cancelable');
|
||||
|
||||
const cancelablePromise = new PCancelable((resolve, reject, onCancel) => {
|
||||
const worker = new SomeLongRunningOperation();
|
||||
|
||||
onCancel(() => {
|
||||
worker.close();
|
||||
});
|
||||
|
||||
worker.on('finish', resolve);
|
||||
worker.on('error', reject);
|
||||
});
|
||||
|
||||
cancelablePromise
|
||||
.then(value => {
|
||||
console.log('Operation finished successfully:', value);
|
||||
})
|
||||
.catch(error => {
|
||||
if (cancelablePromise.isCanceled) {
|
||||
// Handle the cancelation here
|
||||
console.log('Operation was canceled');
|
||||
return;
|
||||
}
|
||||
|
||||
throw error;
|
||||
});
|
||||
|
||||
// Cancel the operation after 10 seconds
|
||||
setTimeout(() => {
|
||||
cancelablePromise.cancel();
|
||||
}, 10000);
|
||||
```
|
||||
|
||||
|
||||
## API
|
||||
|
||||
### new PCancelable(executor)
|
||||
|
||||
Same as the [`Promise` constructor](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise), but with an appended `onCancel` parameter in `executor`.
|
||||
|
||||
`PCancelable` is a subclass of `Promise`.
|
||||
|
||||
#### onCanceled(fn)
|
||||
|
||||
Type: `Function`
|
||||
|
||||
Accepts a function that is called when the promise is canceled.
|
||||
|
||||
You're not required to call this function. You can call this function multiple times to add multiple cancel handlers.
|
||||
|
||||
### PCancelable#cancel()
|
||||
|
||||
Type: `Function`
|
||||
|
||||
Cancel the promise.
|
||||
|
||||
The cancellation is synchronous. Calling it after the promise has settled or multiple times does nothing.
|
||||
|
||||
### PCancelable#isCanceled
|
||||
|
||||
Type: `boolean`
|
||||
|
||||
Whether the promise is canceled.
|
||||
|
||||
### PCancelable.CancelError
|
||||
|
||||
Type: `Error`
|
||||
|
||||
Rejection reason when `.cancel()` is called.
|
||||
|
||||
It includes a `.isCanceled` property for convenience.
|
||||
|
||||
### PCancelable.fn(fn)
|
||||
|
||||
Convenience method to make your promise-returning or async function cancelable.
|
||||
|
||||
The function you specify will have `onCancel` appended to its parameters.
|
||||
|
||||
```js
|
||||
const fn = PCancelable.fn((input, onCancel) => {
|
||||
const job = new Job();
|
||||
|
||||
onCancel(() => {
|
||||
job.cleanup();
|
||||
});
|
||||
|
||||
return job.start(); //=> Promise
|
||||
});
|
||||
|
||||
const promise = fn('input'); //=> PCancelable
|
||||
|
||||
// …
|
||||
|
||||
promise.cancel();
|
||||
```
|
||||
|
||||
|
||||
## FAQ
|
||||
|
||||
### Cancelable vs. Cancellable
|
||||
|
||||
[In American English, the verb cancel is usually inflected canceled and canceling—with one l.](http://grammarist.com/spelling/cancel/)<br>Both a [browser API](https://developer.mozilla.org/en-US/docs/Web/API/Event/cancelable) and the [Cancelable Promises proposal](https://github.com/tc39/proposal-cancelable-promises) use this spelling.
|
||||
|
||||
### What about the official [Cancelable Promises proposal](https://github.com/tc39/proposal-cancelable-promises)?
|
||||
|
||||
~~It's still an early draft and I don't really like its current direction. It complicates everything and will require deep changes in the ecosystem to adapt to it. And the way you have to use cancel tokens is verbose and convoluted. I much prefer the more pragmatic and less invasive approach in this module.~~ The proposal was withdrawn.
|
||||
|
||||
|
||||
## Related
|
||||
|
||||
- [p-progress](https://github.com/sindresorhus/p-progress) - Create a promise that reports progress
|
||||
- [p-lazy](https://github.com/sindresorhus/p-lazy) - Create a lazy promise that defers execution until `.then()` or `.catch()` is called
|
||||
- [More…](https://github.com/sindresorhus/promise-fun)
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Sindre Sorhus](https://sindresorhus.com)
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
'use strict';
|
||||
module.exports = (promise, onFinally) => {
|
||||
onFinally = onFinally || (() => {});
|
||||
|
||||
return promise.then(
|
||||
val => new Promise(resolve => {
|
||||
resolve(onFinally());
|
||||
}).then(() => val),
|
||||
err => new Promise(resolve => {
|
||||
resolve(onFinally());
|
||||
}).then(() => {
|
||||
throw err;
|
||||
})
|
||||
);
|
||||
};
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
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.
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
{
|
||||
"name": "p-finally",
|
||||
"version": "1.0.0",
|
||||
"description": "`Promise#finally()` ponyfill - Invoked when the promise is settled regardless of outcome",
|
||||
"license": "MIT",
|
||||
"repository": "sindresorhus/p-finally",
|
||||
"author": {
|
||||
"name": "Sindre Sorhus",
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"url": "sindresorhus.com"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "xo && ava"
|
||||
},
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"keywords": [
|
||||
"promise",
|
||||
"finally",
|
||||
"handler",
|
||||
"function",
|
||||
"async",
|
||||
"await",
|
||||
"promises",
|
||||
"settled",
|
||||
"ponyfill",
|
||||
"polyfill",
|
||||
"shim",
|
||||
"bluebird"
|
||||
],
|
||||
"devDependencies": {
|
||||
"ava": "*",
|
||||
"xo": "*"
|
||||
},
|
||||
"xo": {
|
||||
"esnext": true
|
||||
}
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
# p-finally [](https://travis-ci.org/sindresorhus/p-finally)
|
||||
|
||||
> [`Promise#finally()`](https://github.com/tc39/proposal-promise-finally) [ponyfill](https://ponyfill.com) - Invoked when the promise is settled regardless of outcome
|
||||
|
||||
Useful for cleanup.
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install --save p-finally
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const pFinally = require('p-finally');
|
||||
|
||||
const dir = createTempDir();
|
||||
|
||||
pFinally(write(dir), () => cleanup(dir));
|
||||
```
|
||||
|
||||
|
||||
## API
|
||||
|
||||
### pFinally(promise, [onFinally])
|
||||
|
||||
Returns a `Promise`.
|
||||
|
||||
#### onFinally
|
||||
|
||||
Type: `Function`
|
||||
|
||||
Note: Throwing or returning a rejected promise will reject `promise` with the rejection reason.
|
||||
|
||||
|
||||
## Related
|
||||
|
||||
- [p-try](https://github.com/sindresorhus/p-try) - `Promise#try()` ponyfill - Starts a promise chain
|
||||
- [More…](https://github.com/sindresorhus/promise-fun)
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Sindre Sorhus](https://sindresorhus.com)
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
'use strict';
|
||||
module.exports = x => (
|
||||
x instanceof Promise ||
|
||||
(
|
||||
x !== null &&
|
||||
typeof x === 'object' &&
|
||||
typeof x.then === 'function' &&
|
||||
typeof x.catch === 'function'
|
||||
)
|
||||
);
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
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.
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
{
|
||||
"name": "p-is-promise",
|
||||
"version": "1.1.0",
|
||||
"description": "Check if something is a promise",
|
||||
"license": "MIT",
|
||||
"repository": "sindresorhus/p-is-promise",
|
||||
"author": {
|
||||
"name": "Sindre Sorhus",
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"url": "sindresorhus.com"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "xo && ava"
|
||||
},
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"keywords": [
|
||||
"promise",
|
||||
"is",
|
||||
"detect",
|
||||
"check",
|
||||
"kind",
|
||||
"type",
|
||||
"thenable",
|
||||
"es2015",
|
||||
"async",
|
||||
"await",
|
||||
"promises",
|
||||
"bluebird"
|
||||
],
|
||||
"devDependencies": {
|
||||
"ava": "*",
|
||||
"bluebird": "^3.4.6",
|
||||
"xo": "*"
|
||||
},
|
||||
"xo": {
|
||||
"esnext": true
|
||||
}
|
||||
}
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
# p-is-promise [](https://travis-ci.org/sindresorhus/p-is-promise)
|
||||
|
||||
> Check if something is a promise
|
||||
|
||||
Why not [`is-promise`](https://github.com/then/is-promise)? That module [checks for a thenable](https://github.com/then/is-promise/issues/6), not an ES2015 promise. This one is stricter.
|
||||
|
||||
You most likely don't need this. Just pass your value to `Promise.resolve()` and let it handle it.
|
||||
|
||||
Can be useful if you need to create a fast path for a synchronous operation.
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install --save p-is-promise
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const pIsPromise = require('p-is-promise');
|
||||
const Bluebird = require('bluebird');
|
||||
|
||||
pIsPromise(Promise.resolve('🦄'));
|
||||
//=> true
|
||||
|
||||
pIsPromise(Bluebird.resolve('🦄'));
|
||||
//=> true
|
||||
|
||||
pIsPromise('🦄');
|
||||
//=> false
|
||||
```
|
||||
|
||||
|
||||
## Related
|
||||
|
||||
- [More…](https://github.com/sindresorhus/promise-fun)
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Sindre Sorhus](https://sindresorhus.com)
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
'use strict';
|
||||
const pFinally = require('p-finally');
|
||||
|
||||
class TimeoutError extends Error {
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = 'TimeoutError';
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = (promise, ms, fallback) => new Promise((resolve, reject) => {
|
||||
if (typeof ms !== 'number' || ms < 0) {
|
||||
throw new TypeError('Expected `ms` to be a positive number');
|
||||
}
|
||||
|
||||
const timer = setTimeout(() => {
|
||||
if (typeof fallback === 'function') {
|
||||
try {
|
||||
resolve(fallback());
|
||||
} catch (err) {
|
||||
reject(err);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const message = typeof fallback === 'string' ? fallback : `Promise timed out after ${ms} milliseconds`;
|
||||
const err = fallback instanceof Error ? fallback : new TimeoutError(message);
|
||||
|
||||
if (typeof promise.cancel === 'function') {
|
||||
promise.cancel();
|
||||
}
|
||||
|
||||
reject(err);
|
||||
}, ms);
|
||||
|
||||
pFinally(
|
||||
promise.then(resolve, reject),
|
||||
() => {
|
||||
clearTimeout(timer);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
module.exports.TimeoutError = TimeoutError;
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
MIT License
|
||||
|
||||
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.
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
{
|
||||
"name": "p-timeout",
|
||||
"version": "2.0.1",
|
||||
"description": "Timeout a promise after a specified amount of time",
|
||||
"license": "MIT",
|
||||
"repository": "sindresorhus/p-timeout",
|
||||
"author": {
|
||||
"name": "Sindre Sorhus",
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"url": "sindresorhus.com"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "xo && ava"
|
||||
},
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"keywords": [
|
||||
"promise",
|
||||
"timeout",
|
||||
"error",
|
||||
"invalidate",
|
||||
"async",
|
||||
"await",
|
||||
"promises",
|
||||
"time",
|
||||
"out",
|
||||
"cancel",
|
||||
"bluebird"
|
||||
],
|
||||
"dependencies": {
|
||||
"p-finally": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"ava": "*",
|
||||
"delay": "^2.0.0",
|
||||
"p-cancelable": "^0.3.0",
|
||||
"xo": "*"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,89 +0,0 @@
|
|||
# p-timeout [](https://travis-ci.org/sindresorhus/p-timeout)
|
||||
|
||||
> Timeout a promise after a specified amount of time
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install p-timeout
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const delay = require('delay');
|
||||
const pTimeout = require('p-timeout');
|
||||
|
||||
const delayedPromise = delay(200);
|
||||
|
||||
pTimeout(delayedPromise, 50).then(() => 'foo');
|
||||
//=> [TimeoutError: Promise timed out after 50 milliseconds]
|
||||
```
|
||||
|
||||
|
||||
## API
|
||||
|
||||
### pTimeout(input, ms, [message | fallback])
|
||||
|
||||
Returns a decorated `input` that times out after `ms` time.
|
||||
|
||||
If you pass in a cancelable promise, specifically a promise with a `.cancel()` method, that method will be called when the `pTimeout` promise times out.
|
||||
|
||||
#### input
|
||||
|
||||
Type: `Promise`
|
||||
|
||||
Promise to decorate.
|
||||
|
||||
#### ms
|
||||
|
||||
Type: `number`
|
||||
|
||||
Milliseconds before timing out.
|
||||
|
||||
#### message
|
||||
|
||||
Type: `string` `Error`<br>
|
||||
Default: `'Promise timed out after 50 milliseconds'`
|
||||
|
||||
Specify a custom error message or error.
|
||||
|
||||
If you do a custom error, it's recommended to sub-class `pTimeout.TimeoutError`.
|
||||
|
||||
#### fallback
|
||||
|
||||
Type: `Function`
|
||||
|
||||
Do something other than rejecting with an error on timeout.
|
||||
|
||||
You could for example retry:
|
||||
|
||||
```js
|
||||
const delay = require('delay');
|
||||
const pTimeout = require('p-timeout');
|
||||
|
||||
const delayedPromise = () => delay(200);
|
||||
|
||||
pTimeout(delayedPromise(), 50, () => {
|
||||
return pTimeout(delayedPromise(), 300);
|
||||
});
|
||||
```
|
||||
|
||||
### pTimeout.TimeoutError
|
||||
|
||||
Exposed for instance checking and sub-classing.
|
||||
|
||||
|
||||
## Related
|
||||
|
||||
- [delay](https://github.com/sindresorhus/delay) - Delay a promise a specified amount of time
|
||||
- [p-min-delay](https://github.com/sindresorhus/p-min-delay) - Delay a promise a minimum amount of time
|
||||
- [p-retry](https://github.com/sindresorhus/p-retry) - Retry a promise-returning function
|
||||
- [More…](https://github.com/sindresorhus/promise-fun)
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Sindre Sorhus](https://sindresorhus.com)
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
const processFn = (fn, opts) => function () {
|
||||
const P = opts.promiseModule;
|
||||
const args = new Array(arguments.length);
|
||||
|
||||
for (let i = 0; i < arguments.length; i++) {
|
||||
args[i] = arguments[i];
|
||||
}
|
||||
|
||||
return new P((resolve, reject) => {
|
||||
if (opts.errorFirst) {
|
||||
args.push(function (err, result) {
|
||||
if (opts.multiArgs) {
|
||||
const results = new Array(arguments.length - 1);
|
||||
|
||||
for (let i = 1; i < arguments.length; i++) {
|
||||
results[i - 1] = arguments[i];
|
||||
}
|
||||
|
||||
if (err) {
|
||||
results.unshift(err);
|
||||
reject(results);
|
||||
} else {
|
||||
resolve(results);
|
||||
}
|
||||
} else if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(result);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
args.push(function (result) {
|
||||
if (opts.multiArgs) {
|
||||
const results = new Array(arguments.length - 1);
|
||||
|
||||
for (let i = 0; i < arguments.length; i++) {
|
||||
results[i] = arguments[i];
|
||||
}
|
||||
|
||||
resolve(results);
|
||||
} else {
|
||||
resolve(result);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn.apply(this, args);
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = (obj, opts) => {
|
||||
opts = Object.assign({
|
||||
exclude: [/.+(Sync|Stream)$/],
|
||||
errorFirst: true,
|
||||
promiseModule: Promise
|
||||
}, opts);
|
||||
|
||||
const filter = key => {
|
||||
const match = pattern => typeof pattern === 'string' ? key === pattern : pattern.test(key);
|
||||
return opts.include ? opts.include.some(match) : !opts.exclude.some(match);
|
||||
};
|
||||
|
||||
let ret;
|
||||
if (typeof obj === 'function') {
|
||||
ret = function () {
|
||||
if (opts.excludeMain) {
|
||||
return obj.apply(this, arguments);
|
||||
}
|
||||
|
||||
return processFn(obj, opts).apply(this, arguments);
|
||||
};
|
||||
} else {
|
||||
ret = Object.create(Object.getPrototypeOf(obj));
|
||||
}
|
||||
|
||||
for (const key in obj) { // eslint-disable-line guard-for-in
|
||||
const x = obj[key];
|
||||
ret[key] = typeof x === 'function' && filter(key) ? processFn(x, opts) : x;
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
MIT License
|
||||
|
||||
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.
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
{
|
||||
"name": "pify",
|
||||
"version": "3.0.0",
|
||||
"description": "Promisify a callback-style function",
|
||||
"license": "MIT",
|
||||
"repository": "sindresorhus/pify",
|
||||
"author": {
|
||||
"name": "Sindre Sorhus",
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"url": "sindresorhus.com"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "xo && ava && npm run optimization-test",
|
||||
"optimization-test": "node --allow-natives-syntax optimization-test.js"
|
||||
},
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"keywords": [
|
||||
"promise",
|
||||
"promises",
|
||||
"promisify",
|
||||
"all",
|
||||
"denodify",
|
||||
"denodeify",
|
||||
"callback",
|
||||
"cb",
|
||||
"node",
|
||||
"then",
|
||||
"thenify",
|
||||
"convert",
|
||||
"transform",
|
||||
"wrap",
|
||||
"wrapper",
|
||||
"bind",
|
||||
"to",
|
||||
"async",
|
||||
"await",
|
||||
"es2015",
|
||||
"bluebird"
|
||||
],
|
||||
"devDependencies": {
|
||||
"ava": "*",
|
||||
"pinkie-promise": "^2.0.0",
|
||||
"v8-natives": "^1.0.0",
|
||||
"xo": "*"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,131 +0,0 @@
|
|||
# pify [](https://travis-ci.org/sindresorhus/pify)
|
||||
|
||||
> Promisify a callback-style function
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install --save pify
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const fs = require('fs');
|
||||
const pify = require('pify');
|
||||
|
||||
// Promisify a single function
|
||||
pify(fs.readFile)('package.json', 'utf8').then(data => {
|
||||
console.log(JSON.parse(data).name);
|
||||
//=> 'pify'
|
||||
});
|
||||
|
||||
// Promisify all methods in a module
|
||||
pify(fs).readFile('package.json', 'utf8').then(data => {
|
||||
console.log(JSON.parse(data).name);
|
||||
//=> 'pify'
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
## API
|
||||
|
||||
### pify(input, [options])
|
||||
|
||||
Returns a `Promise` wrapped version of the supplied function or module.
|
||||
|
||||
#### input
|
||||
|
||||
Type: `Function` `Object`
|
||||
|
||||
Callback-style function or module whose methods you want to promisify.
|
||||
|
||||
#### options
|
||||
|
||||
##### multiArgs
|
||||
|
||||
Type: `boolean`<br>
|
||||
Default: `false`
|
||||
|
||||
By default, the promisified function will only return the second argument from the callback, which works fine for most APIs. This option can be useful for modules like `request` that return multiple arguments. Turning this on will make it return an array of all arguments from the callback, excluding the error argument, instead of just the second argument. This also applies to rejections, where it returns an array of all the callback arguments, including the error.
|
||||
|
||||
```js
|
||||
const request = require('request');
|
||||
const pify = require('pify');
|
||||
|
||||
pify(request, {multiArgs: true})('https://sindresorhus.com').then(result => {
|
||||
const [httpResponse, body] = result;
|
||||
});
|
||||
```
|
||||
|
||||
##### include
|
||||
|
||||
Type: `string[]` `RegExp[]`
|
||||
|
||||
Methods in a module to promisify. Remaining methods will be left untouched.
|
||||
|
||||
##### exclude
|
||||
|
||||
Type: `string[]` `RegExp[]`<br>
|
||||
Default: `[/.+(Sync|Stream)$/]`
|
||||
|
||||
Methods in a module **not** to promisify. Methods with names ending with `'Sync'` are excluded by default.
|
||||
|
||||
##### excludeMain
|
||||
|
||||
Type: `boolean`<br>
|
||||
Default: `false`
|
||||
|
||||
If given module is a function itself, it will be promisified. Turn this option on if you want to promisify only methods of the module.
|
||||
|
||||
```js
|
||||
const pify = require('pify');
|
||||
|
||||
function fn() {
|
||||
return true;
|
||||
}
|
||||
|
||||
fn.method = (data, callback) => {
|
||||
setImmediate(() => {
|
||||
callback(null, data);
|
||||
});
|
||||
};
|
||||
|
||||
// Promisify methods but not `fn()`
|
||||
const promiseFn = pify(fn, {excludeMain: true});
|
||||
|
||||
if (promiseFn()) {
|
||||
promiseFn.method('hi').then(data => {
|
||||
console.log(data);
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
##### errorFirst
|
||||
|
||||
Type: `boolean`<br>
|
||||
Default: `true`
|
||||
|
||||
Whether the callback has an error as the first argument. You'll want to set this to `false` if you're dealing with an API that doesn't have an error as the first argument, like `fs.exists()`, some browser APIs, Chrome Extension APIs, etc.
|
||||
|
||||
##### promiseModule
|
||||
|
||||
Type: `Function`
|
||||
|
||||
Custom promise module to use instead of the native one.
|
||||
|
||||
Check out [`pinkie-promise`](https://github.com/floatdrop/pinkie-promise) if you need a tiny promise polyfill.
|
||||
|
||||
|
||||
## Related
|
||||
|
||||
- [p-event](https://github.com/sindresorhus/p-event) - Promisify an event by waiting for it to be emitted
|
||||
- [p-map](https://github.com/sindresorhus/p-map) - Map over promises concurrently
|
||||
- [More…](https://github.com/sindresorhus/promise-fun)
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Sindre Sorhus](https://sindresorhus.com)
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
'use strict';
|
||||
module.exports = (url, opts) => {
|
||||
if (typeof url !== 'string') {
|
||||
throw new TypeError(`Expected \`url\` to be of type \`string\`, got \`${typeof url}\``);
|
||||
}
|
||||
|
||||
url = url.trim();
|
||||
opts = Object.assign({https: false}, opts);
|
||||
|
||||
if (/^\.*\/|^(?!localhost)\w+:/.test(url)) {
|
||||
return url;
|
||||
}
|
||||
|
||||
return url.replace(/^(?!(?:\w+:)?\/\/)/, opts.https ? 'https://' : 'http://');
|
||||
};
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
MIT License
|
||||
|
||||
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.
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
{
|
||||
"name": "prepend-http",
|
||||
"version": "2.0.0",
|
||||
"description": "Prepend `http://` to humanized URLs like todomvc.com and localhost",
|
||||
"license": "MIT",
|
||||
"repository": "sindresorhus/prepend-http",
|
||||
"author": {
|
||||
"name": "Sindre Sorhus",
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"url": "sindresorhus.com"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "xo && ava"
|
||||
},
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"keywords": [
|
||||
"prepend",
|
||||
"protocol",
|
||||
"scheme",
|
||||
"url",
|
||||
"uri",
|
||||
"http",
|
||||
"https",
|
||||
"humanized"
|
||||
],
|
||||
"devDependencies": {
|
||||
"ava": "*",
|
||||
"xo": "*"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
# prepend-http [](https://travis-ci.org/sindresorhus/prepend-http)
|
||||
|
||||
> Prepend `http://` to humanized URLs like `todomvc.com` and `localhost`
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install prepend-http
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const prependHttp = require('prepend-http');
|
||||
|
||||
prependHttp('todomvc.com');
|
||||
//=> 'http://todomvc.com'
|
||||
|
||||
prependHttp('localhost');
|
||||
//=> 'http://localhost'
|
||||
|
||||
prependHttp('http://todomvc.com');
|
||||
//=> 'http://todomvc.com'
|
||||
|
||||
prependHttp('todomvc.com', {https: true});
|
||||
//=> 'https://todomvc.com'
|
||||
```
|
||||
|
||||
|
||||
## API
|
||||
|
||||
### prependHttp(url, [options])
|
||||
|
||||
#### url
|
||||
|
||||
Type: `string`
|
||||
|
||||
URL to prepend `http://` on.
|
||||
|
||||
#### options
|
||||
|
||||
Type: `Object`
|
||||
|
||||
##### https
|
||||
|
||||
Type: `boolean`<br>
|
||||
Default: `false`
|
||||
|
||||
Prepend `https://` instead of `http://`.
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Sindre Sorhus](https://sindresorhus.com)
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
if (!process.version ||
|
||||
process.version.indexOf('v0.') === 0 ||
|
||||
process.version.indexOf('v1.') === 0 && process.version.indexOf('v1.8.') !== 0) {
|
||||
module.exports = { nextTick: nextTick };
|
||||
} else {
|
||||
module.exports = process
|
||||
}
|
||||
|
||||
function nextTick(fn, arg1, arg2, arg3) {
|
||||
if (typeof fn !== 'function') {
|
||||
throw new TypeError('"callback" argument must be a function');
|
||||
}
|
||||
var len = arguments.length;
|
||||
var args, i;
|
||||
switch (len) {
|
||||
case 0:
|
||||
case 1:
|
||||
return process.nextTick(fn);
|
||||
case 2:
|
||||
return process.nextTick(function afterTickOne() {
|
||||
fn.call(null, arg1);
|
||||
});
|
||||
case 3:
|
||||
return process.nextTick(function afterTickTwo() {
|
||||
fn.call(null, arg1, arg2);
|
||||
});
|
||||
case 4:
|
||||
return process.nextTick(function afterTickThree() {
|
||||
fn.call(null, arg1, arg2, arg3);
|
||||
});
|
||||
default:
|
||||
args = new Array(len - 1);
|
||||
i = 0;
|
||||
while (i < args.length) {
|
||||
args[i++] = arguments[i];
|
||||
}
|
||||
return process.nextTick(function afterTick() {
|
||||
fn.apply(null, args);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
# Copyright (c) 2015 Calvin Metcalf
|
||||
|
||||
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.**
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
{
|
||||
"name": "process-nextick-args",
|
||||
"version": "2.0.0",
|
||||
"description": "process.nextTick but always with args",
|
||||
"main": "index.js",
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"scripts": {
|
||||
"test": "node test.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/calvinmetcalf/process-nextick-args.git"
|
||||
},
|
||||
"author": "",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/calvinmetcalf/process-nextick-args/issues"
|
||||
},
|
||||
"homepage": "https://github.com/calvinmetcalf/process-nextick-args",
|
||||
"devDependencies": {
|
||||
"tap": "~0.2.6"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
process-nextick-args
|
||||
=====
|
||||
|
||||
[](https://travis-ci.org/calvinmetcalf/process-nextick-args)
|
||||
|
||||
```bash
|
||||
npm install --save process-nextick-args
|
||||
```
|
||||
|
||||
Always be able to pass arguments to process.nextTick, no matter the platform
|
||||
|
||||
```js
|
||||
var pna = require('process-nextick-args');
|
||||
|
||||
pna.nextTick(function (a, b, c) {
|
||||
console.log(a, b, c);
|
||||
}, 'step', 3, 'profit');
|
||||
```
|
||||
|
|
@ -1,224 +0,0 @@
|
|||
'use strict';
|
||||
var strictUriEncode = require('strict-uri-encode');
|
||||
var objectAssign = require('object-assign');
|
||||
var decodeComponent = require('decode-uri-component');
|
||||
|
||||
function encoderForArrayFormat(opts) {
|
||||
switch (opts.arrayFormat) {
|
||||
case 'index':
|
||||
return function (key, value, index) {
|
||||
return value === null ? [
|
||||
encode(key, opts),
|
||||
'[',
|
||||
index,
|
||||
']'
|
||||
].join('') : [
|
||||
encode(key, opts),
|
||||
'[',
|
||||
encode(index, opts),
|
||||
']=',
|
||||
encode(value, opts)
|
||||
].join('');
|
||||
};
|
||||
|
||||
case 'bracket':
|
||||
return function (key, value) {
|
||||
return value === null ? encode(key, opts) : [
|
||||
encode(key, opts),
|
||||
'[]=',
|
||||
encode(value, opts)
|
||||
].join('');
|
||||
};
|
||||
|
||||
default:
|
||||
return function (key, value) {
|
||||
return value === null ? encode(key, opts) : [
|
||||
encode(key, opts),
|
||||
'=',
|
||||
encode(value, opts)
|
||||
].join('');
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function parserForArrayFormat(opts) {
|
||||
var result;
|
||||
|
||||
switch (opts.arrayFormat) {
|
||||
case 'index':
|
||||
return function (key, value, accumulator) {
|
||||
result = /\[(\d*)\]$/.exec(key);
|
||||
|
||||
key = key.replace(/\[\d*\]$/, '');
|
||||
|
||||
if (!result) {
|
||||
accumulator[key] = value;
|
||||
return;
|
||||
}
|
||||
|
||||
if (accumulator[key] === undefined) {
|
||||
accumulator[key] = {};
|
||||
}
|
||||
|
||||
accumulator[key][result[1]] = value;
|
||||
};
|
||||
|
||||
case 'bracket':
|
||||
return function (key, value, accumulator) {
|
||||
result = /(\[\])$/.exec(key);
|
||||
key = key.replace(/\[\]$/, '');
|
||||
|
||||
if (!result) {
|
||||
accumulator[key] = value;
|
||||
return;
|
||||
} else if (accumulator[key] === undefined) {
|
||||
accumulator[key] = [value];
|
||||
return;
|
||||
}
|
||||
|
||||
accumulator[key] = [].concat(accumulator[key], value);
|
||||
};
|
||||
|
||||
default:
|
||||
return function (key, value, accumulator) {
|
||||
if (accumulator[key] === undefined) {
|
||||
accumulator[key] = value;
|
||||
return;
|
||||
}
|
||||
|
||||
accumulator[key] = [].concat(accumulator[key], value);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function encode(value, opts) {
|
||||
if (opts.encode) {
|
||||
return opts.strict ? strictUriEncode(value) : encodeURIComponent(value);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
function keysSorter(input) {
|
||||
if (Array.isArray(input)) {
|
||||
return input.sort();
|
||||
} else if (typeof input === 'object') {
|
||||
return keysSorter(Object.keys(input)).sort(function (a, b) {
|
||||
return Number(a) - Number(b);
|
||||
}).map(function (key) {
|
||||
return input[key];
|
||||
});
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
function extract(str) {
|
||||
var queryStart = str.indexOf('?');
|
||||
if (queryStart === -1) {
|
||||
return '';
|
||||
}
|
||||
return str.slice(queryStart + 1);
|
||||
}
|
||||
|
||||
function parse(str, opts) {
|
||||
opts = objectAssign({arrayFormat: 'none'}, opts);
|
||||
|
||||
var formatter = parserForArrayFormat(opts);
|
||||
|
||||
// Create an object with no prototype
|
||||
// https://github.com/sindresorhus/query-string/issues/47
|
||||
var ret = Object.create(null);
|
||||
|
||||
if (typeof str !== 'string') {
|
||||
return ret;
|
||||
}
|
||||
|
||||
str = str.trim().replace(/^[?#&]/, '');
|
||||
|
||||
if (!str) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
str.split('&').forEach(function (param) {
|
||||
var parts = param.replace(/\+/g, ' ').split('=');
|
||||
// Firefox (pre 40) decodes `%3D` to `=`
|
||||
// https://github.com/sindresorhus/query-string/pull/37
|
||||
var key = parts.shift();
|
||||
var val = parts.length > 0 ? parts.join('=') : undefined;
|
||||
|
||||
// missing `=` should be `null`:
|
||||
// http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters
|
||||
val = val === undefined ? null : decodeComponent(val);
|
||||
|
||||
formatter(decodeComponent(key), val, ret);
|
||||
});
|
||||
|
||||
return Object.keys(ret).sort().reduce(function (result, key) {
|
||||
var val = ret[key];
|
||||
if (Boolean(val) && typeof val === 'object' && !Array.isArray(val)) {
|
||||
// Sort object keys, not values
|
||||
result[key] = keysSorter(val);
|
||||
} else {
|
||||
result[key] = val;
|
||||
}
|
||||
|
||||
return result;
|
||||
}, Object.create(null));
|
||||
}
|
||||
|
||||
exports.extract = extract;
|
||||
exports.parse = parse;
|
||||
|
||||
exports.stringify = function (obj, opts) {
|
||||
var defaults = {
|
||||
encode: true,
|
||||
strict: true,
|
||||
arrayFormat: 'none'
|
||||
};
|
||||
|
||||
opts = objectAssign(defaults, opts);
|
||||
|
||||
if (opts.sort === false) {
|
||||
opts.sort = function () {};
|
||||
}
|
||||
|
||||
var formatter = encoderForArrayFormat(opts);
|
||||
|
||||
return obj ? Object.keys(obj).sort(opts.sort).map(function (key) {
|
||||
var val = obj[key];
|
||||
|
||||
if (val === undefined) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (val === null) {
|
||||
return encode(key, opts);
|
||||
}
|
||||
|
||||
if (Array.isArray(val)) {
|
||||
var result = [];
|
||||
|
||||
val.slice().forEach(function (val2) {
|
||||
if (val2 === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
result.push(formatter(key, val2, result.length));
|
||||
});
|
||||
|
||||
return result.join('&');
|
||||
}
|
||||
|
||||
return encode(key, opts) + '=' + encode(val, opts);
|
||||
}).filter(function (x) {
|
||||
return x.length > 0;
|
||||
}).join('&') : '';
|
||||
};
|
||||
|
||||
exports.parseUrl = function (str, opts) {
|
||||
return {
|
||||
url: str.split('?')[0] || '',
|
||||
query: parse(extract(str), opts)
|
||||
};
|
||||
};
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
MIT License
|
||||
|
||||
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.
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
{
|
||||
"name": "query-string",
|
||||
"version": "5.1.1",
|
||||
"description": "Parse and stringify URL query strings",
|
||||
"license": "MIT",
|
||||
"repository": "sindresorhus/query-string",
|
||||
"author": {
|
||||
"name": "Sindre Sorhus",
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"url": "sindresorhus.com"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "xo && ava"
|
||||
},
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"keywords": [
|
||||
"browser",
|
||||
"querystring",
|
||||
"query",
|
||||
"string",
|
||||
"qs",
|
||||
"param",
|
||||
"parameter",
|
||||
"url",
|
||||
"uri",
|
||||
"parse",
|
||||
"stringify",
|
||||
"encode",
|
||||
"decode"
|
||||
],
|
||||
"dependencies": {
|
||||
"decode-uri-component": "^0.2.0",
|
||||
"object-assign": "^4.1.0",
|
||||
"strict-uri-encode": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"ava": "^0.17.0",
|
||||
"xo": "^0.16.0"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,224 +0,0 @@
|
|||
# query-string [](https://travis-ci.org/sindresorhus/query-string)
|
||||
|
||||
> Parse and stringify URL [query strings](https://en.wikipedia.org/wiki/Query_string)
|
||||
|
||||
---
|
||||
|
||||
<p align="center"><b>🔥 Want to strengthen your core JavaScript skills and master ES6?</b><br>I would personally recommend this awesome <a href="https://ES6.io/friend/AWESOME">ES6 course</a> by Wes Bos.<br>Also check out his <a href="https://LearnNode.com/friend/AWESOME">Node.js</a>, <a href="https://ReactForBeginners.com/friend/AWESOME">React</a>, <a href="https://SublimeTextBook.com/friend/AWESOME">Sublime</a> courses.</p>
|
||||
|
||||
---
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install query-string
|
||||
```
|
||||
|
||||
<a href="https://www.patreon.com/sindresorhus">
|
||||
<img src="https://c5.patreon.com/external/logo/become_a_patron_button@2x.png" width="160">
|
||||
</a>
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const queryString = require('query-string');
|
||||
|
||||
console.log(location.search);
|
||||
//=> '?foo=bar'
|
||||
|
||||
const parsed = queryString.parse(location.search);
|
||||
console.log(parsed);
|
||||
//=> {foo: 'bar'}
|
||||
|
||||
console.log(location.hash);
|
||||
//=> '#token=bada55cafe'
|
||||
|
||||
const parsedHash = queryString.parse(location.hash);
|
||||
console.log(parsedHash);
|
||||
//=> {token: 'bada55cafe'}
|
||||
|
||||
parsed.foo = 'unicorn';
|
||||
parsed.ilike = 'pizza';
|
||||
|
||||
const stringified = queryString.stringify(parsed);
|
||||
//=> 'foo=unicorn&ilike=pizza'
|
||||
|
||||
location.search = stringified;
|
||||
// note that `location.search` automatically prepends a question mark
|
||||
console.log(location.search);
|
||||
//=> '?foo=unicorn&ilike=pizza'
|
||||
```
|
||||
|
||||
|
||||
## API
|
||||
|
||||
### .parse(*string*, *[options]*)
|
||||
|
||||
Parse a query string into an object. Leading `?` or `#` are ignored, so you can pass `location.search` or `location.hash` directly.
|
||||
|
||||
The returned object is created with [`Object.create(null)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create) and thus does not have a `prototype`.
|
||||
|
||||
URI components are decoded with [`decode-uri-component`](https://github.com/SamVerschueren/decode-uri-component).
|
||||
|
||||
#### arrayFormat
|
||||
|
||||
Type: `string`<br>
|
||||
Default: `'none'`
|
||||
|
||||
Supports both `index` for an indexed array representation or `bracket` for a *bracketed* array representation.
|
||||
|
||||
- `bracket`: stands for parsing correctly arrays with bracket representation on the query string, such as:
|
||||
|
||||
```js
|
||||
queryString.parse('foo[]=1&foo[]=2&foo[]=3', {arrayFormat: 'bracket'});
|
||||
//=> foo: [1,2,3]
|
||||
```
|
||||
|
||||
- `index`: stands for parsing taking the index into account, such as:
|
||||
|
||||
```js
|
||||
queryString.parse('foo[0]=1&foo[1]=2&foo[3]=3', {arrayFormat: 'index'});
|
||||
//=> foo: [1,2,3]
|
||||
```
|
||||
|
||||
- `none`: is the **default** option and removes any bracket representation, such as:
|
||||
|
||||
```js
|
||||
queryString.parse('foo=1&foo=2&foo=3');
|
||||
//=> foo: [1,2,3]
|
||||
```
|
||||
|
||||
### .stringify(*object*, *[options]*)
|
||||
|
||||
Stringify an object into a query string, sorting the keys.
|
||||
|
||||
#### strict
|
||||
|
||||
Type: `boolean`<br>
|
||||
Default: `true`
|
||||
|
||||
Strictly encode URI components with [strict-uri-encode](https://github.com/kevva/strict-uri-encode). It uses [encodeURIComponent](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent)
|
||||
if set to false. You probably [don't care](https://github.com/sindresorhus/query-string/issues/42) about this option.
|
||||
|
||||
#### encode
|
||||
|
||||
Type: `boolean`<br>
|
||||
Default: `true`
|
||||
|
||||
[URL encode](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent) the keys and values.
|
||||
|
||||
#### arrayFormat
|
||||
|
||||
Type: `string`<br>
|
||||
Default: `'none'`
|
||||
|
||||
Supports both `index` for an indexed array representation or `bracket` for a *bracketed* array representation.
|
||||
|
||||
- `bracket`: stands for parsing correctly arrays with bracket representation on the query string, such as:
|
||||
|
||||
```js
|
||||
queryString.stringify({foo: [1,2,3]}, {arrayFormat: 'bracket'});
|
||||
// => foo[]=1&foo[]=2&foo[]=3
|
||||
```
|
||||
|
||||
- `index`: stands for parsing taking the index into account, such as:
|
||||
|
||||
```js
|
||||
queryString.stringify({foo: [1,2,3]}, {arrayFormat: 'index'});
|
||||
// => foo[0]=1&foo[1]=2&foo[3]=3
|
||||
```
|
||||
|
||||
- `none`: is the __default__ option and removes any bracket representation, such as:
|
||||
|
||||
```js
|
||||
queryString.stringify({foo: [1,2,3]});
|
||||
// => foo=1&foo=2&foo=3
|
||||
```
|
||||
|
||||
#### sort
|
||||
|
||||
Type: `Function` `boolean`
|
||||
|
||||
Supports both `Function` as a custom sorting function or `false` to disable sorting.
|
||||
|
||||
```js
|
||||
const order = ['c', 'a', 'b'];
|
||||
queryString.stringify({ a: 1, b: 2, c: 3}, {
|
||||
sort: (m, n) => order.indexOf(m) >= order.indexOf(n)
|
||||
});
|
||||
// => 'c=3&a=1&b=2'
|
||||
```
|
||||
|
||||
```js
|
||||
queryString.stringify({ b: 1, c: 2, a: 3}, {sort: false});
|
||||
// => 'c=3&a=1&b=2'
|
||||
```
|
||||
|
||||
If omitted, keys are sorted using `Array#sort`, which means, converting them to strings and comparing strings in Unicode code point order.
|
||||
|
||||
### .extract(*string*)
|
||||
|
||||
Extract a query string from a URL that can be passed into `.parse()`.
|
||||
|
||||
### .parseUrl(*string*, *[options]*)
|
||||
|
||||
Extract the URL and the query string as an object.
|
||||
|
||||
The `options` are the same as for `.parse()`.
|
||||
|
||||
Returns an object with a `url` and `query` property.
|
||||
|
||||
```js
|
||||
queryString.parseUrl('https://foo.bar?foo=bar');
|
||||
//=> {url: 'https://foo.bar', query: {foo: 'bar'}}
|
||||
```
|
||||
|
||||
|
||||
## Nesting
|
||||
|
||||
This module intentionally doesn't support nesting as it's not spec'd and varies between implementations, which causes a lot of [edge cases](https://github.com/visionmedia/node-querystring/issues).
|
||||
|
||||
You're much better off just converting the object to a JSON string:
|
||||
|
||||
```js
|
||||
queryString.stringify({
|
||||
foo: 'bar',
|
||||
nested: JSON.stringify({
|
||||
unicorn: 'cake'
|
||||
})
|
||||
});
|
||||
//=> 'foo=bar&nested=%7B%22unicorn%22%3A%22cake%22%7D'
|
||||
```
|
||||
|
||||
However, there is support for multiple instances of the same key:
|
||||
|
||||
```js
|
||||
queryString.parse('likes=cake&name=bob&likes=icecream');
|
||||
//=> {likes: ['cake', 'icecream'], name: 'bob'}
|
||||
|
||||
queryString.stringify({color: ['taupe', 'chartreuse'], id: '515'});
|
||||
//=> 'color=chartreuse&color=taupe&id=515'
|
||||
```
|
||||
|
||||
|
||||
## Falsy values
|
||||
|
||||
Sometimes you want to unset a key, or maybe just make it present without assigning a value to it. Here is how falsy values are stringified:
|
||||
|
||||
```js
|
||||
queryString.stringify({foo: false});
|
||||
//=> 'foo=false'
|
||||
|
||||
queryString.stringify({foo: null});
|
||||
//=> 'foo'
|
||||
|
||||
queryString.stringify({foo: undefined});
|
||||
//=> ''
|
||||
```
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Sindre Sorhus](https://sindresorhus.com)
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
sudo: false
|
||||
language: node_js
|
||||
before_install:
|
||||
- npm install -g npm@2
|
||||
- test $NPM_LEGACY && npm install -g npm@latest-3 || npm install npm -g
|
||||
notifications:
|
||||
email: false
|
||||
matrix:
|
||||
fast_finish: true
|
||||
include:
|
||||
- node_js: '0.8'
|
||||
env:
|
||||
- TASK=test
|
||||
- NPM_LEGACY=true
|
||||
- node_js: '0.10'
|
||||
env:
|
||||
- TASK=test
|
||||
- NPM_LEGACY=true
|
||||
- node_js: '0.11'
|
||||
env:
|
||||
- TASK=test
|
||||
- NPM_LEGACY=true
|
||||
- node_js: '0.12'
|
||||
env:
|
||||
- TASK=test
|
||||
- NPM_LEGACY=true
|
||||
- node_js: 1
|
||||
env:
|
||||
- TASK=test
|
||||
- NPM_LEGACY=true
|
||||
- node_js: 2
|
||||
env:
|
||||
- TASK=test
|
||||
- NPM_LEGACY=true
|
||||
- node_js: 3
|
||||
env:
|
||||
- TASK=test
|
||||
- NPM_LEGACY=true
|
||||
- node_js: 4
|
||||
env: TASK=test
|
||||
- node_js: 5
|
||||
env: TASK=test
|
||||
- node_js: 6
|
||||
env: TASK=test
|
||||
- node_js: 7
|
||||
env: TASK=test
|
||||
- node_js: 8
|
||||
env: TASK=test
|
||||
- node_js: 9
|
||||
env: TASK=test
|
||||
script: "npm run $TASK"
|
||||
env:
|
||||
global:
|
||||
- secure: rE2Vvo7vnjabYNULNyLFxOyt98BoJexDqsiOnfiD6kLYYsiQGfr/sbZkPMOFm9qfQG7pjqx+zZWZjGSswhTt+626C0t/njXqug7Yps4c3dFblzGfreQHp7wNX5TFsvrxd6dAowVasMp61sJcRnB2w8cUzoe3RAYUDHyiHktwqMc=
|
||||
- secure: g9YINaKAdMatsJ28G9jCGbSaguXCyxSTy+pBO6Ch0Cf57ZLOTka3HqDj8p3nV28LUIHZ3ut5WO43CeYKwt4AUtLpBS3a0dndHdY6D83uY6b2qh5hXlrcbeQTq2cvw2y95F7hm4D1kwrgZ7ViqaKggRcEupAL69YbJnxeUDKWEdI=
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
# Developer's Certificate of Origin 1.1
|
||||
|
||||
By making a contribution to this project, I certify that:
|
||||
|
||||
* (a) The contribution was created in whole or in part by me and I
|
||||
have the right to submit it under the open source license
|
||||
indicated in the file; or
|
||||
|
||||
* (b) The contribution is based upon previous work that, to the best
|
||||
of my knowledge, is covered under an appropriate open source
|
||||
license and I have the right under that license to submit that
|
||||
work with modifications, whether created in whole or in part
|
||||
by me, under the same open source license (unless I am
|
||||
permitted to submit under a different license), as indicated
|
||||
in the file; or
|
||||
|
||||
* (c) The contribution was provided directly to me by some other
|
||||
person who certified (a), (b) or (c) and I have not modified
|
||||
it.
|
||||
|
||||
* (d) I understand and agree that this project and the contribution
|
||||
are public and that a record of the contribution (including all
|
||||
personal information I submit with it, including my sign-off) is
|
||||
maintained indefinitely and may be redistributed consistent with
|
||||
this project or the open source license(s) involved.
|
||||
|
||||
## Moderation Policy
|
||||
|
||||
The [Node.js Moderation Policy] applies to this WG.
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
The [Node.js Code of Conduct][] applies to this WG.
|
||||
|
||||
[Node.js Code of Conduct]:
|
||||
https://github.com/nodejs/node/blob/master/CODE_OF_CONDUCT.md
|
||||
[Node.js Moderation Policy]:
|
||||
https://github.com/nodejs/TSC/blob/master/Moderation-Policy.md
|
||||
|
|
@ -1,136 +0,0 @@
|
|||
### Streams Working Group
|
||||
|
||||
The Node.js Streams is jointly governed by a Working Group
|
||||
(WG)
|
||||
that is responsible for high-level guidance of the project.
|
||||
|
||||
The WG has final authority over this project including:
|
||||
|
||||
* Technical direction
|
||||
* Project governance and process (including this policy)
|
||||
* Contribution policy
|
||||
* GitHub repository hosting
|
||||
* Conduct guidelines
|
||||
* Maintaining the list of additional Collaborators
|
||||
|
||||
For the current list of WG members, see the project
|
||||
[README.md](./README.md#current-project-team-members).
|
||||
|
||||
### Collaborators
|
||||
|
||||
The readable-stream GitHub repository is
|
||||
maintained by the WG and additional Collaborators who are added by the
|
||||
WG on an ongoing basis.
|
||||
|
||||
Individuals making significant and valuable contributions are made
|
||||
Collaborators and given commit-access to the project. These
|
||||
individuals are identified by the WG and their addition as
|
||||
Collaborators is discussed during the WG meeting.
|
||||
|
||||
_Note:_ If you make a significant contribution and are not considered
|
||||
for commit-access log an issue or contact a WG member directly and it
|
||||
will be brought up in the next WG meeting.
|
||||
|
||||
Modifications of the contents of the readable-stream repository are
|
||||
made on
|
||||
a collaborative basis. Anybody with a GitHub account may propose a
|
||||
modification via pull request and it will be considered by the project
|
||||
Collaborators. All pull requests must be reviewed and accepted by a
|
||||
Collaborator with sufficient expertise who is able to take full
|
||||
responsibility for the change. In the case of pull requests proposed
|
||||
by an existing Collaborator, an additional Collaborator is required
|
||||
for sign-off. Consensus should be sought if additional Collaborators
|
||||
participate and there is disagreement around a particular
|
||||
modification. See _Consensus Seeking Process_ below for further detail
|
||||
on the consensus model used for governance.
|
||||
|
||||
Collaborators may opt to elevate significant or controversial
|
||||
modifications, or modifications that have not found consensus to the
|
||||
WG for discussion by assigning the ***WG-agenda*** tag to a pull
|
||||
request or issue. The WG should serve as the final arbiter where
|
||||
required.
|
||||
|
||||
For the current list of Collaborators, see the project
|
||||
[README.md](./README.md#members).
|
||||
|
||||
### WG Membership
|
||||
|
||||
WG seats are not time-limited. There is no fixed size of the WG.
|
||||
However, the expected target is between 6 and 12, to ensure adequate
|
||||
coverage of important areas of expertise, balanced with the ability to
|
||||
make decisions efficiently.
|
||||
|
||||
There is no specific set of requirements or qualifications for WG
|
||||
membership beyond these rules.
|
||||
|
||||
The WG may add additional members to the WG by unanimous consensus.
|
||||
|
||||
A WG member may be removed from the WG by voluntary resignation, or by
|
||||
unanimous consensus of all other WG members.
|
||||
|
||||
Changes to WG membership should be posted in the agenda, and may be
|
||||
suggested as any other agenda item (see "WG Meetings" below).
|
||||
|
||||
If an addition or removal is proposed during a meeting, and the full
|
||||
WG is not in attendance to participate, then the addition or removal
|
||||
is added to the agenda for the subsequent meeting. This is to ensure
|
||||
that all members are given the opportunity to participate in all
|
||||
membership decisions. If a WG member is unable to attend a meeting
|
||||
where a planned membership decision is being made, then their consent
|
||||
is assumed.
|
||||
|
||||
No more than 1/3 of the WG members may be affiliated with the same
|
||||
employer. If removal or resignation of a WG member, or a change of
|
||||
employment by a WG member, creates a situation where more than 1/3 of
|
||||
the WG membership shares an employer, then the situation must be
|
||||
immediately remedied by the resignation or removal of one or more WG
|
||||
members affiliated with the over-represented employer(s).
|
||||
|
||||
### WG Meetings
|
||||
|
||||
The WG meets occasionally on a Google Hangout On Air. A designated moderator
|
||||
approved by the WG runs the meeting. Each meeting should be
|
||||
published to YouTube.
|
||||
|
||||
Items are added to the WG agenda that are considered contentious or
|
||||
are modifications of governance, contribution policy, WG membership,
|
||||
or release process.
|
||||
|
||||
The intention of the agenda is not to approve or review all patches;
|
||||
that should happen continuously on GitHub and be handled by the larger
|
||||
group of Collaborators.
|
||||
|
||||
Any community member or contributor can ask that something be added to
|
||||
the next meeting's agenda by logging a GitHub Issue. Any Collaborator,
|
||||
WG member or the moderator can add the item to the agenda by adding
|
||||
the ***WG-agenda*** tag to the issue.
|
||||
|
||||
Prior to each WG meeting the moderator will share the Agenda with
|
||||
members of the WG. WG members can add any items they like to the
|
||||
agenda at the beginning of each meeting. The moderator and the WG
|
||||
cannot veto or remove items.
|
||||
|
||||
The WG may invite persons or representatives from certain projects to
|
||||
participate in a non-voting capacity.
|
||||
|
||||
The moderator is responsible for summarizing the discussion of each
|
||||
agenda item and sends it as a pull request after the meeting.
|
||||
|
||||
### Consensus Seeking Process
|
||||
|
||||
The WG follows a
|
||||
[Consensus
|
||||
Seeking](http://en.wikipedia.org/wiki/Consensus-seeking_decision-making)
|
||||
decision-making model.
|
||||
|
||||
When an agenda item has appeared to reach a consensus the moderator
|
||||
will ask "Does anyone object?" as a final call for dissent from the
|
||||
consensus.
|
||||
|
||||
If an agenda item cannot reach a consensus a WG member can call for
|
||||
either a closing vote or a vote to table the issue to the next
|
||||
meeting. The call for a vote must be seconded by a majority of the WG
|
||||
or else the discussion will continue. Simple majority wins.
|
||||
|
||||
Note that changes to WG membership require a majority consensus. See
|
||||
"WG Membership" above.
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
Node.js is licensed for use as follows:
|
||||
|
||||
"""
|
||||
Copyright Node.js contributors. All rights reserved.
|
||||
|
||||
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.
|
||||
"""
|
||||
|
||||
This license applies to parts of Node.js originating from the
|
||||
https://github.com/joyent/node repository:
|
||||
|
||||
"""
|
||||
Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
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.
|
||||
"""
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
# readable-stream
|
||||
|
||||
***Node-core v8.11.1 streams for userland*** [](https://travis-ci.org/nodejs/readable-stream)
|
||||
|
||||
|
||||
[](https://nodei.co/npm/readable-stream/)
|
||||
[](https://nodei.co/npm/readable-stream/)
|
||||
|
||||
|
||||
[](https://saucelabs.com/u/readable-stream)
|
||||
|
||||
```bash
|
||||
npm install --save readable-stream
|
||||
```
|
||||
|
||||
***Node-core streams for userland***
|
||||
|
||||
This package is a mirror of the Streams2 and Streams3 implementations in
|
||||
Node-core.
|
||||
|
||||
Full documentation may be found on the [Node.js website](https://nodejs.org/dist/v8.11.1/docs/api/stream.html).
|
||||
|
||||
If you want to guarantee a stable streams base, regardless of what version of
|
||||
Node you, or the users of your libraries are using, use **readable-stream** *only* and avoid the *"stream"* module in Node-core, for background see [this blogpost](http://r.va.gg/2014/06/why-i-dont-use-nodes-core-stream-module.html).
|
||||
|
||||
As of version 2.0.0 **readable-stream** uses semantic versioning.
|
||||
|
||||
# Streams Working Group
|
||||
|
||||
`readable-stream` is maintained by the Streams Working Group, which
|
||||
oversees the development and maintenance of the Streams API within
|
||||
Node.js. The responsibilities of the Streams Working Group include:
|
||||
|
||||
* Addressing stream issues on the Node.js issue tracker.
|
||||
* Authoring and editing stream documentation within the Node.js project.
|
||||
* Reviewing changes to stream subclasses within the Node.js project.
|
||||
* Redirecting changes to streams from the Node.js project to this
|
||||
project.
|
||||
* Assisting in the implementation of stream providers within Node.js.
|
||||
* Recommending versions of `readable-stream` to be included in Node.js.
|
||||
* Messaging about the future of streams to give the community advance
|
||||
notice of changes.
|
||||
|
||||
<a name="members"></a>
|
||||
## Team Members
|
||||
|
||||
* **Chris Dickinson** ([@chrisdickinson](https://github.com/chrisdickinson)) <christopher.s.dickinson@gmail.com>
|
||||
- Release GPG key: 9554F04D7259F04124DE6B476D5A82AC7E37093B
|
||||
* **Calvin Metcalf** ([@calvinmetcalf](https://github.com/calvinmetcalf)) <calvin.metcalf@gmail.com>
|
||||
- Release GPG key: F3EF5F62A87FC27A22E643F714CE4FF5015AA242
|
||||
* **Rod Vagg** ([@rvagg](https://github.com/rvagg)) <rod@vagg.org>
|
||||
- Release GPG key: DD8F2338BAE7501E3DD5AC78C273792F7D83545D
|
||||
* **Sam Newman** ([@sonewman](https://github.com/sonewman)) <newmansam@outlook.com>
|
||||
* **Mathias Buus** ([@mafintosh](https://github.com/mafintosh)) <mathiasbuus@gmail.com>
|
||||
* **Domenic Denicola** ([@domenic](https://github.com/domenic)) <d@domenic.me>
|
||||
* **Matteo Collina** ([@mcollina](https://github.com/mcollina)) <matteo.collina@gmail.com>
|
||||
- Release GPG key: 3ABC01543F22DD2239285CDD818674489FBC127E
|
||||
* **Irina Shestak** ([@lrlna](https://github.com/lrlna)) <shestak.irina@gmail.com>
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
# streams WG Meeting 2015-01-30
|
||||
|
||||
## Links
|
||||
|
||||
* **Google Hangouts Video**: http://www.youtube.com/watch?v=I9nDOSGfwZg
|
||||
* **GitHub Issue**: https://github.com/iojs/readable-stream/issues/106
|
||||
* **Original Minutes Google Doc**: https://docs.google.com/document/d/17aTgLnjMXIrfjgNaTUnHQO7m3xgzHR2VXBTmi03Qii4/
|
||||
|
||||
## Agenda
|
||||
|
||||
Extracted from https://github.com/iojs/readable-stream/labels/wg-agenda prior to meeting.
|
||||
|
||||
* adopt a charter [#105](https://github.com/iojs/readable-stream/issues/105)
|
||||
* release and versioning strategy [#101](https://github.com/iojs/readable-stream/issues/101)
|
||||
* simpler stream creation [#102](https://github.com/iojs/readable-stream/issues/102)
|
||||
* proposal: deprecate implicit flowing of streams [#99](https://github.com/iojs/readable-stream/issues/99)
|
||||
|
||||
## Minutes
|
||||
|
||||
### adopt a charter
|
||||
|
||||
* group: +1's all around
|
||||
|
||||
### What versioning scheme should be adopted?
|
||||
* group: +1’s 3.0.0
|
||||
* domenic+group: pulling in patches from other sources where appropriate
|
||||
* mikeal: version independently, suggesting versions for io.js
|
||||
* mikeal+domenic: work with TC to notify in advance of changes
|
||||
simpler stream creation
|
||||
|
||||
### streamline creation of streams
|
||||
* sam: streamline creation of streams
|
||||
* domenic: nice simple solution posted
|
||||
but, we lose the opportunity to change the model
|
||||
may not be backwards incompatible (double check keys)
|
||||
|
||||
**action item:** domenic will check
|
||||
|
||||
### remove implicit flowing of streams on(‘data’)
|
||||
* add isFlowing / isPaused
|
||||
* mikeal: worrying that we’re documenting polyfill methods – confuses users
|
||||
* domenic: more reflective API is probably good, with warning labels for users
|
||||
* new section for mad scientists (reflective stream access)
|
||||
* calvin: name the “third state”
|
||||
* mikeal: maybe borrow the name from whatwg?
|
||||
* domenic: we’re missing the “third state”
|
||||
* consensus: kind of difficult to name the third state
|
||||
* mikeal: figure out differences in states / compat
|
||||
* mathias: always flow on data – eliminates third state
|
||||
* explore what it breaks
|
||||
|
||||
**action items:**
|
||||
* ask isaac for ability to list packages by what public io.js APIs they use (esp. Stream)
|
||||
* ask rod/build for infrastructure
|
||||
* **chris**: explore the “flow on data” approach
|
||||
* add isPaused/isFlowing
|
||||
* add new docs section
|
||||
* move isPaused to that section
|
||||
|
||||
|
||||
|
|
@ -1 +0,0 @@
|
|||
module.exports = require('./lib/_stream_duplex.js');
|
||||
|
|
@ -1 +0,0 @@
|
|||
module.exports = require('./readable').Duplex
|
||||
|
|
@ -1,131 +0,0 @@
|
|||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// 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.
|
||||
|
||||
// a duplex stream is just a stream that is both readable and writable.
|
||||
// Since JS doesn't have multiple prototypal inheritance, this class
|
||||
// prototypally inherits from Readable, and then parasitically from
|
||||
// Writable.
|
||||
|
||||
'use strict';
|
||||
|
||||
/*<replacement>*/
|
||||
|
||||
var pna = require('process-nextick-args');
|
||||
/*</replacement>*/
|
||||
|
||||
/*<replacement>*/
|
||||
var objectKeys = Object.keys || function (obj) {
|
||||
var keys = [];
|
||||
for (var key in obj) {
|
||||
keys.push(key);
|
||||
}return keys;
|
||||
};
|
||||
/*</replacement>*/
|
||||
|
||||
module.exports = Duplex;
|
||||
|
||||
/*<replacement>*/
|
||||
var util = require('core-util-is');
|
||||
util.inherits = require('inherits');
|
||||
/*</replacement>*/
|
||||
|
||||
var Readable = require('./_stream_readable');
|
||||
var Writable = require('./_stream_writable');
|
||||
|
||||
util.inherits(Duplex, Readable);
|
||||
|
||||
{
|
||||
// avoid scope creep, the keys array can then be collected
|
||||
var keys = objectKeys(Writable.prototype);
|
||||
for (var v = 0; v < keys.length; v++) {
|
||||
var method = keys[v];
|
||||
if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable.prototype[method];
|
||||
}
|
||||
}
|
||||
|
||||
function Duplex(options) {
|
||||
if (!(this instanceof Duplex)) return new Duplex(options);
|
||||
|
||||
Readable.call(this, options);
|
||||
Writable.call(this, options);
|
||||
|
||||
if (options && options.readable === false) this.readable = false;
|
||||
|
||||
if (options && options.writable === false) this.writable = false;
|
||||
|
||||
this.allowHalfOpen = true;
|
||||
if (options && options.allowHalfOpen === false) this.allowHalfOpen = false;
|
||||
|
||||
this.once('end', onend);
|
||||
}
|
||||
|
||||
Object.defineProperty(Duplex.prototype, 'writableHighWaterMark', {
|
||||
// making it explicit this property is not enumerable
|
||||
// because otherwise some prototype manipulation in
|
||||
// userland will fail
|
||||
enumerable: false,
|
||||
get: function () {
|
||||
return this._writableState.highWaterMark;
|
||||
}
|
||||
});
|
||||
|
||||
// the no-half-open enforcer
|
||||
function onend() {
|
||||
// if we allow half-open state, or if the writable side ended,
|
||||
// then we're ok.
|
||||
if (this.allowHalfOpen || this._writableState.ended) return;
|
||||
|
||||
// no more data can be written.
|
||||
// But allow more writes to happen in this tick.
|
||||
pna.nextTick(onEndNT, this);
|
||||
}
|
||||
|
||||
function onEndNT(self) {
|
||||
self.end();
|
||||
}
|
||||
|
||||
Object.defineProperty(Duplex.prototype, 'destroyed', {
|
||||
get: function () {
|
||||
if (this._readableState === undefined || this._writableState === undefined) {
|
||||
return false;
|
||||
}
|
||||
return this._readableState.destroyed && this._writableState.destroyed;
|
||||
},
|
||||
set: function (value) {
|
||||
// we ignore the value if the stream
|
||||
// has not been initialized yet
|
||||
if (this._readableState === undefined || this._writableState === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
// backward compatibility, the user is explicitly
|
||||
// managing destroyed
|
||||
this._readableState.destroyed = value;
|
||||
this._writableState.destroyed = value;
|
||||
}
|
||||
});
|
||||
|
||||
Duplex.prototype._destroy = function (err, cb) {
|
||||
this.push(null);
|
||||
this.end();
|
||||
|
||||
pna.nextTick(cb, err);
|
||||
};
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// 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.
|
||||
|
||||
// a passthrough stream.
|
||||
// basically just the most minimal sort of Transform stream.
|
||||
// Every written chunk gets output as-is.
|
||||
|
||||
'use strict';
|
||||
|
||||
module.exports = PassThrough;
|
||||
|
||||
var Transform = require('./_stream_transform');
|
||||
|
||||
/*<replacement>*/
|
||||
var util = require('core-util-is');
|
||||
util.inherits = require('inherits');
|
||||
/*</replacement>*/
|
||||
|
||||
util.inherits(PassThrough, Transform);
|
||||
|
||||
function PassThrough(options) {
|
||||
if (!(this instanceof PassThrough)) return new PassThrough(options);
|
||||
|
||||
Transform.call(this, options);
|
||||
}
|
||||
|
||||
PassThrough.prototype._transform = function (chunk, encoding, cb) {
|
||||
cb(null, chunk);
|
||||
};
|
||||
|
|
@ -1,1019 +0,0 @@
|
|||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// 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.
|
||||
|
||||
'use strict';
|
||||
|
||||
/*<replacement>*/
|
||||
|
||||
var pna = require('process-nextick-args');
|
||||
/*</replacement>*/
|
||||
|
||||
module.exports = Readable;
|
||||
|
||||
/*<replacement>*/
|
||||
var isArray = require('isarray');
|
||||
/*</replacement>*/
|
||||
|
||||
/*<replacement>*/
|
||||
var Duplex;
|
||||
/*</replacement>*/
|
||||
|
||||
Readable.ReadableState = ReadableState;
|
||||
|
||||
/*<replacement>*/
|
||||
var EE = require('events').EventEmitter;
|
||||
|
||||
var EElistenerCount = function (emitter, type) {
|
||||
return emitter.listeners(type).length;
|
||||
};
|
||||
/*</replacement>*/
|
||||
|
||||
/*<replacement>*/
|
||||
var Stream = require('./internal/streams/stream');
|
||||
/*</replacement>*/
|
||||
|
||||
/*<replacement>*/
|
||||
|
||||
var Buffer = require('safe-buffer').Buffer;
|
||||
var OurUint8Array = global.Uint8Array || function () {};
|
||||
function _uint8ArrayToBuffer(chunk) {
|
||||
return Buffer.from(chunk);
|
||||
}
|
||||
function _isUint8Array(obj) {
|
||||
return Buffer.isBuffer(obj) || obj instanceof OurUint8Array;
|
||||
}
|
||||
|
||||
/*</replacement>*/
|
||||
|
||||
/*<replacement>*/
|
||||
var util = require('core-util-is');
|
||||
util.inherits = require('inherits');
|
||||
/*</replacement>*/
|
||||
|
||||
/*<replacement>*/
|
||||
var debugUtil = require('util');
|
||||
var debug = void 0;
|
||||
if (debugUtil && debugUtil.debuglog) {
|
||||
debug = debugUtil.debuglog('stream');
|
||||
} else {
|
||||
debug = function () {};
|
||||
}
|
||||
/*</replacement>*/
|
||||
|
||||
var BufferList = require('./internal/streams/BufferList');
|
||||
var destroyImpl = require('./internal/streams/destroy');
|
||||
var StringDecoder;
|
||||
|
||||
util.inherits(Readable, Stream);
|
||||
|
||||
var kProxyEvents = ['error', 'close', 'destroy', 'pause', 'resume'];
|
||||
|
||||
function prependListener(emitter, event, fn) {
|
||||
// Sadly this is not cacheable as some libraries bundle their own
|
||||
// event emitter implementation with them.
|
||||
if (typeof emitter.prependListener === 'function') return emitter.prependListener(event, fn);
|
||||
|
||||
// This is a hack to make sure that our error handler is attached before any
|
||||
// userland ones. NEVER DO THIS. This is here only because this code needs
|
||||
// to continue to work with older versions of Node.js that do not include
|
||||
// the prependListener() method. The goal is to eventually remove this hack.
|
||||
if (!emitter._events || !emitter._events[event]) emitter.on(event, fn);else if (isArray(emitter._events[event])) emitter._events[event].unshift(fn);else emitter._events[event] = [fn, emitter._events[event]];
|
||||
}
|
||||
|
||||
function ReadableState(options, stream) {
|
||||
Duplex = Duplex || require('./_stream_duplex');
|
||||
|
||||
options = options || {};
|
||||
|
||||
// Duplex streams are both readable and writable, but share
|
||||
// the same options object.
|
||||
// However, some cases require setting options to different
|
||||
// values for the readable and the writable sides of the duplex stream.
|
||||
// These options can be provided separately as readableXXX and writableXXX.
|
||||
var isDuplex = stream instanceof Duplex;
|
||||
|
||||
// object stream flag. Used to make read(n) ignore n and to
|
||||
// make all the buffer merging and length checks go away
|
||||
this.objectMode = !!options.objectMode;
|
||||
|
||||
if (isDuplex) this.objectMode = this.objectMode || !!options.readableObjectMode;
|
||||
|
||||
// the point at which it stops calling _read() to fill the buffer
|
||||
// Note: 0 is a valid value, means "don't call _read preemptively ever"
|
||||
var hwm = options.highWaterMark;
|
||||
var readableHwm = options.readableHighWaterMark;
|
||||
var defaultHwm = this.objectMode ? 16 : 16 * 1024;
|
||||
|
||||
if (hwm || hwm === 0) this.highWaterMark = hwm;else if (isDuplex && (readableHwm || readableHwm === 0)) this.highWaterMark = readableHwm;else this.highWaterMark = defaultHwm;
|
||||
|
||||
// cast to ints.
|
||||
this.highWaterMark = Math.floor(this.highWaterMark);
|
||||
|
||||
// A linked list is used to store data chunks instead of an array because the
|
||||
// linked list can remove elements from the beginning faster than
|
||||
// array.shift()
|
||||
this.buffer = new BufferList();
|
||||
this.length = 0;
|
||||
this.pipes = null;
|
||||
this.pipesCount = 0;
|
||||
this.flowing = null;
|
||||
this.ended = false;
|
||||
this.endEmitted = false;
|
||||
this.reading = false;
|
||||
|
||||
// a flag to be able to tell if the event 'readable'/'data' is emitted
|
||||
// immediately, or on a later tick. We set this to true at first, because
|
||||
// any actions that shouldn't happen until "later" should generally also
|
||||
// not happen before the first read call.
|
||||
this.sync = true;
|
||||
|
||||
// whenever we return null, then we set a flag to say
|
||||
// that we're awaiting a 'readable' event emission.
|
||||
this.needReadable = false;
|
||||
this.emittedReadable = false;
|
||||
this.readableListening = false;
|
||||
this.resumeScheduled = false;
|
||||
|
||||
// has it been destroyed
|
||||
this.destroyed = false;
|
||||
|
||||
// Crypto is kind of old and crusty. Historically, its default string
|
||||
// encoding is 'binary' so we have to make this configurable.
|
||||
// Everything else in the universe uses 'utf8', though.
|
||||
this.defaultEncoding = options.defaultEncoding || 'utf8';
|
||||
|
||||
// the number of writers that are awaiting a drain event in .pipe()s
|
||||
this.awaitDrain = 0;
|
||||
|
||||
// if true, a maybeReadMore has been scheduled
|
||||
this.readingMore = false;
|
||||
|
||||
this.decoder = null;
|
||||
this.encoding = null;
|
||||
if (options.encoding) {
|
||||
if (!StringDecoder) StringDecoder = require('string_decoder/').StringDecoder;
|
||||
this.decoder = new StringDecoder(options.encoding);
|
||||
this.encoding = options.encoding;
|
||||
}
|
||||
}
|
||||
|
||||
function Readable(options) {
|
||||
Duplex = Duplex || require('./_stream_duplex');
|
||||
|
||||
if (!(this instanceof Readable)) return new Readable(options);
|
||||
|
||||
this._readableState = new ReadableState(options, this);
|
||||
|
||||
// legacy
|
||||
this.readable = true;
|
||||
|
||||
if (options) {
|
||||
if (typeof options.read === 'function') this._read = options.read;
|
||||
|
||||
if (typeof options.destroy === 'function') this._destroy = options.destroy;
|
||||
}
|
||||
|
||||
Stream.call(this);
|
||||
}
|
||||
|
||||
Object.defineProperty(Readable.prototype, 'destroyed', {
|
||||
get: function () {
|
||||
if (this._readableState === undefined) {
|
||||
return false;
|
||||
}
|
||||
return this._readableState.destroyed;
|
||||
},
|
||||
set: function (value) {
|
||||
// we ignore the value if the stream
|
||||
// has not been initialized yet
|
||||
if (!this._readableState) {
|
||||
return;
|
||||
}
|
||||
|
||||
// backward compatibility, the user is explicitly
|
||||
// managing destroyed
|
||||
this._readableState.destroyed = value;
|
||||
}
|
||||
});
|
||||
|
||||
Readable.prototype.destroy = destroyImpl.destroy;
|
||||
Readable.prototype._undestroy = destroyImpl.undestroy;
|
||||
Readable.prototype._destroy = function (err, cb) {
|
||||
this.push(null);
|
||||
cb(err);
|
||||
};
|
||||
|
||||
// Manually shove something into the read() buffer.
|
||||
// This returns true if the highWaterMark has not been hit yet,
|
||||
// similar to how Writable.write() returns true if you should
|
||||
// write() some more.
|
||||
Readable.prototype.push = function (chunk, encoding) {
|
||||
var state = this._readableState;
|
||||
var skipChunkCheck;
|
||||
|
||||
if (!state.objectMode) {
|
||||
if (typeof chunk === 'string') {
|
||||
encoding = encoding || state.defaultEncoding;
|
||||
if (encoding !== state.encoding) {
|
||||
chunk = Buffer.from(chunk, encoding);
|
||||
encoding = '';
|
||||
}
|
||||
skipChunkCheck = true;
|
||||
}
|
||||
} else {
|
||||
skipChunkCheck = true;
|
||||
}
|
||||
|
||||
return readableAddChunk(this, chunk, encoding, false, skipChunkCheck);
|
||||
};
|
||||
|
||||
// Unshift should *always* be something directly out of read()
|
||||
Readable.prototype.unshift = function (chunk) {
|
||||
return readableAddChunk(this, chunk, null, true, false);
|
||||
};
|
||||
|
||||
function readableAddChunk(stream, chunk, encoding, addToFront, skipChunkCheck) {
|
||||
var state = stream._readableState;
|
||||
if (chunk === null) {
|
||||
state.reading = false;
|
||||
onEofChunk(stream, state);
|
||||
} else {
|
||||
var er;
|
||||
if (!skipChunkCheck) er = chunkInvalid(state, chunk);
|
||||
if (er) {
|
||||
stream.emit('error', er);
|
||||
} else if (state.objectMode || chunk && chunk.length > 0) {
|
||||
if (typeof chunk !== 'string' && !state.objectMode && Object.getPrototypeOf(chunk) !== Buffer.prototype) {
|
||||
chunk = _uint8ArrayToBuffer(chunk);
|
||||
}
|
||||
|
||||
if (addToFront) {
|
||||
if (state.endEmitted) stream.emit('error', new Error('stream.unshift() after end event'));else addChunk(stream, state, chunk, true);
|
||||
} else if (state.ended) {
|
||||
stream.emit('error', new Error('stream.push() after EOF'));
|
||||
} else {
|
||||
state.reading = false;
|
||||
if (state.decoder && !encoding) {
|
||||
chunk = state.decoder.write(chunk);
|
||||
if (state.objectMode || chunk.length !== 0) addChunk(stream, state, chunk, false);else maybeReadMore(stream, state);
|
||||
} else {
|
||||
addChunk(stream, state, chunk, false);
|
||||
}
|
||||
}
|
||||
} else if (!addToFront) {
|
||||
state.reading = false;
|
||||
}
|
||||
}
|
||||
|
||||
return needMoreData(state);
|
||||
}
|
||||
|
||||
function addChunk(stream, state, chunk, addToFront) {
|
||||
if (state.flowing && state.length === 0 && !state.sync) {
|
||||
stream.emit('data', chunk);
|
||||
stream.read(0);
|
||||
} else {
|
||||
// update the buffer info.
|
||||
state.length += state.objectMode ? 1 : chunk.length;
|
||||
if (addToFront) state.buffer.unshift(chunk);else state.buffer.push(chunk);
|
||||
|
||||
if (state.needReadable) emitReadable(stream);
|
||||
}
|
||||
maybeReadMore(stream, state);
|
||||
}
|
||||
|
||||
function chunkInvalid(state, chunk) {
|
||||
var er;
|
||||
if (!_isUint8Array(chunk) && typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) {
|
||||
er = new TypeError('Invalid non-string/buffer chunk');
|
||||
}
|
||||
return er;
|
||||
}
|
||||
|
||||
// if it's past the high water mark, we can push in some more.
|
||||
// Also, if we have no data yet, we can stand some
|
||||
// more bytes. This is to work around cases where hwm=0,
|
||||
// such as the repl. Also, if the push() triggered a
|
||||
// readable event, and the user called read(largeNumber) such that
|
||||
// needReadable was set, then we ought to push more, so that another
|
||||
// 'readable' event will be triggered.
|
||||
function needMoreData(state) {
|
||||
return !state.ended && (state.needReadable || state.length < state.highWaterMark || state.length === 0);
|
||||
}
|
||||
|
||||
Readable.prototype.isPaused = function () {
|
||||
return this._readableState.flowing === false;
|
||||
};
|
||||
|
||||
// backwards compatibility.
|
||||
Readable.prototype.setEncoding = function (enc) {
|
||||
if (!StringDecoder) StringDecoder = require('string_decoder/').StringDecoder;
|
||||
this._readableState.decoder = new StringDecoder(enc);
|
||||
this._readableState.encoding = enc;
|
||||
return this;
|
||||
};
|
||||
|
||||
// Don't raise the hwm > 8MB
|
||||
var MAX_HWM = 0x800000;
|
||||
function computeNewHighWaterMark(n) {
|
||||
if (n >= MAX_HWM) {
|
||||
n = MAX_HWM;
|
||||
} else {
|
||||
// Get the next highest power of 2 to prevent increasing hwm excessively in
|
||||
// tiny amounts
|
||||
n--;
|
||||
n |= n >>> 1;
|
||||
n |= n >>> 2;
|
||||
n |= n >>> 4;
|
||||
n |= n >>> 8;
|
||||
n |= n >>> 16;
|
||||
n++;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
// This function is designed to be inlinable, so please take care when making
|
||||
// changes to the function body.
|
||||
function howMuchToRead(n, state) {
|
||||
if (n <= 0 || state.length === 0 && state.ended) return 0;
|
||||
if (state.objectMode) return 1;
|
||||
if (n !== n) {
|
||||
// Only flow one buffer at a time
|
||||
if (state.flowing && state.length) return state.buffer.head.data.length;else return state.length;
|
||||
}
|
||||
// If we're asking for more than the current hwm, then raise the hwm.
|
||||
if (n > state.highWaterMark) state.highWaterMark = computeNewHighWaterMark(n);
|
||||
if (n <= state.length) return n;
|
||||
// Don't have enough
|
||||
if (!state.ended) {
|
||||
state.needReadable = true;
|
||||
return 0;
|
||||
}
|
||||
return state.length;
|
||||
}
|
||||
|
||||
// you can override either this method, or the async _read(n) below.
|
||||
Readable.prototype.read = function (n) {
|
||||
debug('read', n);
|
||||
n = parseInt(n, 10);
|
||||
var state = this._readableState;
|
||||
var nOrig = n;
|
||||
|
||||
if (n !== 0) state.emittedReadable = false;
|
||||
|
||||
// if we're doing read(0) to trigger a readable event, but we
|
||||
// already have a bunch of data in the buffer, then just trigger
|
||||
// the 'readable' event and move on.
|
||||
if (n === 0 && state.needReadable && (state.length >= state.highWaterMark || state.ended)) {
|
||||
debug('read: emitReadable', state.length, state.ended);
|
||||
if (state.length === 0 && state.ended) endReadable(this);else emitReadable(this);
|
||||
return null;
|
||||
}
|
||||
|
||||
n = howMuchToRead(n, state);
|
||||
|
||||
// if we've ended, and we're now clear, then finish it up.
|
||||
if (n === 0 && state.ended) {
|
||||
if (state.length === 0) endReadable(this);
|
||||
return null;
|
||||
}
|
||||
|
||||
// All the actual chunk generation logic needs to be
|
||||
// *below* the call to _read. The reason is that in certain
|
||||
// synthetic stream cases, such as passthrough streams, _read
|
||||
// may be a completely synchronous operation which may change
|
||||
// the state of the read buffer, providing enough data when
|
||||
// before there was *not* enough.
|
||||
//
|
||||
// So, the steps are:
|
||||
// 1. Figure out what the state of things will be after we do
|
||||
// a read from the buffer.
|
||||
//
|
||||
// 2. If that resulting state will trigger a _read, then call _read.
|
||||
// Note that this may be asynchronous, or synchronous. Yes, it is
|
||||
// deeply ugly to write APIs this way, but that still doesn't mean
|
||||
// that the Readable class should behave improperly, as streams are
|
||||
// designed to be sync/async agnostic.
|
||||
// Take note if the _read call is sync or async (ie, if the read call
|
||||
// has returned yet), so that we know whether or not it's safe to emit
|
||||
// 'readable' etc.
|
||||
//
|
||||
// 3. Actually pull the requested chunks out of the buffer and return.
|
||||
|
||||
// if we need a readable event, then we need to do some reading.
|
||||
var doRead = state.needReadable;
|
||||
debug('need readable', doRead);
|
||||
|
||||
// if we currently have less than the highWaterMark, then also read some
|
||||
if (state.length === 0 || state.length - n < state.highWaterMark) {
|
||||
doRead = true;
|
||||
debug('length less than watermark', doRead);
|
||||
}
|
||||
|
||||
// however, if we've ended, then there's no point, and if we're already
|
||||
// reading, then it's unnecessary.
|
||||
if (state.ended || state.reading) {
|
||||
doRead = false;
|
||||
debug('reading or ended', doRead);
|
||||
} else if (doRead) {
|
||||
debug('do read');
|
||||
state.reading = true;
|
||||
state.sync = true;
|
||||
// if the length is currently zero, then we *need* a readable event.
|
||||
if (state.length === 0) state.needReadable = true;
|
||||
// call internal read method
|
||||
this._read(state.highWaterMark);
|
||||
state.sync = false;
|
||||
// If _read pushed data synchronously, then `reading` will be false,
|
||||
// and we need to re-evaluate how much data we can return to the user.
|
||||
if (!state.reading) n = howMuchToRead(nOrig, state);
|
||||
}
|
||||
|
||||
var ret;
|
||||
if (n > 0) ret = fromList(n, state);else ret = null;
|
||||
|
||||
if (ret === null) {
|
||||
state.needReadable = true;
|
||||
n = 0;
|
||||
} else {
|
||||
state.length -= n;
|
||||
}
|
||||
|
||||
if (state.length === 0) {
|
||||
// If we have nothing in the buffer, then we want to know
|
||||
// as soon as we *do* get something into the buffer.
|
||||
if (!state.ended) state.needReadable = true;
|
||||
|
||||
// If we tried to read() past the EOF, then emit end on the next tick.
|
||||
if (nOrig !== n && state.ended) endReadable(this);
|
||||
}
|
||||
|
||||
if (ret !== null) this.emit('data', ret);
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
function onEofChunk(stream, state) {
|
||||
if (state.ended) return;
|
||||
if (state.decoder) {
|
||||
var chunk = state.decoder.end();
|
||||
if (chunk && chunk.length) {
|
||||
state.buffer.push(chunk);
|
||||
state.length += state.objectMode ? 1 : chunk.length;
|
||||
}
|
||||
}
|
||||
state.ended = true;
|
||||
|
||||
// emit 'readable' now to make sure it gets picked up.
|
||||
emitReadable(stream);
|
||||
}
|
||||
|
||||
// Don't emit readable right away in sync mode, because this can trigger
|
||||
// another read() call => stack overflow. This way, it might trigger
|
||||
// a nextTick recursion warning, but that's not so bad.
|
||||
function emitReadable(stream) {
|
||||
var state = stream._readableState;
|
||||
state.needReadable = false;
|
||||
if (!state.emittedReadable) {
|
||||
debug('emitReadable', state.flowing);
|
||||
state.emittedReadable = true;
|
||||
if (state.sync) pna.nextTick(emitReadable_, stream);else emitReadable_(stream);
|
||||
}
|
||||
}
|
||||
|
||||
function emitReadable_(stream) {
|
||||
debug('emit readable');
|
||||
stream.emit('readable');
|
||||
flow(stream);
|
||||
}
|
||||
|
||||
// at this point, the user has presumably seen the 'readable' event,
|
||||
// and called read() to consume some data. that may have triggered
|
||||
// in turn another _read(n) call, in which case reading = true if
|
||||
// it's in progress.
|
||||
// However, if we're not ended, or reading, and the length < hwm,
|
||||
// then go ahead and try to read some more preemptively.
|
||||
function maybeReadMore(stream, state) {
|
||||
if (!state.readingMore) {
|
||||
state.readingMore = true;
|
||||
pna.nextTick(maybeReadMore_, stream, state);
|
||||
}
|
||||
}
|
||||
|
||||
function maybeReadMore_(stream, state) {
|
||||
var len = state.length;
|
||||
while (!state.reading && !state.flowing && !state.ended && state.length < state.highWaterMark) {
|
||||
debug('maybeReadMore read 0');
|
||||
stream.read(0);
|
||||
if (len === state.length)
|
||||
// didn't get any data, stop spinning.
|
||||
break;else len = state.length;
|
||||
}
|
||||
state.readingMore = false;
|
||||
}
|
||||
|
||||
// abstract method. to be overridden in specific implementation classes.
|
||||
// call cb(er, data) where data is <= n in length.
|
||||
// for virtual (non-string, non-buffer) streams, "length" is somewhat
|
||||
// arbitrary, and perhaps not very meaningful.
|
||||
Readable.prototype._read = function (n) {
|
||||
this.emit('error', new Error('_read() is not implemented'));
|
||||
};
|
||||
|
||||
Readable.prototype.pipe = function (dest, pipeOpts) {
|
||||
var src = this;
|
||||
var state = this._readableState;
|
||||
|
||||
switch (state.pipesCount) {
|
||||
case 0:
|
||||
state.pipes = dest;
|
||||
break;
|
||||
case 1:
|
||||
state.pipes = [state.pipes, dest];
|
||||
break;
|
||||
default:
|
||||
state.pipes.push(dest);
|
||||
break;
|
||||
}
|
||||
state.pipesCount += 1;
|
||||
debug('pipe count=%d opts=%j', state.pipesCount, pipeOpts);
|
||||
|
||||
var doEnd = (!pipeOpts || pipeOpts.end !== false) && dest !== process.stdout && dest !== process.stderr;
|
||||
|
||||
var endFn = doEnd ? onend : unpipe;
|
||||
if (state.endEmitted) pna.nextTick(endFn);else src.once('end', endFn);
|
||||
|
||||
dest.on('unpipe', onunpipe);
|
||||
function onunpipe(readable, unpipeInfo) {
|
||||
debug('onunpipe');
|
||||
if (readable === src) {
|
||||
if (unpipeInfo && unpipeInfo.hasUnpiped === false) {
|
||||
unpipeInfo.hasUnpiped = true;
|
||||
cleanup();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onend() {
|
||||
debug('onend');
|
||||
dest.end();
|
||||
}
|
||||
|
||||
// when the dest drains, it reduces the awaitDrain counter
|
||||
// on the source. This would be more elegant with a .once()
|
||||
// handler in flow(), but adding and removing repeatedly is
|
||||
// too slow.
|
||||
var ondrain = pipeOnDrain(src);
|
||||
dest.on('drain', ondrain);
|
||||
|
||||
var cleanedUp = false;
|
||||
function cleanup() {
|
||||
debug('cleanup');
|
||||
// cleanup event handlers once the pipe is broken
|
||||
dest.removeListener('close', onclose);
|
||||
dest.removeListener('finish', onfinish);
|
||||
dest.removeListener('drain', ondrain);
|
||||
dest.removeListener('error', onerror);
|
||||
dest.removeListener('unpipe', onunpipe);
|
||||
src.removeListener('end', onend);
|
||||
src.removeListener('end', unpipe);
|
||||
src.removeListener('data', ondata);
|
||||
|
||||
cleanedUp = true;
|
||||
|
||||
// if the reader is waiting for a drain event from this
|
||||
// specific writer, then it would cause it to never start
|
||||
// flowing again.
|
||||
// So, if this is awaiting a drain, then we just call it now.
|
||||
// If we don't know, then assume that we are waiting for one.
|
||||
if (state.awaitDrain && (!dest._writableState || dest._writableState.needDrain)) ondrain();
|
||||
}
|
||||
|
||||
// If the user pushes more data while we're writing to dest then we'll end up
|
||||
// in ondata again. However, we only want to increase awaitDrain once because
|
||||
// dest will only emit one 'drain' event for the multiple writes.
|
||||
// => Introduce a guard on increasing awaitDrain.
|
||||
var increasedAwaitDrain = false;
|
||||
src.on('data', ondata);
|
||||
function ondata(chunk) {
|
||||
debug('ondata');
|
||||
increasedAwaitDrain = false;
|
||||
var ret = dest.write(chunk);
|
||||
if (false === ret && !increasedAwaitDrain) {
|
||||
// If the user unpiped during `dest.write()`, it is possible
|
||||
// to get stuck in a permanently paused state if that write
|
||||
// also returned false.
|
||||
// => Check whether `dest` is still a piping destination.
|
||||
if ((state.pipesCount === 1 && state.pipes === dest || state.pipesCount > 1 && indexOf(state.pipes, dest) !== -1) && !cleanedUp) {
|
||||
debug('false write response, pause', src._readableState.awaitDrain);
|
||||
src._readableState.awaitDrain++;
|
||||
increasedAwaitDrain = true;
|
||||
}
|
||||
src.pause();
|
||||
}
|
||||
}
|
||||
|
||||
// if the dest has an error, then stop piping into it.
|
||||
// however, don't suppress the throwing behavior for this.
|
||||
function onerror(er) {
|
||||
debug('onerror', er);
|
||||
unpipe();
|
||||
dest.removeListener('error', onerror);
|
||||
if (EElistenerCount(dest, 'error') === 0) dest.emit('error', er);
|
||||
}
|
||||
|
||||
// Make sure our error handler is attached before userland ones.
|
||||
prependListener(dest, 'error', onerror);
|
||||
|
||||
// Both close and finish should trigger unpipe, but only once.
|
||||
function onclose() {
|
||||
dest.removeListener('finish', onfinish);
|
||||
unpipe();
|
||||
}
|
||||
dest.once('close', onclose);
|
||||
function onfinish() {
|
||||
debug('onfinish');
|
||||
dest.removeListener('close', onclose);
|
||||
unpipe();
|
||||
}
|
||||
dest.once('finish', onfinish);
|
||||
|
||||
function unpipe() {
|
||||
debug('unpipe');
|
||||
src.unpipe(dest);
|
||||
}
|
||||
|
||||
// tell the dest that it's being piped to
|
||||
dest.emit('pipe', src);
|
||||
|
||||
// start the flow if it hasn't been started already.
|
||||
if (!state.flowing) {
|
||||
debug('pipe resume');
|
||||
src.resume();
|
||||
}
|
||||
|
||||
return dest;
|
||||
};
|
||||
|
||||
function pipeOnDrain(src) {
|
||||
return function () {
|
||||
var state = src._readableState;
|
||||
debug('pipeOnDrain', state.awaitDrain);
|
||||
if (state.awaitDrain) state.awaitDrain--;
|
||||
if (state.awaitDrain === 0 && EElistenerCount(src, 'data')) {
|
||||
state.flowing = true;
|
||||
flow(src);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Readable.prototype.unpipe = function (dest) {
|
||||
var state = this._readableState;
|
||||
var unpipeInfo = { hasUnpiped: false };
|
||||
|
||||
// if we're not piping anywhere, then do nothing.
|
||||
if (state.pipesCount === 0) return this;
|
||||
|
||||
// just one destination. most common case.
|
||||
if (state.pipesCount === 1) {
|
||||
// passed in one, but it's not the right one.
|
||||
if (dest && dest !== state.pipes) return this;
|
||||
|
||||
if (!dest) dest = state.pipes;
|
||||
|
||||
// got a match.
|
||||
state.pipes = null;
|
||||
state.pipesCount = 0;
|
||||
state.flowing = false;
|
||||
if (dest) dest.emit('unpipe', this, unpipeInfo);
|
||||
return this;
|
||||
}
|
||||
|
||||
// slow case. multiple pipe destinations.
|
||||
|
||||
if (!dest) {
|
||||
// remove all.
|
||||
var dests = state.pipes;
|
||||
var len = state.pipesCount;
|
||||
state.pipes = null;
|
||||
state.pipesCount = 0;
|
||||
state.flowing = false;
|
||||
|
||||
for (var i = 0; i < len; i++) {
|
||||
dests[i].emit('unpipe', this, unpipeInfo);
|
||||
}return this;
|
||||
}
|
||||
|
||||
// try to find the right one.
|
||||
var index = indexOf(state.pipes, dest);
|
||||
if (index === -1) return this;
|
||||
|
||||
state.pipes.splice(index, 1);
|
||||
state.pipesCount -= 1;
|
||||
if (state.pipesCount === 1) state.pipes = state.pipes[0];
|
||||
|
||||
dest.emit('unpipe', this, unpipeInfo);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
// set up data events if they are asked for
|
||||
// Ensure readable listeners eventually get something
|
||||
Readable.prototype.on = function (ev, fn) {
|
||||
var res = Stream.prototype.on.call(this, ev, fn);
|
||||
|
||||
if (ev === 'data') {
|
||||
// Start flowing on next tick if stream isn't explicitly paused
|
||||
if (this._readableState.flowing !== false) this.resume();
|
||||
} else if (ev === 'readable') {
|
||||
var state = this._readableState;
|
||||
if (!state.endEmitted && !state.readableListening) {
|
||||
state.readableListening = state.needReadable = true;
|
||||
state.emittedReadable = false;
|
||||
if (!state.reading) {
|
||||
pna.nextTick(nReadingNextTick, this);
|
||||
} else if (state.length) {
|
||||
emitReadable(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
};
|
||||
Readable.prototype.addListener = Readable.prototype.on;
|
||||
|
||||
function nReadingNextTick(self) {
|
||||
debug('readable nexttick read 0');
|
||||
self.read(0);
|
||||
}
|
||||
|
||||
// pause() and resume() are remnants of the legacy readable stream API
|
||||
// If the user uses them, then switch into old mode.
|
||||
Readable.prototype.resume = function () {
|
||||
var state = this._readableState;
|
||||
if (!state.flowing) {
|
||||
debug('resume');
|
||||
state.flowing = true;
|
||||
resume(this, state);
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
function resume(stream, state) {
|
||||
if (!state.resumeScheduled) {
|
||||
state.resumeScheduled = true;
|
||||
pna.nextTick(resume_, stream, state);
|
||||
}
|
||||
}
|
||||
|
||||
function resume_(stream, state) {
|
||||
if (!state.reading) {
|
||||
debug('resume read 0');
|
||||
stream.read(0);
|
||||
}
|
||||
|
||||
state.resumeScheduled = false;
|
||||
state.awaitDrain = 0;
|
||||
stream.emit('resume');
|
||||
flow(stream);
|
||||
if (state.flowing && !state.reading) stream.read(0);
|
||||
}
|
||||
|
||||
Readable.prototype.pause = function () {
|
||||
debug('call pause flowing=%j', this._readableState.flowing);
|
||||
if (false !== this._readableState.flowing) {
|
||||
debug('pause');
|
||||
this._readableState.flowing = false;
|
||||
this.emit('pause');
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
function flow(stream) {
|
||||
var state = stream._readableState;
|
||||
debug('flow', state.flowing);
|
||||
while (state.flowing && stream.read() !== null) {}
|
||||
}
|
||||
|
||||
// wrap an old-style stream as the async data source.
|
||||
// This is *not* part of the readable stream interface.
|
||||
// It is an ugly unfortunate mess of history.
|
||||
Readable.prototype.wrap = function (stream) {
|
||||
var _this = this;
|
||||
|
||||
var state = this._readableState;
|
||||
var paused = false;
|
||||
|
||||
stream.on('end', function () {
|
||||
debug('wrapped end');
|
||||
if (state.decoder && !state.ended) {
|
||||
var chunk = state.decoder.end();
|
||||
if (chunk && chunk.length) _this.push(chunk);
|
||||
}
|
||||
|
||||
_this.push(null);
|
||||
});
|
||||
|
||||
stream.on('data', function (chunk) {
|
||||
debug('wrapped data');
|
||||
if (state.decoder) chunk = state.decoder.write(chunk);
|
||||
|
||||
// don't skip over falsy values in objectMode
|
||||
if (state.objectMode && (chunk === null || chunk === undefined)) return;else if (!state.objectMode && (!chunk || !chunk.length)) return;
|
||||
|
||||
var ret = _this.push(chunk);
|
||||
if (!ret) {
|
||||
paused = true;
|
||||
stream.pause();
|
||||
}
|
||||
});
|
||||
|
||||
// proxy all the other methods.
|
||||
// important when wrapping filters and duplexes.
|
||||
for (var i in stream) {
|
||||
if (this[i] === undefined && typeof stream[i] === 'function') {
|
||||
this[i] = function (method) {
|
||||
return function () {
|
||||
return stream[method].apply(stream, arguments);
|
||||
};
|
||||
}(i);
|
||||
}
|
||||
}
|
||||
|
||||
// proxy certain important events.
|
||||
for (var n = 0; n < kProxyEvents.length; n++) {
|
||||
stream.on(kProxyEvents[n], this.emit.bind(this, kProxyEvents[n]));
|
||||
}
|
||||
|
||||
// when we try to consume some more bytes, simply unpause the
|
||||
// underlying stream.
|
||||
this._read = function (n) {
|
||||
debug('wrapped _read', n);
|
||||
if (paused) {
|
||||
paused = false;
|
||||
stream.resume();
|
||||
}
|
||||
};
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
Object.defineProperty(Readable.prototype, 'readableHighWaterMark', {
|
||||
// making it explicit this property is not enumerable
|
||||
// because otherwise some prototype manipulation in
|
||||
// userland will fail
|
||||
enumerable: false,
|
||||
get: function () {
|
||||
return this._readableState.highWaterMark;
|
||||
}
|
||||
});
|
||||
|
||||
// exposed for testing purposes only.
|
||||
Readable._fromList = fromList;
|
||||
|
||||
// Pluck off n bytes from an array of buffers.
|
||||
// Length is the combined lengths of all the buffers in the list.
|
||||
// This function is designed to be inlinable, so please take care when making
|
||||
// changes to the function body.
|
||||
function fromList(n, state) {
|
||||
// nothing buffered
|
||||
if (state.length === 0) return null;
|
||||
|
||||
var ret;
|
||||
if (state.objectMode) ret = state.buffer.shift();else if (!n || n >= state.length) {
|
||||
// read it all, truncate the list
|
||||
if (state.decoder) ret = state.buffer.join('');else if (state.buffer.length === 1) ret = state.buffer.head.data;else ret = state.buffer.concat(state.length);
|
||||
state.buffer.clear();
|
||||
} else {
|
||||
// read part of list
|
||||
ret = fromListPartial(n, state.buffer, state.decoder);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Extracts only enough buffered data to satisfy the amount requested.
|
||||
// This function is designed to be inlinable, so please take care when making
|
||||
// changes to the function body.
|
||||
function fromListPartial(n, list, hasStrings) {
|
||||
var ret;
|
||||
if (n < list.head.data.length) {
|
||||
// slice is the same for buffers and strings
|
||||
ret = list.head.data.slice(0, n);
|
||||
list.head.data = list.head.data.slice(n);
|
||||
} else if (n === list.head.data.length) {
|
||||
// first chunk is a perfect match
|
||||
ret = list.shift();
|
||||
} else {
|
||||
// result spans more than one buffer
|
||||
ret = hasStrings ? copyFromBufferString(n, list) : copyFromBuffer(n, list);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Copies a specified amount of characters from the list of buffered data
|
||||
// chunks.
|
||||
// This function is designed to be inlinable, so please take care when making
|
||||
// changes to the function body.
|
||||
function copyFromBufferString(n, list) {
|
||||
var p = list.head;
|
||||
var c = 1;
|
||||
var ret = p.data;
|
||||
n -= ret.length;
|
||||
while (p = p.next) {
|
||||
var str = p.data;
|
||||
var nb = n > str.length ? str.length : n;
|
||||
if (nb === str.length) ret += str;else ret += str.slice(0, n);
|
||||
n -= nb;
|
||||
if (n === 0) {
|
||||
if (nb === str.length) {
|
||||
++c;
|
||||
if (p.next) list.head = p.next;else list.head = list.tail = null;
|
||||
} else {
|
||||
list.head = p;
|
||||
p.data = str.slice(nb);
|
||||
}
|
||||
break;
|
||||
}
|
||||
++c;
|
||||
}
|
||||
list.length -= c;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Copies a specified amount of bytes from the list of buffered data chunks.
|
||||
// This function is designed to be inlinable, so please take care when making
|
||||
// changes to the function body.
|
||||
function copyFromBuffer(n, list) {
|
||||
var ret = Buffer.allocUnsafe(n);
|
||||
var p = list.head;
|
||||
var c = 1;
|
||||
p.data.copy(ret);
|
||||
n -= p.data.length;
|
||||
while (p = p.next) {
|
||||
var buf = p.data;
|
||||
var nb = n > buf.length ? buf.length : n;
|
||||
buf.copy(ret, ret.length - n, 0, nb);
|
||||
n -= nb;
|
||||
if (n === 0) {
|
||||
if (nb === buf.length) {
|
||||
++c;
|
||||
if (p.next) list.head = p.next;else list.head = list.tail = null;
|
||||
} else {
|
||||
list.head = p;
|
||||
p.data = buf.slice(nb);
|
||||
}
|
||||
break;
|
||||
}
|
||||
++c;
|
||||
}
|
||||
list.length -= c;
|
||||
return ret;
|
||||
}
|
||||
|
||||
function endReadable(stream) {
|
||||
var state = stream._readableState;
|
||||
|
||||
// If we get here before consuming all the bytes, then that is a
|
||||
// bug in node. Should never happen.
|
||||
if (state.length > 0) throw new Error('"endReadable()" called on non-empty stream');
|
||||
|
||||
if (!state.endEmitted) {
|
||||
state.ended = true;
|
||||
pna.nextTick(endReadableNT, state, stream);
|
||||
}
|
||||
}
|
||||
|
||||
function endReadableNT(state, stream) {
|
||||
// Check that we didn't get one last unshift.
|
||||
if (!state.endEmitted && state.length === 0) {
|
||||
state.endEmitted = true;
|
||||
stream.readable = false;
|
||||
stream.emit('end');
|
||||
}
|
||||
}
|
||||
|
||||
function indexOf(xs, x) {
|
||||
for (var i = 0, l = xs.length; i < l; i++) {
|
||||
if (xs[i] === x) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -1,214 +0,0 @@
|
|||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// 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.
|
||||
|
||||
// a transform stream is a readable/writable stream where you do
|
||||
// something with the data. Sometimes it's called a "filter",
|
||||
// but that's not a great name for it, since that implies a thing where
|
||||
// some bits pass through, and others are simply ignored. (That would
|
||||
// be a valid example of a transform, of course.)
|
||||
//
|
||||
// While the output is causally related to the input, it's not a
|
||||
// necessarily symmetric or synchronous transformation. For example,
|
||||
// a zlib stream might take multiple plain-text writes(), and then
|
||||
// emit a single compressed chunk some time in the future.
|
||||
//
|
||||
// Here's how this works:
|
||||
//
|
||||
// The Transform stream has all the aspects of the readable and writable
|
||||
// stream classes. When you write(chunk), that calls _write(chunk,cb)
|
||||
// internally, and returns false if there's a lot of pending writes
|
||||
// buffered up. When you call read(), that calls _read(n) until
|
||||
// there's enough pending readable data buffered up.
|
||||
//
|
||||
// In a transform stream, the written data is placed in a buffer. When
|
||||
// _read(n) is called, it transforms the queued up data, calling the
|
||||
// buffered _write cb's as it consumes chunks. If consuming a single
|
||||
// written chunk would result in multiple output chunks, then the first
|
||||
// outputted bit calls the readcb, and subsequent chunks just go into
|
||||
// the read buffer, and will cause it to emit 'readable' if necessary.
|
||||
//
|
||||
// This way, back-pressure is actually determined by the reading side,
|
||||
// since _read has to be called to start processing a new chunk. However,
|
||||
// a pathological inflate type of transform can cause excessive buffering
|
||||
// here. For example, imagine a stream where every byte of input is
|
||||
// interpreted as an integer from 0-255, and then results in that many
|
||||
// bytes of output. Writing the 4 bytes {ff,ff,ff,ff} would result in
|
||||
// 1kb of data being output. In this case, you could write a very small
|
||||
// amount of input, and end up with a very large amount of output. In
|
||||
// such a pathological inflating mechanism, there'd be no way to tell
|
||||
// the system to stop doing the transform. A single 4MB write could
|
||||
// cause the system to run out of memory.
|
||||
//
|
||||
// However, even in such a pathological case, only a single written chunk
|
||||
// would be consumed, and then the rest would wait (un-transformed) until
|
||||
// the results of the previous transformed chunk were consumed.
|
||||
|
||||
'use strict';
|
||||
|
||||
module.exports = Transform;
|
||||
|
||||
var Duplex = require('./_stream_duplex');
|
||||
|
||||
/*<replacement>*/
|
||||
var util = require('core-util-is');
|
||||
util.inherits = require('inherits');
|
||||
/*</replacement>*/
|
||||
|
||||
util.inherits(Transform, Duplex);
|
||||
|
||||
function afterTransform(er, data) {
|
||||
var ts = this._transformState;
|
||||
ts.transforming = false;
|
||||
|
||||
var cb = ts.writecb;
|
||||
|
||||
if (!cb) {
|
||||
return this.emit('error', new Error('write callback called multiple times'));
|
||||
}
|
||||
|
||||
ts.writechunk = null;
|
||||
ts.writecb = null;
|
||||
|
||||
if (data != null) // single equals check for both `null` and `undefined`
|
||||
this.push(data);
|
||||
|
||||
cb(er);
|
||||
|
||||
var rs = this._readableState;
|
||||
rs.reading = false;
|
||||
if (rs.needReadable || rs.length < rs.highWaterMark) {
|
||||
this._read(rs.highWaterMark);
|
||||
}
|
||||
}
|
||||
|
||||
function Transform(options) {
|
||||
if (!(this instanceof Transform)) return new Transform(options);
|
||||
|
||||
Duplex.call(this, options);
|
||||
|
||||
this._transformState = {
|
||||
afterTransform: afterTransform.bind(this),
|
||||
needTransform: false,
|
||||
transforming: false,
|
||||
writecb: null,
|
||||
writechunk: null,
|
||||
writeencoding: null
|
||||
};
|
||||
|
||||
// start out asking for a readable event once data is transformed.
|
||||
this._readableState.needReadable = true;
|
||||
|
||||
// we have implemented the _read method, and done the other things
|
||||
// that Readable wants before the first _read call, so unset the
|
||||
// sync guard flag.
|
||||
this._readableState.sync = false;
|
||||
|
||||
if (options) {
|
||||
if (typeof options.transform === 'function') this._transform = options.transform;
|
||||
|
||||
if (typeof options.flush === 'function') this._flush = options.flush;
|
||||
}
|
||||
|
||||
// When the writable side finishes, then flush out anything remaining.
|
||||
this.on('prefinish', prefinish);
|
||||
}
|
||||
|
||||
function prefinish() {
|
||||
var _this = this;
|
||||
|
||||
if (typeof this._flush === 'function') {
|
||||
this._flush(function (er, data) {
|
||||
done(_this, er, data);
|
||||
});
|
||||
} else {
|
||||
done(this, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
Transform.prototype.push = function (chunk, encoding) {
|
||||
this._transformState.needTransform = false;
|
||||
return Duplex.prototype.push.call(this, chunk, encoding);
|
||||
};
|
||||
|
||||
// This is the part where you do stuff!
|
||||
// override this function in implementation classes.
|
||||
// 'chunk' is an input chunk.
|
||||
//
|
||||
// Call `push(newChunk)` to pass along transformed output
|
||||
// to the readable side. You may call 'push' zero or more times.
|
||||
//
|
||||
// Call `cb(err)` when you are done with this chunk. If you pass
|
||||
// an error, then that'll put the hurt on the whole operation. If you
|
||||
// never call cb(), then you'll never get another chunk.
|
||||
Transform.prototype._transform = function (chunk, encoding, cb) {
|
||||
throw new Error('_transform() is not implemented');
|
||||
};
|
||||
|
||||
Transform.prototype._write = function (chunk, encoding, cb) {
|
||||
var ts = this._transformState;
|
||||
ts.writecb = cb;
|
||||
ts.writechunk = chunk;
|
||||
ts.writeencoding = encoding;
|
||||
if (!ts.transforming) {
|
||||
var rs = this._readableState;
|
||||
if (ts.needTransform || rs.needReadable || rs.length < rs.highWaterMark) this._read(rs.highWaterMark);
|
||||
}
|
||||
};
|
||||
|
||||
// Doesn't matter what the args are here.
|
||||
// _transform does all the work.
|
||||
// That we got here means that the readable side wants more data.
|
||||
Transform.prototype._read = function (n) {
|
||||
var ts = this._transformState;
|
||||
|
||||
if (ts.writechunk !== null && ts.writecb && !ts.transforming) {
|
||||
ts.transforming = true;
|
||||
this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform);
|
||||
} else {
|
||||
// mark that we need a transform, so that any data that comes in
|
||||
// will get processed, now that we've asked for it.
|
||||
ts.needTransform = true;
|
||||
}
|
||||
};
|
||||
|
||||
Transform.prototype._destroy = function (err, cb) {
|
||||
var _this2 = this;
|
||||
|
||||
Duplex.prototype._destroy.call(this, err, function (err2) {
|
||||
cb(err2);
|
||||
_this2.emit('close');
|
||||
});
|
||||
};
|
||||
|
||||
function done(stream, er, data) {
|
||||
if (er) return stream.emit('error', er);
|
||||
|
||||
if (data != null) // single equals check for both `null` and `undefined`
|
||||
stream.push(data);
|
||||
|
||||
// if there's nothing in the write buffer, then that means
|
||||
// that nothing more will ever be provided
|
||||
if (stream._writableState.length) throw new Error('Calling transform done when ws.length != 0');
|
||||
|
||||
if (stream._transformState.transforming) throw new Error('Calling transform done when still transforming');
|
||||
|
||||
return stream.push(null);
|
||||
}
|
||||
|
|
@ -1,687 +0,0 @@
|
|||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// 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.
|
||||
|
||||
// A bit simpler than readable streams.
|
||||
// Implement an async ._write(chunk, encoding, cb), and it'll handle all
|
||||
// the drain event emission and buffering.
|
||||
|
||||
'use strict';
|
||||
|
||||
/*<replacement>*/
|
||||
|
||||
var pna = require('process-nextick-args');
|
||||
/*</replacement>*/
|
||||
|
||||
module.exports = Writable;
|
||||
|
||||
/* <replacement> */
|
||||
function WriteReq(chunk, encoding, cb) {
|
||||
this.chunk = chunk;
|
||||
this.encoding = encoding;
|
||||
this.callback = cb;
|
||||
this.next = null;
|
||||
}
|
||||
|
||||
// It seems a linked list but it is not
|
||||
// there will be only 2 of these for each stream
|
||||
function CorkedRequest(state) {
|
||||
var _this = this;
|
||||
|
||||
this.next = null;
|
||||
this.entry = null;
|
||||
this.finish = function () {
|
||||
onCorkedFinish(_this, state);
|
||||
};
|
||||
}
|
||||
/* </replacement> */
|
||||
|
||||
/*<replacement>*/
|
||||
var asyncWrite = !process.browser && ['v0.10', 'v0.9.'].indexOf(process.version.slice(0, 5)) > -1 ? setImmediate : pna.nextTick;
|
||||
/*</replacement>*/
|
||||
|
||||
/*<replacement>*/
|
||||
var Duplex;
|
||||
/*</replacement>*/
|
||||
|
||||
Writable.WritableState = WritableState;
|
||||
|
||||
/*<replacement>*/
|
||||
var util = require('core-util-is');
|
||||
util.inherits = require('inherits');
|
||||
/*</replacement>*/
|
||||
|
||||
/*<replacement>*/
|
||||
var internalUtil = {
|
||||
deprecate: require('util-deprecate')
|
||||
};
|
||||
/*</replacement>*/
|
||||
|
||||
/*<replacement>*/
|
||||
var Stream = require('./internal/streams/stream');
|
||||
/*</replacement>*/
|
||||
|
||||
/*<replacement>*/
|
||||
|
||||
var Buffer = require('safe-buffer').Buffer;
|
||||
var OurUint8Array = global.Uint8Array || function () {};
|
||||
function _uint8ArrayToBuffer(chunk) {
|
||||
return Buffer.from(chunk);
|
||||
}
|
||||
function _isUint8Array(obj) {
|
||||
return Buffer.isBuffer(obj) || obj instanceof OurUint8Array;
|
||||
}
|
||||
|
||||
/*</replacement>*/
|
||||
|
||||
var destroyImpl = require('./internal/streams/destroy');
|
||||
|
||||
util.inherits(Writable, Stream);
|
||||
|
||||
function nop() {}
|
||||
|
||||
function WritableState(options, stream) {
|
||||
Duplex = Duplex || require('./_stream_duplex');
|
||||
|
||||
options = options || {};
|
||||
|
||||
// Duplex streams are both readable and writable, but share
|
||||
// the same options object.
|
||||
// However, some cases require setting options to different
|
||||
// values for the readable and the writable sides of the duplex stream.
|
||||
// These options can be provided separately as readableXXX and writableXXX.
|
||||
var isDuplex = stream instanceof Duplex;
|
||||
|
||||
// object stream flag to indicate whether or not this stream
|
||||
// contains buffers or objects.
|
||||
this.objectMode = !!options.objectMode;
|
||||
|
||||
if (isDuplex) this.objectMode = this.objectMode || !!options.writableObjectMode;
|
||||
|
||||
// the point at which write() starts returning false
|
||||
// Note: 0 is a valid value, means that we always return false if
|
||||
// the entire buffer is not flushed immediately on write()
|
||||
var hwm = options.highWaterMark;
|
||||
var writableHwm = options.writableHighWaterMark;
|
||||
var defaultHwm = this.objectMode ? 16 : 16 * 1024;
|
||||
|
||||
if (hwm || hwm === 0) this.highWaterMark = hwm;else if (isDuplex && (writableHwm || writableHwm === 0)) this.highWaterMark = writableHwm;else this.highWaterMark = defaultHwm;
|
||||
|
||||
// cast to ints.
|
||||
this.highWaterMark = Math.floor(this.highWaterMark);
|
||||
|
||||
// if _final has been called
|
||||
this.finalCalled = false;
|
||||
|
||||
// drain event flag.
|
||||
this.needDrain = false;
|
||||
// at the start of calling end()
|
||||
this.ending = false;
|
||||
// when end() has been called, and returned
|
||||
this.ended = false;
|
||||
// when 'finish' is emitted
|
||||
this.finished = false;
|
||||
|
||||
// has it been destroyed
|
||||
this.destroyed = false;
|
||||
|
||||
// should we decode strings into buffers before passing to _write?
|
||||
// this is here so that some node-core streams can optimize string
|
||||
// handling at a lower level.
|
||||
var noDecode = options.decodeStrings === false;
|
||||
this.decodeStrings = !noDecode;
|
||||
|
||||
// Crypto is kind of old and crusty. Historically, its default string
|
||||
// encoding is 'binary' so we have to make this configurable.
|
||||
// Everything else in the universe uses 'utf8', though.
|
||||
this.defaultEncoding = options.defaultEncoding || 'utf8';
|
||||
|
||||
// not an actual buffer we keep track of, but a measurement
|
||||
// of how much we're waiting to get pushed to some underlying
|
||||
// socket or file.
|
||||
this.length = 0;
|
||||
|
||||
// a flag to see when we're in the middle of a write.
|
||||
this.writing = false;
|
||||
|
||||
// when true all writes will be buffered until .uncork() call
|
||||
this.corked = 0;
|
||||
|
||||
// a flag to be able to tell if the onwrite cb is called immediately,
|
||||
// or on a later tick. We set this to true at first, because any
|
||||
// actions that shouldn't happen until "later" should generally also
|
||||
// not happen before the first write call.
|
||||
this.sync = true;
|
||||
|
||||
// a flag to know if we're processing previously buffered items, which
|
||||
// may call the _write() callback in the same tick, so that we don't
|
||||
// end up in an overlapped onwrite situation.
|
||||
this.bufferProcessing = false;
|
||||
|
||||
// the callback that's passed to _write(chunk,cb)
|
||||
this.onwrite = function (er) {
|
||||
onwrite(stream, er);
|
||||
};
|
||||
|
||||
// the callback that the user supplies to write(chunk,encoding,cb)
|
||||
this.writecb = null;
|
||||
|
||||
// the amount that is being written when _write is called.
|
||||
this.writelen = 0;
|
||||
|
||||
this.bufferedRequest = null;
|
||||
this.lastBufferedRequest = null;
|
||||
|
||||
// number of pending user-supplied write callbacks
|
||||
// this must be 0 before 'finish' can be emitted
|
||||
this.pendingcb = 0;
|
||||
|
||||
// emit prefinish if the only thing we're waiting for is _write cbs
|
||||
// This is relevant for synchronous Transform streams
|
||||
this.prefinished = false;
|
||||
|
||||
// True if the error was already emitted and should not be thrown again
|
||||
this.errorEmitted = false;
|
||||
|
||||
// count buffered requests
|
||||
this.bufferedRequestCount = 0;
|
||||
|
||||
// allocate the first CorkedRequest, there is always
|
||||
// one allocated and free to use, and we maintain at most two
|
||||
this.corkedRequestsFree = new CorkedRequest(this);
|
||||
}
|
||||
|
||||
WritableState.prototype.getBuffer = function getBuffer() {
|
||||
var current = this.bufferedRequest;
|
||||
var out = [];
|
||||
while (current) {
|
||||
out.push(current);
|
||||
current = current.next;
|
||||
}
|
||||
return out;
|
||||
};
|
||||
|
||||
(function () {
|
||||
try {
|
||||
Object.defineProperty(WritableState.prototype, 'buffer', {
|
||||
get: internalUtil.deprecate(function () {
|
||||
return this.getBuffer();
|
||||
}, '_writableState.buffer is deprecated. Use _writableState.getBuffer ' + 'instead.', 'DEP0003')
|
||||
});
|
||||
} catch (_) {}
|
||||
})();
|
||||
|
||||
// Test _writableState for inheritance to account for Duplex streams,
|
||||
// whose prototype chain only points to Readable.
|
||||
var realHasInstance;
|
||||
if (typeof Symbol === 'function' && Symbol.hasInstance && typeof Function.prototype[Symbol.hasInstance] === 'function') {
|
||||
realHasInstance = Function.prototype[Symbol.hasInstance];
|
||||
Object.defineProperty(Writable, Symbol.hasInstance, {
|
||||
value: function (object) {
|
||||
if (realHasInstance.call(this, object)) return true;
|
||||
if (this !== Writable) return false;
|
||||
|
||||
return object && object._writableState instanceof WritableState;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
realHasInstance = function (object) {
|
||||
return object instanceof this;
|
||||
};
|
||||
}
|
||||
|
||||
function Writable(options) {
|
||||
Duplex = Duplex || require('./_stream_duplex');
|
||||
|
||||
// Writable ctor is applied to Duplexes, too.
|
||||
// `realHasInstance` is necessary because using plain `instanceof`
|
||||
// would return false, as no `_writableState` property is attached.
|
||||
|
||||
// Trying to use the custom `instanceof` for Writable here will also break the
|
||||
// Node.js LazyTransform implementation, which has a non-trivial getter for
|
||||
// `_writableState` that would lead to infinite recursion.
|
||||
if (!realHasInstance.call(Writable, this) && !(this instanceof Duplex)) {
|
||||
return new Writable(options);
|
||||
}
|
||||
|
||||
this._writableState = new WritableState(options, this);
|
||||
|
||||
// legacy.
|
||||
this.writable = true;
|
||||
|
||||
if (options) {
|
||||
if (typeof options.write === 'function') this._write = options.write;
|
||||
|
||||
if (typeof options.writev === 'function') this._writev = options.writev;
|
||||
|
||||
if (typeof options.destroy === 'function') this._destroy = options.destroy;
|
||||
|
||||
if (typeof options.final === 'function') this._final = options.final;
|
||||
}
|
||||
|
||||
Stream.call(this);
|
||||
}
|
||||
|
||||
// Otherwise people can pipe Writable streams, which is just wrong.
|
||||
Writable.prototype.pipe = function () {
|
||||
this.emit('error', new Error('Cannot pipe, not readable'));
|
||||
};
|
||||
|
||||
function writeAfterEnd(stream, cb) {
|
||||
var er = new Error('write after end');
|
||||
// TODO: defer error events consistently everywhere, not just the cb
|
||||
stream.emit('error', er);
|
||||
pna.nextTick(cb, er);
|
||||
}
|
||||
|
||||
// Checks that a user-supplied chunk is valid, especially for the particular
|
||||
// mode the stream is in. Currently this means that `null` is never accepted
|
||||
// and undefined/non-string values are only allowed in object mode.
|
||||
function validChunk(stream, state, chunk, cb) {
|
||||
var valid = true;
|
||||
var er = false;
|
||||
|
||||
if (chunk === null) {
|
||||
er = new TypeError('May not write null values to stream');
|
||||
} else if (typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) {
|
||||
er = new TypeError('Invalid non-string/buffer chunk');
|
||||
}
|
||||
if (er) {
|
||||
stream.emit('error', er);
|
||||
pna.nextTick(cb, er);
|
||||
valid = false;
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
Writable.prototype.write = function (chunk, encoding, cb) {
|
||||
var state = this._writableState;
|
||||
var ret = false;
|
||||
var isBuf = !state.objectMode && _isUint8Array(chunk);
|
||||
|
||||
if (isBuf && !Buffer.isBuffer(chunk)) {
|
||||
chunk = _uint8ArrayToBuffer(chunk);
|
||||
}
|
||||
|
||||
if (typeof encoding === 'function') {
|
||||
cb = encoding;
|
||||
encoding = null;
|
||||
}
|
||||
|
||||
if (isBuf) encoding = 'buffer';else if (!encoding) encoding = state.defaultEncoding;
|
||||
|
||||
if (typeof cb !== 'function') cb = nop;
|
||||
|
||||
if (state.ended) writeAfterEnd(this, cb);else if (isBuf || validChunk(this, state, chunk, cb)) {
|
||||
state.pendingcb++;
|
||||
ret = writeOrBuffer(this, state, isBuf, chunk, encoding, cb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
Writable.prototype.cork = function () {
|
||||
var state = this._writableState;
|
||||
|
||||
state.corked++;
|
||||
};
|
||||
|
||||
Writable.prototype.uncork = function () {
|
||||
var state = this._writableState;
|
||||
|
||||
if (state.corked) {
|
||||
state.corked--;
|
||||
|
||||
if (!state.writing && !state.corked && !state.finished && !state.bufferProcessing && state.bufferedRequest) clearBuffer(this, state);
|
||||
}
|
||||
};
|
||||
|
||||
Writable.prototype.setDefaultEncoding = function setDefaultEncoding(encoding) {
|
||||
// node::ParseEncoding() requires lower case.
|
||||
if (typeof encoding === 'string') encoding = encoding.toLowerCase();
|
||||
if (!(['hex', 'utf8', 'utf-8', 'ascii', 'binary', 'base64', 'ucs2', 'ucs-2', 'utf16le', 'utf-16le', 'raw'].indexOf((encoding + '').toLowerCase()) > -1)) throw new TypeError('Unknown encoding: ' + encoding);
|
||||
this._writableState.defaultEncoding = encoding;
|
||||
return this;
|
||||
};
|
||||
|
||||
function decodeChunk(state, chunk, encoding) {
|
||||
if (!state.objectMode && state.decodeStrings !== false && typeof chunk === 'string') {
|
||||
chunk = Buffer.from(chunk, encoding);
|
||||
}
|
||||
return chunk;
|
||||
}
|
||||
|
||||
Object.defineProperty(Writable.prototype, 'writableHighWaterMark', {
|
||||
// making it explicit this property is not enumerable
|
||||
// because otherwise some prototype manipulation in
|
||||
// userland will fail
|
||||
enumerable: false,
|
||||
get: function () {
|
||||
return this._writableState.highWaterMark;
|
||||
}
|
||||
});
|
||||
|
||||
// if we're already writing something, then just put this
|
||||
// in the queue, and wait our turn. Otherwise, call _write
|
||||
// If we return false, then we need a drain event, so set that flag.
|
||||
function writeOrBuffer(stream, state, isBuf, chunk, encoding, cb) {
|
||||
if (!isBuf) {
|
||||
var newChunk = decodeChunk(state, chunk, encoding);
|
||||
if (chunk !== newChunk) {
|
||||
isBuf = true;
|
||||
encoding = 'buffer';
|
||||
chunk = newChunk;
|
||||
}
|
||||
}
|
||||
var len = state.objectMode ? 1 : chunk.length;
|
||||
|
||||
state.length += len;
|
||||
|
||||
var ret = state.length < state.highWaterMark;
|
||||
// we must ensure that previous needDrain will not be reset to false.
|
||||
if (!ret) state.needDrain = true;
|
||||
|
||||
if (state.writing || state.corked) {
|
||||
var last = state.lastBufferedRequest;
|
||||
state.lastBufferedRequest = {
|
||||
chunk: chunk,
|
||||
encoding: encoding,
|
||||
isBuf: isBuf,
|
||||
callback: cb,
|
||||
next: null
|
||||
};
|
||||
if (last) {
|
||||
last.next = state.lastBufferedRequest;
|
||||
} else {
|
||||
state.bufferedRequest = state.lastBufferedRequest;
|
||||
}
|
||||
state.bufferedRequestCount += 1;
|
||||
} else {
|
||||
doWrite(stream, state, false, len, chunk, encoding, cb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
function doWrite(stream, state, writev, len, chunk, encoding, cb) {
|
||||
state.writelen = len;
|
||||
state.writecb = cb;
|
||||
state.writing = true;
|
||||
state.sync = true;
|
||||
if (writev) stream._writev(chunk, state.onwrite);else stream._write(chunk, encoding, state.onwrite);
|
||||
state.sync = false;
|
||||
}
|
||||
|
||||
function onwriteError(stream, state, sync, er, cb) {
|
||||
--state.pendingcb;
|
||||
|
||||
if (sync) {
|
||||
// defer the callback if we are being called synchronously
|
||||
// to avoid piling up things on the stack
|
||||
pna.nextTick(cb, er);
|
||||
// this can emit finish, and it will always happen
|
||||
// after error
|
||||
pna.nextTick(finishMaybe, stream, state);
|
||||
stream._writableState.errorEmitted = true;
|
||||
stream.emit('error', er);
|
||||
} else {
|
||||
// the caller expect this to happen before if
|
||||
// it is async
|
||||
cb(er);
|
||||
stream._writableState.errorEmitted = true;
|
||||
stream.emit('error', er);
|
||||
// this can emit finish, but finish must
|
||||
// always follow error
|
||||
finishMaybe(stream, state);
|
||||
}
|
||||
}
|
||||
|
||||
function onwriteStateUpdate(state) {
|
||||
state.writing = false;
|
||||
state.writecb = null;
|
||||
state.length -= state.writelen;
|
||||
state.writelen = 0;
|
||||
}
|
||||
|
||||
function onwrite(stream, er) {
|
||||
var state = stream._writableState;
|
||||
var sync = state.sync;
|
||||
var cb = state.writecb;
|
||||
|
||||
onwriteStateUpdate(state);
|
||||
|
||||
if (er) onwriteError(stream, state, sync, er, cb);else {
|
||||
// Check if we're actually ready to finish, but don't emit yet
|
||||
var finished = needFinish(state);
|
||||
|
||||
if (!finished && !state.corked && !state.bufferProcessing && state.bufferedRequest) {
|
||||
clearBuffer(stream, state);
|
||||
}
|
||||
|
||||
if (sync) {
|
||||
/*<replacement>*/
|
||||
asyncWrite(afterWrite, stream, state, finished, cb);
|
||||
/*</replacement>*/
|
||||
} else {
|
||||
afterWrite(stream, state, finished, cb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function afterWrite(stream, state, finished, cb) {
|
||||
if (!finished) onwriteDrain(stream, state);
|
||||
state.pendingcb--;
|
||||
cb();
|
||||
finishMaybe(stream, state);
|
||||
}
|
||||
|
||||
// Must force callback to be called on nextTick, so that we don't
|
||||
// emit 'drain' before the write() consumer gets the 'false' return
|
||||
// value, and has a chance to attach a 'drain' listener.
|
||||
function onwriteDrain(stream, state) {
|
||||
if (state.length === 0 && state.needDrain) {
|
||||
state.needDrain = false;
|
||||
stream.emit('drain');
|
||||
}
|
||||
}
|
||||
|
||||
// if there's something in the buffer waiting, then process it
|
||||
function clearBuffer(stream, state) {
|
||||
state.bufferProcessing = true;
|
||||
var entry = state.bufferedRequest;
|
||||
|
||||
if (stream._writev && entry && entry.next) {
|
||||
// Fast case, write everything using _writev()
|
||||
var l = state.bufferedRequestCount;
|
||||
var buffer = new Array(l);
|
||||
var holder = state.corkedRequestsFree;
|
||||
holder.entry = entry;
|
||||
|
||||
var count = 0;
|
||||
var allBuffers = true;
|
||||
while (entry) {
|
||||
buffer[count] = entry;
|
||||
if (!entry.isBuf) allBuffers = false;
|
||||
entry = entry.next;
|
||||
count += 1;
|
||||
}
|
||||
buffer.allBuffers = allBuffers;
|
||||
|
||||
doWrite(stream, state, true, state.length, buffer, '', holder.finish);
|
||||
|
||||
// doWrite is almost always async, defer these to save a bit of time
|
||||
// as the hot path ends with doWrite
|
||||
state.pendingcb++;
|
||||
state.lastBufferedRequest = null;
|
||||
if (holder.next) {
|
||||
state.corkedRequestsFree = holder.next;
|
||||
holder.next = null;
|
||||
} else {
|
||||
state.corkedRequestsFree = new CorkedRequest(state);
|
||||
}
|
||||
state.bufferedRequestCount = 0;
|
||||
} else {
|
||||
// Slow case, write chunks one-by-one
|
||||
while (entry) {
|
||||
var chunk = entry.chunk;
|
||||
var encoding = entry.encoding;
|
||||
var cb = entry.callback;
|
||||
var len = state.objectMode ? 1 : chunk.length;
|
||||
|
||||
doWrite(stream, state, false, len, chunk, encoding, cb);
|
||||
entry = entry.next;
|
||||
state.bufferedRequestCount--;
|
||||
// if we didn't call the onwrite immediately, then
|
||||
// it means that we need to wait until it does.
|
||||
// also, that means that the chunk and cb are currently
|
||||
// being processed, so move the buffer counter past them.
|
||||
if (state.writing) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (entry === null) state.lastBufferedRequest = null;
|
||||
}
|
||||
|
||||
state.bufferedRequest = entry;
|
||||
state.bufferProcessing = false;
|
||||
}
|
||||
|
||||
Writable.prototype._write = function (chunk, encoding, cb) {
|
||||
cb(new Error('_write() is not implemented'));
|
||||
};
|
||||
|
||||
Writable.prototype._writev = null;
|
||||
|
||||
Writable.prototype.end = function (chunk, encoding, cb) {
|
||||
var state = this._writableState;
|
||||
|
||||
if (typeof chunk === 'function') {
|
||||
cb = chunk;
|
||||
chunk = null;
|
||||
encoding = null;
|
||||
} else if (typeof encoding === 'function') {
|
||||
cb = encoding;
|
||||
encoding = null;
|
||||
}
|
||||
|
||||
if (chunk !== null && chunk !== undefined) this.write(chunk, encoding);
|
||||
|
||||
// .end() fully uncorks
|
||||
if (state.corked) {
|
||||
state.corked = 1;
|
||||
this.uncork();
|
||||
}
|
||||
|
||||
// ignore unnecessary end() calls.
|
||||
if (!state.ending && !state.finished) endWritable(this, state, cb);
|
||||
};
|
||||
|
||||
function needFinish(state) {
|
||||
return state.ending && state.length === 0 && state.bufferedRequest === null && !state.finished && !state.writing;
|
||||
}
|
||||
function callFinal(stream, state) {
|
||||
stream._final(function (err) {
|
||||
state.pendingcb--;
|
||||
if (err) {
|
||||
stream.emit('error', err);
|
||||
}
|
||||
state.prefinished = true;
|
||||
stream.emit('prefinish');
|
||||
finishMaybe(stream, state);
|
||||
});
|
||||
}
|
||||
function prefinish(stream, state) {
|
||||
if (!state.prefinished && !state.finalCalled) {
|
||||
if (typeof stream._final === 'function') {
|
||||
state.pendingcb++;
|
||||
state.finalCalled = true;
|
||||
pna.nextTick(callFinal, stream, state);
|
||||
} else {
|
||||
state.prefinished = true;
|
||||
stream.emit('prefinish');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function finishMaybe(stream, state) {
|
||||
var need = needFinish(state);
|
||||
if (need) {
|
||||
prefinish(stream, state);
|
||||
if (state.pendingcb === 0) {
|
||||
state.finished = true;
|
||||
stream.emit('finish');
|
||||
}
|
||||
}
|
||||
return need;
|
||||
}
|
||||
|
||||
function endWritable(stream, state, cb) {
|
||||
state.ending = true;
|
||||
finishMaybe(stream, state);
|
||||
if (cb) {
|
||||
if (state.finished) pna.nextTick(cb);else stream.once('finish', cb);
|
||||
}
|
||||
state.ended = true;
|
||||
stream.writable = false;
|
||||
}
|
||||
|
||||
function onCorkedFinish(corkReq, state, err) {
|
||||
var entry = corkReq.entry;
|
||||
corkReq.entry = null;
|
||||
while (entry) {
|
||||
var cb = entry.callback;
|
||||
state.pendingcb--;
|
||||
cb(err);
|
||||
entry = entry.next;
|
||||
}
|
||||
if (state.corkedRequestsFree) {
|
||||
state.corkedRequestsFree.next = corkReq;
|
||||
} else {
|
||||
state.corkedRequestsFree = corkReq;
|
||||
}
|
||||
}
|
||||
|
||||
Object.defineProperty(Writable.prototype, 'destroyed', {
|
||||
get: function () {
|
||||
if (this._writableState === undefined) {
|
||||
return false;
|
||||
}
|
||||
return this._writableState.destroyed;
|
||||
},
|
||||
set: function (value) {
|
||||
// we ignore the value if the stream
|
||||
// has not been initialized yet
|
||||
if (!this._writableState) {
|
||||
return;
|
||||
}
|
||||
|
||||
// backward compatibility, the user is explicitly
|
||||
// managing destroyed
|
||||
this._writableState.destroyed = value;
|
||||
}
|
||||
});
|
||||
|
||||
Writable.prototype.destroy = destroyImpl.destroy;
|
||||
Writable.prototype._undestroy = destroyImpl.undestroy;
|
||||
Writable.prototype._destroy = function (err, cb) {
|
||||
this.end();
|
||||
cb(err);
|
||||
};
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||||
|
||||
var Buffer = require('safe-buffer').Buffer;
|
||||
var util = require('util');
|
||||
|
||||
function copyBuffer(src, target, offset) {
|
||||
src.copy(target, offset);
|
||||
}
|
||||
|
||||
module.exports = function () {
|
||||
function BufferList() {
|
||||
_classCallCheck(this, BufferList);
|
||||
|
||||
this.head = null;
|
||||
this.tail = null;
|
||||
this.length = 0;
|
||||
}
|
||||
|
||||
BufferList.prototype.push = function push(v) {
|
||||
var entry = { data: v, next: null };
|
||||
if (this.length > 0) this.tail.next = entry;else this.head = entry;
|
||||
this.tail = entry;
|
||||
++this.length;
|
||||
};
|
||||
|
||||
BufferList.prototype.unshift = function unshift(v) {
|
||||
var entry = { data: v, next: this.head };
|
||||
if (this.length === 0) this.tail = entry;
|
||||
this.head = entry;
|
||||
++this.length;
|
||||
};
|
||||
|
||||
BufferList.prototype.shift = function shift() {
|
||||
if (this.length === 0) return;
|
||||
var ret = this.head.data;
|
||||
if (this.length === 1) this.head = this.tail = null;else this.head = this.head.next;
|
||||
--this.length;
|
||||
return ret;
|
||||
};
|
||||
|
||||
BufferList.prototype.clear = function clear() {
|
||||
this.head = this.tail = null;
|
||||
this.length = 0;
|
||||
};
|
||||
|
||||
BufferList.prototype.join = function join(s) {
|
||||
if (this.length === 0) return '';
|
||||
var p = this.head;
|
||||
var ret = '' + p.data;
|
||||
while (p = p.next) {
|
||||
ret += s + p.data;
|
||||
}return ret;
|
||||
};
|
||||
|
||||
BufferList.prototype.concat = function concat(n) {
|
||||
if (this.length === 0) return Buffer.alloc(0);
|
||||
if (this.length === 1) return this.head.data;
|
||||
var ret = Buffer.allocUnsafe(n >>> 0);
|
||||
var p = this.head;
|
||||
var i = 0;
|
||||
while (p) {
|
||||
copyBuffer(p.data, ret, i);
|
||||
i += p.data.length;
|
||||
p = p.next;
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
return BufferList;
|
||||
}();
|
||||
|
||||
if (util && util.inspect && util.inspect.custom) {
|
||||
module.exports.prototype[util.inspect.custom] = function () {
|
||||
var obj = util.inspect({ length: this.length });
|
||||
return this.constructor.name + ' ' + obj;
|
||||
};
|
||||
}
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
/*<replacement>*/
|
||||
|
||||
var pna = require('process-nextick-args');
|
||||
/*</replacement>*/
|
||||
|
||||
// undocumented cb() API, needed for core, not for public API
|
||||
function destroy(err, cb) {
|
||||
var _this = this;
|
||||
|
||||
var readableDestroyed = this._readableState && this._readableState.destroyed;
|
||||
var writableDestroyed = this._writableState && this._writableState.destroyed;
|
||||
|
||||
if (readableDestroyed || writableDestroyed) {
|
||||
if (cb) {
|
||||
cb(err);
|
||||
} else if (err && (!this._writableState || !this._writableState.errorEmitted)) {
|
||||
pna.nextTick(emitErrorNT, this, err);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
// we set destroyed to true before firing error callbacks in order
|
||||
// to make it re-entrance safe in case destroy() is called within callbacks
|
||||
|
||||
if (this._readableState) {
|
||||
this._readableState.destroyed = true;
|
||||
}
|
||||
|
||||
// if this is a duplex stream mark the writable part as destroyed as well
|
||||
if (this._writableState) {
|
||||
this._writableState.destroyed = true;
|
||||
}
|
||||
|
||||
this._destroy(err || null, function (err) {
|
||||
if (!cb && err) {
|
||||
pna.nextTick(emitErrorNT, _this, err);
|
||||
if (_this._writableState) {
|
||||
_this._writableState.errorEmitted = true;
|
||||
}
|
||||
} else if (cb) {
|
||||
cb(err);
|
||||
}
|
||||
});
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
function undestroy() {
|
||||
if (this._readableState) {
|
||||
this._readableState.destroyed = false;
|
||||
this._readableState.reading = false;
|
||||
this._readableState.ended = false;
|
||||
this._readableState.endEmitted = false;
|
||||
}
|
||||
|
||||
if (this._writableState) {
|
||||
this._writableState.destroyed = false;
|
||||
this._writableState.ended = false;
|
||||
this._writableState.ending = false;
|
||||
this._writableState.finished = false;
|
||||
this._writableState.errorEmitted = false;
|
||||
}
|
||||
}
|
||||
|
||||
function emitErrorNT(self, err) {
|
||||
self.emit('error', err);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
destroy: destroy,
|
||||
undestroy: undestroy
|
||||
};
|
||||
|
|
@ -1 +0,0 @@
|
|||
module.exports = require('events').EventEmitter;
|
||||
|
|
@ -1 +0,0 @@
|
|||
module.exports = require('stream');
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
{
|
||||
"name": "readable-stream",
|
||||
"version": "2.3.6",
|
||||
"description": "Streams3, a user-land copy of the stream library from Node.js",
|
||||
"main": "readable.js",
|
||||
"dependencies": {
|
||||
"core-util-is": "~1.0.0",
|
||||
"inherits": "~2.0.3",
|
||||
"isarray": "~1.0.0",
|
||||
"process-nextick-args": "~2.0.0",
|
||||
"safe-buffer": "~5.1.1",
|
||||
"string_decoder": "~1.1.1",
|
||||
"util-deprecate": "~1.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"assert": "^1.4.0",
|
||||
"babel-polyfill": "^6.9.1",
|
||||
"buffer": "^4.9.0",
|
||||
"lolex": "^2.3.2",
|
||||
"nyc": "^6.4.0",
|
||||
"tap": "^0.7.0",
|
||||
"tape": "^4.8.0"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "tap test/parallel/*.js test/ours/*.js && node test/verify-dependencies.js",
|
||||
"ci": "tap test/parallel/*.js test/ours/*.js --tap | tee test.tap && node test/verify-dependencies.js",
|
||||
"cover": "nyc npm test",
|
||||
"report": "nyc report --reporter=lcov"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/nodejs/readable-stream"
|
||||
},
|
||||
"keywords": [
|
||||
"readable",
|
||||
"stream",
|
||||
"pipe"
|
||||
],
|
||||
"browser": {
|
||||
"util": false,
|
||||
"./readable.js": "./readable-browser.js",
|
||||
"./writable.js": "./writable-browser.js",
|
||||
"./duplex.js": "./duplex-browser.js",
|
||||
"./lib/internal/streams/stream.js": "./lib/internal/streams/stream-browser.js"
|
||||
},
|
||||
"nyc": {
|
||||
"include": [
|
||||
"lib/**.js"
|
||||
]
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
module.exports = require('./readable').PassThrough
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
exports = module.exports = require('./lib/_stream_readable.js');
|
||||
exports.Stream = exports;
|
||||
exports.Readable = exports;
|
||||
exports.Writable = require('./lib/_stream_writable.js');
|
||||
exports.Duplex = require('./lib/_stream_duplex.js');
|
||||
exports.Transform = require('./lib/_stream_transform.js');
|
||||
exports.PassThrough = require('./lib/_stream_passthrough.js');
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
var Stream = require('stream');
|
||||
if (process.env.READABLE_STREAM === 'disable' && Stream) {
|
||||
module.exports = Stream;
|
||||
exports = module.exports = Stream.Readable;
|
||||
exports.Readable = Stream.Readable;
|
||||
exports.Writable = Stream.Writable;
|
||||
exports.Duplex = Stream.Duplex;
|
||||
exports.Transform = Stream.Transform;
|
||||
exports.PassThrough = Stream.PassThrough;
|
||||
exports.Stream = Stream;
|
||||
} else {
|
||||
exports = module.exports = require('./lib/_stream_readable.js');
|
||||
exports.Stream = Stream || exports;
|
||||
exports.Readable = exports;
|
||||
exports.Writable = require('./lib/_stream_writable.js');
|
||||
exports.Duplex = require('./lib/_stream_duplex.js');
|
||||
exports.Transform = require('./lib/_stream_transform.js');
|
||||
exports.PassThrough = require('./lib/_stream_passthrough.js');
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
module.exports = require('./readable').Transform
|
||||
|
|
@ -1 +0,0 @@
|
|||
module.exports = require('./lib/_stream_writable.js');
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
var Stream = require("stream")
|
||||
var Writable = require("./lib/_stream_writable.js")
|
||||
|
||||
if (process.env.READABLE_STREAM === 'disable') {
|
||||
module.exports = Stream && Stream.Writable || Writable
|
||||
} else {
|
||||
module.exports = Writable
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
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.
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
# responselike
|
||||
|
||||
> A response-like object for mocking a Node.js HTTP response stream
|
||||
|
||||
[](https://travis-ci.org/lukechilds/responselike)
|
||||
[](https://coveralls.io/github/lukechilds/responselike?branch=master)
|
||||
[](https://www.npmjs.com/package/responselike)
|
||||
[](https://www.npmjs.com/package/responselike)
|
||||
|
||||
Returns a streamable response object similar to a [Node.js HTTP response stream](https://nodejs.org/api/http.html#http_class_http_incomingmessage). Useful for formatting cached responses so they can be consumed by code expecting a real response.
|
||||
|
||||
## Install
|
||||
|
||||
```shell
|
||||
npm install --save responselike
|
||||
```
|
||||
|
||||
Or if you're just using for testing you'll want:
|
||||
|
||||
```shell
|
||||
npm install --save-dev responselike
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const Response = require('responselike');
|
||||
|
||||
const response = new Response(200, { foo: 'bar' }, Buffer.from('Hi!'), 'https://example.com');
|
||||
|
||||
response.statusCode;
|
||||
// 200
|
||||
response.headers;
|
||||
// { foo: 'bar' }
|
||||
response.body;
|
||||
// <Buffer 48 69 21>
|
||||
response.url;
|
||||
// 'https://example.com'
|
||||
|
||||
response.pipe(process.stdout);
|
||||
// Hi!
|
||||
```
|
||||
|
||||
|
||||
## API
|
||||
|
||||
### new Response(statusCode, headers, body, url)
|
||||
|
||||
Returns a streamable response object similar to a [Node.js HTTP response stream](https://nodejs.org/api/http.html#http_class_http_incomingmessage).
|
||||
|
||||
#### statusCode
|
||||
|
||||
Type: `number`
|
||||
|
||||
HTTP response status code.
|
||||
|
||||
#### headers
|
||||
|
||||
Type: `object`
|
||||
|
||||
HTTP headers object. Keys will be automatically lowercased.
|
||||
|
||||
#### body
|
||||
|
||||
Type: `buffer`
|
||||
|
||||
A Buffer containing the response body. The Buffer contents will be streamable but is also exposed directly as `response.body`.
|
||||
|
||||
#### url
|
||||
|
||||
Type: `string`
|
||||
|
||||
Request URL string.
|
||||
|
||||
## License
|
||||
|
||||
MIT © Luke Childs
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
{
|
||||
"name": "responselike",
|
||||
"version": "1.0.2",
|
||||
"description": "A response-like object for mocking a Node.js HTTP response stream",
|
||||
"main": "src/index.js",
|
||||
"scripts": {
|
||||
"test": "xo && nyc ava",
|
||||
"coverage": "nyc report --reporter=text-lcov | coveralls"
|
||||
},
|
||||
"xo": {
|
||||
"extends": "xo-lukechilds"
|
||||
},
|
||||
"keywords": [
|
||||
"http",
|
||||
"https",
|
||||
"response",
|
||||
"mock",
|
||||
"request",
|
||||
"responselike"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/lukechilds/responselike.git"
|
||||
},
|
||||
"author": "lukechilds",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"ava": "^0.22.0",
|
||||
"coveralls": "^2.13.1",
|
||||
"eslint-config-xo-lukechilds": "^1.0.0",
|
||||
"get-stream": "^3.0.0",
|
||||
"nyc": "^11.1.0",
|
||||
"xo": "^0.19.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"lowercase-keys": "^1.0.0"
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue