UNPKG

github-release-info-downloader

Version:

Gets latest release download URL using the GitHub Releases API. It also shows when it was released and the download count.

308 lines (277 loc) 9.55 kB
'use strict'; var lazy = require('../../utils/object').lazy; var isFactory = require('../../utils/object').isFactory; var traverse = require('../../utils/object').traverse; var ArgumentsError = require('../../error/ArgumentsError'); function factory (type, config, load, typed, math) { /** * Import functions from an object or a module * * Syntax: * * math.import(object) * math.import(object, options) * * Where: * * - `object: Object` * An object with functions to be imported. * - `options: Object` An object with import options. Available options: * - `override: boolean` * If true, existing functions will be overwritten. False by default. * - `silent: boolean` * If true, the function will not throw errors on duplicates or invalid * types. False by default. * - `wrap: boolean` * If true, the functions will be wrapped in a wrapper function * which converts data types like Matrix to primitive data types like Array. * The wrapper is needed when extending math.js with libraries which do not * support these data type. False by default. * * Examples: * * // define new functions and variables * math.import({ * myvalue: 42, * hello: function (name) { * return 'hello, ' + name + '!'; * } * }); * * // use the imported function and variable * math.myvalue * 2; // 84 * math.hello('user'); // 'hello, user!' * * // import the npm module 'numbers' * // (must be installed first with `npm install numbers`) * math.import(require('numbers'), {wrap: true}); * * math.fibonacci(7); // returns 13 * * @param {Object | Array} object Object with functions to be imported. * @param {Object} [options] Import options. */ function math_import(object, options) { var num = arguments.length; if (num !== 1 && num !== 2) { throw new ArgumentsError('import', num, 1, 2); } if (!options) { options = {}; } if (isFactory(object)) { _importFactory(object, options); } // TODO: allow a typed-function with name too else if (Array.isArray(object)) { object.forEach(function (entry) { math_import(entry, options); }); } else if (typeof object === 'object') { // a map with functions for (var name in object) { if (object.hasOwnProperty(name)) { var value = object[name]; if (isSupportedType(value)) { _import(name, value, options); } else if (isFactory(object)) { _importFactory(object, options); } else { math_import(value, options); } } } } else { if (!options.silent) { throw new TypeError('Factory, Object, or Array expected'); } } } /** * Add a property to the math namespace and create a chain proxy for it. * @param {string} name * @param {*} value * @param {Object} options See import for a description of the options * @private */ function _import(name, value, options) { // TODO: refactor this function, it's to complicated and contains duplicate code if (options.wrap && typeof value === 'function') { // create a wrapper around the function value = _wrap(value); } if (isTypedFunction(math[name]) && isTypedFunction(value)) { if (options.override) { // give the typed function the right name value = typed(name, value.signatures); } else { // merge the existing and typed function value = typed(math[name], value); } math[name] = value; _importTransform(name, value); math.emit('import', name, function resolver() { return value; }); return; } if (math[name] === undefined || options.override) { math[name] = value; _importTransform(name, value); math.emit('import', name, function resolver() { return value; }); return; } if (!options.silent) { throw new Error('Cannot import "' + name + '": already exists'); } } function _importTransform (name, value) { if (value && typeof value.transform === 'function') { math.expression.transform[name] = value.transform; if (allowedInExpressions(name)) { math.expression.mathWithTransform[name] = value.transform } } else { // remove existing transform delete math.expression.transform[name] if (allowedInExpressions(name)) { math.expression.mathWithTransform[name] = value } } } /** * Create a wrapper a round an function which converts the arguments * to their primitive values (like convert a Matrix to Array) * @param {Function} fn * @return {Function} Returns the wrapped function * @private */ function _wrap (fn) { var wrapper = function wrapper () { var args = []; for (var i = 0, len = arguments.length; i < len; i++) { var arg = arguments[i]; args[i] = arg && arg.valueOf(); } return fn.apply(math, args); }; if (fn.transform) { wrapper.transform = fn.transform; } return wrapper; } /** * Import an instance of a factory into math.js * @param {{factory: Function, name: string, path: string, math: boolean}} factory * @param {Object} options See import for a description of the options * @private */ function _importFactory(factory, options) { if (typeof factory.name === 'string') { var name = factory.name; var existingTransform = name in math.expression.transform var namespace = factory.path ? traverse(math, factory.path) : math; var existing = namespace.hasOwnProperty(name) ? namespace[name] : undefined; var resolver = function () { var instance = load(factory); if (instance && typeof instance.transform === 'function') { throw new Error('Transforms cannot be attached to factory functions. ' + 'Please create a separate function for it with exports.path="expression.transform"'); } if (isTypedFunction(existing) && isTypedFunction(instance)) { if (options.override) { // replace the existing typed function (nothing to do) } else { // merge the existing and new typed function instance = typed(existing, instance); } return instance; } if (existing === undefined || options.override) { return instance; } if (!options.silent) { throw new Error('Cannot import "' + name + '": already exists'); } }; if (factory.lazy !== false) { lazy(namespace, name, resolver); if (!existingTransform) { if (factory.path === 'expression.transform' || factoryAllowedInExpressions(factory)) { lazy(math.expression.mathWithTransform, name, resolver); } } } else { namespace[name] = resolver(); if (!existingTransform) { if (factory.path === 'expression.transform' || factoryAllowedInExpressions(factory)) { math.expression.mathWithTransform[name] = resolver(); } } } math.emit('import', name, resolver, factory.path); } else { // unnamed factory. // no lazy loading load(factory); } } /** * Check whether given object is a type which can be imported * @param {Function | number | string | boolean | null | Unit | Complex} object * @return {boolean} * @private */ function isSupportedType(object) { return typeof object === 'function' || typeof object === 'number' || typeof object === 'string' || typeof object === 'boolean' || object === null || (object && type.isUnit(object)) || (object && type.isComplex(object)) || (object && type.isBigNumber(object)) || (object && type.isFraction(object)) || (object && type.isMatrix(object)) || (object && Array.isArray(object)) } /** * Test whether a given thing is a typed-function * @param {*} fn * @return {boolean} Returns true when `fn` is a typed-function */ function isTypedFunction (fn) { return typeof fn === 'function' && typeof fn.signatures === 'object'; } function allowedInExpressions (name) { return !unsafe.hasOwnProperty(name); } function factoryAllowedInExpressions (factory) { return factory.path === undefined && !unsafe.hasOwnProperty(factory.name); } // namespaces and functions not available in the parser for safety reasons var unsafe = { 'expression': true, 'type': true, 'docs': true, 'error': true, 'json': true, 'chain': true // chain method not supported. Note that there is a unit chain too. }; return math_import; } exports.math = true; // request access to the math namespace as 5th argument of the factory function exports.name = 'import'; exports.factory = factory; exports.lazy = true;