struct/Collection.js

// https://github.com/discordjs/discord.js/blob/11.5.1/src/util/Collection.js

/**
 * A map with more features
 * @extends {Map}
 */
class Collection extends Map {
	/**
	 * Creates a new Collection
	 */
	constructor(iterable) {
		super(iterable);
	}

	/**
	 * filters the collection, returning a collection of values where items passed in to search function returned a truthy value.
	 * @param {function} search A serch function returning true or false
	 * @returns {Collection} A Collection of matches
	 * @example const bugTables = myApp.types.filter(type => type.name.toLowerCase().includes("bug"));
	 */
	filter(fn) {
		for (const [key, val] of this) {
			if (fn(val, key, this)) results[0].set(key, val);
			else results[1].set(key, val);
		}
		return results;
	}

	/**
	 * Searches for a single item where its specified property's value is identical to the given value
	 * (`item[prop] === value`), or the given function returns a truthy value. In the latter case, this is identical to
	 * Array.find().
	 * @param {string|Function} propOrFn The property to test against, or the function to test with
	 * @param {*} [value] The expected value - only applicable and required if using a property for the first argument
	 * @returns {*}
	 * @example
	 * collection.find('username', 'Bob');
	 * @example
	 * collection.find(val => val.username === 'Bob');
	 */
	find(propOrFn, value) {
		if (typeof propOrFn === 'string') {
		if (typeof value === 'undefined') throw new Error('Value must be specified.');
		for (const item of this.values()) {
			if (item[propOrFn] === value) return item;
		}
		return null;
		} else if (typeof propOrFn === 'function') {
		for (const [key, val] of this) {
			if (propOrFn(val, key, this)) return val;
		}
		return null;
		} else {
		throw new Error('First argument must be a property string or a function.');
		}
	}

	/**
	 * The equivilent of Array.map(), where index is the ID of the item
	 * @param {function} fn A function taking up to three arguments; current item, item ID, current collection
	 * @returns {Collection} A new collection
	 * @example const collectionOfFields = goalType.fields.map(field => field.name);
	 */
	map(fn) {
		const c = new this.constructor();
		for (const [key, val] of this) c.set(key, fn(val, key, this));
		return c;
	}
};
module.exports = Collection;