pax_global_header00006660000000000000000000000064131124665270014521gustar00rootroot0000000000000052 comment=e64328eb378e2ecd6bf8c0eb40aa3277680aaff4 pify-3.0.0/000077500000000000000000000000001311246652700124705ustar00rootroot00000000000000pify-3.0.0/.editorconfig000066400000000000000000000002571311246652700151510ustar00rootroot00000000000000root = true [*] indent_style = tab end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true [*.yml] indent_style = space indent_size = 2 pify-3.0.0/.gitattributes000066400000000000000000000000351311246652700153610ustar00rootroot00000000000000* text=auto *.js text eol=lf pify-3.0.0/.gitignore000066400000000000000000000000151311246652700144540ustar00rootroot00000000000000node_modules pify-3.0.0/.travis.yml000066400000000000000000000000531311246652700145770ustar00rootroot00000000000000language: node_js node_js: - '6' - '4' pify-3.0.0/index.js000066400000000000000000000034201311246652700141340ustar00rootroot00000000000000'use strict'; const processFn = (fn, opts) => function () { const P = opts.promiseModule; const args = new Array(arguments.length); for (let i = 0; i < arguments.length; i++) { args[i] = arguments[i]; } return new P((resolve, reject) => { if (opts.errorFirst) { args.push(function (err, result) { if (opts.multiArgs) { const results = new Array(arguments.length - 1); for (let i = 1; i < arguments.length; i++) { results[i - 1] = arguments[i]; } if (err) { results.unshift(err); reject(results); } else { resolve(results); } } else if (err) { reject(err); } else { resolve(result); } }); } else { args.push(function (result) { if (opts.multiArgs) { const results = new Array(arguments.length - 1); for (let i = 0; i < arguments.length; i++) { results[i] = arguments[i]; } resolve(results); } else { resolve(result); } }); } fn.apply(this, args); }); }; module.exports = (obj, opts) => { opts = Object.assign({ exclude: [/.+(Sync|Stream)$/], errorFirst: true, promiseModule: Promise }, opts); const filter = key => { const match = pattern => typeof pattern === 'string' ? key === pattern : pattern.test(key); return opts.include ? opts.include.some(match) : !opts.exclude.some(match); }; let ret; if (typeof obj === 'function') { ret = function () { if (opts.excludeMain) { return obj.apply(this, arguments); } return processFn(obj, opts).apply(this, arguments); }; } else { ret = Object.create(Object.getPrototypeOf(obj)); } for (const key in obj) { // eslint-disable-line guard-for-in const x = obj[key]; ret[key] = typeof x === 'function' && filter(key) ? processFn(x, opts) : x; } return ret; }; pify-3.0.0/license000066400000000000000000000021251311246652700140350ustar00rootroot00000000000000MIT License Copyright (c) Sindre Sorhus (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. pify-3.0.0/optimization-test.js000066400000000000000000000017711311246652700165370ustar00rootroot00000000000000/* eslint-disable no-fallthrough */ 'use strict'; const assert = require('assert'); const v8 = require('v8-natives'); const pify = require('.'); function assertOptimized(fn, name) { const status = v8.getOptimizationStatus(fn); switch (status) { case 1: // `fn` is optimized console.log('pify is optimized'); return; case 2: assert(false, `${name} is not optimized (${status})`); case 3: // `fn` is always optimized return; case 4: assert(false, `${name} is never optimized (${status})`); case 6: assert(false, `${name} is maybe deoptimized (${status})`); default: assert(false, `unknown OptimizationStatus: ${status} (${name})`); } } const sut = pify({ unicorn: cb => { cb(null, 'unicorn'); } }); sut.unicorn().then(() => { v8.optimizeFunctionOnNextCall(sut.unicorn); return sut.unicorn().then(() => { assertOptimized(sut.unicorn, 'unicorn'); }); }).catch(err => { console.error(err.stack); process.exit(1); // eslint-disable-line unicorn/no-process-exit }); pify-3.0.0/package.json000066400000000000000000000016361311246652700147640ustar00rootroot00000000000000{ "name": "pify", "version": "3.0.0", "description": "Promisify a callback-style function", "license": "MIT", "repository": "sindresorhus/pify", "author": { "name": "Sindre Sorhus", "email": "sindresorhus@gmail.com", "url": "sindresorhus.com" }, "engines": { "node": ">=4" }, "scripts": { "test": "xo && ava && npm run optimization-test", "optimization-test": "node --allow-natives-syntax optimization-test.js" }, "files": [ "index.js" ], "keywords": [ "promise", "promises", "promisify", "all", "denodify", "denodeify", "callback", "cb", "node", "then", "thenify", "convert", "transform", "wrap", "wrapper", "bind", "to", "async", "await", "es2015", "bluebird" ], "devDependencies": { "ava": "*", "pinkie-promise": "^2.0.0", "v8-natives": "^1.0.0", "xo": "*" } } pify-3.0.0/readme.md000066400000000000000000000062031311246652700142500ustar00rootroot00000000000000# pify [![Build Status](https://travis-ci.org/sindresorhus/pify.svg?branch=master)](https://travis-ci.org/sindresorhus/pify) > Promisify a callback-style function ## Install ``` $ npm install --save pify ``` ## Usage ```js const fs = require('fs'); const pify = require('pify'); // Promisify a single function pify(fs.readFile)('package.json', 'utf8').then(data => { console.log(JSON.parse(data).name); //=> 'pify' }); // Promisify all methods in a module pify(fs).readFile('package.json', 'utf8').then(data => { console.log(JSON.parse(data).name); //=> 'pify' }); ``` ## API ### pify(input, [options]) Returns a `Promise` wrapped version of the supplied function or module. #### input Type: `Function` `Object` Callback-style function or module whose methods you want to promisify. #### options ##### multiArgs Type: `boolean`
Default: `false` By default, the promisified function will only return the second argument from the callback, which works fine for most APIs. This option can be useful for modules like `request` that return multiple arguments. Turning this on will make it return an array of all arguments from the callback, excluding the error argument, instead of just the second argument. This also applies to rejections, where it returns an array of all the callback arguments, including the error. ```js const request = require('request'); const pify = require('pify'); pify(request, {multiArgs: true})('https://sindresorhus.com').then(result => { const [httpResponse, body] = result; }); ``` ##### include Type: `string[]` `RegExp[]` Methods in a module to promisify. Remaining methods will be left untouched. ##### exclude Type: `string[]` `RegExp[]`
Default: `[/.+(Sync|Stream)$/]` Methods in a module **not** to promisify. Methods with names ending with `'Sync'` are excluded by default. ##### excludeMain 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. ```js const pify = require('pify'); function fn() { return true; } fn.method = (data, callback) => { setImmediate(() => { callback(null, data); }); }; // Promisify methods but not `fn()` const promiseFn = pify(fn, {excludeMain: true}); if (promiseFn()) { promiseFn.method('hi').then(data => { console.log(data); }); } ``` ##### errorFirst Type: `boolean`
Default: `true` Whether the callback has an error as the first argument. You'll want to set this to `false` if you're dealing with an API that doesn't have an error as the first argument, like `fs.exists()`, some browser APIs, Chrome Extension APIs, etc. ##### promiseModule Type: `Function` Custom promise module to use instead of the native one. Check out [`pinkie-promise`](https://github.com/floatdrop/pinkie-promise) if you need a tiny promise polyfill. ## Related - [p-event](https://github.com/sindresorhus/p-event) - Promisify an event by waiting for it to be emitted - [p-map](https://github.com/sindresorhus/p-map) - Map over promises concurrently - [More…](https://github.com/sindresorhus/promise-fun) ## License MIT © [Sindre Sorhus](https://sindresorhus.com) pify-3.0.0/test.js000066400000000000000000000161661311246652700140170ustar00rootroot00000000000000import util from 'util'; import fs from 'fs'; import stream from 'stream'; import test from 'ava'; import pinkiePromise from 'pinkie-promise'; import m from '.'; const fixture = cb => setImmediate(() => cb(null, 'unicorn')); const fixture1 = cb => setImmediate(() => cb('error', 'unicorn', 'rainbow')); const fixture2 = (x, cb) => setImmediate(() => cb(null, x)); const fixture3 = cb => setImmediate(() => cb(null, 'unicorn', 'rainbow')); const fixture4 = cb => setImmediate(() => { cb(null, 'unicorn'); return 'rainbow'; }); fixture4.meow = cb => { setImmediate(() => { cb(null, 'unicorn'); }); }; const fixture5 = () => 'rainbow'; const fixtureModule = { method1: fixture, method2: fixture, method3: fixture5 }; function FixtureGrandparent() {} FixtureGrandparent.prototype.grandparentMethod1 = fixture; FixtureGrandparent.prototype.overriddenMethod1 = fixture; function FixtureParent() {} util.inherits(FixtureParent, FixtureGrandparent); FixtureParent.prototype.parentMethod1 = fixture; FixtureParent.prototype.overriddenMethod1 = fixture2; FixtureParent.prototype.overriddenValue1 = 2; function FixtureClass() { this.instanceMethod1 = fixture; this.instanceValue1 = 72; } util.inherits(FixtureClass, FixtureParent); FixtureClass.prototype.method1 = fixture; FixtureParent.prototype.overriddenValue1 = 4; FixtureClass.prototype.value1 = 'neo'; test('main', async t => { t.is(typeof m(fixture)().then, 'function'); t.is(await m(fixture)(), 'unicorn'); }); test('error', async t => { t.is(await m(fixture1)().catch(err => err), 'error'); }); test('pass argument', async t => { t.is(await m(fixture2)('rainbow'), 'rainbow'); }); test('custom Promise module', async t => { t.is(await m(fixture, {promiseModule: pinkiePromise})(), 'unicorn'); }); test('multiArgs option', async t => { t.deepEqual(await m(fixture3, {multiArgs: true})(), ['unicorn', 'rainbow']); }); test('multiArgs option — rejection', async t => { t.deepEqual(await m(fixture1, {multiArgs: true})().catch(err => err), ['error', 'unicorn', 'rainbow']); }); test('wrap core method', async t => { t.is(JSON.parse(await m(fs.readFile)('package.json')).name, 'pify'); }); test('module support', async t => { t.is(JSON.parse(await m(fs).readFile('package.json')).name, 'pify'); }); test('module support - doesn\'t transform *Sync methods by default', t => { t.is(JSON.parse(m(fs).readFileSync('package.json')).name, 'pify'); }); test('module support - doesn\'t transform *Stream methods by default', t => { t.true(m(fs).createReadStream('package.json') instanceof stream.Readable); }); test('module support - preserves non-function members', t => { const module = { method: () => {}, nonMethod: 3 }; t.deepEqual(Object.keys(module), Object.keys(m(module))); }); test('module support - transforms only members in options.include', t => { const pModule = m(fixtureModule, { include: ['method1', 'method2'] }); t.is(typeof pModule.method1().then, 'function'); t.is(typeof pModule.method2().then, 'function'); t.not(typeof pModule.method3().then, 'function'); }); test('module support - doesn\'t transform members in options.exclude', t => { const pModule = m(fixtureModule, { exclude: ['method3'] }); t.is(typeof pModule.method1().then, 'function'); t.is(typeof pModule.method2().then, 'function'); t.not(typeof pModule.method3().then, 'function'); }); test('module support - options.include over options.exclude', t => { const pModule = m(fixtureModule, { include: ['method1', 'method2'], exclude: ['method2', 'method3'] }); t.is(typeof pModule.method1().then, 'function'); t.is(typeof pModule.method2().then, 'function'); t.not(typeof pModule.method3().then, 'function'); }); test('module support — function modules', t => { const pModule = m(fixture4); t.is(typeof pModule().then, 'function'); t.is(typeof pModule.meow().then, 'function'); }); test('module support — function modules exclusion', t => { const pModule = m(fixture4, { excludeMain: true }); t.is(typeof pModule.meow().then, 'function'); t.not(typeof pModule(() => {}).then, 'function'); }); test('`errorFirst` option', async t => { const fixture = (foo, cb) => { cb(foo); }; t.is(await m(fixture, {errorFirst: false})('🦄'), '🦄'); }); test('`errorFirst` option and `multiArgs`', async t => { const fixture = (foo, bar, cb) => { cb(foo, bar); }; t.deepEqual(await m(fixture, { errorFirst: false, multiArgs: true })('🦄', '🌈'), ['🦄', '🌈']); }); test('class support - creates a copy', async t => { const obj = { x: 'foo', y(cb) { setImmediate(() => { cb(null, this.x); }); } }; const pified = m(obj, {bind: false}); obj.x = 'bar'; t.is(await pified.y(), 'foo'); t.is(pified.x, 'foo'); }); test('class support — transforms inherited methods', t => { const instance = new FixtureClass(); const pInstance = m(instance); const flattened = {}; for (let prot = instance; prot; prot = Object.getPrototypeOf(prot)) { Object.assign(flattened, prot); } const keys = Object.keys(flattened); keys.sort(); const pKeys = Object.keys(pInstance); pKeys.sort(); t.deepEqual(keys, pKeys); t.is(instance.value1, pInstance.value1); t.is(typeof pInstance.instanceMethod1().then, 'function'); t.is(typeof pInstance.method1().then, 'function'); t.is(typeof pInstance.parentMethod1().then, 'function'); t.is(typeof pInstance.grandparentMethod1().then, 'function'); }); test('class support — preserves prototype', t => { const instance = new FixtureClass(); const pInstance = m(instance); t.true(pInstance instanceof FixtureClass); }); test('class support — respects inheritance order', async t => { const instance = new FixtureClass(); const pInstance = m(instance); t.is(instance.overriddenValue1, pInstance.overriddenValue1); t.is(await pInstance.overriddenMethod1('rainbow'), 'rainbow'); }); test('class support - transforms only members in options.include, copies all', t => { const instance = new FixtureClass(); const pInstance = m(instance, { include: ['parentMethod1'] }); const flattened = {}; for (let prot = instance; prot; prot = Object.getPrototypeOf(prot)) { Object.assign(flattened, prot); } const keys = Object.keys(flattened); keys.sort(); const pKeys = Object.keys(pInstance); pKeys.sort(); t.deepEqual(keys, pKeys); t.is(typeof pInstance.parentMethod1().then, 'function'); t.not(typeof pInstance.method1(() => {}).then, 'function'); t.not(typeof pInstance.grandparentMethod1(() => {}).then, 'function'); }); test('class support - doesn\'t transform members in options.exclude', t => { const instance = new FixtureClass(); const pInstance = m(instance, { exclude: ['grandparentMethod1'] }); t.not(typeof pInstance.grandparentMethod1(() => {}).then, 'function'); t.is(typeof pInstance.parentMethod1().then, 'function'); }); test('class support - options.include over options.exclude', t => { const instance = new FixtureClass(); const pInstance = m(instance, { include: ['method1', 'parentMethod1'], exclude: ['parentMethod1', 'grandparentMethod1'] }); t.is(typeof pInstance.method1().then, 'function'); t.is(typeof pInstance.parentMethod1().then, 'function'); t.not(typeof pInstance.grandparentMethod1(() => {}).then, 'function'); });