ixfx
Version:
A framework for programming interactivity
1,600 lines (1,573 loc) • 66.6 kB
TypeScript
import { E as EitherKey, I as ICircularArray, A as ArrayKeys, O as ObjectKeys, c as circularArray } from './Types-MvI-jAuh.js';
import { i as index$6 } from './index-CBSCfhsc.js';
import { a as IStack, I as IStackImmutable } from './IStackImmutable-BNEmWxct.js';
import { S as SetStringImmutable, a as SetStringMutable, i as index$5 } from './index-DKJC7pP5.js';
import { Q as QueueImmutable, i as index$4 } from './index-WK4hvyCs.js';
import { Q as QueueMutable } from './QueueMutable-D_WD8izv.js';
import { S as SimpleEventEmitter } from './Events-DJgOvcWD.js';
import { I as Interval } from './IntervalType-B4PbUkjV.js';
import { I as IsEqual } from './IsEqual-CTTf-Oj9.js';
import { T as ToString } from './ToString-DO94OWoh.js';
import { a as IWithEntries, I as IDictionary } from './IMappish-qfjdy4T9.js';
/**
* Stack (mutable)
*
* @example Overview
* ```
* stack.push(item); // Add one or more items to the top of the stack
* stack.pop(); // Removes and retiurns the item at the top of the stack (ie the newest thing)
* stack.peek; // Return what is at the top of the stack or undefined if empty
* stack.isEmpty/.isFull;
* stack.length; // How many items in stack
* stack.data; // Get the underlying array
* ```
*
* @example
* ```
* const sanga = new MutableStack();
* sanga.push(`bread`, `tomato`, `cheese`);
* sanga.peek; // `cheese`
* sanga.pop(); // removes `cheese`
* sanga.peek; // `tomato`
* sanga.push(`lettuce`, `cheese`); // Stack is now [`bread`, `tomato`, `lettuce`, `cheese`]
* ```
*
* Stack can also be created from the basis of an existing array. First index of array will be the bottom of the stack.
* @typeParam V - Type of stored items
*/
interface IStackMutable<V> extends IStack<V> {
/**
* Add items to the 'top' of the stack.
*
* @param toAdd Items to add.
* @returns How many items were added
*/
push(...toAdd: ReadonlyArray<V>): number;
/**
* Remove and return item from the top of the stack, or _undefined_ if empty.
* If you just want to find out what's at the top, use {@link peek}.
*/
pop(): V | undefined;
}
type StackDiscardPolicy = `older` | `newer` | `additions`;
type StackOpts = {
readonly debug?: boolean;
readonly capacity?: number;
readonly discardPolicy?: StackDiscardPolicy;
};
declare class StackImmutable<V> implements IStackImmutable<V> {
private readonly opts;
readonly data: ReadonlyArray<V>;
constructor(opts?: StackOpts, data?: ReadonlyArray<V>);
push(...toAdd: ReadonlyArray<V>): StackImmutable<V>;
pop(): IStackImmutable<V>;
forEach(fn: (v: V) => void): void;
forEachFromTop(fn: (v: V) => void): void;
get isEmpty(): boolean;
get isFull(): boolean;
get peek(): V | undefined;
get length(): number;
}
/**
* Returns a stack. Immutable. Use {@link Stacks.mutable} for a mutable alternative.
*
* The basic usage is `push`/`pop` to add/remove, returning the modified stack. Use the
* property `peek` to see what's on top.
*
* @example Basic usage
* ```js
* // Create
* let s = stack();
* // Add one or more items
* s = s.push(1, 2, 3, 4);
* // See what's at the top of the stack
* s.peek; // 4
*
* // Remove from the top of the stack, returning
* // a new stack without item
* s = s.pop();
* s.peek; // 3
* ```
* @param options Options
* @param startingItems List of items to add to stack. Items will be pushed 'left to right', ie array index 0 will be bottom of the stack.
*/
declare const immutable$1: <V>(options?: StackOpts, ...startingItems: ReadonlyArray<V>) => IStackImmutable<V>;
/**
* Creates a stack. Mutable. Use {@link StackImmutable} for an immutable alternative.
*
* @example Basic usage
* ```js
* // Create
* const s = new StackMutable();
* // Add one or more items
* s.push(1, 2, 3, 4);
*
* // See what's on top
* s.peek; // 4
*
* // Remove the top-most, and return it
* s.pop(); // 4
*
* // Now there's a new top-most element
* s.peek; // 3
* ```
*/
declare class StackMutable<V> implements IStackMutable<V> {
readonly opts: StackOpts;
data: ReadonlyArray<V>;
constructor(opts?: StackOpts, data?: ReadonlyArray<V>);
/**
* Push data onto the stack.
* If `toAdd` is empty, nothing happens
* @param toAdd Data to add
* @returns Length of stack
*/
push(...toAdd: ReadonlyArray<V>): number;
forEach(fn: (v: V) => void): void;
forEachFromTop(fn: (v: V) => void): void;
pop(): V | undefined;
get isEmpty(): boolean;
get isFull(): boolean;
get peek(): V | undefined;
get length(): number;
}
/**
* Creates a stack. Mutable. Use {@link Stacks.immutable} for an immutable alternative.
*
* @example Basic usage
* ```js
* // Create
* const s = Stacks.mutable();
* // Add one or more items
* s.push(1, 2, 3, 4);
*
* // See what's on top
* s.peek; // 4
*
* // Remove the top-most, and return it
* s.pop(); // 4
*
* // Now there's a new top-most element
* s.peek; // 3
* ```
*/
declare const mutable$1: <V>(opts?: StackOpts, ...startingItems: ReadonlyArray<V>) => IStackMutable<V>;
declare const trimStack: <V>(opts: StackOpts, stack: ReadonlyArray<V>, toAdd: ReadonlyArray<V>) => ReadonlyArray<V>;
declare const push: <V>(opts: StackOpts, stack: ReadonlyArray<V>, ...toAdd: ReadonlyArray<V>) => ReadonlyArray<V>;
declare const pop: <V>(opts: StackOpts, stack: ReadonlyArray<V>) => ReadonlyArray<V>;
/**
* Peek at the top of the stack (end of array)
*
* @typeParam V - Type of stored items
* @param {StackOpts} opts
* @param {V[]} stack
* @returns {(V | undefined)}
*/
declare const peek: <V>(opts: StackOpts, stack: ReadonlyArray<V>) => V | undefined;
declare const isEmpty: <V>(opts: StackOpts, stack: ReadonlyArray<V>) => boolean;
declare const isFull: <V>(opts: StackOpts, stack: ReadonlyArray<V>) => boolean;
declare const index$3_IStack: typeof IStack;
declare const index$3_IStackImmutable: typeof IStackImmutable;
type index$3_IStackMutable<V> = IStackMutable<V>;
type index$3_StackDiscardPolicy = StackDiscardPolicy;
type index$3_StackOpts = StackOpts;
declare const index$3_isEmpty: typeof isEmpty;
declare const index$3_isFull: typeof isFull;
declare const index$3_peek: typeof peek;
declare const index$3_pop: typeof pop;
declare const index$3_push: typeof push;
declare const index$3_trimStack: typeof trimStack;
declare namespace index$3 {
export { index$3_IStack as IStack, index$3_IStackImmutable as IStackImmutable, type index$3_IStackMutable as IStackMutable, type index$3_StackDiscardPolicy as StackDiscardPolicy, type index$3_StackOpts as StackOpts, immutable$1 as immutable, index$3_isEmpty as isEmpty, index$3_isFull as isFull, mutable$1 as mutable, index$3_peek as peek, index$3_pop as pop, index$3_push as push, index$3_trimStack as trimStack };
}
/**
* Expiring map options
*/
type Opts = {
/**
* Capacity limit
*/
readonly capacity?: number;
/**
* Policy for evicting items if capacity is reached
*/
readonly evictPolicy?: `none` | `oldestGet` | `oldestSet`;
/**
* Automatic deletion policy.
* none: no automatic deletion (default)
* get/set: interval based on last get/set
* either: if either interval has elapsed
*/
readonly autoDeletePolicy?: `none` | `get` | `set` | `either`;
/**
* Automatic deletion interval
*/
readonly autoDeleteElapsedMs?: number;
};
/**
* Event from the ExpiringMap
*/
type ExpiringMapEvent<K, V> = {
readonly key: K;
readonly value: V;
};
type ExpiringMapEvents<K, V> = {
/**
* Fires when an item is removed due to eviction
* or automatic expiry
*/
readonly expired: ExpiringMapEvent<K, V>;
/**
* Fires when a item with a new key is added
*/
readonly newKey: ExpiringMapEvent<K, V>;
/**
* Fires when an item is manually removed,
* removed due to eviction or automatic expiry
*/
readonly removed: ExpiringMapEvent<K, V>;
};
/**
* Create a ExpiringMap instance
* @param options Options when creating map
* @returns
*/
declare const create: <K, V>(options?: Opts) => ExpiringMap<K, V>;
/***
* A map that can have a capacity limit. The elapsed time for each get/set
* operation is maintained allowing for items to be automatically removed.
* `has()` does not affect the last access time.
*
* By default, it uses the `none` eviction policy, meaning that when full
* an error will be thrown if attempting to add new keys.
*
* Eviction policies:
* `oldestGet` removes the item that hasn't been accessed the longest,
* `oldestSet` removes the item that hasn't been updated the longest.
*
* ```js
* const map = new ExpiringMap();
* map.set(`fruit`, `apple`);
*
* // Remove all entries that were set more than 100ms ago
* map.deleteWithElapsed(100, `set`);
* // Remove all entries that were last accessed more than 100ms ago
* map.deleteWithElapsed(100, `get`);
* // Returns the elapsed time since `fruit` was last accessed
* map.elapsedGet(`fruit`);
* // Returns the elapsed time since `fruit` was last set
* map.elapsedSet(`fruit`);
* ```
*
* Last set/get time for a key can be manually reset using {@link touch}.
*
*
* Events:
* * 'expired': when an item is automatically removed.
* * 'removed': when an item is manually or automatically removed.
* * 'newKey': when a new key is added
*
* ```js
* map.addEventListener(`expired`, evt => {
* const { key, value } = evt;
* });
* ```
* The map can automatically remove items based on elapsed intervals.
*
* @example
* Automatically delete items that haven't been accessed for one second
* ```js
* const map = new ExpiringMap({
* autoDeleteElapsed: 1000,
* autoDeletePolicy: `get`
* });
* ```
*
* @example
* Automatically delete the oldest item if we reach a capacity limit
* ```js
* const map = new ExpiringMap({
* capacity: 5,
* evictPolicy: `oldestSet`
* });
* ```
* @typeParam K - Type of keys
* @typeParam V - Type of values
*/
declare class ExpiringMap<K, V> extends SimpleEventEmitter<ExpiringMapEvents<K, V>> {
#private;
private capacity;
private store;
private evictPolicy;
private autoDeleteElapsedMs;
private autoDeletePolicy;
private autoDeleteTimer;
private disposed;
constructor(opts?: Opts);
dispose(): void;
/**
* Returns the number of keys being stored.
*/
get keyLength(): number;
entries(): IterableIterator<[k: K, v: V]>;
values(): IterableIterator<V>;
keys(): IterableIterator<K>;
/**
* Returns the elapsed time since `key`
* was set. Returns _undefined_ if `key`
* does not exist
*/
elapsedSet(key: K): number | undefined;
/**
* Returns the elapsed time since `key`
* was accessed. Returns _undefined_ if `key`
* does not exist
*/
elapsedGet(key: K): number | undefined;
/**
* Returns true if `key` is stored.
* Does not affect the key's last access time.
* @param key
* @returns
*/
has(key: K): boolean;
/**
* Gets an item from the map by key, returning
* undefined if not present
* @param key Key
* @returns Value, or undefined
*/
get(key: K): V | undefined;
/**
* Deletes the value under `key`, if present.
*
* Returns _true_ if something was removed.
* @param key
* @returns
*/
delete(key: K): boolean;
/**
* Clears the contents of the map.
* Note: does not fire `removed` event
*/
clear(): void;
/**
* Updates the lastSet/lastGet time for a value
* under `k`.
*
* Returns false if key was not found
* @param key
* @returns
*/
touch(key: K): boolean;
private findEvicteeKey;
/**
* Deletes all values where elapsed time has past
* for get/set or either.
* ```js
* // Delete all keys (and associated values) not accessed for a minute
* em.deleteWithElapsed({mins:1}, `get`);
* // Delete things that were set 1s ago
* em.deleteWithElapsed(1000, `set`);
* ```
*
* @param interval Interval
* @param property Basis for deletion 'get','set' or 'either'
* @returns Items removed
*/
deleteWithElapsed(interval: Interval, property: `get` | `set` | `either`): Array<[k: K, v: V]>;
/**
* Sets the `key` to be `value`.
*
* If the key already exists, it is updated.
*
* If the map is full, according to its capacity,
* another value is selected for removal.
* @param key
* @param value
* @returns
*/
set(key: K, value: V): void;
}
interface IMapOf<V> {
/**
* Iterates over all keys
*/
keys(): IterableIterator<string>;
/**
* Iterates over all values stored under `key`
* @param key
*/
get(key: string): IterableIterator<V>;
/**
* Iterates over all values, regardless of key.
* Same value may re-appear if it's stored under different keys.
*/
valuesFlat(): IterableIterator<V>;
/**
* Iterates over key-value pairs.
* Unlike a normal map, the same key may appear several times.
*/
entriesFlat(): IterableIterator<readonly [key: string, value: V]>;
entries(): IterableIterator<[key: string, value: Array<V>]>;
/**
* Iteates over all keys and the count of values therein
*/
keysAndCounts(): IterableIterator<readonly [string, number]>;
/**
* Returns _true_ if `value` is stored under `key`.
*
* @param key Key
* @param value Value
*/
hasKeyValue(key: string, value: V, eq?: IsEqual<V>): boolean;
/**
* Returns _true_ if `key` has any values
* @param key
*/
has(key: string): boolean;
/**
* Returns _true_ if the map is empty
*/
get isEmpty(): boolean;
/**
* Returns the number of values stored under `key`, or _0_ if `key` is not present.
* @param key Key
*/
count(key: string): number;
/**
* Finds the first key where value is stored.
* Note: value could be stored in multiple keys
* @param value Value to seek
* @returns Key, or undefined if value not found
*/
firstKeyByValue(value: V, eq?: IsEqual<V> | undefined): string | undefined;
}
interface IMapBase<K, V> {
/**
* Gets an item by key
* @example
* ```js
* const item = map.get(`hello`);
* ```
* @param key
*/
get(key: K): V | undefined;
/**
* Returns _true_ if map contains key
* @example
* ```js
* if (map.has(`hello`)) ...
* ```
* @param key
*/
has(key: K): boolean;
/**
* Returns _true_ if map is empty
*/
isEmpty(): boolean;
/**
* Iterates over entries (consisting of [key,value])
* @example
* ```js
* for (const [key, value] of map.entries()) {
* // Use key, value...
* }
* ```
*/
entries(): IterableIterator<readonly [K, V]>;
values(): IterableIterator<V>;
}
/**
* An immutable map. Rather than changing the map, functions like `add` and `delete`
* return a new map reference which must be captured.
*
* Immutable data is useful because as it gets passed around your code, it never
* changes from underneath you. You have what you have.
*
* @example
* ```js
* let m = map(); // Create
* let m2 = m.set(`hello`, `samantha`);
* // m is still empty, only m2 contains a value.
* ```
*
* @typeParam K - Type of map keys. Typically `string`
* @typeParam V - Type of stored values
*/
interface IMapImmutable<K, V> extends IMapBase<K, V> {
/**
* Adds one or more items, returning the changed map.
*
* Can add items in the form of `[key,value]` or `{key, value}`.
* @example These all produce the same result
* ```js
* map.set(`hello`, `samantha`);
* map.add([`hello`, `samantha`]);
* map.add({key: `hello`, value: `samantha`})
* ```
* @param itemsToAdd
*/
add(...itemsToAdd: EitherKey<K, V>): IMapImmutable<K, V>;
/**
* Deletes an item by key, returning the changed map
* @param key
*/
delete(key: K): IMapImmutable<K, V>;
/**
* Returns an empty map
*/
clear(): IMapImmutable<K, V>;
/**
* Sets `key` to be `value`, overwriting anything existing.
* Returns a new map with added key.
* @param key
* @param value
*/
set(key: K, value: V): IMapImmutable<K, V>;
}
/**
* Returns an {@link IMapImmutable}.
* Use {@link Maps.mutable} as a mutable alternatve.
*
* @example Basic usage
* ```js
* // Creating
* let m = map();
* // Add
* m = m.set("name", "sally");
* // Recall
* m.get("name");
* ```
*
* @example Enumerating
* ```js
* for (const [key, value] of map.entries()) {
* console.log(`${key} = ${value}`);
* }
* ```
*
* @example Overview
* ```js
* // Create
* let m = map();
* // Add as array or key & value pair
* m = m.add(["name" , "sally"]);
* m = m.add({ key: "name", value: "sally" });
* // Add using the more typical set
* m = m.set("name", "sally");
* m.get("name"); // "sally";
* m.has("age"); // false
* m.has("name"); // true
* m.isEmpty; // false
* m = m.delete("name");
* m.entries(); // Iterator of key value pairs
* ```
*
* Since it is immutable, `add()`, `delete()` and `clear()` return a new version with change.
*
* @param dataOrMap Optional initial data in the form of an array of `{ key: value }` or `[ key, value ]`
*/
declare const immutable: <K, V>(dataOrMap?: ReadonlyMap<K, V> | EitherKey<K, V>) => IMapImmutable<K, V>;
/**
* A mutable map.
*
* It is a wrapper around the in-built Map type, but adds roughly the same API as {@link IMapImmutable}.
*
* @typeParam K - Type of map keys. Typically `string`
* @typeParam V - Type of stored values
*/
interface IMapMutable<K, V> extends IMapBase<K, V> {
/**
* Adds one or more items to map
*
* Can add items in the form of [key,value] or `{key, value}`.
* @example These all produce the same result
* ```js
* map.set(`hello`, `samantha`);
* map.add([`hello`, `samantha`]);
* map.add({key: `hello`, value: `samantha`})
* ```
* @param itemsToAdd
* @param itemsToAdd
*/
add(...itemsToAdd: EitherKey<K, V>): void;
/**
* Sets a value to a specified key
* @param key
* @param value
*/
set(key: K, value: V): void;
/**
* Deletes an item by key
* @param key
*/
delete(key: K): void;
/**
* Clears map
*/
clear(): void;
}
/**
* Returns a {@link IMapMutable} (which just wraps the in-built Map)
* Use {@link Maps.immutable} for the immutable alternative.
*
* @example Basic usage
* ```js
* const m = mapMutable();
* // Add one or more entries
* m.add(["name", "sally"]);
* // Alternatively:
* m.set("name", "sally");
* // Recall
* m.get("name"); // "sally"
* m.delete("name");
* m.isEmpty; // True
* m.clear();
* ```
* @param data Optional initial data in the form of an array of `{ key: value }` or `[ key, value ]`
*/
declare const mutable: <K, V>(...data: EitherKey<K, V>) => IMapMutable<K, V>;
interface IMapOfMutable<V> extends IMapOf<V> {
/**
* Adds several `values` under the same `key`. Duplicate values are permitted, depending on implementation.
* @param key
* @param values
*/
addKeyedValues(key: string, ...values: ReadonlyArray<V>): void;
/**
* Adds a value, automatically extracting a key via the
* `groupBy` function assigned in the constructor options.
* @param values Adds several values
*/
addValue(...values: ReadonlyArray<V>): void;
/**
* Clears the map
*/
clear(): void;
/**
* Returns the number of keys
*/
get lengthKeys(): number;
/**
* Deletes all values under `key` that match `value`.
* @param key Key
* @param value Value
*/
deleteKeyValue(key: string, value: V): boolean;
/**
* Delete all occurrences of `value`, regardless of
* key it is stored under.
* Returns _true_ if something was deleted.
* @param value
*/
deleteByValue(value: V): boolean;
/**
* Deletes all values stored under `key`. Returns _true_ if key was found
* @param key
*/
delete(key: string): boolean;
}
/**
* Events from mapArray
*/
type MapArrayEvents<V> = {
readonly addedValues: {
readonly values: ReadonlyArray<V>;
};
readonly addedKey: {
readonly key: string;
};
readonly clear: boolean;
readonly deleteKey: {
readonly key: string;
};
};
/**
* Like a `Map` but multiple values can be stored for each key.
* Duplicate values can be added to the same or even a several keys.
*
* Three pre-defined MapOf's are available:
* * {@link ofArrayMutable} - Map of arrays
* * {@link ofSetMutable} - Map of unique items
* * {@link ofCircularMutable} - Hold a limited set of values per key
*
* Adding
* ```js
* // Add one or more values using the predefined key function to generate a key
* map.addValue(value1, value2, ...);
* // Add one or more values under a specified key
* map.addKeyedValues(key, value1, value2, ...);
* ```
*
* Finding/accessing
* ```js
* // Returns all values stored under key
* map.get(key);
* // Returns the first key where value is found, or _undefined_ if not found
* map.findKeyForValue(value);
* // Returns _true_ if value is stored under key
* map.hasKeyValue(key, value);
* // Returns _true_ if map contains key
* map.has(key);
* ```
*
* Removing
* ```js
* // Removes everything
* map.clear();
* // Delete values under key. Returns _true_ if key was found.
* map.delete(key);
* // Deletes specified value under key. Returns _true_ if found.
* map.deleteKeyValue(key, value);
* ```
*
* Metadata about the map:
* ```js
* map.isEmpty; // True/false
* map.lengthMax; // Largest count of items under any key
* map.count(key); // Count of items stored under key, or 0 if key is not present.
* map.keys(); // Returns a string array of keys
* map.keysAndCounts(); // Returns an array of [string,number] for all keys and number of values for each key
* map.debugString(); // Returns a human-readable string dump of the contents
* ```
*
* Events can be listened to via `addEventListener`
* * `addedKey`, `addedValue` - when a new key is added, or when a new value is added
* * `clear` - when contents are cleared
* * `deleteKey` - when a key is deleted
*
* @example Event example
* ```js
* map.addEventLister(`addedKey`, ev => {
* // New key evt.key seen.
* });
* ```
*
* @typeParam V - Values stored under keys
* @typeParam M - Type of data structure managing values
*/
interface IMapOfMutableExtended<V, M> extends SimpleEventEmitter<MapArrayEvents<V>>, IMapOfMutable<V> {
/**
* Returns the object managing values under the specified `key`
* @private
* @param key
*/
getSource(key: string): M | undefined;
/**
* Returns the type name. For in-built implementations, it will be one of: array, set or circular
*/
get typeName(): string;
/**
* Returns a human-readable rendering of contents
*/
debugString(): string;
}
/**
* Map of array options
*/
type MapArrayOpts<V> = MapMultiOpts<V> & {
/**
* Comparer to use
*/
readonly comparer?: IsEqual<V>;
/**
* Key function
*/
readonly convertToString?: ToString<V>;
};
/**
* Returns a {@link IMapOfMutableExtended} to allow storing multiple values under a key, unlike a regular Map.
* @example
* ```js
* const map = ofArrayMutable();
* map.addKeyedValues(`hello`, [1,2,3,4]); // Adds series of numbers under key `hello`
*
* const hello = map.get(`hello`); // Get back values
* ```
*
* Takes options:
* * `comparer`: {@link IsEqual}
* * `toString`: {@link Util.ToString}
*
* A custom {@link Util.ToString} function can be provided as the `convertToString` opion. This is then used when checking value equality (`has`, `without`)
* ```js
* const map = ofArrayMutable({ convertToString:(v) => v.name}); // Compare values based on their `name` field;
* ```
*
* Alternatively, a {@link IsEqual} function can be used:
* ```js
* const map = ofArrayMutable({comparer: (a, b) => a.name === b.name });
* ```
* @param options Optiosn for mutable array
* @typeParam V - Data type of items
* @returns {@link IMapOfMutableExtended}
*/
declare const ofArrayMutable: <V>(options?: MapArrayOpts<V>) => IMapOfMutableExtended<V, ReadonlyArray<V>>;
declare class MapOfSimpleBase<V> {
protected map: Map<string, ReadonlyArray<V>>;
protected readonly groupBy: (value: V) => string;
protected valueEq: IsEqual<V>;
/**
* Constructor
* @param groupBy Creates keys for values when using `addValue`. By default uses JSON.stringify
* @param valueEq Compare values. By default uses JS logic for equality
*/
constructor(groupBy?: (value: V) => string, valueEq?: IsEqual<V>, initial?: Array<[string, ReadonlyArray<V>]>);
/**
* Returns _true_ if `key` exists
* @param key
* @returns
*/
has(key: string): boolean;
/**
* Returns _true_ if `value` exists under `key`.
* @param key Key
* @param value Value to seek under `key`
* @returns _True_ if `value` exists under `key`.
*/
hasKeyValue(key: string, value: V): boolean;
/**
* Debug dump of contents
* @returns
*/
debugString(): string;
/**
* Return number of values stored under `key`.
* Returns 0 if `key` is not found.
* @param key
* @returns
*/
count(key: string): number;
/**
* Returns first key that contains `value`
* @param value
* @param eq
* @returns
*/
firstKeyByValue(value: V, eq?: IsEqual<V>): string | undefined;
/**
* Iterate over all entries
*/
entriesFlat(): IterableIterator<[key: string, value: V]>;
/**
* Iterate over keys and array of values for that key
*/
entries(): IterableIterator<[key: string, value: Array<V>]>;
/**
* Get all values under `key`
* @param key
* @returns
*/
get(key: string): IterableIterator<V>;
/**
* Iterate over all keys
*/
keys(): IterableIterator<string>;
/**
* Iterate over all values (regardless of key).
* Use {@link values} to iterate over a set of values per key
*/
valuesFlat(): IterableIterator<V>;
/**
* Yields the values for each key in sequence, returning an array.
* Use {@link valuesFlat} to iterate over all keys regardless of key.
*/
values(): IterableIterator<ReadonlyArray<V>>;
/**
* Iterate over keys and length of values stored under keys
*/
keysAndCounts(): IterableIterator<[string, number]>;
/**
* Returns the count of keys.
*/
get lengthKeys(): number;
/**
* _True_ if empty
*/
get isEmpty(): boolean;
}
/**
* A simple mutable map of arrays, without events. It can store multiple values
* under the same key.
*
* For a fancier approaches, consider ofArrayMutable, ofCircularMutable or ofSetMutable.
*
* @example
* ```js
* const m = mapOfSimpleMutable();
* m.add(`hello`, 1, 2, 3); // Adds numbers under key `hello`
* m.delete(`hello`); // Deletes everything under `hello`
*
* const hellos = m.get(`hello`); // Get list of items under `hello`
* ```
*
* Constructor takes a `groupBy` parameter, which yields a string key for a value. This is the
* basis by which values are keyed when using `addValues`.
*
* Constructor takes a `valueEq` parameter, which compares values. This is used when checking
* if a value exists under a key, for example.
* @typeParam V - Type of items
*/
declare class MapOfSimpleMutable<V> extends MapOfSimpleBase<V> implements IMapOfMutable<V> {
addKeyedValues(key: string, ...values: ReadonlyArray<V>): void;
/**
* Set `values` to `key`.
* Previous data stored under `key` is thrown away.
* @param key
* @param values
*/
setValues(key: string, values: ReadonlyArray<V>): void;
/**
* Adds a value, automatically extracting a key via the
* `groupBy` function assigned in the constructor options.
* @param values Adds several values
*/
addValue(...values: ReadonlyArray<V>): void;
/**
* Delete `value` under a particular `key`
* @param key
* @param value
* @returns _True_ if `value` was found under `key`
*/
deleteKeyValue(key: string, value: V): boolean;
/**
* Deletes `value` regardless of key.
*
* Uses the constructor-defined equality function.
* @param value Value to delete
* @returns
*/
deleteByValue(value: V): boolean;
/**
* Deletes all values under `key`,
* @param key
* @returns _True_ if `key` was found and values stored
*/
delete(key: string): boolean;
/**
* Clear contents
*/
clear(): void;
}
/**
* A simple mutable map of arrays, without events. It can store multiple values
* under the same key.
*
* For a fancier approaches, consider {@link ofArrayMutable}, {@link ofCircularMutable} or {@link ofSetMutable}.
*
* @example
* ```js
* const m = mapOfSimpleMutable();
* m.add(`hello`, 1, 2, 3); // Adds numbers under key `hello`
* m.delete(`hello`); // Deletes everything under `hello`
*
* const hellos = m.get(`hello`); // Get list of items under `hello`
* ```
*
* @typeParam V - Type of items
* @returns New instance
*/
declare const ofSimpleMutable: <V>(groupBy?: (value: V) => string, valueEq?: IsEqual<V>) => IMapOfMutable<V>;
/**
* Like a `Map` but multiple values can be stored for each key. Immutable.
* Duplicate values can be added to the same or even a several keys.
*
* Adding
* ```js
* // Add one or more values using the predefined key function to generate a key
* map = map.addValue(value1, value2, ...);
* // Add one or more values under a specified key
* map = map.addKeyedValues(key, value1, value2, ...);
* ```
*
* Finding/accessing
* ```js
* // Returns all values stored under key
* map.get(key);
* // Returns the first key where value is found, or _undefined_ if not found
* map.findKeyForValue(value);
* // Returns _true_ if value is stored under key
* map.hasKeyValue(key, value);
* // Returns _true_ if map contains key
* map.has(key);
* ```
*
* Removing
* ```js
* // Removes everything
* map = map.clear();
* // Delete values under key. Returns _true_ if key was found.
* map = map.delete(key);
* // Deletes specified value under key. Returns _true_ if found.
* map = map.deleteKeyValue(key, value);
* ```
*
* Metadata about the map:
* ```js
* map.isEmpty; // True/false
* map.lengthMax; // Largest count of items under any key
* map.count(key); // Count of items stored under key, or 0 if key is not present.
* map.keys(); // Returns a string array of keys
* map.keysAndCounts(); // Returns an array of [string,number] for all keys and number of values for each key
* map.debugString(); // Returns a human-readable string dump of the contents
* ```
*
* @typeParam V - Values stored under keys
* @typeParam M - Type of data structure managing values
*/
interface IMapOfImmutable<V> extends IMapOf<V> {
/**
* Adds several `values` under the same `key`. Duplicate values are permitted, depending on implementation.
* @param key
* @param values
*/
addKeyedValues(key: string, ...values: ReadonlyArray<V>): IMapOfImmutable<V>;
/**
* Adds a value, automatically extracting a key via the
* `groupBy` function assigned in the constructor options.
* @param values Adds several values
*/
addValue(...values: ReadonlyArray<V>): IMapOfImmutable<V>;
/**
* Clears the map
*/
clear(): IMapOfImmutable<V>;
/**
* Deletes all values under `key` that match `value`.
* @param key Key
* @param value Value
*/
deleteKeyValue(key: string, value: V): IMapOfImmutable<V>;
/**
* Delete all occurrences of `value`, regardless of
* key it is stored under.
* @param value
*/
deleteByValue(value: V): IMapOfImmutable<V>;
/**
* Deletes all values stored under `key`.
* @param key
*/
delete(key: string): IMapOfImmutable<V>;
}
/**
* Simple immutable MapOf
*/
declare class MapOfSimple<V> extends MapOfSimpleBase<V> implements IMapOf<V>, IMapOfImmutable<V> {
addKeyedValues(key: string, ...values: ReadonlyArray<V>): IMapOfImmutable<V>;
addValue(...values: ReadonlyArray<V>): IMapOfImmutable<V>;
addBatch(entries: Array<[key: string, value: ReadonlyArray<V>]>): IMapOfImmutable<V>;
clear(): IMapOfImmutable<V>;
deleteKeyValue(_key: string, _value: V): IMapOfImmutable<V>;
deleteByValue(value: V, eq?: IsEqual<V>): IMapOfImmutable<V>;
delete(key: string): IMapOfImmutable<V>;
}
/**
* A simple immutable map of arrays, without events. It can store multiple values
* under the same key.
*
* For a fancier approaches, consider {@link ofArrayMutable}, {@link ofCircularMutable} or {@link ofSetMutable}.
*
* @example
* ```js
* let m = mapSimple();
* m = m.add(`hello`, 1, 2, 3); // Adds numbers under key `hello`
* m = m.delete(`hello`); // Deletes everything under `hello`
*
* const hellos = m.get(`hello`); // Get list of items under `hello`
* ```
*
* @typeParam V - Type of items
* @returns New instance
*/
declare const ofSimple: <V>(groupBy?: ToString<V>, valueEq?: IsEqual<V>) => IMapOfImmutable<V>;
/**
* @internal
*/
declare class MapOfMutableImpl<V, M> extends SimpleEventEmitter<MapArrayEvents<V>> implements IMapOfMutableExtended<V, M> {
#private;
readonly groupBy: ToString<V>;
readonly type: MultiValue<V, M>;
constructor(type: MultiValue<V, M>, opts?: MapMultiOpts<V>);
/**
* Returns the type name. For in-built implementations, it will be one of: array, set or circular
*/
get typeName(): string;
/**
* Returns the number of keys
*/
get lengthKeys(): number;
/**
* Returns the length of the longest child list
*/
get lengthMax(): number;
debugString(): string;
get isEmpty(): boolean;
clear(): void;
addKeyedValues(key: string, ...values: Array<V>): void;
set(key: string, values: Array<V>): this;
addValue(...values: ReadonlyArray<V>): void;
hasKeyValue(key: string, value: V, eq: IsEqual<V>): boolean;
has(key: string): boolean;
deleteKeyValue(key: string, value: V): boolean;
private deleteKeyValueFromMap;
deleteByValue(value: V): boolean;
delete(key: string): boolean;
firstKeyByValue(value: V, eq?: IsEqual<V>): string | undefined;
count(key: string): number;
/**
* Iterates over values stored under `key`
* An empty array is returned if there are no values
*/
get(key: string): IterableIterator<V>;
/**
* Iterate over the values stored under `key`.
* If key does not exist, iteration is essentially a no-op
* @param key
* @returns
*/
valuesFor(key: string): Generator<V, void, any>;
getSource(key: string): M | undefined;
keys(): IterableIterator<string>;
entriesFlat(): IterableIterator<[key: string, value: V]>;
valuesFlat(): IterableIterator<V>;
entries(): IterableIterator<[key: string, value: Array<V>]>;
keysAndCounts(): IterableIterator<[string, number]>;
merge(other: IMapOf<V>): void;
get size(): number;
get [Symbol.toStringTag](): string;
}
/**
* Finds first entry by iterable value. Expects a map with an iterable as values.
*
* ```js
* const map = new Map();
* map.set('hello', ['a', 'b', 'c']);
* map.set('there', ['d', 'e', 'f']);
*
* const entry = firstEntry(map, (value, key) => {
* return (value === 'e');
* });
* // Entry is: ['there', ['d', 'e', 'f']]
* ```
*
* An alternative is {@link firstEntryByValue} to search by value.
* @param map Map to search
* @param predicate Filter function returns true when there is a match of value
* @returns Entry, or _undefined_ if `filter` function never returns _true_
*/
declare const firstEntry: <K, V>(map: IWithEntries<K, Iterable<V>>, predicate: (value: V, key: K) => boolean) => readonly [key: K, value: Iterable<V>] | undefined;
/**
* Returns the size of the largest key, or 0 if empty.
*/
declare const lengthMax: <V>(map: IMapOf<V>) => number;
/**
* Finds first entry by iterable value. Expects a map with an iterable as values.
*
* ```js
* const map = new Map();
* map.set('hello', ['a', 'b', 'c']);
* map.set('there', ['d', 'e', 'f']);
*
* const entry = firstEntryByValue(map, 'e');
* // Entry is: ['there', ['d', 'e', 'f']]
* ```
*
* An alternative is {@link firstEntry} to search by predicate function.
* @param map Map to search
* @param value Value to seek
* @param isEqual Filter function which checks equality. Uses JS comparer by default.
* @returns Entry, or _undefined_ if `value` not found.
*/
declare const firstEntryByValue: <K, V>(map: IWithEntries<K, Iterable<V>>, value: V, isEqual?: IsEqual<V>) => readonly [key: K, value: Iterable<V>] | undefined;
/**
* @private
*/
type MultiValue<V, M> = {
get name(): string;
has(source: M, value: V, eq: IsEqual<V>): boolean;
add(destination: M | undefined, values: Iterable<V>): M;
toArray(source: M): ReadonlyArray<V>;
iterable(source: M): IterableIterator<V>;
find(source: M, predicate: (v: V) => boolean): V | undefined;
filter(source: M, predicate: (v: V) => boolean): Iterable<V>;
without(source: M, value: V): ReadonlyArray<V>;
count(source: M): number;
};
type MapMultiOpts<V> = {
/**
* Returns a group for values added via `addValue`. Eg. maybe you want to
* group values in the shape `{name: 'Samantha' city: 'Copenhagen'}` by city:
*
* ```
* const opts = {
* groupBy: (v) => v.city
* }
* ```
*
* @type {(ToString<V>|undefined)}
*/
readonly groupBy?: ((value: V) => string) | undefined;
};
type MapSetOpts<V> = MapMultiOpts<V> & {
readonly hash: (value: V) => string;
};
/**
* Returns a {@link IMapOfMutableExtended} that uses a set to hold values.
* This means that only unique values are stored under each key. By default it
* uses the JSON representation to compare items.
*
* Options: `{ hash: toStringFn } }`
*
* `hash` is a {@link Util.ToString} function: `(object) => string`. By default it uses
* `JSON.stringify`.
*
* @example Only storing the newest three items per key
* ```js
* const map = mapOfSetMutable();
* map.add(`hello`, [1, 2, 3, 1, 2, 3]);
* const hello = map.get(`hello`); // [1, 2, 3]
* ```
*
* @example
* ```js
* const hash = (v) => v.name; // Use name as the key
* const map = mapOfSetMutable(hash);
* map.add(`hello`, {age:40, name: `Mary`});
* map.add(`hello`, {age:29, name: `Mary`}); // Value ignored as same name exists
* ```
* @param options
* @returns
*/
declare const ofSetMutable: <V>(options?: MapSetOpts<V>) => IMapOfMutableExtended<V, ReadonlyMap<string, V>>;
type MapCircularOpts<V> = MapMultiOpts<V> & {
readonly capacity: number;
};
/**
* Returns a {@link IMapOfMutableExtended} that uses a {@link ICircularArray} to hold values. Mutable.
* This means that the number of values stored under each key will be limited to the defined
* capacity.
*
* Required option:
* * `capacity`: how many items to hold
*
* @example Only store the most recent three items per key
* ```js
* const map = ofCircularMutable({capacity: 3});
* map.add(`hello`, [1, 2, 3, 4, 5]);
* const hello = map.get(`hello`); // [3, 4, 5]
* ```
*
*
* @param options
* @returns
*/
declare const ofCircularMutable: <V>(options: MapCircularOpts<V>) => IMapOfMutableExtended<V, ICircularArray<V>>;
/**
* Simple map for numbers.
*
* Keys not present in map return the `defaultValue` given in the constructor
* ```js
* // All keys default to zero.
* const map = new NumberMap();
* map.get(`hello`); // 0
* ```
*
* To check if a key is present, use `has`:
* ```js
* map.has(`hello`); // false
* ```
*
* Math:
* ```js
* // Adds 1 by default to value of `hello`
* map.add(`hello`); // 1
* map.multiply(`hello`, 2); // 2
*
* // Reset key to default value
* map.reset(`hello`); // 0
* ```
*
* Different default value:
* ```js
* const map = new NumberMap(10);
* map.get(`hello`); // 10
* ```
*
* Regular `set` works as well:
* ```js
* map.set(`hello`, 5);
* map.add(`hello`, 2); // 7
* ```
*/
declare class NumberMap<K> extends Map<K, number> {
readonly defaultValue: number;
constructor(defaultValue?: number);
get(key: K): number;
reset(key: K): number;
multiply(key: K, amount: number): number;
add(key: K, amount?: number): number;
subtract(key: K, amount?: number): number;
}
type index$2_ExpiringMapEvent<K, V> = ExpiringMapEvent<K, V>;
type index$2_ExpiringMapEvents<K, V> = ExpiringMapEvents<K, V>;
type index$2_IMapImmutable<K, V> = IMapImmutable<K, V>;
type index$2_IMapMutable<K, V> = IMapMutable<K, V>;
type index$2_IMapOf<V> = IMapOf<V>;
type index$2_IMapOfImmutable<V> = IMapOfImmutable<V>;
type index$2_IMapOfMutable<V> = IMapOfMutable<V>;
type index$2_IMapOfMutableExtended<V, M> = IMapOfMutableExtended<V, M>;
declare const index$2_IWithEntries: typeof IWithEntries;
type index$2_MapArrayEvents<V> = MapArrayEvents<V>;
type index$2_MapArrayOpts<V> = MapArrayOpts<V>;
type index$2_MapCircularOpts<V> = MapCircularOpts<V>;
type index$2_MapMultiOpts<V> = MapMultiOpts<V>;
type index$2_MapOfMutableImpl<V, M> = MapOfMutableImpl<V, M>;
declare const index$2_MapOfMutableImpl: typeof MapOfMutableImpl;
type index$2_MapOfSimple<V> = MapOfSimple<V>;
declare const index$2_MapOfSimple: typeof MapOfSimple;
type index$2_MapSetOpts<V> = MapSetOpts<V>;
type index$2_MultiValue<V, M> = MultiValue<V, M>;
type index$2_NumberMap<K> = NumberMap<K>;
declare const index$2_NumberMap: typeof NumberMap;
declare const index$2_firstEntry: typeof firstEntry;
declare const index$2_firstEntryByValue: typeof firstEntryByValue;
declare const index$2_immutable: typeof immutable;
declare const index$2_lengthMax: typeof lengthMax;
declare const index$2_mutable: typeof mutable;
declare const index$2_ofArrayMutable: typeof ofArrayMutable;
declare const index$2_ofCircularMutable: typeof ofCircularMutable;
declare const index$2_ofSetMutable: typeof ofSetMutable;
declare const index$2_ofSimple: typeof ofSimple;
declare namespace index$2 {
export { type index$2_ExpiringMapEvent as ExpiringMapEvent, type index$2_ExpiringMapEvents as ExpiringMapEvents, type Opts as ExpiringMapOpts, type index$2_IMapImmutable as IMapImmutable, type index$2_IMapMutable as IMapMutable, type index$2_IMapOf as IMapOf, type index$2_IMapOfImmutable as IMapOfImmutable, type index$2_IMapOfMutable as IMapOfMutable, type index$2_IMapOfMutableExtended as IMapOfMutableExtended, IDictionary as IMappish, index$2_IWithEntries as IWithEntries, type index$2_MapArrayEvents as MapArrayEvents, type index$2_MapArrayOpts as MapArrayOpts, type index$2_MapCircularOpts as MapCircularOpts, type index$2_MapMultiOpts as MapMultiOpts, index$2_MapOfMutableImpl as MapOfMutableImpl, index$2_MapOfSimple as MapOfSimple, type index$2_MapSetOpts as MapSetOpts, type index$2_MultiValue as MultiValue, index$2_NumberMap as NumberMap, create as expiringMap, index$2_firstEntry as firstEntry, index$2_firstEntryByValue as firstEntryByValue, index$2_immutable as immutable, index$2_lengthMax as lengthMax, ofSimpleMutable as mapOfSimpleMutable, index$2_mutable as mutable, index$2_ofArrayMutable as ofArrayMutable, index$2_ofCircularMutable as ofCircularMutable, index$2_ofSetMutable as ofSetMutable, index$2_ofSimple as ofSimple };
}
declare class Table<V> {
rows: Array<Array<V | undefined>>;
rowLabels: Array<string>;
colLabels: Array<string>;
labelColumns(...labels: Array<string>): void;
labelColumn(columnNumber: number, label: string): void;
getColumnLabelIndex(label: string): number | undefined;
print(): void;
rowsWithLabelsArray(): Generator<[label: string | undefined, value: V | undefined][] | undefined, void, unknown>;
/**
* Return a copy of table as nested array
* ```js
* const t = new Table();
* // add stuff
* // ...
* const m = t.asArray();
* for (const row of m) {
* for (const colValue of row) {
* // iterate over all column values for this row
* }
* }
* ```
*
* Alternative: get value at row Y and column X
* ```js
* const value = m[y][x];
* ```
* @returns
*/
asArray(): Array<Array<V | undefined>>;
/**
* Return the number of rows
*/
get rowCount(): number;
/**
* Return the maximum number of columns in any row
*/
get columnCount(): number;
rowsWithLabelsObject(): Generator<object | undefined, void, unknown>;
labelRows(...labels: Array<string>): void;
appendRow(...data: Array<V | undefined>): void;
getRowWithLabelsArray(rowNumber: number): Array<[label: string | undefined, value: V | undefined]> | undefined;
/**
* Return a row of objects. Keys use the column labels.
*
* ```js
* const row = table.getRowWithLabelsObject(10);
* // eg:
* // [{ colour: red, size: 10}, { colour: blue, size: 20 }]
* ```
* @param rowNumber
* @returns
*/
getRowWithLabelsObject(rowNumber: number): object | undefined;
/**
* Gets or creates a row at `rowNumber`.
* @param rowNumber
* @returns
*/
private getOrCreateRow;
/**
* Gets the values at `rowNumber`
* @param rowNumber
* @returns
*/
row(rowNumber: number): Array<V | undefined> | undefined;
/**
* Set the value of row,column to `value`
* @param rowNumber
* @param columnNumber
* @param value
*/
set(rowNumber: number, columnNumber: number, value: V | undefined): void;
get(rowNumber: number, column: number | string): V | undefined;
/**
* For a given row number, set all the columns to `value`.
* `cols` gives the number of columns to set
* @param rowNumber
* @param cols
* @param value
*/
setRow(rowNumber: number, cols: number, value: V | undefined): void;
}
type DistanceCompute = (graph: DirectedGraph, edge: Edge$1) => number;
/**
* Vertex. These are the _nodes_ of the graph. Immutable.
*
* They keep track of all of their outgoing edges, and
* a unique id.
*
* Ids are used for accessing/updating vertices as well as in the
* {@link Edge} type. They must be unique.
*/
type Vertex$1 = Readonly<{
out: ReadonlyArray<Edge$1>;
id: string;
}>;
/**
* Edge. Immutable.
*
* Only encodes the destination vertex. The from
* is known since edges are stored on the from vertex.
*/
type Edge$1 = Readonly<{
/**
* Vertex id edge connects to (ie. destination)
*/
id: string;
/**
* Optional weight of edge
*/
weight?: number;
}>;
/**
* Create a vertex with given id
* @param id
* @returns
*/
declare const createVertex$1: (id: string) => Vertex$1;
/**
* Options for connecting vertices
*/
type ConnectOptions$1 = Readonly<{
/**
* From, or source of connection
*/
from: string;
/**
* To, or destination of connection. Can be multiple vertices for quick use
*/
to: string | Array<string>;
/**
* If true, edges in opposite direction are made as well
*/
bidi?: boolean;
/**
* Weight for this connection (optional)
*/
weight?: number;
}>;
/**
* Directed graph. Immutable.
*
* Consists of {@link Vertex|vertices}, which all have zero or more outgoing {@link Edge|Edges}.
*/
type DirectedGraph = Readonly<{
vertices: IMapImmutable<string, Vertex$1>;
}>;
/**
* Returns _true_ if graph contains `key`.
*
* ```js
* // Same as
* g.vertices.has(key)
* ```
* @param graph
* @param key
* @returns
*/
declare function hasKey(graph: DirectedGraph, key: string): boolean;
/**
* Returns {@link Vertex} under `key`, or _undefined_
* if not found.
*
* ```js
* // Same as
* g.vertices.get(key)
* ```
* @param graph
* @param key
* @returns
*/
declare function get(graph: DirectedGraph, key: string): Vertex$1 | undefined;
/**
* Returns the graph connections as an adjacency matrix
* @param graph
* @returns
*/
declare function toAdjacencyMatrix$1(graph: DirectedGraph): Table<boolean>;
/**
* Return a string representation of the graph for debug inspection
* @param graph
* @returns
*/
declare const dumpGraph$1: (graph: DirectedGraph | Iterable<Vertex$1>) => string;
declare const distance: (graph: DirectedGraph, edge: Edge$1) => number;
/**
* Iterate over all the edges in the graph
* @param graph
*/
declare function edges(graph: DirectedGraph): Generator<Readonly<{
/**
* Vertex id edge connects to (ie. destination)
*/
id: string;
/**
* Optional weight of edge
*/
weight?: number;
}>, void, unknown>;
/**
* Iterate over all the vertices of the graph
* @param graph
*/
declare function vertices(graph: DirectedGraph): Generator<Readonly<{
out: ReadonlyArray<Edge$1>;
id: string;
}>, void, unknown>;
/**
* Iterate over all the vertices connected to `context` vertex
* @param graph Graph
* @param context id or Vertex.
* @returns
*/
declare function adjacentVertices$1(graph: DirectedGraph, context: Vertex$1 | string | undefined): Generator<Readonly<{
out: ReadonlyArray<Edge$1>;
id: string;
}>, void, unknown>;
/**
* Returns _true_ if `vertex` has an outgoing connection to
* the supplied id or vertex.
*
* If `vertex` is undefined, _false_ is returned.
* @param vertex From vertex
* @param outIdOrVertex To vertex
* @returns
*/
declare const vert