[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
|
@ -20,12 +20,6 @@
|
||||||
"config": {
|
"config": {
|
||||||
"optimize-autoloader": true,
|
"optimize-autoloader": true,
|
||||||
"autoloader-suffix": "AdvancedContentFilterAddon",
|
"autoloader-suffix": "AdvancedContentFilterAddon",
|
||||||
"preferred-install": "dist",
|
"preferred-install": "dist"
|
||||||
"fxp-asset": {
|
|
||||||
"installer-paths": {
|
|
||||||
"npm-asset-library": "vendor/asset",
|
|
||||||
"bower-asset-library": "vendor/asset"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
||||||
[![Build Status](https://travis-ci.org/lukechilds/cacheable-request.svg?branch=master)](https://travis-ci.org/lukechilds/cacheable-request)
|
|
||||||
[![Coverage Status](https://coveralls.io/repos/github/lukechilds/cacheable-request/badge.svg?branch=master)](https://coveralls.io/github/lukechilds/cacheable-request?branch=master)
|
|
||||||
[![npm](https://img.shields.io/npm/dm/cacheable-request.svg)](https://www.npmjs.com/package/cacheable-request)
|
|
||||||
[![npm](https://img.shields.io/npm/v/cacheable-request.svg)](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
|
|
||||||
|
|
||||||
[![Build Status](https://travis-ci.org/lukechilds/clone-response.svg?branch=master)](https://travis-ci.org/lukechilds/clone-response)
|
|
||||||
[![Coverage Status](https://coveralls.io/repos/github/lukechilds/clone-response/badge.svg?branch=master)](https://coveralls.io/github/lukechilds/clone-response?branch=master)
|
|
||||||
[![npm](https://img.shields.io/npm/dm/clone-response.svg)](https://www.npmjs.com/package/clone-response)
|
|
||||||
[![npm](https://img.shields.io/npm/v/clone-response.svg)](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
|
|
||||||
|
|
||||||
[![Build Status](https://travis-ci.org/SamVerschueren/decode-uri-component.svg?branch=master)](https://travis-ci.org/SamVerschueren/decode-uri-component) [![Coverage Status](https://coveralls.io/repos/SamVerschueren/decode-uri-component/badge.svg?branch=master&service=github)](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 [![Build Status](https://travis-ci.org/sindresorhus/decompress-response.svg?branch=master)](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 [![Build Status](https://travis-ci.org/floatdrop/duplexer3.svg?branch=master)](https://travis-ci.org/floatdrop/duplexer3) [![Coverage Status](https://coveralls.io/repos/floatdrop/duplexer3/badge.svg?branch=master&service=github)](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 [![Flattr this!](https://api.flattr.com/button/flattr-badge-large.png)](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)[![experimental](http://hughsk.github.io/stability-badges/dist/experimental.svg)](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 ##
|
|
||||||
|
|
||||||
[![from2](https://nodei.co/npm/from2.png?mini=true)](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"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -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 [![Build Status](https://travis-ci.org/sindresorhus/get-stream.svg?branch=master)](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;
|
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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
|
|
||||||
|
|
||||||
[![Build Status](https://travis-ci.org/sindresorhus/got.svg?branch=master)](https://travis-ci.org/sindresorhus/got) [![Coverage Status](https://coveralls.io/repos/github/sindresorhus/got/badge.svg?branch=master)](https://coveralls.io/github/sindresorhus/got?branch=master) [![Downloads](https://img.shields.io/npm/dm/got.svg)](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
|
|
||||||
|
|
||||||
[![Sindre Sorhus](https://github.com/sindresorhus.png?size=100)](https://sindresorhus.com) | [![Vsevolod Strukchinsky](https://github.com/floatdrop.png?size=100)](https://github.com/floatdrop) | [![Alexander Tesfamichael](https://github.com/AlexTes.png?size=100)](https://github.com/AlexTes) | [![Luke Childs](https://github.com/lukechilds.png?size=100)](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? [![Build Status](https://travis-ci.org/pornel/http-cache-semantics.svg?branch=master)](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
|
|
||||||
|
|
||||||
![satisfiesWithoutRevalidation](fresh.jpg)
|
|
||||||
|
|
||||||
## 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 [![Build Status](https://travis-ci.org/sindresorhus/into-stream.svg?branch=master)](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 [![Build Status](https://travis-ci.org/sindresorhus/is-plain-obj.svg?branch=master)](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;
|
|
||||||
};
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user