chore: add jimp dependency, icon padding script, and update configuration
This commit is contained in:
+21
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 Ethan Davis
|
||||
|
||||
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.
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
<p align="center" style="text-align: center"><img src="https://raw.githubusercontent.com/ethanent/phin/master/media/phin-textIncluded.png" width="250" alt="phin logo"/></p>
|
||||
|
||||
---
|
||||
|
||||
> The lightweight Node.js HTTP client
|
||||
|
||||
[Full documentation](https://ethanent.github.io/phin/global.html) | [GitHub](https://github.com/ethanent/phin) | [NPM](https://www.npmjs.com/package/phin)
|
||||
|
||||
## Deprecated
|
||||
|
||||
This package is deprecated and should not be used. Please see [#91](https://github.com/ethanent/phin/issues/91) for more information.
|
||||
|
||||
## Simple Usage
|
||||
|
||||
```javascript
|
||||
const p = require('phin')
|
||||
|
||||
const res = await p('https://ethanent.me')
|
||||
|
||||
console.log(res.body)
|
||||
```
|
||||
|
||||
Note that the above should be in an async context! Phin also provides an unpromisified version of the library.
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
npm install phin
|
||||
```
|
||||
|
||||
|
||||
## Why Phin?
|
||||
|
||||
Phin is relied upon by important projects and large companies. The hundreds of contributors at [Less](https://github.com/less/less.js), for example, depend on Phin as part of their development process.
|
||||
|
||||
Also, Phin is very lightweight. To compare to other libraries, see [Phin vs. the Competition](https://github.com/ethanent/phin/blob/master/README.md#phin-vs-the-competition).
|
||||
|
||||
## Quick Demos
|
||||
|
||||
Simple POST:
|
||||
|
||||
```js
|
||||
await p({
|
||||
url: 'https://ethanent.me',
|
||||
method: 'POST',
|
||||
data: {
|
||||
hey: 'hi'
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### Unpromisified Usage
|
||||
|
||||
```js
|
||||
const p = require('phin').unpromisified
|
||||
|
||||
p('https://ethanent.me', (err, res) => {
|
||||
if (!err) console.log(res.body)
|
||||
})
|
||||
```
|
||||
|
||||
Simple parsing of JSON:
|
||||
|
||||
```js
|
||||
// (In async function in this case.)
|
||||
|
||||
const res = await p({
|
||||
'url': 'https://ethanent.me/name',
|
||||
'parse': 'json'
|
||||
})
|
||||
|
||||
console.log(res.body.first)
|
||||
```
|
||||
|
||||
### Default Options
|
||||
|
||||
```js
|
||||
const ppostjson = p.defaults({
|
||||
'method': 'POST',
|
||||
'parse': 'json',
|
||||
'timeout': 2000
|
||||
})
|
||||
|
||||
// In async function...
|
||||
|
||||
const res = await ppostjson('https://ethanent.me/somejson')
|
||||
// ^ An options object could also be used here to set other options.
|
||||
|
||||
// Do things with res.body?
|
||||
```
|
||||
|
||||
### Custom Core HTTP Options
|
||||
|
||||
Phin allows you to set [core HTTP options](https://nodejs.org/api/http.html#http_http_request_url_options_callback).
|
||||
|
||||
```js
|
||||
await p({
|
||||
'url': 'https://ethanent.me/name',
|
||||
'core': {
|
||||
'agent': myAgent // Assuming you'd already created myAgent earlier.
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
|
||||
## Full Documentation
|
||||
|
||||
There's a lot more which can be done with the Phin library.
|
||||
|
||||
See [the Phin documentation](https://ethanent.github.io/phin/global.html).
|
||||
|
||||
|
||||
## Phin vs. the Competition
|
||||
|
||||
Phin is a very lightweight library, yet it contains all of the common HTTP client features included in competing libraries!
|
||||
|
||||
Here's a size comparison table:
|
||||
|
||||
Package | Size
|
||||
--- | ---
|
||||
request | [](https://packagephobia.now.sh/result?p=request)
|
||||
superagent | [](https://packagephobia.now.sh/result?p=superagent)
|
||||
got | [](https://packagephobia.now.sh/result?p=got)
|
||||
axios | [](https://packagephobia.now.sh/result?p=axios)
|
||||
isomorphic-fetch | [](https://packagephobia.now.sh/result?p=isomorphic-fetch)
|
||||
r2 | [](https://packagephobia.now.sh/result?p=r2)
|
||||
node-fetch | [](https://packagephobia.now.sh/result?p=node-fetch)
|
||||
phin | [](https://packagephobia.now.sh/result?p=phin)
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
const {URL} = require('url')
|
||||
|
||||
const centra = require('centra')
|
||||
|
||||
const unspecifiedFollowRedirectsDefault = 20
|
||||
|
||||
/**
|
||||
* phin options object. phin also supports all options from <a href="https://nodejs.org/api/http.html#http_http_request_options_callback">http.request(options, callback)</a> by passing them on to this method (or similar).
|
||||
* @typedef {Object} phinOptions
|
||||
* @property {string} url - URL to request (autodetect infers from this URL)
|
||||
* @property {string} [method=GET] - Request method ('GET', 'POST', etc.)
|
||||
* @property {string|Buffer|object} [data] - Data to send as request body (phin may attempt to convert this data to a string if it isn't already)
|
||||
* @property {Object} [form] - Object to send as form data (sets 'Content-Type' and 'Content-Length' headers, as well as request body) (overwrites 'data' option if present)
|
||||
* @property {Object} [headers={}] - Request headers
|
||||
* @property {Object} [core={}] - Custom core HTTP options
|
||||
* @property {string} [parse=none] - Response parsing. Errors will be given if the response can't be parsed. 'none' returns body as a `Buffer`, 'json' attempts to parse the body as JSON, and 'string' attempts to parse the body as a string
|
||||
* @property {boolean} [followRedirects=false] - Enable HTTP redirect following
|
||||
* @property {boolean} [stream=false] - Enable streaming of response. (Removes body property)
|
||||
* @property {boolean} [compression=false] - Enable compression for request
|
||||
* @property {?number} [timeout=null] - Request timeout in milliseconds
|
||||
* @property {string} [hostname=autodetect] - URL hostname
|
||||
* @property {Number} [port=autodetect] - URL port
|
||||
* @property {string} [path=autodetect] - URL path
|
||||
*/
|
||||
|
||||
/**
|
||||
* Response data
|
||||
* @callback phinResponseCallback
|
||||
* @param {?(Error|string)} error - Error if any occurred in request, otherwise null.
|
||||
* @param {?http.serverResponse} phinResponse - phin response object. Like <a href='https://nodejs.org/api/http.html#http_class_http_serverresponse'>http.ServerResponse</a> but has a body property containing response body, unless stream. If stream option is enabled, a stream property will be provided to callback with a readable stream.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Sends an HTTP request
|
||||
* @param {phinOptions|string} options - phin options object (or string for auto-detection)
|
||||
* @returns {Promise<http.serverResponse>} - phin-adapted response object
|
||||
*/
|
||||
const phin = async (opts) => {
|
||||
if (typeof(opts) !== 'string') {
|
||||
if (!opts.hasOwnProperty('url')) {
|
||||
throw new Error('Missing url option from options for request method.')
|
||||
}
|
||||
}
|
||||
|
||||
const req = centra(typeof opts === 'object' ? opts.url : opts, opts.method || 'GET')
|
||||
|
||||
if (opts.headers) req.header(opts.headers)
|
||||
if (opts.stream) req.stream()
|
||||
if (opts.timeout) req.timeout(opts.timeout)
|
||||
if (opts.data) req.body(opts.data)
|
||||
if (opts.form) req.body(opts.form, 'form')
|
||||
if (opts.compression) req.compress()
|
||||
|
||||
if (opts.followRedirects) {
|
||||
if (opts.followRedirects === true) {
|
||||
req.followRedirects(unspecifiedFollowRedirectsDefault)
|
||||
} else if (typeof opts.followRedirects === 'number') {
|
||||
req.followRedirects(opts.followRedirects)
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof opts.core === 'object') {
|
||||
Object.keys(opts.core).forEach((optName) => {
|
||||
req.option(optName, opts.core[optName])
|
||||
})
|
||||
}
|
||||
|
||||
const res = await req.send()
|
||||
|
||||
if (opts.stream) {
|
||||
res.stream = res
|
||||
|
||||
return res
|
||||
}
|
||||
else {
|
||||
res.coreRes.body = res.body
|
||||
|
||||
if (opts.parse) {
|
||||
if (opts.parse === 'json') {
|
||||
res.coreRes.body = await res.json()
|
||||
|
||||
return res.coreRes
|
||||
}
|
||||
else if (opts.parse === 'string') {
|
||||
res.coreRes.body = res.coreRes.body.toString()
|
||||
|
||||
return res.coreRes
|
||||
}
|
||||
}
|
||||
|
||||
return res.coreRes
|
||||
}
|
||||
}
|
||||
|
||||
// If we're running Node.js 8+, let's promisify it
|
||||
|
||||
phin.promisified = phin
|
||||
|
||||
phin.unpromisified = (opts, cb) => {
|
||||
phin(opts).then((data) => {
|
||||
if (cb) cb(null, data)
|
||||
}).catch((err) => {
|
||||
if (cb) cb(err, null)
|
||||
})
|
||||
}
|
||||
|
||||
// Defaults
|
||||
|
||||
phin.defaults = (defaultOpts) => async (opts) => {
|
||||
const nops = typeof opts === 'string' ? {'url': opts} : opts
|
||||
|
||||
Object.keys(defaultOpts).forEach((doK) => {
|
||||
if (!nops.hasOwnProperty(doK) || nops[doK] === null) {
|
||||
nops[doK] = defaultOpts[doK]
|
||||
}
|
||||
})
|
||||
|
||||
return await phin(nops)
|
||||
}
|
||||
|
||||
module.exports = phin
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"name": "phin",
|
||||
"version": "3.7.1",
|
||||
"description": "The ultra-lightweight Node.js HTTP client",
|
||||
"main": "lib/phin.js",
|
||||
"types": "types.d.ts",
|
||||
"scripts": {
|
||||
"test": "node ./tests/test.js",
|
||||
"prepublishOnly": "npm test"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/ethanent/phin.git"
|
||||
},
|
||||
"keywords": [
|
||||
"http",
|
||||
"https",
|
||||
"request",
|
||||
"fetch",
|
||||
"ajax",
|
||||
"url",
|
||||
"uri"
|
||||
],
|
||||
"author": "Ethan Davis",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/ethanent/phin/issues"
|
||||
},
|
||||
"homepage": "https://github.com/ethanent/phin",
|
||||
"files": [
|
||||
"lib/phin.js",
|
||||
"types.d.ts"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
},
|
||||
"dependencies": {
|
||||
"centra": "^2.7.0"
|
||||
}
|
||||
}
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
// Default Options feature is not supported because it's basically impossible to write strongly-typed definitions for it.
|
||||
|
||||
import * as http from 'http'
|
||||
import { URL } from 'url';
|
||||
|
||||
interface IOptionsBase {
|
||||
url: string | URL
|
||||
method?: string
|
||||
headers?: object
|
||||
core?: http.ClientRequestArgs
|
||||
followRedirects?: boolean
|
||||
stream?: boolean
|
||||
compression?: boolean
|
||||
timeout?: number
|
||||
hostname?: string
|
||||
port?: number
|
||||
path?: string
|
||||
}
|
||||
|
||||
declare function phin<T>(options:
|
||||
phin.IJSONResponseOptions |
|
||||
phin.IWithData<phin.IJSONResponseOptions> |
|
||||
phin.IWithForm<phin.IJSONResponseOptions>): Promise<phin.IJSONResponse<T>>
|
||||
|
||||
declare function phin(options:
|
||||
phin.IStringResponseOptions |
|
||||
phin.IWithData<phin.IStringResponseOptions> |
|
||||
phin.IWithForm<phin.IStringResponseOptions>): Promise<phin.IStringResponse>
|
||||
|
||||
declare function phin(options:
|
||||
phin.IStreamResponseOptions |
|
||||
phin.IWithData<phin.IStreamResponseOptions> |
|
||||
phin.IWithForm<phin.IStreamResponseOptions>): Promise<phin.IStreamResponse>
|
||||
|
||||
declare function phin(options:
|
||||
phin.IOptions |
|
||||
phin.IWithData<phin.IOptions> |
|
||||
phin.IWithForm<phin.IOptions> |
|
||||
string): Promise<phin.IResponse>
|
||||
|
||||
declare namespace phin {
|
||||
// Form and data property has been written this way so they're mutually exclusive.
|
||||
export type IWithData<T extends IOptionsBase> = T & {
|
||||
data: string | Buffer | object;
|
||||
}
|
||||
|
||||
export type IWithForm<T extends IOptionsBase> = T & {
|
||||
form: {
|
||||
[index: string]: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface IJSONResponseOptions extends IOptionsBase {
|
||||
parse: 'json'
|
||||
}
|
||||
|
||||
export interface IStringResponseOptions extends IOptionsBase {
|
||||
parse: 'string';
|
||||
}
|
||||
|
||||
export interface IStreamResponseOptions extends IOptionsBase {
|
||||
stream: true
|
||||
}
|
||||
|
||||
export interface IOptions extends IOptionsBase {
|
||||
parse?: 'none'
|
||||
}
|
||||
|
||||
export interface IJSONResponse<T> extends http.IncomingMessage {
|
||||
body: T
|
||||
}
|
||||
|
||||
export interface IStringResponse extends http.IncomingMessage {
|
||||
body: string;
|
||||
}
|
||||
|
||||
export interface IStreamResponse extends http.IncomingMessage {
|
||||
stream: http.IncomingMessage
|
||||
}
|
||||
|
||||
export interface IResponse extends http.IncomingMessage {
|
||||
body: Buffer;
|
||||
}
|
||||
|
||||
// NOTE: Typescript cannot infer type of union callback on the consumer side
|
||||
// https://github.com/Microsoft/TypeScript/pull/17819#issuecomment-363636904
|
||||
type IErrorCallback = (error: Error | string, response: null) => void
|
||||
type ICallback<T> = (error: null, response: NonNullable<T>) => void
|
||||
|
||||
export let promisified: typeof phin
|
||||
|
||||
export function unpromisified<T>(
|
||||
options:
|
||||
IJSONResponseOptions |
|
||||
IWithData<IJSONResponseOptions> |
|
||||
IWithForm<IJSONResponseOptions>,
|
||||
callback: IErrorCallback | ICallback<IJSONResponse<T>>): void
|
||||
|
||||
export function unpromisified(
|
||||
options:
|
||||
IStringResponseOptions |
|
||||
IWithData<IStringResponseOptions> |
|
||||
IWithForm<IStringResponseOptions>,
|
||||
callback: IErrorCallback | ICallback<IStringResponse>): void
|
||||
|
||||
export function unpromisified(
|
||||
options:
|
||||
IStreamResponseOptions |
|
||||
IWithData<IStreamResponseOptions> |
|
||||
IWithForm<IStreamResponseOptions>,
|
||||
callback: IErrorCallback | ICallback<IStreamResponse>): void
|
||||
|
||||
export function unpromisified(
|
||||
options:
|
||||
IOptions |
|
||||
IWithData<IOptions> |
|
||||
IWithForm<IOptions> |
|
||||
string,
|
||||
callback: IErrorCallback | ICallback<IResponse>): void
|
||||
}
|
||||
|
||||
export = phin
|
||||
Reference in New Issue
Block a user