From 20f36cc573cfbe0b740ed1d5594a848420dd14b8 Mon Sep 17 00:00:00 2001 From: ztimson Date: Tue, 27 Aug 2024 11:41:22 -0400 Subject: [PATCH] Added some doc strings & sleepUntil function --- package.json | 2 +- src/aset.ts | 67 +++++++++++++++++++++++++++++++++++++++++++------ src/time.ts | 70 ++++++++++++++++++++++++++++++---------------------- 3 files changed, 101 insertions(+), 38 deletions(-) diff --git a/package.json b/package.json index 57edab4..9c2ddef 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@ztimson/utils", - "version": "0.15.1", + "version": "0.15.2", "description": "Utility library", "author": "Zak Timson", "license": "MIT", diff --git a/src/aset.ts b/src/aset.ts index 72b7b50..cbd50d5 100644 --- a/src/aset.ts +++ b/src/aset.ts @@ -1,57 +1,108 @@ +/** + * An array which functions as a set. It guarantees unique elements + * and provides set functions for comparisons + */ export class ASet extends Array { + /** Number of elements in set */ get size() { return this.length; } + /** + * Array to create set from, duplicate values will be removed + * @param {T[]} elements Elements which will be added to set + */ constructor(elements: T[] = []) { super(); if(!!elements?.['forEach']) elements.forEach(el => this.add(el)); } + /** + * Add single element to set if unique + * @param {T} el Element to add + */ add(el: T) { if(!this.has(el)) this.push(el); } + /** + * Delete element from set + * @param {T} el Element that will be deleted + */ delete(el: T) { const index = this.indexOf(el); if(index != -1) this.slice(index, 1); } + /** + * Create list of elements this set has which the comparison set does not + * @param {ASet} set Set to compare against + * @return {ASet} Different elements + */ difference(set: ASet) { - return new ASet(this.reduce((acc, el) => { - if(!set.has(el)) acc.push(el); - return acc; - }, [])); + return new ASet(this.filter(el => !set.has(el))); } + /** + * Check if set includes element + * @param {T} el Element to look for + * @return {boolean} True if element was found, false otherwise + */ has(el: T) { return this.indexOf(el) != -1; } + /** + * Create list of elements this set has in common with the comparison set + * @param {ASet} set Set to compare against + * @return {boolean} Set of common elements + */ intersection(set: ASet) { - return new ASet(this.reduce((acc, el) => { - if(set.has(el)) acc.push(el); - return acc; - }, [])); + return new ASet(this.filter(el => set.has(el))); } + /** + * Check if this set has no elements in common with the comparison set + * @param {ASet} set Set to compare against + * @return {boolean} True if nothing in common, false otherwise + */ isDisjointFrom(set: ASet) { return this.intersection(set).size == 0; } + /** + * Check if all elements in this set are included in the comparison set + * @param {ASet} set Set to compare against + * @return {boolean} True if all elements are included, false otherwise + */ isSubsetOf(set: ASet) { return this.findIndex(el => !set.has(el)) == -1; } + /** + * Check if all elements from comparison set are included in this set + * @param {ASet} set Set to compare against + * @return {boolean} True if all elements are included, false otherwise + */ isSuperset(set: ASet) { return set.findIndex(el => !this.has(el)) == -1; } + /** + * Create list of elements that are only in one set but not both (XOR) + * @param {ASet} set Set to compare against + * @return {ASet} New set of unique elements + */ symmetricDifference(set: ASet) { return new ASet([...this.difference(set), ...set.difference(this)]); } + /** + * Create joined list of elements included in this & the comparison set + * @param {ASet} set Set join + * @return {ASet} New set of both previous sets combined + */ union(set: ASet | Array) { return new ASet([...this, ...set]); } diff --git a/src/time.ts b/src/time.ts index 6af474d..10994d2 100644 --- a/src/time.ts +++ b/src/time.ts @@ -1,32 +1,3 @@ -/** - * Calculate the number of milliseconds until date/time - * - * @param {Date | number} date - Target - * @returns {number} - Number of milliseconds until target - */ -export function timeUntil(date: Date | number): number { - return (date instanceof Date ? date.getTime() : date) - (new Date()).getTime(); -} - -/** - * Use in conjunction with `await` to pause an async script - * - * @example - * ```ts - * async () => { - * ... - * await sleep(1000) // Pause for 1 second - * ... - * } - * ``` - * - * @param {number} ms - Time to pause for in milliseconds - * @returns {Promise} - Resolves promise when it's time to resume - */ -export function sleep(ms: number) { - return new Promise(res => setTimeout(res, ms)); -} - export function formatDate(date: Date | number | string) { const d = date instanceof Date ? date : new Date(date); return new Intl.DateTimeFormat("en-us", { @@ -38,3 +9,44 @@ export function formatDate(date: Date | number | string) { hour12: true }).format(d); } + +/** + * Use in conjunction with `await` to pause an async script + * + * @example + * ```js + * await sleep(1000) // Pause for 1 second + * ``` + * @param {number} ms - Time to pause for in milliseconds + * @returns {Promise} - Resolves promise when it's time to resume + */ +export function sleep(ms: number): Promise { + return new Promise(res => setTimeout(res, ms)); +} + +/** + * Sleep while function returns true + * + * @example + * ```js + * let loading = true; + * setTimeout(() => wait = false, 1000); + * await sleepUntil(() => loading); // Won't continue until loading flag is false + * ``` + * @param {() => boolean} fn Return true to continue + * @param {number} checkInterval Run function ever x milliseconds + * @return {Promise} Callback when sleep is over + */ +export async function sleepUntil(fn : () => boolean, checkInterval=100): Promise { + while(fn()) await sleep(checkInterval); +} + +/** + * Calculate the number of milliseconds until date/time + * + * @param {Date | number} date - Target + * @returns {number} - Number of milliseconds until target + */ +export function timeUntil(date: Date | number): number { + return (date instanceof Date ? date.getTime() : date) - (new Date()).getTime(); +}