Comparing version 0.0.2 to 0.1.0
{ | ||
"name": "pipep", | ||
"description": "Functional, composable, immutable and curried promise sequences that automatically handle Promise resolution.", | ||
"version": "0.0.2", | ||
"version": "0.1.0", | ||
"author": "Declan de Wet <declandewet@me.com>", | ||
@@ -14,2 +14,3 @@ "ava": { | ||
"ava": "^0.15.2", | ||
"babel-eslint": "^6.1.0", | ||
"codecov": "^1.0.1", | ||
@@ -19,2 +20,3 @@ "cross-env": "^1.0.8", | ||
"nyc": "^6.6.1", | ||
"standard": "^7.1.2", | ||
"uglify-js": "^2.6.4", | ||
@@ -47,3 +49,3 @@ "umd": "^3.0.1" | ||
"include": [ | ||
"src/*.js" | ||
"index.js" | ||
], | ||
@@ -61,4 +63,4 @@ "reporter": [ | ||
"build": "concurrently \"npm run build-umd\" \"npm run build-umd-min\"", | ||
"build-umd": "cat src/index.js | umd pipe-p -c > pipep.js", | ||
"build-umd-min": "cat src/index.js | umd pipe-p -c | uglifyjs -c -m > pipep.min.js", | ||
"build-umd": "cat index.js | umd pipe-p -c > pipep.js", | ||
"build-umd-min": "cat index.js | umd pipe-p -c | uglifyjs -c -m > pipep.min.js", | ||
"codecov": "npm run coverage && codecov", | ||
@@ -65,0 +67,0 @@ "coverage": "cross-env NODE_ENV=test nyc report", |
206
pipep.js
(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.pipeP = f()}})(function(){var define,module,exports;module={exports:(exports={})}; | ||
'use strict' | ||
module.exports = pipeP | ||
// enable point-free capabilities | ||
var call = curry(_call) | ||
var replace = curry(_replace) | ||
var resolvePromises = curry(_resolvePromises) | ||
var _slice = [].slice | ||
/** | ||
@@ -22,74 +23,64 @@ * returns a variadic function that pipes its arguments through a promise chain | ||
*/ | ||
function pipeP () { | ||
module.exports = function pipeP () { | ||
// throw error if environment has no Promise support | ||
if (Promise == null) { | ||
throw new Error('[pipeP] Use a `Promise` polyfill for environments that do not support native ES2015 Promises.') | ||
if (!exists(Promise)) { | ||
throw new Error(s('Use a `Promise` polyfill for environments that do not support native ES2015 Promises.')) | ||
} | ||
// throw error if environment has no Object.assign support | ||
if (!_is(Function, Object.assign)) { | ||
throw new Error('[pipeP] Use an `Object.assign` polyfill for environments that do not support native ES2015 Object properties.') | ||
if (!is(Function, Object.assign)) { | ||
throw new Error(s('Use an `Object.assign` polyfill for environments that do not support native ES2015 Object properties.')) | ||
} | ||
// flatten arguments in case they contain arrays | ||
var rest = _slice.apply(arguments).reduce(function concat (prev, next) { | ||
return prev.concat(next) | ||
}, []) | ||
var remainingHandlers = flatten(arrayFrom(arguments)) | ||
// grab the initial handler from args | ||
var initial = rest.shift() | ||
var initialHandler = remainingHandlers.shift() | ||
// throw if first handler is missing | ||
if (!initial) { | ||
throw new SyntaxError('[pipeP] expects at least one argument') | ||
if (!exists(initialHandler)) { | ||
throw new SyntaxError(s('expects at least one argument')) | ||
} | ||
// throw if first handler has incorrect type | ||
if (!_is(Function, initial)) { | ||
throw new SyntaxError('[pipeP] first handler must be a variadic function that returns a promise or value') | ||
if (!is(Function, initialHandler)) { | ||
throw new SyntaxError(s('first handler must be a variadic function that returns a promise or value')) | ||
} | ||
// create curried executor function that accepts n paramaters and evaluates all functions as a dynamic promise chain | ||
var _executor = _curryN(initial.length, function _executor () { | ||
var values = _slice.apply(arguments) | ||
// store arity of initial handler for future reference | ||
var initialArity = length(initialHandler) | ||
// prevent mutations | ||
var clonedValues = values.map(function clone (val) { | ||
if (_is(Function, val.then)) { // if val is a promise, just return it | ||
return val | ||
} else if (_is(Array, val)) { | ||
return Promise.all([].concat(val)) // wait for resolution of arrays containing promises | ||
} else if (_is(Object, val)) { | ||
return Object.assign({}, val) | ||
} | ||
return val | ||
}) | ||
// create curried sequencer function that accepts n paramaters and evaluates all functions as a dynamic promise chain | ||
var callSequence = curryN(initialArity, function executor () { | ||
// duplicate values & resolve all individual promises | ||
var resolvedValues = arrayFrom(arguments).map(resolvePromises({ duplicate: true })) | ||
// compute initial values | ||
var computedValues = Promise.all(clonedValues).then(function initialize (args) { | ||
return initial.apply(null, args) | ||
}) | ||
var initialComputation = Promise.all(resolvedValues).then(call(initialHandler)) | ||
// pipe all handlers through promise chain | ||
var promise = rest.reduce(function sequence (prev, next, i) { | ||
if (_is(Function, next)) { | ||
return prev.then(resolveArrayValue).then(next) | ||
} | ||
var promiseForFinalComputation = remainingHandlers.reduce(function sequence (prev, next, i) { | ||
return is(Function, next) | ||
// resolve individual promises before calling next handler | ||
? prev.then(resolvePromises(null)).then(next) | ||
// if next handler is not a function, reject the promise | ||
: Promise.reject(new SyntaxError(s("expected handler '%d' to have type 'function', got '%s': '%s'", i + 2, typeof next, next))) | ||
}, initialComputation) | ||
// if next handler is not a function, reject the promise | ||
return Promise.reject(new SyntaxError("[pipeP] expected handler '" + (i + 2) + "' to have type 'function', got '" + typeof next + "': '" + next + "'")) | ||
}, computedValues) | ||
// return resolved promise in case of arrays | ||
return promise.then(resolveArrayValue) | ||
// resolve individual promises in final computation | ||
return promiseForFinalComputation.then(resolvePromises(null)) | ||
}) | ||
// ensure returned executor reports correct arity | ||
Object.defineProperty(_executor, 'length', { | ||
get: function get () { | ||
return initial.length | ||
} | ||
}) | ||
try { | ||
// ensure sequencer reports correct arity so currying works when callSequence is the first handler in a sequence | ||
Object.defineProperty(callSequence, 'length', { | ||
get: function get () { | ||
return initialArity | ||
} | ||
}) | ||
} catch (error) {} // supress errors on Object.defineProperty in case of IE8 | ||
return _executor | ||
// return the promise-sequence-calling curried function | ||
return callSequence | ||
} | ||
@@ -99,10 +90,66 @@ | ||
* Calls Promise.all on passed value if it is an array | ||
* Duplicates value if required. | ||
* @param {Object} opts - options | ||
* @param {*} val - value to resolve | ||
* @return {*} - if val is an array, a promise for all resolved elements, else the original value | ||
*/ | ||
function resolveArrayValue (val) { | ||
return _is(Array, val) ? Promise.all(val) : val | ||
function _resolvePromises (opts, val) { | ||
opts = opts || {} | ||
var duplicate = opts.duplicate | ||
if (is(Array, val)) { | ||
return Promise.all(duplicate ? concat([], val) : val) | ||
} else if (duplicate && is(Object, val) && !is(Function, val.then)) { | ||
return Object.assign({}, val) | ||
} | ||
return val | ||
} | ||
/** | ||
* Flattens an array of arrays and values into an array of values | ||
* @param {Array} list - the array to flatten | ||
* @return {Array} - flattened result | ||
*/ | ||
function flatten (list) { | ||
return list.reduce(concat, []) | ||
} | ||
/** | ||
* Converts an array-like object into an array | ||
* @param {Object} args - an array-like object | ||
* @return {Array} - array representation | ||
*/ | ||
function arrayFrom (args) { | ||
return [].slice.apply(args) | ||
} | ||
/** | ||
* Returns the length property of passed value | ||
* @param {*} val - Object to access length on | ||
* @return {Number} - Object's length value | ||
*/ | ||
function length (val) { | ||
return val.length | ||
} | ||
/** | ||
* Calls a function with supplied arguments | ||
* @param {Function} fn - function to call | ||
* @param {Array} args - array of arguments to supply | ||
* @return {*} - return value of function `fn` called with `args` | ||
*/ | ||
function _call (fn, args) { | ||
return fn.apply(null, args) | ||
} | ||
/** | ||
* Concatenates "b" onto "a" | ||
* @param {String|Array} a - the value in which to concat | ||
* @param {*} b - value to concat onto "a" | ||
* @return {String|Array} - the new value containing "a" & "b" merged | ||
*/ | ||
function concat (a, b) { | ||
return a.concat(b) | ||
} | ||
/** | ||
* Checks that the type of value provided as second argument is the same as the constructor provided as first argument | ||
@@ -113,7 +160,25 @@ * @param {Function} Ctor - Constructor function / class of the type to check on `val` | ||
*/ | ||
function _is (Ctor, val) { | ||
return val != null && val.constructor === Ctor || val instanceof Ctor | ||
function is (Ctor, val) { | ||
return exists(val) && val.constructor === Ctor || val instanceof Ctor | ||
} | ||
/** | ||
* Checks if val is not null or undefined. | ||
* @param {*} val - value to check | ||
* @return {Boolean} - true if val exists | ||
*/ | ||
function exists (val) { | ||
return val != null | ||
} | ||
/** | ||
* Takes a function and curries it to it's own arity | ||
* @param {Function} fn - function to curry | ||
* @return {Function} - curried function | ||
*/ | ||
function curry (fn) { | ||
return _curry(length(fn), fn) | ||
} | ||
/** | ||
* Takes an arity and a function and returns a new function curried to arity | ||
@@ -124,3 +189,3 @@ * @param {Number} n - arity | ||
*/ | ||
function _curryN (n, fn) { | ||
function curryN (n, fn) { | ||
return _curry(n, fn) | ||
@@ -139,10 +204,33 @@ } | ||
return function partial () { | ||
var rest = _slice.apply(arguments) | ||
var allArgs = args.concat(rest) | ||
return n > allArgs.length | ||
var rest = arrayFrom(arguments) | ||
var allArgs = concat(args, rest) | ||
return n > length(allArgs) | ||
? _curry(n, fn, allArgs) | ||
: fn.apply(null, allArgs.slice(0, n)) | ||
: _call(fn, allArgs.slice(0, n)) | ||
} | ||
} | ||
/** | ||
* Replaces `pattern` found in `str` with `val` | ||
* @param {Regex|String} pattern - the pattern to replace | ||
* @param {*} val - the value that will replace pattern | ||
* @param {String} str - the string which is being manipulated | ||
* @return {String} - the new string | ||
*/ | ||
function _replace (pattern, str, val) { | ||
return str.replace(pattern, val) | ||
} | ||
/** | ||
* Generic error message utility. Takes a formatted string | ||
* and returns that string with a `[pipep]` label. | ||
* Behaves in similar fashion to `sprintf` | ||
* @return {String} - the new message | ||
*/ | ||
function s () { | ||
var args = arrayFrom(arguments) | ||
var msg = args.shift() | ||
return args.reduce(replace(/(?:%s|%d)/), '[pipeP] ' + msg) | ||
} | ||
return module.exports;}); |
@@ -1,1 +0,1 @@ | ||
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;n="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,n.pipeP=e()}}(function(){function e(){if(null==Promise)throw new Error("[pipeP] Use a `Promise` polyfill for environments that do not support native ES2015 Promises.");if(!t(Function,Object.assign))throw new Error("[pipeP] Use an `Object.assign` polyfill for environments that do not support native ES2015 Object properties.");var e=a.apply(arguments).reduce(function(e,n){return e.concat(n)},[]),o=e.shift();if(!o)throw new SyntaxError("[pipeP] expects at least one argument");if(!t(Function,o))throw new SyntaxError("[pipeP] first handler must be a variadic function that returns a promise or value");var i=r(o.length,function(){var r=a.apply(arguments),i=r.map(function(e){return t(Function,e.then)?e:t(Array,e)?Promise.all([].concat(e)):t(Object,e)?Object.assign({},e):e}),u=Promise.all(i).then(function(e){return o.apply(null,e)}),p=e.reduce(function(e,r,o){return t(Function,r)?e.then(n).then(r):Promise.reject(new SyntaxError("[pipeP] expected handler '"+(o+2)+"' to have type 'function', got '"+typeof r+"': '"+r+"'"))},u);return p.then(n)});return Object.defineProperty(i,"length",{get:function(){return o.length}}),i}function n(e){return t(Array,e)?Promise.all(e):e}function t(e,n){return null!=n&&n.constructor===e||n instanceof e}function r(e,n){return o(e,n)}function o(e,n,t){return t=t||[],function(){var r=a.apply(arguments),i=t.concat(r);return e>i.length?o(e,n,i):n.apply(null,i.slice(0,e))}}var i,u;i={exports:u={}},i.exports=e;var a=[].slice;return i.exports}); | ||
!function(n){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=n();else if("function"==typeof define&&define.amd)define([],n);else{var e;e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,e.pipeP=n()}}(function(){function n(n,e){n=n||{};var t=n.duplicate;return u(Array,e)?Promise.all(t?i([],e):e):t&&u(Object,e)&&!u(Function,e.then)?Object.assign({},e):e}function e(n){return n.reduce(i,[])}function t(n){return[].slice.apply(n)}function r(n){return n.length}function o(n,e){return n.apply(null,e)}function i(n,e){return n.concat(e)}function u(n,e){return f(e)&&e.constructor===n||e instanceof n}function f(n){return null!=n}function c(n){return s(r(n),n)}function a(n,e){return s(n,e)}function s(n,e,u){return u=u||[],function(){var f=t(arguments),c=i(u,f);return n>r(c)?s(n,e,c):o(e,c.slice(0,n))}}function l(n,e,t){return e.replace(n,t)}function p(){var n=t(arguments),e=n.shift();return n.reduce(v(/(?:%s|%d)/),"[pipeP] "+e)}var d,h;d={exports:h={}};var y=c(o),v=c(l),m=c(n);return d.exports=function(){if(!f(Promise))throw new Error(p("Use a `Promise` polyfill for environments that do not support native ES2015 Promises."));if(!u(Function,Object.assign))throw new Error(p("Use an `Object.assign` polyfill for environments that do not support native ES2015 Object properties."));var n=e(t(arguments)),o=n.shift();if(!f(o))throw new SyntaxError(p("expects at least one argument"));if(!u(Function,o))throw new SyntaxError(p("first handler must be a variadic function that returns a promise or value"));var i=r(o),c=a(i,function(){var e=t(arguments).map(m({duplicate:!0})),r=Promise.all(e).then(y(o)),i=n.reduce(function(n,e,t){return u(Function,e)?n.then(m(null)).then(e):Promise.reject(new SyntaxError(p("expected handler '%d' to have type 'function', got '%s': '%s'",t+2,typeof e,e)))},r);return i.then(m(null))});try{Object.defineProperty(c,"length",{get:function(){return i}})}catch(s){}return c},d.exports}); |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No README
QualityPackage does not have a README. This may indicate a failed publish or a low quality package.
Found 1 instance in 1 package
212
12984
9
4
2
0
1