61 lines
1.9 KiB
Markdown
61 lines
1.9 KiB
Markdown
|
|
# @peoplesgrocers/lseq
|
||
|
|
|
||
|
|
TypeScript implementation of the L-SEQ algorithm for fractional indexing and list CRDTs.
|
||
|
|
|
||
|
|
## Installation
|
||
|
|
|
||
|
|
```bash
|
||
|
|
npm install @peoplesgrocers/lseq
|
||
|
|
```
|
||
|
|
|
||
|
|
## Usage
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
import { LSEQ, compareLSEQ } from '@peoplesgrocers/lseq';
|
||
|
|
|
||
|
|
// Create a new L-SEQ instance
|
||
|
|
const lseq = new LSEQ();
|
||
|
|
|
||
|
|
// Allocate identifiers
|
||
|
|
const id1 = lseq.alloc(null, null); // First identifier
|
||
|
|
const id2 = lseq.alloc(id1, null); // After id1
|
||
|
|
const id3 = lseq.alloc(id1, id2); // Between id1 and id2
|
||
|
|
|
||
|
|
// Sort identifiers
|
||
|
|
const ids = [id3, id1, id2];
|
||
|
|
ids.sort(compareLSEQ);
|
||
|
|
console.log(ids); // [id1, id3, id2] - properly ordered
|
||
|
|
|
||
|
|
// Custom random function (useful for deterministic testing)
|
||
|
|
const deterministicLSEQ = new LSEQ(() => 0.5);
|
||
|
|
```
|
||
|
|
|
||
|
|
## API
|
||
|
|
|
||
|
|
### `LSEQ`
|
||
|
|
|
||
|
|
#### `constructor(random?: () => number)`
|
||
|
|
|
||
|
|
Creates a new L-SEQ instance.
|
||
|
|
|
||
|
|
- `random`: Optional custom random function (defaults to `Math.random`)
|
||
|
|
|
||
|
|
#### `alloc(before: string | null, after: string | null): string`
|
||
|
|
|
||
|
|
Allocates a new identifier between two existing identifiers.
|
||
|
|
|
||
|
|
- `before`: The identifier that should come before the new one (or `null` for beginning)
|
||
|
|
- `after`: The identifier that should come after the new one (or `null` for end)
|
||
|
|
- Returns: A new identifier that sorts between `before` and `after`
|
||
|
|
|
||
|
|
### `compareLSEQ(a: string, b: string): number`
|
||
|
|
|
||
|
|
Compares two L-SEQ identifiers for sorting.
|
||
|
|
|
||
|
|
- Returns: `-1` if `a < b`, `1` if `a > b`, `0` if `a === b`
|
||
|
|
|
||
|
|
## How it works
|
||
|
|
|
||
|
|
L-SEQ generates identifiers using a base-64 alphabet that maintains lexicographic ordering. Each identifier is a sequence of characters from this alphabet, and new identifiers are generated by finding space between existing ones at different depths.
|
||
|
|
|
||
|
|
The algorithm uses alternating allocation strategies (bias toward min or max) at different depths to avoid degenerative cases and maintain good performance characteristics.
|