22-character URL-safe IDs that round-trip with .NET Guid.ToByteArray().
This is the JavaScript encoding used by TecPoint ShortId values. It is the same scheme as CSharpVitamins.ShortGuid and the Mads Kristensen short GUID: mixed-endian GUID bytes, URL-safe base64, padding stripped.
import { ShortId, generate } from '@tecpoint/short-id'
const id = ShortId.new().toString()
// e.g. "X_YtZReHKkia_vC7lnwVYA"
// same thing, string only
const id2 = generate()ShortId.new() (and generate()) use UUIDv7.
npm install @tecpoint/short-idimport { decode, encode, generate, ShortId } from '@tecpoint/short-id'
encode('652df65f-8717-482a-9afe-f0bb967c1560')
// 'X_YtZReHKkia_vC7lnwVYA'
decode('X_YtZReHKkia_vC7lnwVYA')
// '652df65f-8717-482a-9afe-f0bb967c1560'
const id = ShortId.new()
id.shortValue // 22 chars, what the TecPoint API expects
id.guidValue // 36-char lowercase GUID
id.toString() // short value
JSON.stringify({ id }) // {"id":"..."} — serializes as the short value
ShortId.from('652df65f-8717-482a-9afe-f0bb967c1560')
ShortId.from('X_YtZReHKkia_vC7lnwVYA')
ShortId.empty()
ShortId.equals(id, id.guidValue) // trueInvalid input throws Error: The Id supplied ('...') is not valid.
Most npm “short UUID” packages encode RFC / network-order UUID bytes. This package encodes Windows / .NET GUID bytes (Guid.ToByteArray()): the first three fields are little-endian, the last eight bytes are stored as in the canonical string.
Those two layouts produce different 22-character strings for the same GUID. Do not mix this with uuid-url, short-uuid, or similar unless you only need uniqueness, not TecPoint / .NET interop.
| Guid | Short |
|---|---|
c9a646d3-9c61-4cb7-bfcd-ee2522c8f633 |
00amyWGct0y_ze4lIsj2Mw |
652df65f-8717-482a-9afe-f0bb967c1560 |
X_YtZReHKkia_vC7lnwVYA |
39240e2a-4ef7-406b-882a-920f72fc047a |
Kg4kOfdOa0CIKpIPcvwEeg |
00000000-0000-0000-0000-000000000000 |
AAAAAAAAAAAAAAAAAAAAAA |
16 bytes is 128 bits; 22 base64 characters are 132 bits. Two bits are unused, so in theory more than one 22-character string can decode to the same GUID. The encoder never emits those alternate forms. Decode does not reject them. Hitting this by accident is effectively zero.
string Encode(Guid guid)
{
var enc = Convert.ToBase64String(guid.ToByteArray());
return enc.Replace("/", "_").Replace("+", "-")[..22];
}
Guid Decode(string encoded)
{
var work = encoded.Replace("_", "/").Replace("-", "+") + "==";
return new Guid(Convert.FromBase64String(work));
}On .NET this is also new ShortId(guid) in TecPoint, or CSharpVitamins.ShortGuid.
uuid.UUID.bytes_le is the same mixed-endian layout as Guid.ToByteArray().
import base64
import uuid
def encode(g: uuid.UUID) -> str:
return base64.urlsafe_b64encode(g.bytes_le).decode("ascii").rstrip("=")
def decode(s: str) -> uuid.UUID:
return uuid.UUID(bytes_le=base64.urlsafe_b64decode(s + "=="))MIT