Verified on node.js v6, v8, v10, v11 and v12
Table of Contents
AnyID is a simple and flexible API to generate various kinds of string ID / code.
The generated ID is compounded by sections with optional delimiter. Each section is encoded into specificed chars and may have fix length.
sdk3ksxjcs-JEDke3x8F-sldle34CZs
^^^^^^^^^^ ^
│ │
└ section └ delimiter
A section may contain one or more values. Multiple values are concatenated into bit stream before encoded.
┌───────────────────────┬───────────────┬──────────────────┐
│ timestamp (41 bits) │ seq (12 bits) │ worker (10 bits) │
└───────────────────────┴───────────────┴──────────────────┘
Use it in your code:
import {anyid} from 'anyid';
const ids = anyid().encode('Aa0').length(21).random();
console.log(ids.id());If you aren't using ES6, this is the way to require it:
var anyid = require('anyid').anyid;>>> Try it in your browser. <<<
Encode with given charset:
encode(charset: string)Charset is specified by simple letter:
A- Alphabet in upper casea- Alphabet in lower case0- Numeric
Individual letters can be exclude by followed after -, be appended by followed after +.
Example:
Aa0= A-Z a-z 0-90A-IO= 0-9 A-Z, excludesIandO0+ABCDEF= 0-9 A-FA+012-IO= A-Z 0 1 2, excludesIandO
A section accepts an AnyId object as parameter. For ID containing single section, section function is not used.
section( anyid: AnyId )Section length can be fixed or variant. When length is specified, section will be trimmed or padded at beginning side.
length(n: number)For some kinds of value, e.g. random, length must be given.
Hint What length will be if not specified?
b: value bytes a: charset size length ≧ logₐ256ᵇ = log₂ 256ᵇ / log₂ a = 8b / log₂ aFor example:
Value is 4 bytes UInt32, charset is A-Za-z0-9 which has 62 characters.
8 * 4 / log₂ 62 = 5.37. Maximum length will be 6.
Delimiter can be put between sections. It's output as is and never be encoded.
delimiter( s: string )AnyID supports several kinds of value:
- random
- timestamp
- sequence
- fix value
- function result
- variable
Value is either non-negative integer (UInt32) or Buffer (byte array).
A section may have more than one values. Values will be concatenated as bit stream before encoded.
You can use bits to specify the bit width of a value. Higher bits will be discard if value has more bits than desired.
bits( n: number )Generate value by random. Length or bits must be specified.
random()Internally it uses crypto.randomBytes() to generate random.
Hint The probability of duplicates in
nrandom IDs is:p(n) ≈ n²/(2*C^L)Where
Lis the length of random id,Cis the size of encode charset.For example: using
anyid().encode('Aa0').length(21).random()to generate randome ID,Lis 21 andCis 62. Thenp(n) ≈ n²/(2*62^21). It has lower probability of duplicates then type 4 (random) UUID.
Use current timestamp as value.
time( unit: string = 'ms' )Unit can be ms, s, m, h, d.
By default, timestamp value is since UNIX epoch time. You can overwrite it to a recent date to save some bits.
since( t: Date )Sequence increases everytime an ID is generated.
seq()By default, sequence starts from 0. You can set it to any non-negative integer.
startWith( n: number )Sequence will be reset after it reaches max value.
It can not exceed 2^32 (max value represented by UInt32).
max( n: number )Or, let it reset when timestamp changes:
resetByTime()To use resetByTime, there must be a timestamp value in the ID.
fixed( n: number | Buffer )Value is either non-negative integer (UInt32) or Buffer (byte array).
Similar to fix value, but the value is returned by a function which is called an ID is to be generated.
of( f: () => number | Buffer )Similar to fix value, but the value is given in id function call.
variable( name?: string )When there is only one variable used in ID generator, the name can be omitted in variable() and the value is directly passing in id function call:
id( v: number | Buffer )When there are multiple variables used in ID generator, the values need to be passing in id in an object:
id( v: {[name: string]: number | Buffer} )Read example below to check how it's used.
This id has essence the same low probability of a clash as type 4 (random) UUID:
const ids = anyid().encode('Aa0').length(21).random()
const id = ids.id();1LrKcmd0uk1Ma8szUxtda
const ids = anyid()
.encode('0A-IO')
.section( anyid().fixed(process.pid) )
.delimiter('-')
.section( anyid().time() );It uses human friendly charset: I and O are excluded because of similarity to 1 and 0.
008CL-00TYMZS0P3
It's Twitter Snowflake style ID with timestamp, sequence and worker.
const ids = anyid()
.encode('0')
.bits(41).time().since(new Date('2016-7-1'))
.bits(12).seq().resetByTime();
.bits(10).fix(workerId);Timestamp is since 2016-7-1. Sequence is reset every millisecond.
071243223959339218
ID contains second and nanosecond. Nanosecond is retrieved by a function.
const nanotime = () => process.hrtime()[1];
const ids = anyid()
.encode('Aa0')
.section( anyid().time('s') )
.delimiter('+')
.section( anyid().of(nanotime) );BlX6bX+j3Uz0
The ID has default charset A-IO. The second section uses charset 0.
const ids = anyid()
.encode('A-IO')
.section( anyid().length(3).random() )
.delimiter(' ')
.section( anyid().encode('0').length(3).random() )
.delimiter(' ')
.section( anyid().length(3).random() );HQX 552 ATC
const ids = anyid()
.encode('Aa0')
.section( anyid().variable() )
.delimiter('-')
.section( anyid().time() );
const id = ids(Buffer.from('user-xxx'));KFLnaOrolmA-AAZ28TmMo
const ids = anyid()
.encode('Aa0')
.section( anyid().variable('countryId') )
.delimiter('-')
.section( anyid().variable('userId') )
.delimiter('-')
.section( anyid().length(5).random() );
const id = ids.id({ countryId: 86, userId: 635023 });AAABY-ACpMT-EBwQJ