uniku
Migration

Migrate to uniku v1

Prepare for the v1 entry-point contract without changing identifier data.

uniku v1 keeps its canonical identifier formats stable while finalizing its pre-v1 entry points and machine-readable error contract.

Move CUID v2 to the versioned entry point

V1 removes the pre-v1 uniku/cuid2 alias. Use the canonical versioned import:

- import { cuid2 } from 'uniku/cuid2'
+ import { cuidv2 } from 'uniku/cuid/v2'

The generator behavior is the same. This is an import migration, not a data migration: existing CUID v2 values remain valid.

Convert second-based timestamp options to milliseconds

KSUID, ObjectID, and XID now expose only the shared msecs timestamp option. Convert an existing Unix-seconds value before passing it:

- const ksuidValue = ksuid({ secs })
- const objectIdValue = objectid({ secs })
- const xidValue = xid({ secs })
+ const ksuidValue = ksuid({ msecs: secs * 1000 })
+ const objectIdValue = objectid({ msecs: secs * 1000 })
+ const xidValue = xid({ msecs: secs * 1000 })

The conversion is msecs = secs * 1000; these formats still store whole seconds, so equivalent deterministic inputs produce the same identifier data.

Rename UUID v7 and TypeID counters

The pre-v1 seq spelling is now counter for UUID v7 and for TypeID, which inherits the UUID v7 options:

- const uuid = uuidv7({ seq: 42 })
- const userId = typeid('user', { seq: 42 })
+ const uuid = uuidv7({ counter: 42 })
+ const userId = typeid('user', { counter: 42 })

Only the option name changes. The counter value is packed identically.

Rename Nanoid's object-form length

Use length instead of size in Nanoid's object form:

- const id = nanoid({ alphabet: '0123456789abcdef', size: 12 })
+ const id = nanoid({ alphabet: '0123456789abcdef', length: 12 })

The positional nanoid(number) overload is unchanged:

const id = nanoid(12)

These migrations change imports and option names, not identifier formats. Existing persisted UUID v7, TypeID, KSUID, ObjectID, XID, Nanoid, and CUID v2 values require no data migration.

Update error-code matches

