pax_global_header00006660000000000000000000000064136305413200014507gustar00rootroot0000000000000052 comment=17c5efbc1bc96c201d8b0b116d43f7b5e2cad297 universalify-1.0.0/000077500000000000000000000000001363054132000142255ustar00rootroot00000000000000universalify-1.0.0/.gitignore000066400000000000000000000012211363054132000162110ustar00rootroot00000000000000# Logs logs *.log npm-debug.log* # Runtime data pids *.pid *.seed *.pid.lock # Directory for instrumented libs generated by jscoverage/JSCover lib-cov # Coverage directory used by tools like istanbul coverage # nyc test coverage .nyc_output # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) .grunt # node-waf configuration .lock-wscript # Compiled binary addons (http://nodejs.org/api/addons.html) build/Release # Dependency directories node_modules jspm_packages # Optional npm cache directory .npm # Optional eslint cache .eslintcache # Optional REPL history .node_repl_history # Output of 'npm pack' *.tgz universalify-1.0.0/.travis.yml000066400000000000000000000001501363054132000163320ustar00rootroot00000000000000language: node_js node_js: - "12" - "10" after_success: nyc report --reporter=text-lcov | coveralls universalify-1.0.0/LICENSE000066400000000000000000000021141363054132000152300ustar00rootroot00000000000000(The MIT License) Copyright (c) 2017, Ryan Zimmerman 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. universalify-1.0.0/README.md000066400000000000000000000037261363054132000155140ustar00rootroot00000000000000# universalify [![Travis branch](https://img.shields.io/travis/RyanZim/universalify/master.svg)](https://travis-ci.org/RyanZim/universalify) ![Coveralls github branch](https://img.shields.io/coveralls/github/RyanZim/universalify/master.svg) ![npm](https://img.shields.io/npm/dm/universalify.svg) ![npm](https://img.shields.io/npm/l/universalify.svg) Make a callback- or promise-based function support both promises and callbacks. Uses the native promise implementation. ## Installation ```bash npm install universalify ``` ## API ### `universalify.fromCallback(fn)` Takes a callback-based function to universalify, and returns the universalified function. Function must take a callback as the last parameter that will be called with the signature `(error, result)`. `universalify` does not support calling the callback with three or more arguments, and does not ensure that the callback is only called once. ```js function callbackFn (n, cb) { setTimeout(() => cb(null, n), 15) } const fn = universalify.fromCallback(callbackFn) // Works with Promises: fn('Hello World!') .then(result => console.log(result)) // -> Hello World! .catch(error => console.error(error)) // Works with Callbacks: fn('Hi!', (error, result) => { if (error) return console.error(error) console.log(result) // -> Hi! }) ``` ### `universalify.fromPromise(fn)` Takes a promise-based function to universalify, and returns the universalified function. Function must return a valid JS promise. `universalify` does not ensure that a valid promise is returned. ```js function promiseFn (n) { return new Promise(resolve => { setTimeout(() => resolve(n), 15) }) } const fn = universalify.fromPromise(promiseFn) // Works with Promises: fn('Hello World!') .then(result => console.log(result)) // -> Hello World! .catch(error => console.error(error)) // Works with Callbacks: fn('Hi!', (error, result) => { if (error) return console.error(error) console.log(result) // -> Hi! }) ``` ## License MIT universalify-1.0.0/index.js000066400000000000000000000012731363054132000156750ustar00rootroot00000000000000'use strict' exports.fromCallback = function (fn) { return Object.defineProperty(function (...args) { if (typeof args[args.length - 1] === 'function') fn.apply(this, args) else { return new Promise((resolve, reject) => { fn.apply( this, args.concat([(err, res) => err ? reject(err) : resolve(res)]) ) }) } }, 'name', { value: fn.name }) } exports.fromPromise = function (fn) { return Object.defineProperty(function (...args) { const cb = args[args.length - 1] if (typeof cb !== 'function') return fn.apply(this, args) else fn.apply(this, args.slice(0, -1)).then(r => cb(null, r), cb) }, 'name', { value: fn.name }) } universalify-1.0.0/package.json000066400000000000000000000014651363054132000165210ustar00rootroot00000000000000{ "name": "universalify", "version": "1.0.0", "description": "Make a callback- or promise-based function support both promises and callbacks.", "keywords": [ "callback", "native", "promise" ], "homepage": "https://github.com/RyanZim/universalify#readme", "bugs": "https://github.com/RyanZim/universalify/issues", "license": "MIT", "author": "Ryan Zimmerman ", "files": [ "index.js" ], "repository": { "type": "git", "url": "git+https://github.com/RyanZim/universalify.git" }, "scripts": { "test": "standard && nyc tape test/*.js | colortape" }, "devDependencies": { "colortape": "^0.1.2", "coveralls": "^3.0.1", "nyc": "^15.0.0", "standard": "^14.3.1", "tape": "^4.6.3" }, "engines": { "node": ">= 10.0.0" } } universalify-1.0.0/test/000077500000000000000000000000001363054132000152045ustar00rootroot00000000000000universalify-1.0.0/test/from-callback.js000066400000000000000000000024701363054132000202420ustar00rootroot00000000000000'use strict' const test = require('tape') const universalify = require('..') const fn = universalify.fromCallback(function (a, b, cb) { setTimeout(() => cb(null, [this, a, b]), 15) }) const errFn = universalify.fromCallback(function (cb) { setTimeout(() => cb(new Error('test')), 15) }) test('callback function works with callbacks', t => { t.plan(4) fn.call({ a: 'a' }, 1, 2, (err, arr) => { t.ifError(err, 'should not error') t.is(arr[0].a, 'a') t.is(arr[1], 1) t.is(arr[2], 2) t.end() }) }) test('callback function works with promises', t => { t.plan(3) fn.call({ a: 'a' }, 1, 2) .then(arr => { t.is(arr[0].a, 'a') t.is(arr[1], 1) t.is(arr[2], 2) t.end() }) .catch(t.end) }) test('callback function error works with callbacks', t => { t.plan(2) errFn(err => { t.assert(err, 'should error') t.is(err.message, 'test') t.end() }) }) test('callback function error works with promises', t => { t.plan(2) errFn() .then(() => t.end('Promise should not resolve')) .catch(err => { t.assert(err, 'should error') t.is(err.message, 'test') t.end() }) }) test('fromCallback() sets correct .name', t => { t.plan(1) const res = universalify.fromCallback(function hello () {}) t.is(res.name, 'hello') t.end() }) universalify-1.0.0/test/from-promise.js000066400000000000000000000046351363054132000201710ustar00rootroot00000000000000'use strict' const test = require('tape') const universalify = require('..') const fn = universalify.fromPromise(function (a, b) { return new Promise(resolve => { setTimeout(() => resolve([this, a, b]), 15) }) }) const errFn = universalify.fromPromise(function () { return new Promise((resolve, reject) => { setTimeout(() => reject(new Error('test')), 15) }) }) test('promise function works with callbacks', t => { t.plan(4) fn.call({ a: 'a' }, 1, 2, (err, arr) => { t.ifError(err, 'should not error') t.is(arr[0].a, 'a') t.is(arr[1], 1) t.is(arr[2], 2) t.end() }) }) test('promise function works with promises', t => { t.plan(3) fn.call({ a: 'a' }, 1, 2) .then(arr => { t.is(arr[0].a, 'a') t.is(arr[1], 1) t.is(arr[2], 2) t.end() }) .catch(t.end) }) test('promise function optional param works with callbacks', t => { t.plan(4) fn.call({ a: 'a' }, 1, (err, arr) => { t.ifError(err, 'should not error') t.is(arr[0].a, 'a') t.is(arr[1], 1) t.is(arr[2], undefined) t.end() }) }) test('promise function optional param works with promises', t => { t.plan(3) fn.call({ a: 'a' }, 1) .then(arr => { t.is(arr[0].a, 'a') t.is(arr[1], 1) t.is(arr[2], undefined) t.end() }) .catch(t.end) }) test('promise function error works with callbacks', t => { t.plan(2) errFn(err => { t.assert(err, 'should error') t.is(err.message, 'test') t.end() }) }) test('promise function error works with promises', t => { t.plan(2) errFn() .then(() => t.end('Promise should not resolve')) .catch(err => { t.assert(err, 'should error') t.is(err.message, 'test') t.end() }) }) test('fromPromise() sets correct .name', t => { t.plan(1) const res = universalify.fromPromise(function hello () {}) t.is(res.name, 'hello') t.end() }) test('fromPromise() handles an error in callback correctly', t => { // We need to make sure that the callback isn't called twice if there's an // error inside the callback. This should instead generate an unhandled // promise rejection. We verify one is created, with the correct message. t.plan(2) const errMsg = 'some callback error' process.once('unhandledRejection', (err) => { t.is(err.message, errMsg, 'correct error message') }) fn(1, 2, err => { t.ifError(err, 'no error here') throw new Error(errMsg) }) })