Comparing version 4.0.1 to 5.0.0
101
index.js
'use strict'; | ||
const processFn = (fn, options) => function (...args) { | ||
const processFn = (fn, options, proxy, unwrapped) => function (...arguments_) { | ||
const P = options.promiseModule; | ||
@@ -8,3 +8,3 @@ | ||
if (options.multiArgs) { | ||
args.push((...result) => { | ||
arguments_.push((...result) => { | ||
if (options.errorFirst) { | ||
@@ -22,3 +22,3 @@ if (result[0]) { | ||
} else if (options.errorFirst) { | ||
args.push((error, result) => { | ||
arguments_.push((error, result) => { | ||
if (error) { | ||
@@ -31,41 +31,86 @@ reject(error); | ||
} else { | ||
args.push(resolve); | ||
arguments_.push(resolve); | ||
} | ||
fn.apply(this, args); | ||
const self = this === proxy ? unwrapped : this; | ||
Reflect.apply(fn, self, arguments_); | ||
}); | ||
}; | ||
const filterCache = new WeakMap(); | ||
module.exports = (input, options) => { | ||
options = Object.assign({ | ||
exclude: [/.+(Sync|Stream)$/], | ||
options = { | ||
exclude: [/.+(?:Sync|Stream)$/], | ||
errorFirst: true, | ||
promiseModule: Promise | ||
}, options); | ||
promiseModule: Promise, | ||
...options | ||
}; | ||
const objType = typeof input; | ||
if (!(input !== null && (objType === 'object' || objType === 'function'))) { | ||
throw new TypeError(`Expected \`input\` to be a \`Function\` or \`Object\`, got \`${input === null ? 'null' : objType}\``); | ||
const objectType = typeof input; | ||
if (!(input !== null && (objectType === 'object' || objectType === 'function'))) { | ||
throw new TypeError(`Expected \`input\` to be a \`Function\` or \`Object\`, got \`${input === null ? 'null' : objectType}\``); | ||
} | ||
const filter = key => { | ||
const match = pattern => typeof pattern === 'string' ? key === pattern : pattern.test(key); | ||
return options.include ? options.include.some(match) : !options.exclude.some(match); | ||
const filter = (target, key) => { | ||
let cached = filterCache.get(target); | ||
if (!cached) { | ||
cached = {}; | ||
filterCache.set(target, cached); | ||
} | ||
if (key in cached) { | ||
return cached[key]; | ||
} | ||
const match = pattern => (typeof pattern === 'string' || typeof key === 'symbol') ? key === pattern : pattern.test(key); | ||
const desc = Reflect.getOwnPropertyDescriptor(target, key); | ||
const writableOrConfigurableOwn = (desc === undefined || desc.writable || desc.configurable); | ||
const included = options.include ? options.include.some(match) : !options.exclude.some(match); | ||
const shouldFilter = included && writableOrConfigurableOwn; | ||
cached[key] = shouldFilter; | ||
return shouldFilter; | ||
}; | ||
let ret; | ||
if (objType === 'function') { | ||
ret = function (...args) { | ||
return options.excludeMain ? input(...args) : processFn(input, options).apply(this, args); | ||
}; | ||
} else { | ||
ret = Object.create(Object.getPrototypeOf(input)); | ||
} | ||
const cache = new WeakMap(); | ||
for (const key in input) { // eslint-disable-line guard-for-in | ||
const property = input[key]; | ||
ret[key] = typeof property === 'function' && filter(key) ? processFn(property, options) : property; | ||
} | ||
const proxy = new Proxy(input, { | ||
apply(target, thisArg, args) { | ||
const cached = cache.get(target); | ||
return ret; | ||
if (cached) { | ||
return Reflect.apply(cached, thisArg, args); | ||
} | ||
const pified = options.excludeMain ? target : processFn(target, options, proxy, target); | ||
cache.set(target, pified); | ||
return Reflect.apply(pified, thisArg, args); | ||
}, | ||
get(target, key) { | ||
const property = target[key]; | ||
// eslint-disable-next-line no-use-extend-native/no-use-extend-native | ||
if (!filter(target, key) || property === Function.prototype[key]) { | ||
return property; | ||
} | ||
const cached = cache.get(property); | ||
if (cached) { | ||
return cached; | ||
} | ||
if (typeof property === 'function') { | ||
const pified = processFn(property, options, proxy, target); | ||
cache.set(property, pified); | ||
return pified; | ||
} | ||
return property; | ||
} | ||
}); | ||
return proxy; | ||
}; |
{ | ||
"name": "pify", | ||
"version": "4.0.1", | ||
"version": "5.0.0", | ||
"description": "Promisify a callback-style function", | ||
"license": "MIT", | ||
"repository": "sindresorhus/pify", | ||
"funding": "https://github.com/sponsors/sindresorhus", | ||
"author": { | ||
"name": "Sindre Sorhus", | ||
"email": "sindresorhus@gmail.com", | ||
"url": "sindresorhus.com" | ||
"url": "https://sindresorhus.com" | ||
}, | ||
"engines": { | ||
"node": ">=6" | ||
"node": ">=10" | ||
}, | ||
@@ -23,10 +24,8 @@ "scripts": { | ||
"keywords": [ | ||
"promisify", | ||
"callback", | ||
"promise", | ||
"promises", | ||
"promisify", | ||
"all", | ||
"denodify", | ||
"denodeify", | ||
"callback", | ||
"cb", | ||
"node", | ||
@@ -40,3 +39,2 @@ "then", | ||
"bind", | ||
"to", | ||
"async", | ||
@@ -48,7 +46,7 @@ "await", | ||
"devDependencies": { | ||
"ava": "^0.25.0", | ||
"ava": "^2.4.0", | ||
"pinkie-promise": "^2.0.0", | ||
"v8-natives": "^1.1.0", | ||
"xo": "^0.23.0" | ||
"xo": "^0.26.1" | ||
} | ||
} |
@@ -5,17 +5,2 @@ # pify [![Build Status](https://travis-ci.org/sindresorhus/pify.svg?branch=master)](https://travis-ci.org/sindresorhus/pify) | ||
--- | ||
<div align="center"> | ||
<b> | ||
<a href="https://tidelift.com/subscription/pkg/npm-pify?utm_source=npm-pify&utm_medium=referral&utm_campaign=readme">Get professional support for 'pify' with a Tidelift subscription</a> | ||
</b> | ||
<br> | ||
<sub> | ||
Tidelift helps make open source sustainable for maintainers while giving companies<br>assurances about security, maintenance, and licensing for their dependencies. | ||
</sub> | ||
</div> | ||
--- | ||
## Install | ||
@@ -27,3 +12,2 @@ | ||
## Usage | ||
@@ -35,19 +19,18 @@ | ||
// Promisify a single function | ||
pify(fs.readFile)('package.json', 'utf8').then(data => { | ||
(async () => { | ||
// Promisify a single function. | ||
const data = await pify(fs.readFile)('package.json', 'utf8'); | ||
console.log(JSON.parse(data).name); | ||
//=> 'pify' | ||
}); | ||
// Promisify all methods in a module | ||
pify(fs).readFile('package.json', 'utf8').then(data => { | ||
console.log(JSON.parse(data).name); | ||
// Promisify all methods in a module. | ||
const data2 = await pify(fs).readFile('package.json', 'utf8'); | ||
console.log(JSON.parse(data2).name); | ||
//=> 'pify' | ||
}); | ||
})(); | ||
``` | ||
## API | ||
### pify(input, [options]) | ||
### pify(input, options?) | ||
@@ -58,3 +41,3 @@ Returns a `Promise` wrapped version of the supplied function or module. | ||
Type: `Function` `Object` | ||
Type: `Function | object` | ||
@@ -65,5 +48,7 @@ Callback-style function or module whose methods you want to promisify. | ||
Type: `object` | ||
##### multiArgs | ||
Type: `boolean`<br> | ||
Type: `boolean`\ | ||
Default: `false` | ||
@@ -77,5 +62,7 @@ | ||
pify(request, {multiArgs: true})('https://sindresorhus.com').then(result => { | ||
const [httpResponse, body] = result; | ||
}); | ||
const pRequest = pify(request, {multiArgs: true}); | ||
(async () => { | ||
const [httpResponse, body] = await pRequest('https://sindresorhus.com'); | ||
})(); | ||
``` | ||
@@ -85,3 +72,3 @@ | ||
Type: `string[]` `RegExp[]` | ||
Type: `Array<string | RegExp>` | ||
@@ -92,4 +79,4 @@ Methods in a module to promisify. Remaining methods will be left untouched. | ||
Type: `string[]` `RegExp[]`<br> | ||
Default: `[/.+(Sync|Stream)$/]` | ||
Type: `Array<string | RegExp>`\ | ||
Default: `[/.+(?:Sync|Stream)$/]` | ||
@@ -100,6 +87,6 @@ Methods in a module **not** to promisify. Methods with names ending with `'Sync'` are excluded by default. | ||
Type: `boolean`<br> | ||
Type: `boolean`\ | ||
Default: `false` | ||
If given module is a function itself, it will be promisified. Turn this option on if you want to promisify only methods of the module. | ||
If the given module is a function itself, it will be promisified. Enable this option if you want to promisify only methods of the module. | ||
@@ -119,10 +106,10 @@ ```js | ||
// Promisify methods but not `fn()` | ||
const promiseFn = pify(fn, {excludeMain: true}); | ||
(async () => { | ||
// Promisify methods but not `fn()`. | ||
const promiseFn = pify(fn, {excludeMain: true}); | ||
if (promiseFn()) { | ||
promiseFn.method('hi').then(data => { | ||
console.log(data); | ||
}); | ||
} | ||
if (promiseFn()) { | ||
console.log(await promiseFn.method('hi')); | ||
} | ||
})(); | ||
``` | ||
@@ -132,3 +119,3 @@ | ||
Type: `boolean`<br> | ||
Type: `boolean`\ | ||
Default: `true` | ||
@@ -144,5 +131,12 @@ | ||
Check out [`pinkie-promise`](https://github.com/floatdrop/pinkie-promise) if you need a tiny promise polyfill. | ||
## FAQ | ||
#### How is this different from Node.js's [`util.promisify`](https://nodejs.org/api/util.html#util_util_promisify_original)? | ||
- Pify existed long before `util.promisify`. | ||
- Pify is [faster](https://github.com/sindresorhus/pify/issues/41#issuecomment-429988506). | ||
- Pify supports wrapping a whole module/object, not just a specific method. | ||
- Pify has useful options like the ability to handle multiple arguments (`multiArgs`). | ||
- Pify does not have [magic behavior](https://nodejs.org/api/util.html#util_custom_promisified_functions) for certain Node.js methods and instead focuses on predictability. | ||
## Related | ||
@@ -154,5 +148,12 @@ | ||
--- | ||
## License | ||
MIT © [Sindre Sorhus](https://sindresorhus.com) | ||
<div align="center"> | ||
<b> | ||
<a href="https://tidelift.com/subscription/pkg/npm-pify?utm_source=npm-pify&utm_medium=referral&utm_campaign=readme">Get professional support for 'pify' with a Tidelift subscription</a> | ||
</b> | ||
<br> | ||
<sub> | ||
Tidelift helps make open source sustainable for maintainers while giving companies<br>assurances about security, maintenance, and licensing for their dependencies. | ||
</sub> | ||
</div> |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
8867
92
147