Skip to main content

@ttoss/ids

This package provides a opinionated way to work with different ids in the application.

Check the blog post for more information.

Installation​

pnpm add @ttoss/ids

Usage​

From database id to global id​

Example with PostgreSQL:

import { toRecordId, toGlobalId } from '@ttoss/ids';

const itemFromPostgreSQL = {
id: 1,
name: 'John Doe',
};

const recordId = toRecordId(itemFromPostgreSQL.id);

console.log(recordId); // 1

const globalId = toGlobalId('User', recordId);

console.log(globalId); // VXNlcjox

Example with DynamoDB:

import { toRecordId, toGlobalId } from '@ttoss/ids';

const itemFromDynamoDB = {
partitionKey: 'USER',
sortKey: '1',
name: 'John Doe',
};

const recordId = toRecordId([
itemFromDynamoDB.partitionKey,
itemFromDynamoDB.sortKey,
]);

console.log(recordId); // USER:1

const globalId = toGlobalId('User', recordId);

console.log(globalId); // VXNlcjpVU0VSOjE=

From global id to database id​

Example with PostgreSQL:

import { fromGlobalId, fromRecordId } from '@ttoss/ids';

const globalId = 'VXNlcjox';

const { type, recordId } = fromGlobalId(globalId);

console.log(type); // User
console.log(recordId); // 1

const [databaseId] = fromRecordId(recordId);

console.log(databaseId); // 1

Example with DynamoDB:

import { fromGlobalId, fromRecordId } from '@ttoss/ids';

const globalId = 'VXNlcjpVU0VSOjE=';

const { type, recordId } = fromGlobalId(globalId);

console.log(type); // User
console.log(recordId); // USER:1

const [partitionKey, sortKey] = fromRecordId(recordId);

console.log(partitionKey); // USER
console.log(sortKey); // 1

Public ids​

A public id is a type prefix, an underscore and random characters — task_x7kp2mq4vb. The server assigns it and stores it beside the internal primary key, so the key rows join on can change without any id a client holds changing.

import { createPublicId, isPublicId, publicIdPattern } from '@ttoss/ids';

const id = createPublicId({ prefix: 'task' }); // task_x7kp2mq4vb

isPublicId({ value: id, prefix: 'task' }); // true
isPublicId({ value: id, prefix: 'proj' }); // false

// For a validator at the API boundary, e.g. z.string().regex(pattern).
const pattern = publicIdPattern({ prefix: 'task' });

The random part uses lowercase Crockford base32 (PUBLIC_ID_ALPHABET), which leaves out i, l, o and u, so an id copied by hand or by a model is not misread as 1 or 0. It comes from crypto.getRandomValues, so ids are not guessable, and it works in Node.js and in browsers. The default length is 10 characters (DEFAULT_PUBLIC_ID_LENGTH), about 50 bits; pass length to change it. A prefix must be lowercase letters and digits, starting with a letter.