Pre-v1 error codes included the generator name. V1 uses strategy-agnostic codes and reports the generator separately through error.strategy:

 if (error instanceof ParseError) {
-  if (error.code === 'ULID_INVALID_CHAR') {
+  if (error.code === 'INVALID_CHAR' && error.strategy === 'ulid') {
     // handle an invalid ULID character
   }
 }

uniku/errors exports ERROR_CODES, the authoritative runtime catalog, and its derived ErrorCode type. The _tag classes and human-readable messages keep their existing roles.

This table maps every machine-readable code emitted by uniku@0.4.3 to its v1 replacement:

Pre-v1 code(s)V1 code
UUID_TIMESTAMP_OUT_OF_RANGE, ULID_TIMESTAMP_OUT_OF_RANGE, ULID_TIMESTAMP_OVERFLOW, KSUID_TIMESTAMP_TOO_LOW, KSUID_TIMESTAMP_TOO_HIGH, OBJECTID_TIMESTAMP_OUT_OF_RANGE, XID_TIMESTAMP_OUT_OF_RANGE, TSID_TIMESTAMP_INVALID, TSID_TIMESTAMP_OUT_OF_RANGETIMESTAMP_OUT_OF_RANGE
UUID_INVALID_HEX_CHAR, ULID_INVALID_CHAR, KSUID_INVALID_CHAR, OBJECTID_INVALID_CHAR, XID_INVALID_CHAR, TSID_INVALID_CHAR, TYPEID_SUFFIX_INVALID_CHARACTERINVALID_CHAR
UUID_INVALID_LENGTH, ULID_INVALID_LENGTH, KSUID_INVALID_LENGTH, OBJECTID_INVALID_LENGTH, XID_INVALID_LENGTH, TSID_INVALID_LENGTH, TYPEID_SUFFIX_INVALID_LENGTHINVALID_LENGTH
UUID_INVALID_SEPARATORS, TYPEID_INVALID_FORMATINVALID_FORMAT
KSUID_OVERFLOW, TYPEID_SUFFIX_OVERFLOW, TSID_LEADING_CHAR_OUT_OF_RANGE, TSID_VALUE_OUT_OF_RANGEVALUE_OUT_OF_RANGE
XID_NON_CANONICALNON_CANONICAL
UUID_BYTES_INVALID_LENGTH, ULID_BYTES_INVALID_LENGTH, KSUID_BYTES_INVALID_LENGTH, KSUID_BYTES_TOO_SHORT, OBJECTID_BYTES_INVALID_LENGTH, OBJECTID_BYTES_TOO_SHORT, XID_BYTES_INVALID_LENGTH, TSID_BYTES_INVALID_LENGTH, TYPEID_UUID_BYTES_INVALID_LENGTHBYTES_INVALID_LENGTH
UUID_BUFFER_OUT_OF_BOUNDS, ULID_BUFFER_OUT_OF_BOUNDS, KSUID_BUFFER_OUT_OF_BOUNDS, OBJECTID_BUFFER_OUT_OF_BOUNDS, XID_BUFFER_OUT_OF_BOUNDS, TSID_BUFFER_OUT_OF_BOUNDSBUFFER_OUT_OF_BOUNDS
UUID_RANDOM_BYTES_TOO_SHORT, ULID_RANDOM_BYTES_TOO_SHORT, KSUID_RANDOM_BYTES_TOO_SHORT, OBJECTID_RANDOM_BYTES_TOO_SHORT, NANOID_RANDOM_BYTES_INSUFFICIENT, CUID2_RANDOM_BYTES_EMPTYRANDOM_BYTES_TOO_SHORT
ULID_RANDOM_OVERFLOWRANDOM_OVERFLOW
UUID_SEQUENCE_OUT_OF_RANGE, OBJECTID_COUNTER_OUT_OF_RANGE, XID_COUNTER_OUT_OF_RANGE, TSID_COUNTER_OUT_OF_RANGECOUNTER_OUT_OF_RANGE
TSID_NODE_OUT_OF_RANGENODE_OUT_OF_RANGE
TSID_NODE_BITS_OUT_OF_RANGENODE_BITS_OUT_OF_RANGE
TSID_EPOCH_INVALIDEPOCH_INVALID
XID_PROCESS_ID_OUT_OF_RANGEPROCESS_ID_OUT_OF_RANGE
XID_MACHINE_ID_BYTES_TOO_SHORTMACHINE_ID_BYTES_TOO_SHORT
TYPEID_PREFIX_TOO_LONGPREFIX_TOO_LONG
TYPEID_PREFIX_INVALID_CHARACTERPREFIX_INVALID_CHAR
TYPEID_PREFIX_INVALID_BOUNDARYPREFIX_INVALID_BOUNDARY
TYPEID_UUID_NOT_V7UUID_NOT_V7
NANOID_ALPHABET_TOO_SHORT, NANOID_ALPHABET_TOO_LONGALPHABET_OUT_OF_RANGE
NANOID_ALPHABET_INVALID_CHARALPHABET_INVALID_CHAR
NANOID_ALPHABET_DUPLICATEALPHABET_DUPLICATE
NANOID_SIZE_INVALID, NANOID_SIZE_TOO_LARGE, CUID2_LENGTH_OUT_OF_RANGELENGTH_OUT_OF_RANGE

Several old codes intentionally converge on one v1 meaning. This only changes error handling; generated and persisted identifier data is unaffected.

What remains stable

Within 1.x, uniku will not remove or rename documented entry points, exports, options, methods, or constants. Canonical string formats, byte order, timestamp units, and documented error codes are part of the contract.

Read the stability contract for the full release and runtime policy.

On this page