About Identifiers
Identifiers are self-describing strings of data that can be decoded into semantically-meaningful values. Identifiers can define basic data types, like numbers and bytes. They can also describe values like geolocations, date-times and uuids.
Try out an online version at identifiers.io
Installation and Usage
Identifiers-js is published to NPM and includes packaging for TypeScript, node modules and minified JS.
npm install identifiers-js
For yarn:
yarn add identifiers-js
TypeScript
import * as ID from "identifiers";
JavaScript
const ID = require('identifiers');
Browsers
<script src="https://unpkg.com/identifiers-js/dist/identifiers.bundle.js" crossorigin="anonymous"></script>
<script language="javascript">
var id = ID.factory.string("a string ID");
</script>
The ID
reference comes with methods to parse Identifier strings as well as a factory to create Identifier instances. For further details see the Factory API Reference section.
Immutability
Identifier instances are immutable. Their values are also immutable.
const integerId = ID.factory.integer(22);
console.log(integerId.value);
const dataString = integerId.toDataString();
const humanString = integerId.toHumanString();
const decodedId = ID.parse(dataString);
const decodedId2 = ID.parse(humanString);
console.log(decodedId.value === decodedId2.value);
Lists and Map Identifiers
Identifiers-js supports list and map identifiers in the factories. Each type factory has a .list()
and .map()
factory method which sets the type of structure.
const listId = ID.factory.boolean.list(true, true, false);
const mapId = ID.factory.long.map({a: 335843, b: -997});
Composite Identifiers
A composite identifier is a list or map of mixed-type identifiers. One can compose a single identifier from multiple types of identifiers. A composite identifier can include any other type of identifier.
const id1 = ID.factory.boolean(true);
const id2 = ID.factory.string.list('q', 'pr');
const compositeListId = ID.factory.composite.list(id1, id2);
const compositeMapId = ID.factory.composite.map({a: id1, b: id2});
The values of a composite are the identifiers themselves, so one would read them as normal identifiers in a collection.
const aBooleanValue = compositeListId.value[0].value;
const aStringListValue = compositeMapId.value.b.value;
JSON Support
Identifiers-js has support for both generating and parsing JSON data values. Identifier instances safely encode themselves into a JSON.stringify()
process. Additionally, a JSON reviver
is provided for JSON.parse()
calls.
const id = ID.factory.string('Hello, World!');
const anObject = { a: 'a message', b: id };
const json = JSON.stringify(anObject);
console.log(json);
const parsedObject = JSON.parse(json, ID.JSON_reviver);
const parsedId = parsedObject.b;
console.log(parsedId.value);
Supported Types
These types are defined in the Identifiers specification.
Primitive identifiers
- string
- boolean
- integer
- float
- long
- bytes
Semantic Identifiers
Structured Variants
Composites
Factory API Reference
The factory has methods for each type of identifier. These methods can consume various inputs to build an identifier.
Each identifier type's factory has methods to construct structural identifiers of their type. Each structural factory method accepts the same inputs as the single value methods, but in structural form.
String
const id = ID.factory.string('Hello');
console.log(id.type);
console.log(typeof id.value);
ID.factory.string.list('Hello', 'friend', 'welcome!');
ID.factory.string.list(['an', 'array', 'of', 'strings']);
ID.factory.string.map({a: 'oil', b: 'vinegar'});
Boolean
const id = ID.factory.boolean(true);
console.log(id.type);
console.log(typeof id.value);
ID.factory.boolean.list(true, false, true);
ID.factory.boolean.list([false, false, true]);
ID.factory.boolean.map({a: false, b: true});
Integer
const id = ID.factory.integer(15);
console.log(id.type);
console.log(typeof id.value);
ID.factory.integer.list(-10000, 0, 2234);
ID.factory.integer.list([1, 2, 4]);
ID.factory.integer.map({a: 55, b: -9550});
Float
const id = ID.factory.float(-0.58305);
console.log(id.type);
console.log(typeof id.value);
ID.factory.float.list(3.665, 0.1, -664.12234);
ID.factory.float.list([1.1, 2.2, 4.4]);
ID.factory.float.map({a: 80.1, b: -625.11});
Long
const id = ID.factory.long(8125);
console.log(id.type);
console.log(typeof id.value);
console.log(id.value);
ID.factory.long({low: -4434, high: 22});
ID.factory.long.list(-10, 21, {low: 96, high: 34});
ID.factory.long.list([{low: 224456, high: -4}, 2, 4]);
ID.factory.long.map({a: {low: -1, high: 0}, b: -95503343432});
Bytes
const id = ID.factory.bytes([100, 0, 12, 33]);
console.log(id.type);
console.log(typeof id.value);
ID.factory.bytes(Buffer.from([255, 0, 128]));
ID.factory.bytes(new ArrayBuffer(16));
ID.factory.bytes(Uint8Array.of(255, 0, 128));
ID.factory.bytes(Uint8ClampedArray.of(100, 99, 38));
ID.factory.bytes({length: 2, '0': 1, '1': 75});
ID.factory.bytes.list([10, 1, 0, 0], [212, 196]);
ID.factory.bytes.list([[1, 2, 4]]);
ID.factory.bytes.map({a: [50, 0], b: [45, 61, 121]});
Semantic Identifiers
UUID
Base identifier type is bytes so the factory accepts multiple types of byte array inputs. The array-like input must contain 16 bytes. The factory also accepts a uuid-encoded string.
const id = ID.factory.uuid('8cdcbe23-c04e-4ea2-ae51-15c9cf16e1b3');
console.log(id.type);
console.log(typeof id.value);
ID.factory.uuid([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
ID.factory.uuid(Buffer.from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]));
ID.factory.uuid(Uint8Array.of(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15));
ID.factory.uuid.list([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], '13f3eae9-18d6-46fc-9b3a-d6d32aaee26c');
ID.factory.uuid.list([
'cebfc569-2ba6-4cd7-ba25-f51d64c13087',
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
Uint8ClampedArray.of(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)]);
ID.factory.uuid.map({
a: '7894746d-62a5-425f-adb7-0a609ababf3f',
b: Buffer.from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])
});
Datetime
Base identifier type is long so the factory accepts the same multiple types of long inputs. It also accepts a JS Date object as an input.
const id = ID.factory.datetime(new Date());
console.log(id.type);
console.log(typeof id.value);
ID.factory.datetime(10000000);
ID.factory.datetime.list(new Date(), 10000000);
ID.factory.datetime.list([3576585434, new Date(10000000)]);
ID.factory.datetime.map({a: 3576585434, b: new Date()});
Geo
Base identifier type of geo is a list of 2 floats. Factory accepts a geo-like object or a list of 2 floats (lat, then long).
const id = ID.factory.geo({latitude: 14.8653, longitude: -23.0987877});
console.log(id.type);
console.log(typeof id.value);
ID.factory.geo([-45.6768494, 13.224]);
ID.factory.geo.list({latitude: 14.8653, longitude: -23.0987877}, [90.0, 100.7685944]);
ID.factory.geo.list([[0.23433, -0.1001002], {latitude: 0.0, longitude: 10.11}]);
ID.factory.geo.map({a: {latitude: 14.262, longitude: -123.0923}, b: [10.0021, 90.4]});