UNPKG

@grandom/pick

Version:

A configurable, flexible, seedable, and overall great random picker.

136 lines (132 loc) 5.44 kB
'use strict'; var core = require('@grandom/core'); // TODO: remove istanbul ignore and write tests for it // TODO: implement unique // TODO: include / exclude / filter function // TODO: implement edge cases (including infinite loops) const DEFAULT_FALLBACK = undefined; class RandomPick extends core.RandomGenerator { // ----------------------------------------------------------------------------------------------- pick(arg1, arg2, arg3) { if (typeof arg1 !== 'undefined') { let count; let options = {}; // process count and options if (typeof arg2 !== 'undefined') { if (typeof arg2 === 'number') { count = arg2; } else if (typeof arg2 === 'object' && arg2 !== null) { options = arg2; } else { throw new TypeError('2nd argument must be a number (count), or an object (options), ' + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions `got: ${arg2} (typeof === '${typeof arg2}').`); } if (typeof arg3 !== 'undefined') { /* istanbul ignore next */ if (typeof arg3 === 'object' && arg3 !== null) { options = arg3; } else { throw new TypeError('3rd argument must be an object (options), ' + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions `got: ${arg3} (typeof === '${typeof arg3}').`); } } } // process strings if (typeof arg1 === 'string') { return this._pickString(arg1, count, options); // process arrays } else if (Array.isArray(arg1)) { return this._pickArray(arg1, count, options); // process objects } else if (typeof arg1 === 'object' && arg1 !== null) { return this._pickObject(arg1, count, options); } } // type guard ---------------------------------------------------------------------------------- throw new TypeError( // eslint-disable-next-line @typescript-eslint/restrict-template-expressions `Must be called with a string, array, or object, got: ${arg1} (typeof === '${typeof arg1}').`); } _pickString(string, count, options) { if (typeof count !== 'undefined') { // NaN check and bound checks // eslint-disable-next-line no-self-compare if (count !== count || count < 1 || count > Number.MAX_SAFE_INTEGER) { throw new RangeError(`Count must be 1 >= count <= Number.MAX_SAFE_INTEGER, got: ${count}.`); } } // return the fallback if the string is empty ('') if (string.length === 0) { return 'fallback' in options ? options.fallback : DEFAULT_FALLBACK; } if (count > 1) { let str = ''; for (let i = 0; i < count; i++) { str += this._engine.pickArray(string); } return str; } return this._engine.pickArray(string); } _pickArray(array, count, options) { if (typeof count !== 'undefined') { // NaN check and bound checks // eslint-disable-next-line no-self-compare if (count !== count || count < 1 || count > Number.MAX_SAFE_INTEGER) { throw new RangeError(`Count must be 1 >= count <= Number.MAX_SAFE_INTEGER, got: ${count}.`); } } // return the fallback if the array is empty ([]) if (array.length === 0) { return 'fallback' in options ? options.fallback : DEFAULT_FALLBACK; } if (count > 1) { const result = []; for (let i = 0; i < count; i++) { result.push(this._engine.pickArray(array)); } return result; } return this._engine.pickArray(array); } _pickObject(object, count, options) { if (typeof count !== 'undefined') { // NaN check and bound checks // eslint-disable-next-line no-self-compare if (count !== count || count < 1 || count > Number.MAX_SAFE_INTEGER) { throw new RangeError(`Count must be 1 >= count <= Number.MAX_SAFE_INTEGER, got: ${count}.`); } } const keys = Object.keys(object); // return the fallback if the keys array is empty (object === {}) if (keys.length === 0) { return 'fallback' in options ? options.fallback : DEFAULT_FALLBACK; } if (count > 1) { const result = []; let key; for (let i = 0; i < count; i++) { key = this._engine.pickArray(keys); result.push([key, object[key]]); } return result; } const key = this._engine.pickArray(keys); return [key, object[key]]; } } module.exports = RandomPick; //# sourceMappingURL=index.js.map