fugue
Version:
Fractional indexing without conflicts.
124 lines (122 loc) • 4.25 kB
TypeScript
declare const FIRST = "";
declare const LAST = "~";
type FuguePosition<TClientID extends string = string> = `${string}${TClientID}.${string}` | typeof FIRST | typeof LAST;
type FugueOptions<TClientID extends string = string> = {
/**
* The unique ID for this client.
*/
clientID: TClientID;
};
declare class Fugue<TClientID extends string = string> {
/**
* A string that is less than all positions.
*/
static readonly FIRST = "";
/**
* A string that is greater than all positions.
*/
static readonly LAST = "~";
/**
* The unique ID for this client.
*/
readonly clientID: TClientID;
/**
* The waypoints' long name: `,${clientID}.`.
*/
private readonly longName;
/**
* Variant of longName used for a position's first ID: `${clientID}.`.
* (Otherwise every position would start with a redundant ','.)
*/
private readonly firstName;
/**
* For each waypoint that we created, maps a prefix (see getPrefix)
* for that waypoint to its last (most recent) valueSeq.
* We always store the right-side version (odd valueSeq).
*/
private lastValueSeqs;
private readonly maxCachedPrefixes;
constructor(clientID: TClientID);
/**
* Creates a new position between two existing positions.
* The new position will be greater than `a` and less than `b`.
*
* @param a - An existing position to insert after, or null to insert at the beginning
* @param b - An existing position to insert before, or null to insert at the end
* @returns A new position that satisfies `a < new < b`
*
* @example
* ```typescript
* const fugue = new Fugue("client1");
* const pos1 = fugue.between(null, null); // First position
* const pos2 = fugue.between(pos1, null); // Insert after pos1
* const pos3 = fugue.between(pos1, pos2); // Insert between pos1 and pos2
* // pos1 < pos3 < pos2
* ```
*
* @throws Will warn and adjust inputs if:
* - `a >= b` (when both are non-null)
* - `b > Fugue.LAST`
*/
between(a: string | null, b: string | null): FuguePosition<TClientID> & {};
/**
* Creates a new position immediately after the given position.
* This is equivalent to calling `between(position, null)`.
*
* @param position - The existing position to insert after
* @returns A new position that is greater than the given position
*
* @example
* ```typescript
* const fugue = new Fugue("client1");
* const pos1 = fugue.between(null, null); // First position
* const pos2 = fugue.after(pos1); // Insert after pos1
* // pos1 < pos2
* ```
*/
after(position: string): "" | "~" | `${string}${TClientID}.${string}`;
/**
* Creates a new position immediately before the given position.
* This is equivalent to calling `between(null, position)`.
*
* @param position - The existing position to insert before
* @returns A new position that is less than the given position
*
* @example
* ```typescript
* const fugue = new Fugue("client1");
* const pos1 = fugue.between(null, null); // First position
* const pos2 = fugue.before(pos1); // Insert before pos1
* // pos2 < pos1
* ```
*/
before(position: string): "" | "~" | `${string}${TClientID}.${string}`;
/**
* Creates the first position in a sequence.
* This is equivalent to calling `between(null, null)`.
*
* @returns A new position that is greater than all existing positions
*
* @example
* ```typescript
* const fugue = new Fugue("client1");
* const pos1 = fugue.first(); // First position
* const pos2 = fugue.after(pos1); // Insert after pos1
* // pos1 < pos2
* ```
*/
first(): "" | "~" | `${string}${TClientID}.${string}`;
/**
* Appends a waypoint to the ancestor.
*/
private appendWaypoint;
/**
* The number of prefixes in the cache.
*/
get cacheSize(): number;
/**
* Cleans up the cache of last value sequences.
*/
private cleanupLastValueSeqs;
}
export { Fugue, type FugueOptions, type FuguePosition };