@mdrv/surrealid
v0.1.0
Published
SurrealDB-compatible ID generation (rand/ulid/uuid) — pure, zero-dependency
Readme
@mdrv/surrealid
SurrealDB-compatible ID generation — pure, zero-dependency.
Client-side ID generation whose output matches SurrealDB's built-in rand() and ulid(), so IDs generated in TypeScript are interchangeable with IDs generated by the server. Extracted from @mdrv/tinybase-surrealdb-sync.
Install
bun add @mdrv/surrealidUsage
import { generateId, surrealId, surrealUlid, type IdMode } from '@mdrv/surrealid'
surrealId() // 'a1b2c3d4e5f6g7h8i9j0' (20-char [a-z0-9], matches SurrealDB rand())
surrealId(10) // custom length
surrealUlid() // '01H8...' (26-char Crockford base-32, time-sortable, matches SurrealDB ulid())
generateId() // defaults to rand
generateId('ulid') // explicit mode
generateId('uuid') // crypto.randomUUID()Modes (IdMode)
| Mode | Format | Entropy | Sortable | Matches |
| --- | --- | --- | --- | --- |
| 'rand' (default) | 20-char [a-z0-9] | ~103 bits | no | SurrealDB rand() |
| 'ulid' | 26-char Crockford base-32 | 80-bit random + 48-bit ms | yes (lexicographic) | SurrealDB ulid() |
| 'uuid' | UUIDv4 | 122 bits | no | crypto.randomUUID() |
ULIDs are monotonic within a single runtime (same-millisecond calls increment the random suffix by 1), so they sort by creation time — useful for WHERE id > $cursor range queries.
Why
So that a note/row created on the client (e.g. in filesystem mode before a SurrealDB round-trip, or on a mobile device) gets the same shape of ID the server would have assigned — no tmp- prefixes, no migration when syncing upstream.
License
MIT
