UNPKG

ts-data-forge

Version:

[![npm version](https://img.shields.io/npm/v/ts-data-forge.svg)](https://www.npmjs.com/package/ts-data-forge) [![npm downloads](https://img.shields.io/npm/dm/ts-data-forge.svg)](https://www.npmjs.com/package/ts-data-forge) [![License](https://img.shields.

362 lines (359 loc) 12.1 kB
import '../number/branded-types/finite-number.mjs'; import '../number/branded-types/int.mjs'; import '../number/branded-types/int16.mjs'; import '../number/branded-types/int32.mjs'; import '../number/branded-types/non-negative-finite-number.mjs'; import '../number/branded-types/non-negative-int16.mjs'; import '../number/branded-types/non-negative-int32.mjs'; import '../number/branded-types/non-zero-finite-number.mjs'; import '../number/branded-types/non-zero-int.mjs'; import '../number/branded-types/non-zero-int16.mjs'; import '../number/branded-types/non-zero-int32.mjs'; import '../number/branded-types/non-zero-safe-int.mjs'; import '../number/branded-types/non-zero-uint16.mjs'; import '../number/branded-types/non-zero-uint32.mjs'; import '../number/branded-types/positive-finite-number.mjs'; import '../number/branded-types/positive-int.mjs'; import '../number/branded-types/positive-int16.mjs'; import '../number/branded-types/positive-int32.mjs'; import '../number/branded-types/positive-safe-int.mjs'; import '../number/branded-types/positive-uint16.mjs'; import '../number/branded-types/positive-uint32.mjs'; import '../number/branded-types/safe-int.mjs'; import '../number/branded-types/safe-uint.mjs'; import '../number/branded-types/uint.mjs'; import '../number/branded-types/uint16.mjs'; import { asUint32 } from '../number/branded-types/uint32.mjs'; import '../number/enum/int8.mjs'; import '../number/enum/uint8.mjs'; import '../number/num.mjs'; import '../number/refined-number-utils.mjs'; import { unknownToString } from '../others/unknown-to-string.mjs'; // No imports from functional needed anymore /** Provides utility functions for ISet. */ var ISet; (function (ISet) { /** * Creates a new ISet instance from an iterable of elements. * * This factory function accepts any iterable of elements, including arrays, * JavaScript Sets, other ISets, or custom iterables. Duplicate elements in * the input iterable will be automatically deduplicated in the resulting * set. * * **Performance:** O(n) where n is the number of elements in the iterable. * * @example * * ```ts * const set = ISet.create(['a', 'a', 'b']); * * assert.deepStrictEqual(Array.from(set), ['a', 'b']); * ``` * * @template K The type of the elements. Must extend MapSetKeyType. * @param iterable An iterable of elements (e.g., Array, Set, ISet, etc.) * @returns A new ISet instance containing all unique elements from the * iterable. */ ISet.create = (iterable) => new ISetClass(iterable); /** * Checks if two ISet instances are structurally equal. * * Two ISets are considered equal if they have the same size and contain * exactly the same elements. The order of elements does not matter for * equality comparison since sets are unordered collections. Elements are * compared using JavaScript's `===` operator. * * **Performance:** O(n) where n is the size of the smaller set. * * @example * * ```ts * const first = ISet.create<number>([1, 2]); * * const second = ISet.create<number>([2, 1]); * * const third = ISet.create<number>([1, 3]); * * assert.isTrue(ISet.equal(first, second)); * * assert.isFalse(ISet.equal(first, third)); * ``` * * @template K The type of the elements. * @param a The first ISet instance to compare. * @param b The second ISet instance to compare. * @returns `true` if the sets contain exactly the same elements, `false` * otherwise. */ ISet.equal = (a, b) => a.size === b.size && a.every((e) => b.has(e)); /** * Computes the difference between two ISet instances, identifying added and * deleted elements. * * This function performs a set difference operation to determine what * elements were added and what elements were deleted when transitioning from * the old set to the new set. This is useful for change detection, state * management, and synchronization scenarios. * * **Performance:** O(n + m) where n and m are the sizes of the old and new * sets respectively. * * @example * * ```ts * const previous = ISet.create<string>(['draft', 'review']); * * const current = ISet.create<string>(['review', 'published']); * * const { added, deleted } = ISet.diff(previous, current); * * assert.deepStrictEqual(Array.from(added), ['published']); * * assert.deepStrictEqual(Array.from(deleted), ['draft']); * ``` * * @template K The type of the elements. * @param oldSet The original set representing the previous state. * @param newSet The new set representing the current state. * @returns An object with `added` and `deleted` properties, each containing * an ISet of elements that were added or removed respectively. */ ISet.diff = (oldSet, newSet) => ({ deleted: oldSet.subtract(newSet), added: newSet.subtract(oldSet), }); /** * Computes the intersection of two ISet instances. * * Returns a new set containing only the elements that are present in both * input sets. This operation is commutative: `intersection(a, b) === * intersection(b, a)`. * * **Performance:** O(min(n, m)) where n and m are the sizes of the input * sets. * * @example * * ```ts * const left = ISet.create<number>([1, 2, 3]); * * const right = ISet.create<number>([2, 4]); * * const overlap = ISet.intersection(left, right); * * assert.deepStrictEqual(Array.from(overlap), [2]); * ``` * * @template K The type of the elements. * @param a The first set. * @param b The second set. * @returns A new ISet instance containing elements common to both sets. */ ISet.intersection = (a, b) => a.intersect(b); /** * Computes the union of two ISet instances. * * Returns a new set containing all elements that are present in either input * set. Duplicate elements are automatically handled since sets only contain * unique values. This operation is commutative: `union(a, b) === union(b, * a)`. * * **Performance:** O(n + m) where n and m are the sizes of the input sets. * * @example * * ```ts * const numbers = ISet.create([1, 2]); * * const words = ISet.create(['one', 'two']); * * const union = ISet.union(numbers, words); * * assert.deepStrictEqual(Array.from(union), [1, 2, 'one', 'two']); * ``` * * @template K1 The type of elements in the first set. * @template K2 The type of elements in the second set. * @param a The first set. * @param b The second set. * @returns A new ISet instance containing all elements from both sets. */ ISet.union = (a, b) => a.union(b); })(ISet || (ISet = {})); /** * Internal class implementation for ISet providing immutable set operations. * * This class implements the ISet interface using JavaScript's native Set as the * underlying storage mechanism for optimal performance. All mutation operations * create new instances rather than modifying the existing set, ensuring * immutability. * * **Implementation Details:** * * - Uses ReadonlySet<K> internally for type safety and performance * - Implements copy-on-write semantics for efficiency * - Provides optional debug messaging for development * * @template K The type of the elements. Must extend MapSetKeyType. * @implements ISet * @implements Iterable * @internal This class should not be used directly. Use ISet.create() instead. */ class ISetClass { #set; #showNotFoundMessage; /** * Constructs an ISetClass instance with the given elements. * * @param iterable An iterable of elements to populate the set. * @param showNotFoundMessage Whether to log warning messages when operations * are performed on non-existent elements. Useful for debugging. Defaults to * false for production use. * @internal Use ISet.create() instead of calling this constructor directly. */ constructor(iterable, showNotFoundMessage = false) { this.#set = new Set(iterable); this.#showNotFoundMessage = showNotFoundMessage; } /** @inheritdoc */ get size() { return asUint32(this.#set.size); } /** @inheritdoc */ get isEmpty() { return this.size === 0; } /** @inheritdoc */ has(key) { // eslint-disable-next-line total-functions/no-unsafe-type-assertion return this.#set.has(key); } /** @inheritdoc */ every(predicate) { for (const key of this.values()) { if (!predicate(key)) return false; } return true; } /** @inheritdoc */ some(predicate) { for (const key of this.values()) { if (predicate(key)) return true; } return false; } /** @inheritdoc */ add(key) { if (this.has(key)) return this; return ISet.create([...this.#set, key]); } /** @inheritdoc */ delete(key) { if (!this.has(key)) { if (this.#showNotFoundMessage) { const keyStr = unknownToString(key); console.warn(`ISet.delete: key not found: ${keyStr}`); } return this; } return ISet.create(Array.from(this.#set).filter((k) => !Object.is(k, key))); } /** @inheritdoc */ withMutations(actions) { const mut_result = new Set(this.#set); for (const action of actions) { switch (action.type) { case 'delete': mut_result.delete(action.key); break; case 'add': mut_result.add(action.key); break; } } return ISet.create(mut_result); } /** @inheritdoc */ map(mapFn) { return ISet.create(this.toArray().map(mapFn)); } /** @inheritdoc */ filter(predicate) { return ISet.create(this.toArray().filter(predicate)); } /** @inheritdoc */ filterNot(predicate) { return ISet.create(this.toArray().filter((e) => !predicate(e))); } /** @inheritdoc */ forEach(callbackfn) { for (const v of this.#set.values()) { callbackfn(v); } } /** @inheritdoc */ isSubsetOf(set) { // eslint-disable-next-line total-functions/no-unsafe-type-assertion return this.every((k) => set.has(k)); } /** @inheritdoc */ isSupersetOf(set) { // eslint-disable-next-line total-functions/no-unsafe-type-assertion return set.every((k) => this.has(k)); } /** @inheritdoc */ subtract(set) { return ISet.create(this.toArray().filter((k) => !set.has(k))); } /** @inheritdoc */ intersect(set) { return ISet.create(this.toArray().filter((k) => set.has(k))); } /** @inheritdoc */ union(set) { return ISet.create([...this, ...set]); } /** * @example * * ```ts * const set = ISet.create(['first', 'second']); * * const collected = Array.from(set); * * assert.deepStrictEqual(collected, ['first', 'second']); * ``` * * @inheritdoc */ [Symbol.iterator]() { return this.#set[Symbol.iterator](); } /** @inheritdoc */ keys() { return this.#set.keys(); } /** @inheritdoc */ values() { return this.#set.values(); } /** @inheritdoc */ entries() { return this.#set.entries(); } /** @inheritdoc */ toArray() { return Array.from(this.values()); } /** @inheritdoc */ toRawSet() { return this.#set; } } export { ISet }; //# sourceMappingURL=iset.mjs.map