Full Code of aarondcohen/id128 for AI

master 4a8f911e306e cached
55 files
144.9 KB
42.4k tokens
260 symbols
1 requests
Download .txt
Repository: aarondcohen/id128
Branch: master
Commit: 4a8f911e306e
Files: 55
Total size: 144.9 KB

Directory structure:
gitextract_yj1hrjym/

├── .eslintrc.js
├── .gitignore
├── CHANGES
├── LICENSE
├── README.md
├── benchmark/
│   ├── basics.js
│   ├── factory-uuid.js
│   ├── memory.js
│   └── stats.js
├── index.d.ts
├── index.js
├── package.json
├── src/
│   ├── coder/
│   │   ├── base.js
│   │   ├── crockford32.js
│   │   ├── hex.js
│   │   └── uuid.js
│   ├── common/
│   │   ├── byte-array.js
│   │   ├── epoch-converter.js
│   │   ├── exception.js
│   │   ├── fake-machine.js
│   │   ├── machine.js
│   │   ├── random-bytes-browser.js
│   │   └── random-bytes.js
│   ├── factory/
│   │   ├── id.js
│   │   └── versioned-id.js
│   └── id/
│       ├── base.js
│       ├── ulid-monotonic.js
│       ├── ulid.js
│       ├── uuid-1.js
│       ├── uuid-4.js
│       ├── uuid-6.js
│       ├── uuid-nil.js
│       └── uuid.js
├── test/
│   ├── coder/
│   │   ├── crockford32.js
│   │   ├── hex.js
│   │   ├── shared.js
│   │   └── uuid.js
│   ├── common/
│   │   ├── byte-array.js
│   │   ├── epoch-converter.js
│   │   ├── fake-machine.js
│   │   └── machine.js
│   ├── factory/
│   │   ├── id.js
│   │   └── versioned-id.js
│   ├── id/
│   │   ├── shared.js
│   │   ├── ulid-monotonic.js
│   │   ├── ulid.js
│   │   ├── uuid-1.js
│   │   ├── uuid-4.js
│   │   ├── uuid-6.js
│   │   └── uuid-nil.js
│   └── id128.js
├── types/
│   ├── test.ts
│   ├── tsconfig.json
│   └── tslint.json
└── utils.js

================================================
FILE CONTENTS
================================================

================================================
FILE: .eslintrc.js
================================================
/* eslint max-lines: "off" */

module.exports = {
	env: {
		browser: true,
		commonjs: true,
		es6: true,
		node: true,
	},
	extends: 'eslint:recommended',
	parserOptions: { sourceType: 'module' },
	rules: {
		'accessor-pairs': ['error'],
		'array-bracket-spacing': ['warn', 'never'],
		'array-callback-return': ['warn'],
		'arrow-body-style': ['error'],
		'arrow-parens': ['error', 'always'],
		'arrow-spacing': ['error', {
			after: true,
			before: true,
		}],
		'block-scoped-var': ['off'],
		'block-spacing': ['warn', 'always'],
		'brace-style': ['warn', 'stroustrup', { allowSingleLine: true }],
		'callback-return': ['warn'],
		'camelcase': ['off'], //<- consider error, never
		'capitalized-comments': ['off'],
		'class-methods-use-this': ['off'],
		'comma-dangle': ['error', 'always-multiline'],
		'comma-spacing': ['error'],
		'comma-style': ['error'],
		'complexity': ['warn', { max: 15 }],
		'computed-property-spacing': ['error'],
		'consistent-return': ['off'],
		'consistent-this': ['error'],
		'constructor-super': ['error'],
		'curly': ['error', 'all'],
		'default-case': ['off'],
		'dot-location': ['error', 'property'],
		'dot-notation': ['error'],
		'eol-last': ['warn', 'always'],
		'eqeqeq': ['error'],
		'func-call-spacing': ['error', 'never'],
		'func-name-matching': ['off'],
		'func-names': ['off'],
		'func-style': ['off'],
		'generator-star-spacing': ['error', 'after'],
		'global-require': ['error'],
		'guard-for-in': ['warn'],
		'handle-callback-err': ['warn'],
		'id-blacklist': ['off'],
		'id-length': ['off'],
		'id-match': ['off'],
		'indent': ['error', 'tab'],
		'init-declarations': ['off'],
		'jsx-quotes': ['off'],
		'key-spacing': ['error'],
		'keyword-spacing': ['error', { after: true }],
		'line-comment-position': ['off'],
		'linebreak-style': ['error', 'unix'],
		'lines-around-comment': ['off'],
		'lines-around-directive': ['error'],
		'max-depth': ['warn', { max: 4 }],
		'max-len': ['error', {
			code: 100,
			ignoreRegExpLiterals: true,
			ignoreStrings: true,
			ignoreTemplateLiterals: true,
			ignoreUrls: true,
			tabWidth: 2,
		}],
		'max-lines': ['error', {
			max: 200,
			skipBlankLines: true,
			skipComments: true,
		}],
		'max-nested-callbacks': ['warn', { max: 5 }],
		'max-params': ['warn', { max: 3 }],
		'max-statements': ['warn', { max: 20 }],
		'max-statements-per-line': ['error', { max: 2 }],
		'multiline-ternary': ['off'],
		'new-cap': ['off'],
		'new-parens': ['off'],
		'newline-after-var': ['warn', 'always'],
		'newline-before-return': ['warn'],
		'newline-per-chained-call': ['warn', { ignoreChainWithDepth: 3 }],
		'no-alert': ['error'],
		'no-array-constructor': ['error'],
		'no-await-in-loop': ['warn'],
		'no-bitwise': ['off'],
		'no-caller': ['error'],
		'no-case-declarations': ['error'],
		'no-catch-shadow': ['error'],
		'no-class-assign': ['error'],
		'no-cond-assign': ['error', 'except-parens'],
		'no-confusing-arrow': ['error', { allowParens: true }],
		'no-console': ['error'],
		'no-const-assign': ['error'],
		'no-constant-condition': ['error'],
		'no-continue': ['off'],
		'no-control-regex': ['off'],
		'no-debugger': ['error'],
		'no-delete-var': ['error'],
		'no-div-regex': ['error'],
		'no-dupe-args': ['error'],
		'no-dupe-class-members': ['error'],
		'no-dupe-keys': ['error'],
		'no-duplicate-case': ['error'],
		'no-duplicate-imports': ['error'],
		'no-else-return': ['off'],
		'no-empty': ['error'],
		'no-empty-character-class': ['error'],
		'no-empty-function': ['off'],
		'no-empty-pattern': ['error'],
		'no-eq-null': ['error'],
		'no-eval': ['error'],
		'no-ex-assign': ['error'],
		'no-extend-native': ['error'],
		'no-extra-bind': ['error'],
		'no-extra-boolean-cast': ['error'],
		'no-extra-label': ['warn'],
		'no-extra-parens': ['error', 'functions'],
		'no-extra-semi': ['error'],
		'no-fallthrough': ['error'],
		'no-floating-decimal': ['error'],
		'no-func-assign': ['error'],
		'no-global-assign': ['error'],
		'no-implicit-coercion': ['error'],
		'no-implicit-globals': ['warn'],
		'no-implied-eval': ['error'],
		'no-inline-comments': ['off'],
		'no-inner-declarations': ['error', 'functions'],
		'no-invalid-regexp': ['error'],
		'no-invalid-this': ['error'],
		'no-irregular-whitespace': ['error'],
		'no-iterator': ['error'],
		'no-label-var': ['error'],
		'no-labels': ['off'],
		'no-lone-blocks': ['error'],
		'no-lonely-if': ['error'],
		'no-loop-func': ['error'],
		'no-magic-numbers': ['error', {
			enforceConst: true,
			ignore: [-1, 0, 1],
			ignoreArrayIndexes: true,
		}],
		'no-mixed-operators': ['off'],
		'no-mixed-requires': ['off'],
		'no-mixed-spaces-and-tabs': ['error', 'smart-tabs'],
		'no-multi-assign': ['off'],
		'no-multi-spaces': ['error'],
		'no-multi-str': ['off'],
		'no-multiple-empty-lines': ['error', {
			max: 1,
			maxBOF: 0,
			maxEOF: 1,
		}],
		'no-negated-condition': ['off'],
		'no-nested-ternary': ['off'],
		'no-new': ['warn'],
		'no-new-func': ['error'],
		'no-new-object': ['error'],
		'no-new-require': ['warn'],
		'no-new-symbol': ['error'],
		'no-new-wrappers': ['error'],
		'no-obj-calls': ['error'],
		'no-octal-escape': ['error'],
		'no-param-reassign': ['error'],
		'no-path-concat': ['warn'],
		'no-plusplus': ['off'],
		'no-process-env': ['error'],
		'no-process-exit': ['error'],
		'no-proto': ['error'],
		'no-prototype-builtins': ['off'],
		'no-redeclare': ['error'],
		'no-regex-spaces': ['off'],
		'no-restricted-globals': ['off'],
		'no-restricted-imports': ['off'],
		'no-restricted-modules': ['off'],
		'no-restricted-properties': ['off'],
		'no-restricted-syntax': ['off'],
		'no-return-assign': ['error', 'except-parens'],
		'no-return-await': ['error'],
		'no-script-url': ['error'],
		'no-self-assign': ['error'],
		'no-self-compare': ['error'],
		'no-sequences': ['error'],
		'no-shadow': ['warn', { builtinGlobals: true }],
		'no-shadow-restricted-names': ['error'],
		'no-sparse-arrays': ['error'],
		'no-sync': ['warn'],
		'no-tabs': ['off'],
		'no-template-curly-in-string': ['error'],
		'no-ternary': ['off'],
		'no-this-before-super': ['error'],
		'no-throw-literal': ['error'],
		'no-trailing-spaces': ['error'],
		'no-undef': ['error'],
		'no-undef-init': ['off'],
		'no-undefined': ['off'],
		'no-underscore-dangle': ['off'],
		'no-unexpected-multiline': ['error'],
		'no-unmodified-loop-condition': ['warn'],
		'no-unneeded-ternary': ['error', { defaultAssignment: false }],
		'no-unreachable': ['error'],
		'no-unsafe-finally': ['error'],
		'no-unsafe-negation': ['error'],
		'no-unused-expressions': ['error', {
			allowShortCircuit: true,
			allowTernary: false,
		}],
		'no-unused-labels': ['error'],
		'no-unused-vars': ['error', {
			args: 'all',
			argsIgnorePattern: '^_',
			caughtErrorsIgnorePattern: '^_',
			ignoreRestSiblings: true,
			vars: 'all',
			varsIgnorePattern: '^_',
		}],
		'no-use-before-define': ['error', {
			classes: false,
			functions: false,
		}],
		'no-useless-call': ['error'],
		'no-useless-computed-key': ['error'],
		'no-useless-concat': ['warn'],
		'no-useless-constructor': ['error'],
		'no-useless-escape': ['warn'],
		'no-useless-rename': ['warn'],
		'no-useless-return': ['warn'],
		'no-var': ['off'],
		'no-void': ['warn'],
		'no-warning-comments': ['warn'],
		'no-whitespace-before-property': ['error'],
		'no-with': ['error'],
		'object-curly-newline': ['error', {
			minProperties: 3,
			multiline: true,
		}],
		'object-curly-spacing': ['error', 'always'],
		'object-property-newline': ['off'],
		'object-shorthand': ['off'],
		'one-var': ['off'],
		'one-var-declaration-per-line': ['error', 'initializations'],
		'operator-assignment': ['off'],
		'operator-linebreak': ['error', 'before'],
		'padded-blocks': ['error', 'never'],
		'prefer-arrow-callback': ['warn'],
		'prefer-const': ['warn'],
		'prefer-destructuring': ['off'],
		'prefer-numeric-literals': ['warn'],
		'prefer-promise-reject-errors': ['error'],
		'prefer-rest-params': ['warn'],
		'prefer-spread': ['warn'],
		'prefer-template': ['warn'],
		'quote-props': ['error', 'consistent-as-needed'],
		'quotes': ['error', 'single', { allowTemplateLiterals: true }],
		'radix': ['error', 'always'],
		'require-await': ['error'],
		'require-jsdoc': ['off'],
		'require-yield': ['error'],
		'rest-spread-spacing': ['error', 'never'],
		'semi': ['error', 'never'],
		'semi-spacing': ['error', {
			after: true,
			before: false,
		}],
		'sort-imports': ['off'],
		'sort-keys': ['warn', 'asc', {
			caseSensitive: true,
			natural: true,
		}],
		'sort-vars': ['warn'],
		'space-before-blocks': ['error', 'always'],
		'space-before-function-paren': ['error', {
			anonymous: 'always',
			asyncArrow: 'always',
			named: 'never',
		}],
		'space-in-parens': ['error', 'never'],
		'space-infix-ops': ['error', { int32Hint: false }],
		'space-unary-ops': ['error', {
			nonwords: false,
			words: true,
		}],
		'spaced-comment': ['off'],
		'strict': ['error'],
		'symbol-description': ['error'],
		'template-curly-spacing': ['off'],
		'template-tag-spacing': ['error', 'always'],
		'unicode-bom': ['error'],
		'use-isnan': ['error'],
		'valid-jsdoc': ['warn'],
		'valid-typeof': ['error'],
		'vars-on-top': ['off'],
		'wrap-iife': ['error', 'inside', { functionPrototypeMethods: true }],
		'wrap-regex': ['off'],
		'yield-star-spacing': ['error', 'after'],
		'yoda': ['off'],
	},
}


================================================
FILE: .gitignore
================================================
.node-version
node_modules/
yarn.lock
*.swp


================================================
FILE: CHANGES
================================================
- 0.1.0 : Move extraneous exports from index.js into utils.js.
- 0.2.0 : Add browser support for Browserify/Webpack.
- 0.3.0 : Pass named arguments to .generate instead of positional.
- 1.0.0 : Added support for Uuid V1 and extracted competitive benchmarks.
- 1.0.1 : Remove lockfile from release.
- 1.0.2 : Fix bad version push.
- 1.0.3 : Delete the extra benchmarks for real.
- 1.1.0 : Performance improvements and renamed resetClockSequence to reset.
- 1.1.1 : Fixed repo link.
- 1.2.0 : Added generic UUID factory.
- 1.3.0 : Added UUID V6 support.
- 1.4.0 : Exposed encoding verifiers.
- 1.5.0 : Fixed benchmarks and added support for node +12.5.
- 1.6.0 : Added Typescript support and top-level id comparators.
- 1.6.1 : Tweaked random memory allocation and updated benchmarks.
- 1.6.2 : Fixed docs
- 1.6.3 : Fixed memory profile by reusing the buffer of random.
- 1.6.4 : Fixed worker support
- 1.6.5 : Removed erroneous packaged files
- 1.6.6 : Fix CHANGES and add credit for worker support


================================================
FILE: LICENSE
================================================
Copyright 2018 Aaron Cohen <aarondcohen@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


================================================
FILE: README.md
================================================
# Id128

Generate 128-bit unique identifiers for various specifications.  In particular:
- [ULID](#ulid)
- [Monotonic ULID](#ulidmonotonic)
- [UUID 1 (Variant 1 Version 1)](#uuid1)
- [UUID 4 (Variant 1 Version 4)](#uuid4)
- [UUID 6 (Variant 1 Version 6)](#uuid6)
- [Nil UUID (Variant 0 Version 0)](#uuidnil)
- [Uuid (Unknown Variant and Version)](#uuid)

# Common Usage

```es6
const {
	Ulid,
	UlidMonotonic,
	Uuid,
	Uuid1,
	Uuid4,
	Uuid6,
	UuidNil,
	idCompare,
	idEqual,
} = require('id128');

// Id factories
[
	Ulid,
	UlidMonotonic,
	Uuid1,
	Uuid4,
	Uuid6,
	UuidNil,
].forEach((IdType) => {
	// Identify the factory
	console.log(IdType.name);

	// Generate a new id
	const id = IdType.generate();

	// Get the smallest valid id
	const min = IdType.MIN();

	// Get the largest valid id
	const max = IdType.MAX();

	// Type-check the id
	console.log(id instanceof IdType.type)

	// Compare ids
	console.log(id.equal(id));
	console.log(! id.equal(min));
	console.log(! id.equal(max));
	console.log(id.compare(min) === 1);
	console.log(id.compare(id) === 0);
	console.log(id.compare(max) === -1);

	// Encode the id in its canonical form
	const canonical = id.toCanonical();
	console.log(canonical);

	// Encode the id for efficient db storage
	const raw = id.toRaw();
	console.log(raw);

	// Verify a canonically formatted id
	console.log(IdType.isCanonical(canonical));

	// Decode a valid canonically formatted id
	console.log(id.equal(IdType.fromCanonical(canonical)));

	// Decode a canonically formatted id, skipping validation
	console.log(id.equal(IdType.fromCanonicalTrusted(canonical)));

	// Verify a raw formatted id
	console.log(IdType.isRaw(raw));

	// Decode a valid raw formatted id
	console.log(id.equal(IdType.fromRaw(raw)));

	// Decode a raw formatted id, skipping validation
	console.log(id.equal(IdType.fromRawTrusted(raw)));
});

// Uuid Factory
[0, 1, 4, 6].forEach((version) => {
	// Generate a new id
	const id = Uuid.generate({ version });

	// Get the smallest valid id
	const min = Uuid.MIN({ version });

	// Get the largest valid id
	const max = Uuid.MAX({ version });

	// Type-check the id
	console.log(id instanceof Uuid.type)

	// Encode the id in its canonical form
	const canonical = id.toCanonical();
	console.log(canonical);

	// Encode the id for efficient db storage
	const raw = id.toRaw();
	console.log(raw);

	// Decode a valid canonically formatted id
	console.log(id.equal(Uuid.fromCanonical(canonical)));

	// Decode a canonically formatted id, skipping validation
	console.log(id.equal(Uuid.fromCanonicalTrusted(canonical)));

	// Decode a valid raw formatted id
	console.log(id.equal(Uuid.fromRaw(raw)));

	// Decode a raw formatted id, skipping validation
	console.log(id.equal(Uuid.fromRawTrusted(raw)));
});

// Static Utilities

// Equate arbitrary ids
console.log(idEqual(Ulid.generate(), Uuid4.generate()))

// Compare arbitrary ids
console.log(idCompare(Ulid.generate(), Uuid4.generate()))
```

## Common Factory Properties

### name
Return the name of the generated id type.

### type
Return the type of the generated id instances for type-checking
with the `instanceof` operator.

## Common Factory Methods

### .construct(bytes) => id
Return a new id instance without validating the bytes.

### .generate() => id
Return a new id instance.

### .MIN() => id
Return the id instance with the smallest valid value.

### .MAX() => id
Return the id instance with the largest valid value.

### .fromCanonical(canonical_string) => id
Decode an id from its canonical representation.
Throw `InvalidEncoding` if the string is undecodable.

### .fromCanonicalTrusted(canonical_string) => id
Decode an id from its canonical representation.
Skip validation and assume the input is decodable.

### .fromRaw(raw_string) => id
Decode an id from its raw representation.
Throw `InvalidEncoding` if the string is undecodable.

### .fromRawTrusted(raw_string) => id
Decode an id from its raw representation.
Skip validation and assume the input is decodable.

### .toCanonical(id) => canonical_string
Encode the given id in the canonical form.
Throw `InvalidBytes` if the id is not 128-bit conformant.

### .toRaw(id) => raw_string
Encode the given id in the raw form.
Throw `InvalidBytes` if the id is not 128-bit conformant.

### .isCanonical(canonical_string) => (true|false)
Verify if a string is a valid canonical encoding.

### .isRaw(raw_string) => (true|false)
Verify if a string is a valid raw encoding.

## Common Instance Properties

### bytes
Return the actual byte array representing the id.

## Common Instance Methods

### .clone() => deep_copy
Return a new instance of the id with the same bit signature.

### .compare(other) => (-1|0|1)
Determine how this id is ordered against another.

### .equal(other) => (true|false)
Determine if this id has the same bytes as another.

### .toCanonical() => canonical_string
Encode this id in its canonical form.

### .toRaw() => raw_string
Encode this id in its raw form.

## Namespace Static Utilities

### idCompare(left_id, right_id) => (-1|0|1)
Determine if the left id is `less than | equal to | greater than`
the right id using lexicographical byte order.

### idEqual(left_id, right_id) => (true|false)
Determine if 2 ids have the same byte value.

# Ulid
```es6
const { Ulid } = require('id128');
```

Ulid, as [specified](https://github.com/ulid/spec), has some nice properties:
- collision resistant: 80-bits of randomness
- k-ordered: prefixed with millisecond precision timestamp
- database friendly: fits within a uuid and generally appends to the index
- human friendly: canonically encodes as a case-insensitive Crockford 32 number

It is useful when you need a distributed domain unique id.

## Additional Instance Properties

### time
Return a Date object for the epoch milliseconds encoded in the id.

## Additional Factory Methods

### .generate({ time }) => id
Return a new id instance.  Set any argument to `null` or `undefined` to trigger
its default behavior.

`time` defaults to the current time.  It can be given either as a `Date` object
or epoch milliseconds (milliseconds since January 1st, 1970).
Throw `InvalidEpoch` for times before the epoch or after approximately August 2nd, 10889.
This is provided mostly for unit tests.

## Byte Format
Format `tttt tttt tttt rrrr rrrr rrrr rrrr rrrr` where:
- `t` is 4 bits of time
- `r` is 4 bits of random

# UlidMonotonic
```es6
const { UlidMonotonic } = require('id128');
```

UlidMonotonic is inspired by the [specification](https://github.com/ulid/spec#monotonicity):
- collision resistant: 15-bits of random seeded clock sequence plus 64-bits of randomness
- total ordered: prefixed with millisecond precision timestamp plus 15-bit clock sequence
- database friendly: fits within a uuid and generally appends to the index
- human friendly: canonically encodes as a case-insensitive Crockford 32 number

It is useful when you need to guarantee a process unique id.

## Additional Instance Properties

### time
Return a Date object for the epoch milliseconds encoded in the id.

## Additional Factory Methods

### .generate({ time }) => id
Return a new id instance.  Set any argument to `null` or `undefined` to trigger
its default behavior.

`time` defaults to the current time.  It can be given either as a `Date` object
or epoch milliseconds (milliseconds since January 1st, 1970).  Extra caution is
required since setting a future time and subsequently calling `generate`
guarantees usage of the clock sequence.
Throw `InvalidEpoch` for times before the epoch or after approximately August 2nd, 10889.
Throw `ClockSequenceOverflow` when the clock sequence is exhausted.
This is provided mostly for unit tests.

### .reset()
Return the clock sequence to its starting position.  This is provided mostly for
unit tests.

## Byte Format
Format `tttt tttt tttt cccc rrrr rrrr rrrr rrrr` where:
- `t` is 4 bits of time
- `c` is 4 bits of random-seeded clock sequence
- `r` is 4 bits of random

More specifically, the clock sequence is a counter.  When the first id for a new
timestamp is generated, the clock sequence is seeded with random bits and the
left-most clock sequence bit is set to 0, reserving 2^15 clock ticks.  Whenever
a time from the past seeds the generator, the previous id's time and clock sequence
are used instead, with the clock sequence incremented by 1.  This guarantees
strict local monotonicity and preserves lexical ordering and general randomness.

Without a seeded time, UlidMonotonic is unlikely to exceed the clock sequence
(the clock sequence supports generating a new id every 31 nanoseconds). However,
in the unlikely event of an overflow, id generation is aborted.

# Uuid1
```es6
const { Uuid1 } = require('id128');
```

Uuid1 implements the [RFC 4122 time specification](https://tools.ietf.org/html/rfc4122#section-4.2):
- time-based: encodes the current millisecond timestamp
- location-based: encodes the mac address of the machine

While this mostly adheres to the spec, there are a few nuances in the handling
of time.  Instead of encoding time as 100-nanoseconds since the Gregorian epoch,
48 bits encode milliseconds since the Gregorian epoch time and 12 bits count past
time collisions, resetting whenever given a new future time.  There are a few benefits:
- high precision time is unreliable in the browser so this ensures better precision
- the max supported date is now around the year 10502 instead of around 5236
- generating 4096 ids/ms (~4,000,000 ids/s) is wildly unlikely in real world uses
- in the rare  hi-res overflow, the count simply spills over to the clock sequence

## Additional Instance Properties

### clock_sequence
Return the clock sequence encoded in the id.

### hires_time
Return the number of prior ids generated while time stood still.

### node
Return the MAC address encoded in the id.

### time
Return a Date object for the epoch milliseconds encoded in the id.

### variant
Return the variant as encoded in the id.  Should be 1.

### version
Return the version as encoded in the id.  Should be 1.

## Additional Factory Methods

### .generate({ node, time }) => id
Return a new id instance.  Set any argument to `null` or `undefined` to trigger
its default behavior.

`time` defaults to the current time.  It can be given either as a `Date` object
or Gregorian milliseconds (milliseconds since October 15th, 1582).  Extra caution
is required since setting a future time and subsequently calling `generate`
guarantees usage of the hi-res counter and clock sequence.
Throw `InvalidEpoch` for times before the Gregorian epoch or after approximately May 17, 10502.
This is provided mostly for unit tests.

`node` defaults to the MAC address, or a random multicast address when the MAC
address is unavailable.  It can be given as an array of 6 bytes.

### .reset()
Return the hi-res counter to its starting position and generate a new random
clock sequence seed.  This is provided mostly for unit tests.

## Byte Format
Format `llll lnnn mmmm vhhh tccc aaaa aaaa aaaa` where:
- `l` is 4 bits of low millisecond time
- `n` is 4 bits of hi-res time
- `m` is 4 bits of mid millisecond time
- `v` is 4 bits of the version
- `h` is 4 bits of high millisecond time
- `t` is 2 bits of the variant followed by 2 bits of the clock sequence
- `c` is 4 bits of the clock sequence
- `a` is 4 bits of the machine address

# Uuid4
```es6
const { Uuid4 } = require('id128');
```

Uuid4 implements the [RFC 4122 random uuid specification](https://tools.ietf.org/html/rfc4122#section-4.4):

- 122 random bits
- 2 bits reserved for the variant (1)
- 4 bits reserved for the version (4)

It is useful when you need a well-supported globally unique id.

## Additional Instance Properties

### variant
Return the variant as encoded in the id.  Should be 1.

### version
Return the version as encoded in the id.  Should be 4.

## Byte Format
Format `rrrr rrrr rrrr vrrr trrr rrrr rrrr rrrr` where:
- `r` is 4 bits of random
- `v` is 4 bits of the version
- `t` is 2 bits of the variant followed by 2 bits of random

# Uuid6
```es6
const { Uuid6 } = require('id128');
```

Uuid6 implements this [controversial blog post](https://bradleypeabody.github.io/uuidv6/):
- time-based: encodes the current millisecond timestamp
- location-based: encodes the mac address of the machine

This is essentially the same implementation as Uuid1, however the time bits are
arranged in lexicographical order.  If you're looking for a spacial UUID that
is optimized for clustered indices, consider Uuid6 as a viable option.

## Additional Instance Properties

### clock_sequence
Return the clock sequence encoded in the id.

### hires_time
Return the number of prior ids generated while time stood still.

### node
Return the MAC address encoded in the id.

### time
Return a Date object for the epoch milliseconds encoded in the id.

### variant
Return the variant as encoded in the id.  Should be 1.

### version
Return the version as encoded in the id.  Should be 6.

## Additional Factory Methods

### .generate({ node, time }) => id
Return a new id instance.  Set any argument to `null` or `undefined` to trigger
its default behavior.

`time` defaults to the current time.  It can be given either as a `Date` object
or Gregorian milliseconds (milliseconds since October 15th, 1582).  Extra caution
is required since setting a future time and subsequently calling `generate`
guarantees usage of the hi-res counter and clock sequence.
Throw `InvalidEpoch` for times before the Gregorian epoch or after approximately May 17, 10502.
This is provided mostly for unit tests.

`node` defaults to the MAC address, or a random multicast address when the MAC
address is unavailable.  It can be given as an array of 6 bytes.

### .reset()
Return the hi-res counter to its starting position and generate a new random
clock sequence seed.  This is provided mostly for unit tests.

## Byte Format
Format `mmmm mmmm mmmm vnnn tccc aaaa aaaa aaaa` where:
- `m` is 4 bits of millisecond time
- `v` is 4 bits of the version
- `n` is 4 bits of hi-res time
- `t` is 2 bits of the variant followed by 2 bits of the clock sequence
- `c` is 4 bits of the clock sequence
- `a` is 4 bits of the machine address

# UuidNil
```es6
const { UuidNil } = require('id128');
```

UuidNil implements the [RFC 4122 nil uuid specification](https://tools.ietf.org/html/rfc4122#section-4.1.7):

- 128 bits of glorious 0

It is useful as placeholder for other 128-bit ids.

## Additional Instance Properties

### variant
Return the variant as encoded in the id.  Should be 0.

### version
Return the version as encoded in the id.  Should be 0.

## Byte Format
Format `0000 0000 0000 v000 t000 0000 0000 0000` where:
- `0` is 4 bits of 0
- `v` is 4 bits of the version (also 0)
- `t` is 2 bits of the variant (also 0) followed by 2 bits of 0

# Uuid
```es6
const { Uuid } = require('id128');
```

Uuid is a factory for generating and decoding UUIDs when the version is unknown
until runtime.  If the version is supported, it will produce UUIDs of the
appropriate type.  In exchange for the runtime flexibility, there is a necessary
performance degradation.  It is recommended to use this for decoding data from
uncontrolled sources rather than generating new ids.

Uuid supports all the same methods as the other ID factories.  All modifications
to typical behavior are noted below.

## Factory Properties

### versioned_ids
Return the factories of all the supported ids.

## Factory Methods

### .construct(bytes) => versioned_id
Return a new versioned id instance without validating the bytes.
Return a Uuid if an appropriate version does not exist.

### .generate({ version, ... }) => versioned_id
Return a new versioned id instance.  All additional arguments are passed through
to the associated version.
Throw `UnsupportedVersion` if no associated version exists.

### .MIN({ version }) => versioned_id
Return the versioned id instance with the smallest valid value.
Throw `UnsupportedVersion` if no associated version exists.

### .MAX({ version }) => versioned_id
Return the versioned id instance with the largest valid value.
Throw `UnsupportedVersion` if no associated version exists.

### .fromCanonical(canonical_string) => versioned_id
Decode a versioned id from its canonical representation.
Return a Uuid if an appropriate version does not exist.
Throw `InvalidEncoding` if the string is undecodable.

### .fromCanonicalTrusted(canonical_string) => versioned_id
Decode a versioned id from its canonical representation.
Return a Uuid if an appropriate version does not exist.
Skip validation and assume the input is decodable.

### .fromRaw(raw_string) => versioned_id
Decode a versioned id from its raw representation.
Return a Uuid if an appropriate version does not exist.
Throw `InvalidEncoding` if the string is undecodable.

### .fromRawTrusted(raw_string) => versioned_id
Decode a versioned id from its raw representation.
Return a Uuid if an appropriate version does not exist.
Skip validation and assume the input is decodable.

# Exceptions
```es6
const { Exception } = require('id128');
```
All exceptions are namespaced under `Exception` for clarity.

## Id128Error
```es6
const { Exception: { Id128Error } } = require('id128');
```
Base exception class for generic error catching.

## ClockSequenceOverflow
```es6
const { Exception: { ClockSequenceOverflow } } = require('id128');
```
Incrementing the clock sequence is impossible.  Should not happen unless manually seeding `#generate`.

## InvalidBytes
```es6
const { Exception: { InvalidBytes } } = require('id128');
```
Encoding something other than 16 bytes.  Likely to happen when encoding untrusted user input.

## InvalidEncoding
```es6
const { Exception: { InvalidEncoding } } = require('id128');
```
Decoding an invalid format or non-string object.  Likely to happen when decoding untrusted user input.

## InvalidEpoch
```es6
const { Exception: { InvalidEpoch } } = require('id128');
```
Generating an id with an invalid timestamp.  Should not happen unless manually seeding `#generate`.

## UnsupportedVersion
```es6
const { Exception: { UnsupportedVersion } } = require('id128');
```
Failed to find a factory for the desired version.  Likely to happen when decoding untrusted user input.

# Browser Support

This module supports browser compilation though Webpack/Browserify with a few caveats:
- Random number generation is optimized for memory usage over speed since only a
handful of ids are likely to be generated during a user's session so the overhead
of generating a page of random values has poor amortized cost.
- The browser must have native support for `crypto`.  `Math.random` is far too
insecure to support as a fallback, especially since the fallback only makes sense
for older browsers with proven security holes.  `msCrypto` is not a supported
fallback due to many of the other required features.
- The browser must support:
	* classes
	* closures
	* `const` and `let`
	* `Uint8Array`
	* `Symbol`

This library is intended for modern browsers that keep pace with Javascript's
growing ecosystem.  I philosophically object to supporting efforts of companies
to pour more money into broken browsers that only cause headaches for developers
to support.  I expect these caveats to be unnecessary within the next 5 years.

All that said, please notify me of any issues with modern browsers and I'll do
my best to support you.

# Typescript Support

This module includes Typescript bindings for all primary usage patterns.
I'd like to highlight some design decisions:

## Id Types and Factory Types
Each factory is exported as an instance using the same name as the type of id
it produces.  In Javascript, this is desirable as it provides a uniform interface
regardless of the implementation.  However, this complicates the Typescript
type imports.

For simple cases, like constructing an id and passing it around the program,
this will behave exactly as desired:
```
import { Ulid } from 'id128'

const id: Ulid = Ulid.generate()
```

When you need to check the type of the id, you should use the `type` attribute:
```
import { Ulid } from 'id128'

const id: Ulid = Ulid.generate()
if (id instanceof Ulid.type) { ... }
```

If you wish to pass around the factory itself, you can import the factory type:
```
import { Ulid } from 'id128'
import type { UlidFactory } from 'id128'

function doSomething(factory: UlidFactory) { ... }
doSomething(Ulid)
```

Finally, if you need to operate on any id or id factory, you can import base types:
```
import type { Id, AnyIdFactory } from 'id128'

function makeOne(factory: AnyIdFactory): Id {
	return factory.generate()
}
```

## Exception Handling
Exception classes are designed to be checked using `instanceof`.  Unfortunately,
Typescript broke `instanceof` `Error` support for a more compliant compilation.
Fortunately, the included exceptions bypass the issues caused by inheriting from
the native `Error` by never overriding the constructor and implementing `name`
as a readonly getter,  As a consequence, the exceptions actually violate the
standard `Error` interface, but they fulfill the standard `Function` interface.
Therefore, you can safely use `instanceof` as intended:
```
import { UlidMonotonic } from 'id128'
import { Exception } from 'id128'

try { UlidMonotonic.generate() }
catch (err) {
	if (err instanceof Exception.ClockSequenceOverflow ) { ... }
}
```

# Motivation

Originally, I was looking for an id that is independent of the database, but plays
nice with database indices and data types.  Most databases have built-in support
for storing UUIDs efficiently, but UUID v4 does not cluster well and the other UUIDs
require bit manipulation to get good performance, which will likely cause future
maintenance headaches.

After a bit of research, ULID was determined to nicely solve the problem.  However,
the javascript implementation had 2 major issues:
1. lacks database support
2. it's slow, which in a single-threaded Node server is deadly

I considered sending in a patch, however I saw an opportunity for a more expressive
interface, which is typically a bit harder to modify once a project is in wide use.
There was also a clear pattern for encoding 128-bit ids into various formats,
which seems generally useful.

Ultimately, this library strives to be:
- secure: uses cryptographic randomness to ensure general uniqueness
- performant: currently one of the fastest id generators available
- maintainable: heavily tested isolated code with a consistent interface
- extensible: modular design to easily add new ids and new encodings

# Tests

To run the tests:
```bash
npm install
npm run test-all
```

# Benchmarks

Competitive benchmarks have been moved to [benchmark-guid](https://github.com/aarondcohen/benchmark-guid)

To run the benchmarks:
```bash
npm install
npm run benchmark
```

```
Platform info:
==============
   Darwin 18.2.0 x64
   Node.JS: 15.0.0
   V8: 8.6.395.16-node.15
   Intel(R) Core(TM) i7-4578U CPU @ 3.00GHz × 4

Ulid
====
   generate:                  (4,590,833rps)   (avg: 217ns)
   MIN:                      (12,491,186rps)   (avg: 80ns)
   MAX:                      (12,669,223rps)   (avg: 78ns)
   fromCanonical:             (1,707,717rps)   (avg: 585ns)
   fromCanonicalTrusted:      (2,078,278rps)   (avg: 481ns)
   fromRaw:                   (1,483,373rps)   (avg: 674ns)
   fromRawTrusted:            (1,979,964rps)   (avg: 505ns)
   toCanonical:               (3,256,155rps)   (avg: 307ns)
   toRaw:                     (6,012,244rps)   (avg: 166ns)

UlidMonotonic
=============
   generate:                  (3,787,685rps)   (avg: 264ns)
   MIN:                       (6,306,928rps)   (avg: 158ns)
   MAX:                       (6,301,217rps)   (avg: 158ns)
   fromCanonical:             (1,423,104rps)   (avg: 702ns)
   fromCanonicalTrusted:      (1,722,958rps)   (avg: 580ns)
   fromRaw:                   (1,381,296rps)   (avg: 723ns)
   fromRawTrusted:            (1,698,639rps)   (avg: 588ns)
   toCanonical:               (3,205,394rps)   (avg: 311ns)
   toRaw:                     (5,774,288rps)   (avg: 173ns)

Uuid1
=====
   generate:                  (4,984,699rps)   (avg: 200ns)
   MIN:                      (12,888,384rps)   (avg: 77ns)
   MAX:                      (12,817,435rps)   (avg: 78ns)
   fromCanonical:             (1,226,007rps)   (avg: 815ns)
   fromCanonicalTrusted:      (1,578,429rps)   (avg: 633ns)
   fromRaw:                   (1,306,295rps)   (avg: 765ns)
   fromRawTrusted:            (1,626,095rps)   (avg: 614ns)
   toCanonical:               (5,859,714rps)   (avg: 170ns)
   toRaw:                     (5,973,139rps)   (avg: 167ns)

Uuid4
=====
   generate:                  (6,492,849rps)   (avg: 154ns)
   MIN:                       (6,400,528rps)   (avg: 156ns)
   MAX:                       (6,617,714rps)   (avg: 151ns)
   fromCanonical:             (1,286,561rps)   (avg: 777ns)
   fromCanonicalTrusted:      (1,625,362rps)   (avg: 615ns)
   fromRaw:                   (1,313,004rps)   (avg: 761ns)
   fromRawTrusted:            (1,672,463rps)   (avg: 597ns)
   toCanonical:               (6,103,543rps)   (avg: 163ns)
   toRaw:                     (6,235,448rps)   (avg: 160ns)

Uuid6
=====
   generate:                  (3,466,357rps)   (avg: 288ns)
   MIN:                       (5,244,292rps)   (avg: 190ns)
   MAX:                       (5,151,746rps)   (avg: 194ns)
   fromCanonical:             (1,324,905rps)   (avg: 754ns)
   fromCanonicalTrusted:      (1,676,541rps)   (avg: 596ns)
   fromRaw:                   (1,357,353rps)   (avg: 736ns)
   fromRawTrusted:            (1,717,530rps)   (avg: 582ns)
   toCanonical:               (5,061,822rps)   (avg: 197ns)
   toRaw:                     (4,839,125rps)   (avg: 206ns)

UuidNil
=======
   generate:                  (9,312,932rps)   (avg: 107ns)
   MIN:                       (5,158,703rps)   (avg: 193ns)
   MAX:                       (8,795,275rps)   (avg: 113ns)
   fromCanonical:             (1,293,946rps)   (avg: 772ns)
   fromCanonicalTrusted:      (1,629,605rps)   (avg: 613ns)
   fromRaw:                   (1,472,042rps)   (avg: 679ns)
   fromRawTrusted:            (1,780,904rps)   (avg: 561ns)
   toCanonical:               (5,169,323rps)   (avg: 193ns)
   toRaw:                     (5,196,170rps)   (avg: 192ns)

Uuid processing Uuid1
=====================
   generate:                  (4,159,340rps)   (avg: 240ns)
   MIN:                       (4,877,918rps)   (avg: 205ns)
   MAX:                       (4,907,348rps)   (avg: 203ns)
   fromCanonical:             (1,045,214rps)   (avg: 956ns)
   fromCanonicalTrusted:      (1,255,223rps)   (avg: 796ns)
   fromRaw:                   (1,021,436rps)   (avg: 979ns)
   fromRawTrusted:            (1,268,213rps)   (avg: 788ns)

Uuid processing Uuid4
=====================
   generate:                  (5,695,823rps)   (avg: 175ns)
   MIN:                       (4,886,337rps)   (avg: 204ns)
   MAX:                       (4,907,325rps)   (avg: 203ns)
   fromCanonical:             (1,047,372rps)   (avg: 954ns)
   fromCanonicalTrusted:      (1,292,729rps)   (avg: 773ns)
   fromRaw:                   (1,031,590rps)   (avg: 969ns)
   fromRawTrusted:            (1,266,122rps)   (avg: 789ns)

Uuid processing Uuid6
=====================
   generate:                  (4,122,279rps)   (avg: 242ns)
   MIN:                       (4,744,102rps)   (avg: 210ns)
   MAX:                       (4,860,271rps)   (avg: 205ns)
   fromCanonical:             (1,066,004rps)   (avg: 938ns)
   fromCanonicalTrusted:      (1,298,925rps)   (avg: 769ns)
   fromRaw:                   (1,053,871rps)   (avg: 948ns)
   fromRawTrusted:            (1,286,373rps)   (avg: 777ns)

Uuid processing UuidNil
=======================
   generate:                  (8,140,742rps)   (avg: 122ns)
   MIN:                       (4,717,779rps)   (avg: 211ns)
   MAX:                       (8,261,012rps)   (avg: 121ns)
   fromCanonical:             (1,052,765rps)   (avg: 949ns)
   fromCanonicalTrusted:      (1,285,968rps)   (avg: 777ns)
   fromRaw:                   (1,130,468rps)   (avg: 884ns)
   fromRawTrusted:            (1,312,878rps)   (avg: 761ns)
```

# Acknowledgments

Much of this library would not exist without the great work and documentation of
other engineers.  In particular:

- [ksuid](https://github.com/segmentio/ksuid): an in-depth exploration of the guid nuances
- [ulid](https://github.com/ulid/javascript): an elegant solution to a persistent problem
- [uuid-random](https://github.com/jchook/uuid-random): allocating pages of randomness is by far the biggest performance factor

Also, thank you:
- [ruleb](https://github.com/ruleb): researching and patching worker support

# Contributing

Feel free to make a branch and send a pull request through [github](https://github.com/aarondcohen/id128)

# Issues

Please report any issues or bugs through [github](https://github.com/aarondcohen/id128/issues)


================================================
FILE: benchmark/basics.js
================================================
const Benchmarkify = require('benchmarkify');
const Id128 = require('../');
const { IdFactory } = require('../utils');
const { VersionedIdFactory } = require('../utils');

const benchmark = new Benchmarkify("Basics").printHeader();
const suites_by_name = Object.fromEntries([
	'generate',
	'MIN',
	'MAX',
	'fromCanonical',
	'fromCanonicalTrusted',
	'fromRaw',
	'fromRawTrusted',
	'toCanonical',
	'toRaw'
].map((name) => [name, benchmark.createSuite(name, { cycles: 1000000 })]));

Object.values(Id128)
	.filter(x => x instanceof IdFactory)
	.filter(x => !(x instanceof VersionedIdFactory))
	.sort((l, r)  => l.name.localeCompare(r.name))
	.forEach((id_type) => {
		const name = id_type.name;
		const id = id_type.generate();
		const canonical = id.toCanonical();
		const raw = id.toRaw();

		suites_by_name.generate.add(name, () => id_type.generate());
		suites_by_name.MIN.add(name, () => id_type.MIN());
		suites_by_name.MAX.add(name, () => id_type.MAX());
		suites_by_name.fromCanonical.add(name, () => id_type.fromCanonical(canonical));
		suites_by_name.fromCanonicalTrusted.add(name, () => id_type.fromCanonicalTrusted(canonical));
		suites_by_name.fromRaw.add(name, () => id_type.fromRaw(raw));
		suites_by_name.fromRawTrusted.add(name, () => id_type.fromRawTrusted(raw));
		suites_by_name.toCanonical.add(name, () => id.toCanonical());
		suites_by_name.toRaw.add(name, () => id.toRaw());
	});

benchmark.run(Object.values(suites_by_name));


================================================
FILE: benchmark/factory-uuid.js
================================================
const Benchmarkify = require('benchmarkify');
const Id128 = require('../');

const benchmark = new Benchmarkify("UUID Processing").printHeader();
const suites_by_name = Object.fromEntries([
	'generate',
	'MIN',
	'MAX',
	'fromCanonical',
	'fromCanonicalTrusted',
	'fromRaw',
	'fromRawTrusted',
].map((name) => [name, benchmark.createSuite(name, { cycles: 100000 })]));

const factory = Id128.Uuid;
factory.versioned_ids
	.sort((l, r)  => l.name.localeCompare(r.name))
	.forEach((id_type) => {
		const name = id_type.name;
		const id = id_type.generate();
		const canonical = id.toCanonical();
		const raw = id.toRaw();
		const type = { version: id.version };

		suites_by_name.generate.add(name, () => factory.generate(type));
		suites_by_name.MIN.add(name, () => factory.MIN(type));
		suites_by_name.MAX.add(name, () => factory.MAX(type));
		suites_by_name.fromCanonical.add(name, () => factory.fromCanonical(canonical));
		suites_by_name.fromCanonicalTrusted.add(name, () => factory.fromCanonicalTrusted(canonical));
		suites_by_name.fromRaw.add(name, () => factory.fromRaw(raw));
		suites_by_name.fromRawTrusted.add(name, () => factory.fromRawTrusted(raw));
	});

benchmark.run(Object.values(suites_by_name));


================================================
FILE: benchmark/memory.js
================================================
const ByteArray = require('common/byte-array');

let count = 0
let result = null;
let now = new Date;
try {
	while (++count) {
		result = ByteArray.generateRandomFilled();
		result = null

		if (!(count % 10000000)) {
			global.gc && global.gc();
			const used = process.memoryUsage();
			console.log(`Runs: ${count}`)
			for (let key in used) {
				console.log(`${key} ${Math.round(used[key] / 1024 * 100) / 100} KB`);
			}
		}
	}
} catch (err) {
	const end = new Date;
	console.log(err);
	console.log([String(count).padStart(12), ...result].join(':'));
	console.log(`Time: ${end - now}, ${count/(end - now)}ops/ms`);
}


================================================
FILE: benchmark/stats.js
================================================
const Benchmarkify = require('benchmarkify');
const Id128 = require('../');
const { Uuid } = Id128;

const benchmark = new Benchmarkify("Stats").printHeader();

const id_suites = [
	Id128.Ulid,
	Id128.UlidMonotonic,
	Id128.Uuid1,
	Id128.Uuid4,
	Id128.Uuid6,
	Id128.UuidNil,
].map((id_type) => {
	const id = id_type.generate();
	const canonical = id.toCanonical();
	const raw = id.toRaw();
	const suite = benchmark.createSuite(id_type.name, { cycles: 1000000 });

	suite.add('generate:', () => id_type.generate());
	suite.add('MIN:', () => id_type.MIN());
	suite.add('MAX:', () => id_type.MAX());
	suite.add('fromCanonical:', () => id_type.fromCanonical(canonical));
	suite.add('fromCanonicalTrusted:', () => id_type.fromCanonicalTrusted(canonical));
	suite.add('fromRaw:', () => id_type.fromRaw(raw));
	suite.add('fromRawTrusted:', () => id_type.fromRawTrusted(raw));
	suite.add('toCanonical:', () => id.toCanonical());
	suite.add('toRaw:', () => id.toRaw());

	return suite;
});

const uuid_suites = Uuid.versioned_ids
	.sort((l, r)  => l.name.localeCompare(r.name))
	.map((id_type) => {
		const id = id_type.generate();
		const canonical = id.toCanonical();
		const raw = id.toRaw();
		const type = { version: id.version };

		const suite = benchmark.createSuite(
			`Uuid processing ${id_type.name}`,
			{ cycles: 1000000 }
		);

		suite.add('generate:', () => Uuid.generate(type));
		suite.add('MIN:', () => Uuid.MIN(type));
		suite.add('MAX:', () => Uuid.MAX(type));
		suite.add('fromCanonical:', () => Uuid.fromCanonical(canonical));
		suite.add('fromCanonicalTrusted:', () => Uuid.fromCanonicalTrusted(canonical));
		suite.add('fromRaw:', () => Uuid.fromRaw(raw));
		suite.add('fromRawTrusted:', () => Uuid.fromRawTrusted(raw));

		return suite;
	});

benchmark.run(id_suites.concat(uuid_suites));


================================================
FILE: index.d.ts
================================================
/* eslint-disable @typescript-eslint/no-empty-interface */
export {};

// Utility Types

interface ConstructorOf<C> {
	new(...args: any[]): C;
}

// Id Types

export interface Id {
	readonly bytes: Uint8Array;
	readonly [Symbol.toStringTag]: string;

	clone(): this;

	toCanonical(): string;
	toRaw(): string;

	compare(rhs: Id): number;
	equal(rhs: Id): boolean;
}

export interface Uuid extends Id {
	readonly variant: number;
	readonly version: number;
}

export interface Ulid extends Id {
	readonly time: Date;
}

export interface UlidMonotonic extends Id {
	readonly time: Date;
}

export interface Uuid1 extends Uuid {
	readonly clock_sequence: number;
	readonly hires_time: number;
	readonly node: Uint8Array;
	readonly time: Date;
}

export interface Uuid4 extends Uuid {}

export interface Uuid6 extends Uuid {
	readonly clock_sequence: number;
	readonly hires_time: number;
	readonly node: Uint8Array;
	readonly time: Date;
}

export interface UuidNil extends Uuid {}

// Id Factories

interface IdFactory<T> {
	readonly name: string;
	readonly type: ConstructorOf<T>;

	construct(bytes: Uint8Array): T;
	generate(options?: {}): T;
	MIN(options?: {}): T;
	MAX(options?: {}): T;

	fromCanonical(canonical: string): T;
	fromCanonicalTrusted(canonical: string): T;
	fromRaw(raw: string): T;
	fromRawTrusted(raw: string): T;

	toCanonical(id: T): string;
	toRaw(id: T): string;

	compare(lhs: Id, rhs: Id): number;
	equal(lhs: Id, rhs: Id): boolean;

	isCanonical(canonical: string): boolean;
	isRaw(raw: string): boolean;
}

interface VersionedIdFactory<T> extends IdFactory<T> {
	readonly versioned_ids: Array<IdFactory<T>>;

	MIN(options: VersionOption): T;
	MAX(options: VersionOption): T;
}

interface NodeOption {
	node?: Uint8Array | null;
}

interface TimeOption {
	time?: Date | number | null;
}

interface VersionOption {
	version: number;
}

export type AnyIdFactory = IdFactory<Id>;

export interface UlidFactory extends IdFactory<Ulid> {
	generate(options?: TimeOption): Ulid;
}

export interface UlidMonotonicFactory extends IdFactory<UlidMonotonic> {
	generate(options?: TimeOption): UlidMonotonic;
}

export interface UuidFactory extends VersionedIdFactory<Uuid> {
	generate(options: NodeOption & TimeOption & VersionOption): Uuid;
}

export interface Uuid1Factory extends IdFactory<Uuid1> {
	generate(options?: NodeOption & TimeOption): Uuid1;
}

export interface Uuid4Factory extends IdFactory<Uuid4> {
	generate(options?: {}): Uuid4;
}

export interface Uuid6Factory extends IdFactory<Uuid6> {
	generate(options?: NodeOption & TimeOption): Uuid6;
}

export interface UuidNilFactory extends IdFactory<UuidNil> {
	generate(options?: {}): UuidNil;
}

// Errors

// NOTE: Actually extends Error, but typescript breaks instanceof support
export interface Id128Error extends Function {
	readonly name: string;
	message: string;
	stack?: string;
}
export interface ClockSequenceOverflow extends Id128Error {}
export interface InvalidBytes extends Id128Error {}
export interface InvalidEncoding extends Id128Error {}
export interface InvalidEpoch extends Id128Error {}
export interface UnsupportedVersion extends Id128Error {}

// Exported Functions

export function idCompare(lhs: Id, rhs: Id): number;
export function idEqual(lhs: Id, rhs: Id): boolean;

// Exported Constants

export const Ulid: UlidFactory;
export const UlidMonotonic: UlidMonotonicFactory;
export const Uuid: UuidFactory;
export const Uuid1: Uuid1Factory;
export const Uuid4: Uuid4Factory;
export const Uuid6: Uuid6Factory;
export const UuidNil: UuidNilFactory;

export namespace Exception {
	const Id128Error: ConstructorOf<Id128Error>;
	const ClockSequenceOverflow: ConstructorOf<ClockSequenceOverflow>;
	const InvalidBytes: ConstructorOf<InvalidBytes>;
	const InvalidEncoding: ConstructorOf<InvalidEncoding>;
	const InvalidEpoch: ConstructorOf<InvalidEpoch>;
	const UnsupportedVersion: ConstructorOf<UnsupportedVersion>;
}


================================================
FILE: index.js
================================================
const { Ulid } = require('./src/id/ulid');
const { UlidMonotonic } = require('./src/id/ulid-monotonic');
const { Uuid } = require('./src/id/uuid');
const { Uuid1 } = require('./src/id/uuid-1');
const { Uuid4 } = require('./src/id/uuid-4');
const { Uuid6 } = require('./src/id/uuid-6');
const { UuidNil } = require('./src/id/uuid-nil');

const Crockford32Coder = require('./src/coder/crockford32');
const HexCoder = require('./src/coder/hex');
const UuidCoder = require('./src/coder/uuid');

const { IdFactory } = require('./src/factory/id');
const { VersionedIdFactory } = require('./src/factory/versioned-id');
const Exception = require('./src/common/exception');

const namespace = {
	idCompare: function(lhs, rhs) { return lhs.compare(rhs); },
	idEqual: function(lhs, rhs) { return lhs.equal(rhs); },
	Exception,
	Ulid: new IdFactory({
		id: Ulid,
		canonical_coder: Crockford32Coder,
		raw_coder: HexCoder,
	}),
	UlidMonotonic: new IdFactory({
		id: UlidMonotonic,
		canonical_coder: Crockford32Coder,
		raw_coder: HexCoder,
	}),
	Uuid: new VersionedIdFactory({
		abstract_id: Uuid,
		versioned_ids: [
			Uuid1,
			Uuid4,
			Uuid6,
			UuidNil,
		],
		canonical_coder: UuidCoder,
		raw_coder: HexCoder,
	}),
};

namespace.Uuid.versioned_ids.reduce(
	(ns, uuid) => Object.assign(ns, {[uuid.name]: uuid}),
	namespace
);

module.exports = namespace;


================================================
FILE: package.json
================================================
{
	"name": "id128",
	"description": "Collection of 128-bit Id generators",
	"version": "1.6.6",
	"author": "Aaron Cohen <aarondcohen@gmail.com>",
	"license": "MIT",
	"main": "index.js",
	"types": "index.d.ts",
	"files": [
		"index.d.ts",
		"index.js",
		"src/",
		"utils.js"
	],
	"homepage": "https://github.com/aarondcohen/id128#id128",
	"repository": {
		"type": "git",
		"url": "git+https://github.com/aarondcohen/id128.git"
	},
	"bugs": {
		"url": "https://github.com/aarondcohen/id128/issues"
	},
	"browser": {
		"./src/common/machine.js": "./src/common/fake-machine.js",
		"./src/common/random-bytes.js": "./src/common/random-bytes-browser.js"
	},
	"scripts": {
		"benchmark": "NODE_PATH='./src/' node benchmark/stats.js",
		"call": "NODE_PATH='./src/' node",
		"dtslint": "dtslint types",
		"test": "NODE_PATH='./src/' mocha",
		"test-all": "NODE_PATH='./src/' mocha test/*"
	},
	"engines": {
		"node": ">=v6.9.0"
	},
	"devDependencies": {
		"benchmarkify": "github:aarondcohen/benchmarkify",
		"chai": "*",
		"dtslint": "^3.4.1",
		"mocha": "*",
		"sinon": "*"
	},
	"keywords": [
		"128-bit",
		"crockford32",
		"guid",
		"id",
		"monotonic",
		"random",
		"rfc-4122",
		"rfc4122",
		"uid",
		"ulid",
		"unique",
		"universal",
		"uuid",
		"uuid-v1",
		"uuid-v4",
		"uuid-v6",
		"uuid1",
		"uuid4",
		"uuid6",
		"uuidv1",
		"uuidv4",
		"uuidv6"
	]
}


================================================
FILE: src/coder/base.js
================================================
'use strict';

const {
	InvalidEncoding,
	InvalidBytes,
} = require('../common/exception');

const _valid_encoding_pattern = Symbol('valid_encoding_pattern');

class BaseCoder {
	constructor({
		valid_encoding_pattern,
	} = {}) {
		this[_valid_encoding_pattern] = valid_encoding_pattern;
	}

	decode(encoding) {
		if (this.isValidEncoding(encoding)) {
			return this.decodeTrusted(encoding);
		}
		else {
			throw new InvalidEncoding(`Encoding [${encoding}] does not satisfy ${this[_valid_encoding_pattern]}`);
		}
	}

	decodeTrusted(encoding) { return ByteArray.generateRandomFilled() }

	encode(bytes) {
		if (this.isValidBytes(bytes)) {
			return this.encodeTrusted(bytes);
		}
		else {
			throw new InvalidBytes('Requires a 16-byte Uint8Array');
		}

	}

	encodeTrusted(bytes) { return '' }

	isValidBytes(bytes) {
		return true
			&& (bytes instanceof Uint8Array)
			&& bytes.length === 16;
	}

	isValidEncoding(encoding) {
		return true
			&& (typeof encoding === 'string' || encoding instanceof String)
			&& this[_valid_encoding_pattern].test(encoding);
	}
}

module.exports = { BaseCoder };


================================================
FILE: src/coder/crockford32.js
================================================
'use strict';

const { BaseCoder } = require('./base');

const ALPHABET = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';
const MAX_QUINTET = 0b11111;

const CHAR_TO_QUINTET = Array.from(ALPHABET).reduce(
	(acc, chr, idx) => (acc[chr] = acc[chr.toLowerCase()] = idx, acc),
	{
		'I': ALPHABET.indexOf('1'),
		'i': ALPHABET.indexOf('1'),
		'L': ALPHABET.indexOf('1'),
		'l': ALPHABET.indexOf('1'),
		'O': ALPHABET.indexOf('0'),
		'o': ALPHABET.indexOf('0'),
		'U': ALPHABET.indexOf('V'),
		'u': ALPHABET.indexOf('V'),
	}
);
const QUINTET_TO_CHAR = Array.from(ALPHABET);

function _charToQuintet(chr) {
	return CHAR_TO_QUINTET[chr];
}

function _quintetToChar(quintet) {
	return QUINTET_TO_CHAR[quintet & MAX_QUINTET];
}

class Crockford32Coder extends BaseCoder {
	constructor() {
		super({
			valid_encoding_pattern: /^[0-7][^\W_]{25}$/,
		});
	}

	decodeTrusted(encoding) {
		const bytes = new Uint8Array(16);
		const quintets = [];

		for (let idx = 0, end = encoding.length; idx < end; ++idx) {
			quintets.push(_charToQuintet(encoding[idx]));
		}

		//Note: unrolled for performance
		bytes[0] = quintets[0] << 5 | quintets[1];

		bytes[1] = quintets[2] << 3 | quintets[3] >> 2;
		bytes[2] = quintets[3] << 6 | quintets[4] << 1 | quintets[5] >> 4;
		bytes[3] = quintets[5] << 4 | quintets[6] >> 1;
		bytes[4] = quintets[6] << 7 | quintets[7] << 2 | quintets[8] >> 3;
		bytes[5] = quintets[8] << 5 | quintets[9];

		bytes[6] = quintets[10] << 3 | quintets[11] >> 2;
		bytes[7] = quintets[11] << 6 | quintets[12] << 1 | quintets[13] >> 4;
		bytes[8] = quintets[13] << 4 | quintets[14] >> 1;
		bytes[9] = quintets[14] << 7 | quintets[15] << 2 | quintets[16] >> 3;
		bytes[10] = quintets[16] << 5 | quintets[17];

		bytes[11] = quintets[18] << 3 | quintets[19] >> 2;
		bytes[12] = quintets[19] << 6 | quintets[20] << 1 | quintets[21] >> 4;
		bytes[13] = quintets[21] << 4 | quintets[22] >> 1;
		bytes[14] = quintets[22] << 7 | quintets[23] << 2 | quintets[24] >> 3;
		bytes[15] = quintets[24] << 5 | quintets[25];

		return bytes;
	}

	encodeTrusted(bytes) {
		//Note: unrolled for performance
		let quintets = [
			(bytes[0] >> 5),
			(bytes[0]),

			(bytes[1] >> 3),
			(bytes[1] << 2 | bytes[2] >> 6),
			(bytes[2] >> 1),
			(bytes[2] << 4 | bytes[3] >> 4),
			(bytes[3] << 1 | bytes[4] >> 7),
			(bytes[4] >> 2),
			(bytes[4] << 3 | bytes[5] >> 5),
			(bytes[5]),

			(bytes[6] >> 3),
			(bytes[6] << 2 | bytes[7] >> 6),
			(bytes[7] >> 1),
			(bytes[7] << 4 | bytes[8] >> 4),
			(bytes[8] << 1 | bytes[9] >> 7),
			(bytes[9] >> 2),
			(bytes[9] << 3 | bytes[10] >> 5),
			(bytes[10]),

			(bytes[11] >> 3),
			(bytes[11] << 2 | bytes[12] >> 6),
			(bytes[12] >> 1),
			(bytes[12] << 4 | bytes[13] >> 4),
			(bytes[13] << 1 | bytes[14] >> 7),
			(bytes[14] >> 2),
			(bytes[14] << 3 | bytes[15] >> 5),
			(bytes[15]),
		];

		//Note: Massive performance losses occured when
		// using the more legible Array.map and Array.join
		let encoding = '';
		for (let idx = 0, end = quintets.length; idx < end; ++idx) {
			encoding += _quintetToChar(quintets[idx]);
		}
		return encoding;
	}
}

module.exports = new Crockford32Coder;


================================================
FILE: src/coder/hex.js
================================================
'use strict';

const { BaseCoder } = require('./base');

const ALPHABET = '0123456789ABCDEF';

const BYTE_TO_HEX = Array
	.from({ length: ALPHABET.length * ALPHABET.length })
	.map((_, key) => (
		''
		+ ALPHABET.charAt(key / ALPHABET.length)
		+ ALPHABET.charAt(key % ALPHABET.length)
	));

const HEX_TO_BYTE = Array.from(ALPHABET).reduce(
	(mapping, hex, idx) => Object.assign(mapping, {
		[hex.toUpperCase()]: idx,
		[hex.toLowerCase()]: idx,
	}),
	Object.create(null)
);

class HexCoder extends BaseCoder {
	constructor() {
		super({
			valid_encoding_pattern: /^[0-9A-Fa-f]{32}$/,
		});
	}

	decodeTrusted(encoding) {
		let bytes = new Uint8Array(16);

		for (
			let
				dst = 0,
				hi_hex = true,
				src = 0,
				end = encoding.length;
			src < end;
			++src
		) {
			const hex = encoding[src];
			if (hi_hex) {
				bytes[dst] = HEX_TO_BYTE[hex] << 4;
			} else {
				bytes[dst++] |= HEX_TO_BYTE[hex];
			}
			hi_hex = !hi_hex;
		}

		return bytes;
	}

	encodeTrusted(bytes) {
		let encoding = '';
		for (let idx = 0, end = bytes.length; idx < end; ++idx) {
			encoding += BYTE_TO_HEX[bytes[idx]];
		}
		return encoding;
	}
}

module.exports = new HexCoder;


================================================
FILE: src/coder/uuid.js
================================================
'use strict';

const { BaseCoder } = require('./base');

const ALPHABET = '0123456789ABCDEF';

const BYTE_TO_HEX = Array
	.from({ length: ALPHABET.length * ALPHABET.length })
	.map((_, key) => (
		''
		+ ALPHABET.charAt(key / ALPHABET.length)
		+ ALPHABET.charAt(key % ALPHABET.length)
	));

const HEX_TO_BYTE = Array.from(ALPHABET).reduce(
	(mapping, hex, idx) => Object.assign(mapping, {
		[hex.toUpperCase()]: idx,
		[hex.toLowerCase()]: idx,
	}),
	Object.create(null)
);

class UuidCoder extends BaseCoder {
	constructor() {
		super({
			valid_encoding_pattern: /^[0-9A-Fa-f]{4}(?:-?[0-9A-Fa-f]{4}){7}$/,
		});
	}

	decodeTrusted(encoding) {
		let bytes = new Uint8Array(16);

		for (
			let
				dst = 0,
				hi_hex = true,
				src = 0,
				end = encoding.length;
			src < end;
			++src
		) {
			const hex = encoding[src];
			if(hex !== '-') {
				if (hi_hex) {
					bytes[dst] = HEX_TO_BYTE[hex] << 4;
				} else {
					bytes[dst++] |= HEX_TO_BYTE[hex];
				}
				hi_hex = ! hi_hex;
			}
		}

		return bytes;
	}

	encodeTrusted(bytes) {
		let idx = -1;
		const encoding = (''
			+ BYTE_TO_HEX[bytes[++idx]] + BYTE_TO_HEX[bytes[++idx]]
			+ BYTE_TO_HEX[bytes[++idx]] + BYTE_TO_HEX[bytes[++idx]]
			+ '-'
			+ BYTE_TO_HEX[bytes[++idx]] + BYTE_TO_HEX[bytes[++idx]]
			+ '-'
			+ BYTE_TO_HEX[bytes[++idx]] + BYTE_TO_HEX[bytes[++idx]]
			+ '-'
			+ BYTE_TO_HEX[bytes[++idx]] + BYTE_TO_HEX[bytes[++idx]]
			+ '-'
			+ BYTE_TO_HEX[bytes[++idx]] + BYTE_TO_HEX[bytes[++idx]]
			+ BYTE_TO_HEX[bytes[++idx]] + BYTE_TO_HEX[bytes[++idx]]
			+ BYTE_TO_HEX[bytes[++idx]] + BYTE_TO_HEX[bytes[++idx]]
		);
		return encoding;
	}
}

module.exports = new UuidCoder;



================================================
FILE: src/common/byte-array.js
================================================
const { randomBytes } = require('./random-bytes');

const MAX_BYTES = 16;

class ByteArray {
	compare(lhs, rhs) {
		const mismatch_idx =
			lhs.findIndex((byt, idx) => (byt !== rhs[idx]));
		return ~mismatch_idx
			&& Math.sign(lhs[mismatch_idx] - rhs[mismatch_idx]);
	}

	generateOneFilled() {
		return new Uint8Array(MAX_BYTES).fill(0xFF);
	}

	generateRandomFilled() {
		return randomBytes(MAX_BYTES);
	}

	generateZeroFilled() {
		return new Uint8Array(MAX_BYTES).fill(0);
	}
}

module.exports = new ByteArray;


================================================
FILE: src/common/epoch-converter.js
================================================
const { InvalidEpoch } = require('./exception');

const MIN_MS = 0;
const MAX_MS = Math.pow(2, 48);

class EpochConverter {
	fromEpoch(origin_ms, epoch_ms) {
		return new Date(epoch_ms + origin_ms);
	}

	toEpoch(origin_ms, time = null) {
		const coerced_ms =
			time === null ? Date.now() :
			Number.isInteger(time) ? time :
			time instanceof Date ? time.getTime() :
				(() => {
					throw new InvalidEpoch(`Failed to coerce time [${time}] to epoch`);
				})();

		const epoch_ms = coerced_ms - origin_ms;

		if (epoch_ms < MIN_MS || epoch_ms >= MAX_MS) {
			const min_iso = new Date(MIN_MS + origin_ms).toISOString();
			const max_iso = new Date(MAX_MS - 1 + origin_ms).toISOString();
			throw new InvalidEpoch(`Epoch must be between ${min_iso} and ${max_iso}`);
		}

		return epoch_ms;
	}
}

module.exports = new EpochConverter;


================================================
FILE: src/common/exception.js
================================================
class Id128Error extends Error {
	get name() { return this.constructor.name }
}

class ClockSequenceOverflow extends Id128Error {}
class InvalidBytes extends Id128Error {}
class InvalidEncoding extends Id128Error {}
class InvalidEpoch extends Id128Error {}
class UnsupportedVersion extends Id128Error {}

module.exports = {
	Id128Error,
	ClockSequenceOverflow,
	InvalidBytes,
	InvalidEncoding,
	InvalidEpoch,
	UnsupportedVersion,
};


================================================
FILE: src/common/fake-machine.js
================================================
const { randomBytes } = require('./random-bytes');

const _mac_address = Symbol('mac-address');

class FakeMachine {
	constructor() {
		this.reset();
	}

	get mac_address() {
		let mac_address = this[_mac_address];

		if (! mac_address) {
			mac_address = this[_mac_address] = randomBytes(6);
			mac_address[0] |= 0b00000001;
		}

		return mac_address;
	}

	reset() {
		this[_mac_address] = null;
	}
}

module.exports = new FakeMachine;


================================================
FILE: src/common/machine.js
================================================
const Os = require('os');
const { randomBytes } = require('./random-bytes');

const _mac_address = Symbol('mac-address');

class Machine {
	constructor() {
		this.reset();
	}

	get mac_address() {
		let mac_address = this[_mac_address];

		if (! mac_address) {
			const { mac } = Object.values(Os.networkInterfaces())
				.reduce((memo, arr) => memo.concat(arr), [])
				.find((iface) => ! iface.internal && iface.mac)
				|| {};

			mac_address = this[_mac_address] = mac
				? Uint8Array.from(mac.split(':'), (hex) => Number.parseInt(hex, 16))
				: randomBytes(6);

			if (! mac) {
				mac_address[0] |= 0b00000001;
			}
		}

		return mac_address;
	}

	reset() {
		this[_mac_address] = null;
	}
}

module.exports = new Machine;


================================================
FILE: src/common/random-bytes-browser.js
================================================
const Crypto = self.crypto;

function randomBytes(size) {
	const bytes = new Uint8Array(size);
	Crypto.getRandomValues(bytes);
	return bytes;
};

module.exports = { randomBytes };


================================================
FILE: src/common/random-bytes.js
================================================
const Crypto = require('crypto');

const BUFFER_SIZE = 4096 /* typical page size */ - 96 /* Empty buffer overhead */;

const buffer = new Uint8Array(BUFFER_SIZE)
let offset = BUFFER_SIZE;

function randomBytes(size) {
	if (offset + size >= BUFFER_SIZE) {
		offset = 0;
		Crypto.randomFillSync(buffer)
	}

	return buffer.slice(offset, offset += size);
}

module.exports = { randomBytes };


================================================
FILE: src/factory/id.js
================================================
'use strict';

const _id = Symbol('id');
const _canonical_coder = Symbol('canonical_coder');
const _raw_coder = Symbol('raw_coder');

class IdFactory {
	constructor({
		id,
		canonical_coder,
		raw_coder,
	} = {}) {
		this[_id] = class extends id {
			static get name() { return id.name; }
			static get [Symbol.species]() { return id; }
			get [Symbol.toStringTag]() { return `${id.name} ${this.toRaw()}`; }
			toCanonical() { return canonical_coder.encodeTrusted(this.bytes); }
			toRaw() { return raw_coder.encodeTrusted(this.bytes); }
		};
		this[_canonical_coder] = canonical_coder;
		this[_raw_coder] = raw_coder;
	}

	// Properties

	get name() { return this[_id].name; }
	get type() { return this[_id][Symbol.species]; }

	// Generators

	construct(bytes) {
		return new this[_id](bytes);
	}

	generate() {
		return this[_id].generate(...arguments);
	}

	MIN() {
		return this[_id].MIN(...arguments);
	}

	MAX() {
		return this[_id].MAX(...arguments);
	}

	// Coders

	fromCanonical(canonical) {
		return this.construct(this[_canonical_coder].decode(canonical));
	}

	fromCanonicalTrusted(canonical) {
		return this.construct(this[_canonical_coder].decodeTrusted(canonical));
	}

	fromRaw(raw) {
		return this.construct(this[_raw_coder].decode(raw));
	}

	fromRawTrusted(raw) {
		return this.construct(this[_raw_coder].decodeTrusted(raw));
	}

	toCanonical(id) {
		return this[_canonical_coder].encode(id.bytes);
	}

	toRaw(id) {
		return this[_raw_coder].encode(id.bytes);
	}

	// Comparators

	compare(lhs, rhs) {
		console.warn("Deprecated: use generic idCompare instead.")
		return lhs.compare(rhs);
	}

	equal(lhs, rhs) {
		console.warn("Deprecated: use generic idEqual instead.")
		return lhs.equal(rhs);
	}

	// Verifiers

	isCanonical(canonical) {
		return this[_canonical_coder].isValidEncoding(canonical);
	}

	isRaw(raw) {
		return this[_raw_coder].isValidEncoding(raw);
	}
}

module.exports = { IdFactory };


================================================
FILE: src/factory/versioned-id.js
================================================
'use strict';

const { IdFactory } = require('./id');
const { UnsupportedVersion } = require('../common/exception');

const _id_by_version = Symbol('id_by_version');

function detect(factory, { version } = {}) {
	return factory[_id_by_version][version]
		|| (() => { throw new UnsupportedVersion(
			`No support for version [${version}]`
		) })();
}

class VersionedIdFactory extends IdFactory {
	constructor({
		abstract_id,
		versioned_ids,
		canonical_coder,
		raw_coder,
	}) {
		super({
			id: abstract_id,
			canonical_coder,
			raw_coder,
		});

		this[_id_by_version] = versioned_ids.reduce(
			(mapping, id) => Object.assign(mapping, {
				[id.MIN().version]: new IdFactory({
					id,
					canonical_coder,
					raw_coder,
				})
			}),
			Object.create(null),
		);
	}

	get versioned_ids() {
		return Object.values(this[_id_by_version]);
	}

	// Generators

	construct(bytes) {
		const id = super.construct(bytes);
		const version = id.version;

		try {
			return detect(this, { version }).construct(bytes);
		}
		catch (error) {
			if (error instanceof UnsupportedVersion) { return id }
			else { throw error }
		}
	}

	generate() {
		return detect(this, ...arguments).generate(...arguments);
	}

	MIN() {
		return detect(this, ...arguments).MIN();
	}

	MAX() {
		return detect(this, ...arguments).MAX();
	}
}

module.exports = { VersionedIdFactory };


================================================
FILE: src/id/base.js
================================================
'use strict';

const ByteArray = require('../common/byte-array');

const _bytes = Symbol('bytes');

class BaseId {
	//Constructors

	constructor(bytes) {
		this[_bytes] = bytes;
	}

	clone() {
		return new this.constructor(this.bytes.slice());
	}

	// Accessors

	get bytes() {
		return this[_bytes];
	}

	get [Symbol.toStringTag]() {
		return this.constructor.name;
	}

	// Comparators

	compare(rhs) {
		return ByteArray.compare(this.bytes, rhs.bytes);
	}

	equal(rhs) {
		return this.compare(rhs) === 0;
	}
}

module.exports = { BaseId };


================================================
FILE: src/id/ulid-monotonic.js
================================================
const { Ulid, setTime } = require('./ulid');
const ByteArray = require('../common/byte-array');
const EpochConverter = require('../common/epoch-converter');
const { ClockSequenceOverflow } = require('../common/exception');

const TIME_OFFSET = 0;
const CLOCK_SEQUENCE_OFFSET = 6;
const RANDOM_OFFSET = 8;

const EPOCH_ORIGIN_MS = 0;

let _previous_id;
let _previous_time;

function incrementClockSequence(bytes) {
	for (
		let
			idx = RANDOM_OFFSET - 1,
			end = CLOCK_SEQUENCE_OFFSET - 1;
		idx > end;
		--idx
	) {
		if (bytes[idx] === 0xFF) {
			bytes[idx] = 0;
		} else {
			++bytes[idx];
			return;
		}
	}

	throw new ClockSequenceOverflow('Exhausted clock sequence');
};

function reserveClockSequence(bytes) {
	bytes[CLOCK_SEQUENCE_OFFSET] &= 0b01111111;
};

function restoreClockSequence(bytes) {
	for (let idx = TIME_OFFSET; idx < RANDOM_OFFSET; ++idx) {
		bytes[idx] = _previous_id.bytes[idx];
	}
};

class UlidMonotonic extends Ulid {
	static reset() {
		_previous_time = -1;
		_previous_id = this.MIN();
	}

	//Constructors

	static generate({ time } = {}) {
		time = EpochConverter.toEpoch(EPOCH_ORIGIN_MS, time);
		let bytes = ByteArray.generateRandomFilled();

		if (time <= _previous_time) {
			restoreClockSequence(bytes);
			incrementClockSequence(bytes);
		} else {
			setTime(time, bytes)
			reserveClockSequence(bytes);
			_previous_time = time;
		}

		return (_previous_id = new this(bytes));
	}
}

UlidMonotonic.reset();

module.exports = { UlidMonotonic };


================================================
FILE: src/id/ulid.js
================================================
const ByteArray = require('../common/byte-array');
const EpochConverter = require('../common/epoch-converter');
const { BaseId } = require('./base');

const TIME_OFFSET = 0;

const EPOCH_ORIGIN_MS = 0;
const UINT32_RADIX = Math.pow(2, 32);
const UINT8_MAX = 0b11111111;

function setTime(time, bytes) {
	const time_low = time % UINT32_RADIX;
	const time_high = (time - time_low) / UINT32_RADIX;

	let idx = TIME_OFFSET - 1;
	bytes[++idx] = (time_high >>> 8) & UINT8_MAX;
	bytes[++idx] = (time_high >>> 0) & UINT8_MAX;
	bytes[++idx] = (time_low >>> 24) & UINT8_MAX;
	bytes[++idx] = (time_low >>> 16) & UINT8_MAX;
	bytes[++idx] = (time_low >>> 8) & UINT8_MAX;
	bytes[++idx] = (time_low >>> 0) & UINT8_MAX;
}

class Ulid extends BaseId {

	//Constructors

	static generate({ time } = {}) {
		time = EpochConverter.toEpoch(EPOCH_ORIGIN_MS, time);

		let bytes = ByteArray.generateRandomFilled();

		setTime(time, bytes);

		return new this(bytes);
	}

	static MIN() {
		return new this(ByteArray.generateZeroFilled());
	}

	static MAX() {
		return new this(ByteArray.generateOneFilled());
	}

	// Accessors

	get time() {
		let idx = TIME_OFFSET - 1;
		const time_high = 0
			| (this.bytes[++idx] << 8)
			| (this.bytes[++idx] << 0);
		const time_low = 0
			| (this.bytes[++idx] << 24)
			| (this.bytes[++idx] << 16)
			| (this.bytes[++idx] << 8)
			| (this.bytes[++idx] << 0);
		const epoch_ms = (time_high * UINT32_RADIX) + (time_low >>> 0);

		return EpochConverter.fromEpoch(EPOCH_ORIGIN_MS, epoch_ms);
	};
}

module.exports = { Ulid, setTime };


================================================
FILE: src/id/uuid-1.js
================================================
'use strict';

const ByteArray = require('../common/byte-array');
const EpochConverter = require('../common/epoch-converter');
const Machine = require('../common/machine');
const {
	Uuid,
	setVariant,
	setVersion,
} = require('./uuid');

const TIME_OFFSET = 0;
const HIRES_TIME_OFFSET = 2;
const CLOCK_SEQUENCE_OFFSET = 8;
const NODE_OFFSET = 10;

const CLOCK_SEQUENCE_RADIX = Math.pow(2, 14);
const EPOCH_ORIGIN_MS = Date.parse('1582-10-15Z');
const HIRES_TIME_RADIX = Math.pow(2, 12);
const TIME_LOW_MS_RADIX = Math.pow(2, 20);
const UINT8_MAX = 0b11111111;

let _clock_sequence;
let _hires_time;
let _previous_time;

function incrementClockSequence() {
	_clock_sequence = (_clock_sequence + 1) % CLOCK_SEQUENCE_RADIX;
}

function setClockSequence(time, bytes) {
	if (_clock_sequence === null) {
		const random_bytes = ByteArray.generateRandomFilled();
		_clock_sequence = (
			0
			| random_bytes[CLOCK_SEQUENCE_OFFSET + 0] << 8
			| random_bytes[CLOCK_SEQUENCE_OFFSET + 1] << 0
		) % CLOCK_SEQUENCE_RADIX;
	}
	else if (time < _previous_time) {
		incrementClockSequence();
	}

	let idx = CLOCK_SEQUENCE_OFFSET - 1;
	bytes[++idx] = (_clock_sequence >>> 8) & UINT8_MAX;
	bytes[++idx] = (_clock_sequence >>> 0) & UINT8_MAX;
}

function setNode(node, bytes) {
	for (let idx = 0; idx < 6; ++idx) {
		bytes[NODE_OFFSET + idx] = node[idx];
	}
}

function setTime(time, bytes) {
	_hires_time = time > _previous_time ? 0 : _hires_time + 1;
	if (_hires_time === HIRES_TIME_RADIX) {
		_hires_time = 0;
		incrementClockSequence();
	}

	const time_low_ms = time % TIME_LOW_MS_RADIX;
	const time_low = time_low_ms * HIRES_TIME_RADIX + _hires_time;
	const time_high = (time - time_low_ms) / TIME_LOW_MS_RADIX;

	let idx = TIME_OFFSET - 1;
	bytes[++idx] = (time_low >>> 24) & UINT8_MAX;
	bytes[++idx] = (time_low >>> 16) & UINT8_MAX;
	bytes[++idx] = (time_low >>> 8) & UINT8_MAX;
	bytes[++idx] = (time_low >>> 0) & UINT8_MAX;
	bytes[++idx] = (time_high >>> 8) & UINT8_MAX;
	bytes[++idx] = (time_high >>> 0) & UINT8_MAX;
	bytes[++idx] = (time_high >>> 24) & UINT8_MAX;
	bytes[++idx] = (time_high >>> 16) & UINT8_MAX;
}

class Uuid1 extends Uuid {
	static get VARIANT() { return 1 }
	static get VERSION() { return 1 }

	static reset() {
		_clock_sequence = null;
		_hires_time = -1;
		_previous_time = -1;
	}

	//Constructors

	static generate({ node, time } = {}) {
		time = EpochConverter.toEpoch(EPOCH_ORIGIN_MS, time);

		let bytes = ByteArray.generateZeroFilled();

		setTime(time, bytes);
		setClockSequence(time, bytes);
		setNode(node || Machine.mac_address, bytes);
		setVariant(this.VARIANT, bytes);
		setVersion(this.VERSION, bytes);

		if (time > _previous_time) {
			_previous_time = time;
		}

		return new this(bytes);
	}

	// Accessors

	get clock_sequence() {
		return (
			0
			| this.bytes[CLOCK_SEQUENCE_OFFSET] << 8
			| this.bytes[CLOCK_SEQUENCE_OFFSET + 1]
		) & (CLOCK_SEQUENCE_RADIX - 1);
	}

	get hires_time() {
		return (
			0
			| this.bytes[HIRES_TIME_OFFSET] << 8
			| this.bytes[HIRES_TIME_OFFSET + 1]
		) & (HIRES_TIME_RADIX - 1);
	}

	get node() {
		return this.bytes.slice(NODE_OFFSET);
	}

	get time() {
		let idx = TIME_OFFSET - 1;
		const time_low_ms = 0
			| (this.bytes[++idx] << 12)
			| (this.bytes[++idx] << 4)
			| (this.bytes[++idx] >>> 4);
		++idx; // Skip hi-res bits
		const time_high = 0
			| (this.bytes[++idx] << 8)
			| (this.bytes[++idx] << 0)
			| ((this.bytes[++idx] & 0x0F) << 24)
			| (this.bytes[++idx] << 16);
		const epoch_ms = time_high * TIME_LOW_MS_RADIX + time_low_ms;

		return EpochConverter.fromEpoch(EPOCH_ORIGIN_MS, epoch_ms);
	};
}

Uuid1.reset();

module.exports = { Uuid1 };


================================================
FILE: src/id/uuid-4.js
================================================
'use strict';

const ByteArray = require('../common/byte-array');
const {
	Uuid,
	setVariant,
	setVersion,
} = require('./uuid');

class Uuid4 extends Uuid {
	static get VARIANT() { return 1 }
	static get VERSION() { return 4 }

	static generate() {
		let bytes = ByteArray.generateRandomFilled();

		setVariant(this.VARIANT, bytes);
		setVersion(this.VERSION, bytes);

		return new this(bytes);
	}
}

module.exports = { Uuid4 };


================================================
FILE: src/id/uuid-6.js
================================================
'use strict';

const ByteArray = require('../common/byte-array');
const EpochConverter = require('../common/epoch-converter');
const Machine = require('../common/machine');
const {
	Uuid,
	setVariant,
	setVersion,
} = require('./uuid');

const TIME_OFFSET = 0;
const HIRES_TIME_OFFSET = 6;
const CLOCK_SEQUENCE_OFFSET = 8;
const NODE_OFFSET = 10;

const CLOCK_SEQUENCE_RADIX = Math.pow(2, 14);
const EPOCH_ORIGIN_MS = Date.parse('1582-10-15Z');
const HIRES_TIME_RADIX = Math.pow(2, 12);
const UINT32_RADIX = Math.pow(2, 32);
const UINT8_MAX = 0b11111111;

let _clock_sequence;
let _hires_time;
let _previous_time;

function incrementClockSequence() {
	_clock_sequence = (_clock_sequence + 1) % CLOCK_SEQUENCE_RADIX;
}

function setClockSequence(time, bytes) {
	if (_clock_sequence === null) {
		const random_bytes = ByteArray.generateRandomFilled();
		_clock_sequence = (
			0
			| random_bytes[CLOCK_SEQUENCE_OFFSET + 0] << 8
			| random_bytes[CLOCK_SEQUENCE_OFFSET + 1] << 0
		) % CLOCK_SEQUENCE_RADIX;
	}
	else if (time < _previous_time) {
		incrementClockSequence();
	}

	let idx = CLOCK_SEQUENCE_OFFSET - 1;
	bytes[++idx] = (_clock_sequence >>> 8) & UINT8_MAX;
	bytes[++idx] = (_clock_sequence >>> 0) & UINT8_MAX;
}

function setNode(node, bytes) {
	for (let idx = 0; idx < 6; ++idx) {
		bytes[NODE_OFFSET + idx] = node[idx];
	}
}

function setTime(time, bytes) {
	_hires_time = time > _previous_time ? 0 : _hires_time + 1;
	if (_hires_time === HIRES_TIME_RADIX) {
		_hires_time = 0;
		incrementClockSequence();
	}

	const time_low = time % UINT32_RADIX;
	const time_high = (time - time_low) / UINT32_RADIX;

	let idx = TIME_OFFSET - 1;
	bytes[++idx] = (time_high >>> 8) & UINT8_MAX;
	bytes[++idx] = (time_high >>> 0) & UINT8_MAX;
	bytes[++idx] = (time_low >>> 24) & UINT8_MAX;
	bytes[++idx] = (time_low >>> 16) & UINT8_MAX;
	bytes[++idx] = (time_low >>> 8) & UINT8_MAX;
	bytes[++idx] = (time_low >>> 0) & UINT8_MAX;
	bytes[++idx] = (_hires_time >>> 8) & UINT8_MAX;
	bytes[++idx] = (_hires_time >>> 0) & UINT8_MAX;
}

class Uuid6 extends Uuid {
	static get VARIANT() { return 1 }
	static get VERSION() { return 6 }

	static reset() {
		_clock_sequence = null;
		_hires_time = -1;
		_previous_time = -1;
	}

	//Constructors

	static generate({ node, time } = {}) {
		time = EpochConverter.toEpoch(EPOCH_ORIGIN_MS, time);

		let bytes = ByteArray.generateZeroFilled();

		setTime(time, bytes);
		setClockSequence(time, bytes);
		setNode(node || Machine.mac_address, bytes);
		setVariant(this.VARIANT, bytes);
		setVersion(this.VERSION, bytes);

		if (time > _previous_time) {
			_previous_time = time;
		}

		return new this(bytes);
	}

	// Accessors

	get clock_sequence() {
		return (
			0
			| this.bytes[CLOCK_SEQUENCE_OFFSET] << 8
			| this.bytes[CLOCK_SEQUENCE_OFFSET + 1]
		) & (CLOCK_SEQUENCE_RADIX - 1);
	}

	get hires_time() {
		return (
			0
			| this.bytes[HIRES_TIME_OFFSET] << 8
			| this.bytes[HIRES_TIME_OFFSET + 1]
		) & (HIRES_TIME_RADIX - 1);
	}

	get node() {
		return this.bytes.slice(NODE_OFFSET);
	}

	get time() {
		let idx = TIME_OFFSET - 1;
		const time_high = 0
			| (this.bytes[++idx] << 8)
			| (this.bytes[++idx] << 0);
		const time_low = 0
			| (this.bytes[++idx] << 24)
			| (this.bytes[++idx] << 16)
			| (this.bytes[++idx] << 8)
			| (this.bytes[++idx] << 0);
		const epoch_ms = (time_high * UINT32_RADIX) + (time_low >>> 0);

		return EpochConverter.fromEpoch(EPOCH_ORIGIN_MS, epoch_ms);
	};
}

Uuid6.reset();

module.exports = { Uuid6 };


================================================
FILE: src/id/uuid-nil.js
================================================
'use strict';

const ByteArray = require('../common/byte-array');
const {
	Uuid,
	setVariant,
	setVersion,
} = require('./uuid');

class UuidNil extends Uuid {
	static get VARIANT() { return 0 }
	static get VERSION() { return 0 }

	static generate() {
		let bytes = ByteArray.generateZeroFilled();

		setVariant(this.VARIANT, bytes);
		setVersion(this.VERSION, bytes);

		return new this(bytes);
	}

	static MAX() {
		let bytes = ByteArray.generateZeroFilled();

		setVariant(this.VARIANT, bytes);
		setVersion(this.VERSION, bytes);

		return new this(bytes);
	}
}

module.exports = { UuidNil };


================================================
FILE: src/id/uuid.js
================================================
'use strict';

const { BaseId } = require('./base');
const ByteArray = require('../common/byte-array');

const VARIANT_BYTE = 8;
const VERSION_BYTE = 6;

function setVariant(variant, bytes) {
	bytes[VARIANT_BYTE] &= 0b11111111 >>> (variant + 1);
	bytes[VARIANT_BYTE] |= ((0b111 << (3 - variant)) & 0b111) << 5;
};

function setVersion(version, bytes) {
	bytes[VERSION_BYTE] &= 0b00001111;
	bytes[VERSION_BYTE] |= version << 4;
};

class Uuid extends BaseId {
	static MIN() {
		let bytes = ByteArray.generateZeroFilled();

		setVariant(this.VARIANT, bytes);
		setVersion(this.VERSION, bytes);

		return new this(bytes);
	}

	static MAX() {
		let bytes = ByteArray.generateOneFilled();

		setVariant(this.VARIANT, bytes);
		setVersion(this.VERSION, bytes);

		return new this(bytes);
	}

	get variant() {
		const bits = this.bytes[VARIANT_BYTE] >>> 5;

		return (
			bits === 0b111 ? 3 :
			(bits & 0b110) === 0b110 ? 2 :
			(bits & 0b100) === 0b100 ? 1 :
				0
		);
	}

	get version() {
		return this.bytes[VERSION_BYTE] >>> 4;
	}
}

module.exports = {
	Uuid,
	setVersion,
	setVariant,
};


================================================
FILE: test/coder/crockford32.js
================================================
'use strict';

const { expect } = require('chai');
const {
	ALPHABET,
	assertDecode,
	assertEncode,
	describeNamespace,
	makeBytes,
	makeString,
} = require('./shared');

const { InvalidEncoding } = require('common/exception');

const described_namespace =  require('coder/crockford32');

const encoding_any = ''
	+ makeString(1, '01234567')
	+ makeString(25, ALPHABET.CROCKFORD32);
const encoding_max = '7' + makeString(25, 'Z');
const encoding_min = makeString(26, '0');

describe(describeNamespace(described_namespace, encoding_any), function() {
	assertDecode({
		described_namespace,
		encoding_any,
		encoding_max,
		encoding_min,
	});

	describe('.decode', function() {
		const subject = described_namespace.decode.bind(described_namespace);

		it('requires a 26-character Crockford32 string', function() {
			[
				subject,
				subject.bind(null, makeBytes(26)),
				subject.bind(null, encoding_any.slice(0, -1)),
				subject.bind(null, encoding_any + makeString(1, ALPHABET.CROCKFORD32)),
				subject.bind(null, makeString(25, ALPHABET.ASCII) + '!'),
			].forEach(expectation => expect(subject).to.throw(InvalidEncoding));

			expect(subject.bind(null, encoding_any)).not.to.throw();
		});
	});

	describe('.decodeTrusted extended', function() {
		const subject = described_namespace.decodeTrusted.bind(described_namespace);

		it('ignores case', function() {
			const encoding = makeString(1, '01234567')
				+ makeString(25, ALPHABET.CROCKFORD32 + ALPHABET.CROCKFORD32.toLowerCase());

			expect(subject(encoding)).to.deep.equal(subject(encoding.toUpperCase()));
			expect(subject(encoding)).to.deep.equal(subject(encoding.toLowerCase()));
		});

		it('converts visually similar characters', function() {
			const encoding = encoding_any.slice(0, -1);
			const conversions = [
				['i', '1'],
				['I', '1'],
				['l', '1'],
				['L', '1'],
				['o', '0'],
				['O', '0'],
				['u', 'V'],
				['U', 'V'],
			];

			conversions.forEach(([character, replacement]) => {
				expect(subject(encoding + character), `Failed to convert ${character}`)
					.to.deep.equal(subject(encoding + replacement));
			});
		});
	});

	assertEncode({
		described_namespace,
		encoding_any,
		encoding_max,
		encoding_min,
	});
});



================================================
FILE: test/coder/hex.js
================================================
'use strict';

const { expect } = require('chai');
const {
	ALPHABET,
	assertDecode,
	assertEncode,
	describeNamespace,
	makeBytes,
	makeString,
} = require('./shared');

const { InvalidEncoding } = require('common/exception');

const described_namespace = require('coder/hex');

const encoding_any = makeString(32, ALPHABET.HEX);
const encoding_max = makeString(32, 'F');
const encoding_min = makeString(32, '0');

describe(describeNamespace(described_namespace, encoding_any), function() {
	assertDecode({
		described_namespace,
		encoding_any,
		encoding_max,
		encoding_min,
	});

	describe('.decode', function() {
		const subject = described_namespace.decode.bind(described_namespace);

		it('requires a 32-character hex string', function() {
			[
				subject,
				subject.bind(null, makeBytes(32)),
				subject.bind(null, encoding_any.slice(0, -1)),
				subject.bind(null, encoding_any + makeString(1, ALPHABET.HEX)),
				subject.bind(null, makeString(31, ALPHABET.ASCII) + '\0'),
			].forEach(expectation => expect(subject).to.throw(InvalidEncoding));

			expect(subject.bind(null, encoding_any)).not.to.throw();
		});
	});

	describe('.decodeTrusted extended', function() {
		const subject = described_namespace.decodeTrusted.bind(described_namespace);

		it('ignores case', function() {
			const encoding = makeString(32, ALPHABET.HEX + ALPHABET.HEX.toLowerCase());

			expect(subject(encoding)).to.deep.equal(subject(encoding.toUpperCase()));
			expect(subject(encoding)).to.deep.equal(subject(encoding.toLowerCase()));
		});
	});

	assertEncode({
		described_namespace,
		encoding_any,
		encoding_max,
		encoding_min,
	});
});


================================================
FILE: test/coder/shared.js
================================================
'use strict';

const { expect } = require('chai');

const ByteArray = require('common/byte-array');
const {
	InvalidBytes,
	InvalidEncoding,
} = require('common/exception');

// Constants

const BYTES = Object.freeze({
	ANY: ByteArray.generateRandomFilled(),
	MAX: ByteArray.generateOneFilled(),
	MIN: ByteArray.generateZeroFilled(),
});

const ALPHABET = Object.freeze({
	ASCII: Array.from({ length: 128 }, (v, k) => String.fromCharCode(k)).join(''),
	CROCKFORD32: '0123456789ABCDEFGHJKMNPQRSTVWXYZ',
	HEX: '0123456789ABCDEF',
});

//Helpers

function describeNamespace(described_namespace, encoding_any) {
	return described_namespace.constructor.name
		+ ` (with random encoding ${encoding_any})`;
}

function makeBytes(length) {
	return Uint8Array.from({length});
}

function makeString(length, alphabet) {
	const generator = () => randomChar(alphabet);
	return Array.from({length}, generator).join('');
}

function randomChar(alphabet) {
	const random_idx = Math.floor(alphabet.length * Math.random());
	return alphabet.charAt(random_idx);
}

//Assertions

function assertDecode({
	described_namespace,
	encoding_any,
	encoding_max,
	encoding_min,
} = {}) {
	describe('.decodeTrusted', function() {
		const subject = described_namespace.decodeTrusted.bind(described_namespace);

		it(`decodes ${encoding_min} to all 0-bits`, function() {
			expect(subject(encoding_min)).to.deep.equal(BYTES.MIN);
		});

		it(`decodes ${encoding_max} to all 1-bits`, function() {
			expect(subject(encoding_max)).to.deep.equal(BYTES.MAX);
		});

		it('inverts encode', function() {
			expect(subject(described_namespace.encode(BYTES.ANY)))
				.to.deep.equal(BYTES.ANY);
		});
	});
}

function assertEncode({
	described_namespace,
	encoding_any,
	encoding_max,
	encoding_min,
} = {}) {
	describe('.encode', function() {
		const subject = described_namespace.encode.bind(described_namespace);

		it('requires a 16-byte Uint8Array', function() {
			[
				subject,
				subject.bind(null, makeString(16, '\0')),
				subject.bind(null, makeBytes(15)),
				subject.bind(null, makeBytes(17)),
			].forEach((expectation) => expect(subject)
				.to.throw(InvalidBytes, 'Requires a 16-byte Uint8Array'));

			expect(subject.bind(null, BYTES.ANY)).not.to.throw();
		});
	});

	describe('.encodeTrusted', function() {
		const subject = described_namespace.encodeTrusted.bind(described_namespace);
		it(`encodes all 0-bits to ${encoding_min}`, function() {
			expect(subject(BYTES.MIN)).to.equal(encoding_min);
		});

		it(`encodes all 1-bits to ${encoding_max}`, function() {
			expect(subject(BYTES.MAX)).to.equal(encoding_max);
		});

		it('inverts decode', function() {
			expect(subject(described_namespace.decode(encoding_any)))
				.to.equal(encoding_any);
		});
	});
}

module.exports = {
	ALPHABET,
	assertDecode,
	assertEncode,
	describeNamespace,
	makeBytes,
	makeString,
};


================================================
FILE: test/coder/uuid.js
================================================
'use strict';

const { expect } = require('chai');
const {
	ALPHABET,
	assertDecode,
	assertEncode,
	describeNamespace,
	makeBytes,
	makeString,
} = require('./shared');

const { InvalidEncoding } = require('common/exception');

const described_namespace =  require('coder/uuid');

function makeUuid(alphabet) {
	return [8, 4, 4, 4, 12].map(len => makeString(len, alphabet)).join('-');
}

const encoding_any = makeUuid(ALPHABET.HEX);
const encoding_max = makeUuid('F');
const encoding_min = makeUuid('0');

describe(describeNamespace(described_namespace, encoding_any), function() {
	assertDecode({
		described_namespace,
		encoding_any,
		encoding_max,
		encoding_min,
	});

	describe('.decode', function() {
		const subject = described_namespace.decode.bind(described_namespace);

		it('requires a 32-character hex string (excluding hyphens)', function() {
			[
				subject,
				subject.bind(null, makeBytes(32)),
				subject.bind(null, encoding_any.slice(0, -1)),
				subject.bind(null, encoding_any + makeString(1, ALPHABET.HEX)),
				subject.bind(null, makeString(31, ALPHABET.ASCII) + '\0'),
			].forEach(expectation => expect(subject).to.throw(InvalidEncoding));

			expect(subject.bind(null, encoding_any)).not.to.throw();
		});
	});

	describe('.decodeTrusted extended', function() {
		const subject = described_namespace.decodeTrusted.bind(described_namespace);

		it('accepts without hyphens', function() {
			expect(subject(encoding_any.replace(/-/g, '')))
				.to.deep.equal(subject(encoding_any));
		});

		it('accepts hyphens in even groups of 4', function() {
			const encoding = encoding_any
				.replace(/-/g, '')
				.split(/(.{4})/)
				.filter(Boolean)
				.join('-');

			expect(subject(encoding)).to.deep.equal(subject(encoding_any));
		});

		it('ignores case', function() {
			const encoding = makeUuid(ALPHABET.HEX + ALPHABET.HEX.toLowerCase());

			expect(subject(encoding)).to.deep.equal(subject(encoding.toUpperCase()));
			expect(subject(encoding)).to.deep.equal(subject(encoding.toLowerCase()));
		});
	});

	assertEncode({
		described_namespace,
		encoding_any,
		encoding_max,
		encoding_min,
	});
});


================================================
FILE: test/common/byte-array.js
================================================
'use strict';

const { expect } = require('chai');

const described_namespace = require('common/byte-array');

function assertByteArray(subject) {
	it('returns a Uint8Array', function() {
		expect(subject()).to.be.a('Uint8Array');
	});

	it('returns 16 bytes', function() {
		expect(subject()).to.have.lengthOf(16);
	});
}

describe(described_namespace.constructor.name, function() {
	describe('.compare', function() {
		const subject = described_namespace.compare;
		[
			['lhs < rhs', [1], [9], -1],
			['lhs = rhs', [5], [5], 0],
			['lhs > rhs', [9], [1], 1],
			['non-leading lhs < rhs', [5, 9], [5, 3], 1],
			['non-leading lhs = rhs', [5, 7], [5, 7], 0],
			['non-leading lhs > rhs', [5, 3], [5, 9], -1],
		].forEach(([label, lhs, rhs, result]) => {
			it(`resolves ${label} to ${result}`, function() {
				expect(subject(lhs, rhs)).to.equal(result);
			});
		});
	});

	describe('.generateOneFilled', function() {
		const subject = described_namespace.generateOneFilled;

		assertByteArray(subject);

		it('has only one bits', function() {
			expect(subject().every((val) => val === 0xFF)).to.be.true;
		});
	});

	describe('.generateRandomFilled', function() {
		const subject = described_namespace.generateRandomFilled;

		assertByteArray(subject);

		it('has mixed bits', function() {
			// NOTE: given the nature of random and the bit entropy,
			// we're guarding against extreme misfortune
      this.retries(1);

			const bytes = subject();
			expect(bytes.some((val) => val !== 0xFF)).to.be.true;
			expect(bytes.some((val) => val !== 0)).to.be.true;
		});

		it('almost always has different bits', function() {
			// NOTE: given the nature of random and the bit entropy,
			// we're guarding against extreme misfortune
      this.retries(1);

			expect(subject()).not.to.deep.equal(subject());
		});

		it('every call allocates distinct memory', function() {
			// NOTE: given the nature of random and the bit entropy,
			// we're guarding against extreme misfortune
      this.retries(1);

			const byte_arrays = Array.from({ length: 1000 })
				.map(subject)
				.map(x => x.toString());
			expect(new Set(byte_arrays)).to.have.lengthOf(1000);
		});
	});

	describe('.generateZeroFilled', function() {
		const subject = described_namespace.generateZeroFilled;

		assertByteArray(subject);

		it('has only zero bits', function() {
			expect(subject().every((val) => val === 0)).to.be.true;
		});
	});
});


================================================
FILE: test/common/epoch-converter.js
================================================
'use strict';

const { expect } = require('chai');
const { InvalidEpoch } = require('common/exception');

const described_namespace = require('common/epoch-converter');

describe(described_namespace.constructor.name, function() {
	const epoch_origin_ms = Date.parse('1955-11-05Z');
	const min_time = 0 + epoch_origin_ms;
	const max_time = Math.pow(2, 48) - 1 + epoch_origin_ms;
	const now = Date.now();

	describe('.fromEpoch', function() {
		const subject = (time) => described_namespace.fromEpoch(epoch_origin_ms, time);

		it('returns a Date', function() {
			expect(subject(0)).to.be.a('Date');
		});

		it('returns the time after adjusting for the origin', function() {
			[
				['min', 0, min_time],
				['origin', -epoch_origin_ms, 0],
				['now', now, now + epoch_origin_ms],
				['max', Math.pow(2, 48) - 1, max_time],
			].forEach(([label, epoch_ms, time]) => {
				expect(subject(epoch_ms).getTime(), label).to.equal(time);
			});
		});
	});

	describe('.toEpoch', function() {
		const subject = (time) => described_namespace.toEpoch(epoch_origin_ms, time);

		it('accepts a Date', function() {
			[
				['start of epoch time', new Date(min_time), 0],
				['origin of epoch time', new Date(0), -epoch_origin_ms],
				['current time', new Date(now + epoch_origin_ms), now],
				['end of epoch time', new Date(max_time), Math.pow(2, 48) - 1],
			].forEach(([label, value, epoch]) => {
				expect(() => subject(value), label).not.to.throw();
				expect(subject(value), label).to.equal(epoch);
			});
		});

		it('accepts milliseconds', function() {
			[
				['start of epoch time', min_time, 0],
				['origin of epoch time', 0, -epoch_origin_ms],
				['current time', now + epoch_origin_ms, now],
				['end of epoch time', max_time, Math.pow(2, 48) - 1],
			].forEach(([label, value, epoch]) => {
				expect(() => subject(value), label).not.to.throw();
				expect(subject(value), label).to.equal(epoch);
			});
		});

		it('defaults to now for null and undefined', function() {
			[
				['null', null],
				['undefined', void(null)],
			].forEach(([label, value]) => {
				const now = Date.now() - epoch_origin_ms;

				expect(subject(value), label).to.be.within(now, now + 1);
			});
		});

		it('rejects other falsey values', function() {
			[
				['false', false],
				['empty string', ''],
			].forEach(([label, value]) => {
				expect(() => subject(value), label).to.throw(InvalidEpoch);
			});
		});

		it('rejects other Date-like values', function() {
			[
				['date string', '2018-01-10'],
				['duck type', { getTime: (() => {}) }],
			].forEach(([label, value]) => {
				expect(() => subject(value), label).to.throw(InvalidEpoch);
			});
		});

		it('rejects pre/post-epoch values', function() {
			[
				['date before epoch time', new Date(min_time - 1)],
				['ms before epoch time', min_time - 1],
				['date after epoch time', new Date(max_time + 1)],
				['ms after epoch time', max_time + 1],
			].forEach(([label, value]) => {
				expect(() => subject(value), label).to.throw(InvalidEpoch);
			});
		});
	});
});


================================================
FILE: test/common/fake-machine.js
================================================
'use strict';

const { expect } = require('chai');

const described_singleton = require('common/fake-machine');

describe(described_singleton.constructor.name, function() {
	beforeEach(() => described_singleton.reset());
	after(() => described_singleton.reset());

	describe('.mac_address', function() {
		const subject = () => described_singleton.mac_address;

		it('returns a 6 byte address', function() {
			expect(subject()).to.be.a('Uint8Array');
			expect(subject()).to.have.length(6);
		});

		it('sets the multicast bit', function() {
			expect(subject()[0]).to.satisfy((num) => (num & 0b00000001))
		});

		it('returns the same value every time', function() {
			expect(subject()).to.deep.equal(subject());
		});

		it('returns a new value after a reset', function() {
			const original = subject();
			described_singleton.reset();
			expect(subject()).not.to.deep.equal(original);
		});
	});
});


================================================
FILE: test/common/machine.js
================================================
'use strict';

const { expect } = require('chai');
const Os = require('os') || {};
const Sinon = require('sinon');
const ByteArray = require('common/byte-array');
const FakeMachine = require('common/fake-machine');

const described_singleton = require('common/machine');

describe(described_singleton.constructor.name, function() {
	beforeEach(() => described_singleton.reset());
	after(() => described_singleton.reset());

	describe('.mac_address', function() {
		const subject = () => described_singleton.mac_address;

		function assertFaked() {
			it('returns a 6 byte address', function() {
				expect(subject()).to.be.a('Uint8Array');
				expect(subject()).to.have.length(6);
			});

			it('sets the multicast bit', function() {
				expect(subject()[0]).to.satisfy((num) => (num & 0b00000001))
			});

			it('returns the same value every time', function() {
				expect(subject()).to.deep.equal(subject());
			});

			it('returns a new value after a reset', function() {
				const original = subject();
				described_singleton.reset();
				expect(subject()).not.to.deep.equal(original);
			});
		}

		let stubbed_os;
		before(() => (stubbed_os = Sinon.stub(Os, 'networkInterfaces')));
		beforeEach(() => stubbed_os.reset());
		after(() => stubbed_os.restore());

		it('detects a hardware mac address', function() {
			stubbed_os.callThrough();
			let is_supported = false;
			try {
				if (ByteArray.compare(subject(), FakeMachine.mac_address)) {
					is_supported = true;
				}
			}
			catch (_err) {}

			if (! is_supported) {
				this.skip();
			}
		});

		context('when the network interfaces are unavailable', function() {
			beforeEach(() => stubbed_os.returns([]));

			assertFaked();
		});

		context('when the network interfaces are available', function() {
			let interfaces;
			beforeEach(() => stubbed_os.returns(interfaces));

			context('when the interface is internal', function() {
				before(() => (interfaces = {
					lo: [{
							address: '127.0.0.1',
							netmask: '255.0.0.0',
							family: 'IPv4',
							mac: '00:00:00:00:00:00',
							internal: true,
							cidr: '127.0.0.1/8'
					}]
				}));

				assertFaked();
			});

			context('when the interface is missing a mac', function() {
				before(() => (interfaces = {
					wierd0: [{
						address: '192.168.1.108',
						netmask: '255.255.255.0',
						family: 'IPv4',
						mac: '',
						internal: false,
						cidr: '192.168.1.108/24'
					}]
				}));

				assertFaked();
			});

			context('when the interface is external and valid', function() {
				before(() => (interfaces = {
					eth0: [{
						address: '192.168.1.108',
						netmask: '255.255.255.0',
						family: 'IPv4',
						mac: '01:02:03:0a:0b:0c',
						internal: false,
						cidr: '192.168.1.108/24'
					}]
				}));

				it('returns a 6 byte address', function() {
					expect(subject()).to.be.a('Uint8Array');
					expect(subject()).to.have.length(6);
				});

				it('returns the same value every time', function() {
					expect(subject()).to.deep.equal(subject());
				});

				it('return the same value after a reset', function() {
					const original = subject();
					described_singleton.reset();
					expect(subject()).to.deep.equal(original);
				});
			});
		});
	});
});



================================================
FILE: test/factory/id.js
================================================
'use strict';

const { expect } = require('chai');

const { IdFactory: described_class } = require('factory/id');

const id_class = class {
	static generate() { return new this(`id_${Date.now()}`) }
	static MIN() { return new this('\x00') }
	static MAX() { return new this('\xFF') }
	constructor(value) { this._bytes = value }
	get bytes() { return this._bytes }
};

const factory = new described_class({
	id: id_class,
	canonical_coder: {
		encode: (bytes) => `canonical ${bytes}`,
		encodeTrusted: (bytes) => `canonical ${bytes}`,
		decode: (str) => str.replace(/^canonical(?:_distrusted)? /, ''),
		decodeTrusted: (str) => str.replace(/^canonical /, ''),
		isValidEncoding: (str) => /^canonical /.test(str),
	},
	raw_coder: {
		encode: (bytes) => `raw ${bytes}`,
		encodeTrusted: (bytes) => `raw ${bytes}`,
		decode: (str) => str.replace(/^raw(?:_distrusted)? /, ''),
		decodeTrusted: (str) => str.replace(/^raw /, ''),
		isValidEncoding: (str) => /^raw /.test(str),
	},
});


function assertDecoder(method, encoding) {
	describe(`#${method}`, function() {
		const subject = () => factory[method](encoding);

		it('returns an id', function() {
			expect(subject()).to.be.an.instanceOf(id_class);
		});

		assertInjectsInstanceMethod('toCanonical', subject);
		assertInjectsInstanceMethod('toRaw', subject);
	});
}

function assertEncoder(method, pattern) {
	describe(`#${method}`, function() {
		const subject = () => factory[method](factory.generate());

		it('encodes the bytes of the id', function() {
			expect(subject()).to.match(pattern);
		});
	});
}

function assertGenerator(method) {
	describe(`#${method}`, function() {
		const subject = () => factory[method]();

		it(`returns an id`, function() {
			expect(subject()).to.be.an.instanceOf(id_class);
		});

		it('always returns a different object', function() {
			expect(subject()).not.to.equal(subject());
		});

		assertInjectsInstanceMethod('toCanonical', subject);
		assertInjectsInstanceMethod('toRaw', subject);
	});
}

function assertInjectsInstanceMethod(injected_method, generator) {
	describe(injected_method, function() {
		it(`is injected into the instance`, function() {
			const id = generator();

			expect(() => id[injected_method]()).not.to.throw();
			expect(id[injected_method]()).to.equal(factory[injected_method](id));
		});

		it('is only injected into the instance', function() {
			const id = generator();

			expect(new id_class()[injected_method]).to.be.undefined;
		});
	});
}

function assertVerifier(method, validEncoding) {
	const conditions = [
		['canonical', factory.generate().toCanonical()],
		['raw', factory.generate().toRaw()],
		['other', 'some random string'],
	];

	describe(`#${method}`, function() {
		const subject = str => factory[method](str);

		const {
			true: trueConditions,
			false: falseConditions,
		} = conditions.reduce(
			(partitions, condition) => {
				const [name] = condition;
				partitions[validEncoding === name].push(condition);
				return partitions;
			},
			{ true: [], false: [] },
		);

		it('detects valid encodings', function() {
			trueConditions.forEach(([name, encoding]) =>
				expect(subject(encoding), name).to.be.true);
		});

		it('rejects invalid encodings', function() {
			falseConditions.forEach(([name, encoding]) =>
				expect(subject(encoding), name).to.be.false);
		});
	});
}


describe(described_class.name, function() {
	describe('#construct', function() {
		const subject = () => factory.construct('some bytes');

		it('returns an id', function() {
			expect(subject()).to.be.an.instanceOf(id_class);
		});

		it('directly stores the bytes', function() {
			expect(subject()).to.have.property('bytes', 'some bytes');
		});
	});

	describe('#name', function() {
		const subject = () => factory.name;

		it('returns the name of the id generated by the factory', function() {
			expect(subject()).to.equal(id_class.name);
		});
	});

	describe('#type', function() {
		const subject = () => factory.type;

		it('returns the class of the id generated by the factory', function() {
			expect(subject()).to.equal(id_class);
		});

		it('provides support for the instanceof operator', function() {
			expect(factory.generate()).to.be.an.instanceOf(subject())
		});
	});

	assertGenerator('generate');
	assertGenerator('MIN');
	assertGenerator('MAX');

	assertDecoder('fromCanonical', 'canonical_distrusted some_id');
	assertDecoder('fromCanonicalTrusted', 'canonical some_id');
	assertDecoder('fromRaw', 'raw_distrusted some_id');
	assertDecoder('fromRawTrusted', 'raw some_id');

	assertEncoder('toCanonical', /^canonical id_\d+$/);
	assertEncoder('toRaw', /^raw id_\d+$/);

	assertVerifier('isCanonical', 'canonical');
	assertVerifier('isRaw', 'raw');
});



================================================
FILE: test/factory/versioned-id.js
================================================
'use strict';

const { expect } = require('chai');
const { UnsupportedVersion } = require('common/exception');

const { VersionedIdFactory: described_class } = require('factory/versioned-id');

const buildIdClass = (version) => class {
	static get VERSION() { return version }
	static generate() { return new this(`id_${Date.now()} vrsn:${this.VERSION}`) }
	static MIN() { return new this(`\x00 vrsn:${this.VERSION}`) }
	static MAX() { return new this(`\xFF vrsn:${this.VERSION}`) }
	constructor(value) { this._bytes = value }
	get bytes() { return this._bytes }
	get version() { return /vrsn:(\w+)/.exec(this._bytes)[1] }
};

const version = 'VER';
const abstract_id_class = buildIdClass(undefined);
const versioned_id_class = buildIdClass(version);
const versioned_id_classes = [
	buildIdClass('OTHER1'),
	versioned_id_class,
	buildIdClass('OTHER2'),
];

const factory = new described_class({
	abstract_id: abstract_id_class,
	versioned_ids: versioned_id_classes,
	canonical_coder: {
		encode: (bytes) => `canonical ${bytes}`,
		encodeTrusted: (bytes) => `canonical ${bytes}`,
		decode: (str) => str.replace(/^canonical(?:_distrusted)? /, ''),
		decodeTrusted: (str) => str.replace(/^canonical /, ''),
	},
	raw_coder: {
		encode: (bytes) => `raw ${bytes}`,
		encodeTrusted: (bytes) => `raw ${bytes}`,
		decode: (str) => str.replace(/^raw(?:_distrusted)? /, ''),
		decodeTrusted: (str) => str.replace(/^raw /, ''),
	},
});

function assertDecoder(method, encoding) {
	describe(`#${method}`, function() {
		const subject = () => factory[method](encoding);

		it('returns a versioned id', function() {
			expect(subject()).to.be.an.instanceOf(versioned_id_class);
		});

		it('returns an abstract id when the version is unsupported', function() {
			expect(factory[method](encoding.replace(version, 'IDUNNO')))
				.to.be.an.instanceOf(abstract_id_class);
		});

		assertInjectsInstanceMethod('toCanonical', subject);
		assertInjectsInstanceMethod('toRaw', subject);
	});
}

function assertEncoder(method, pattern) {
	describe(`#${method}`, function() {
		const subject = () => factory[method](factory.generate({ version }));

		it('encodes the bytes of the id', function() {
			expect(subject()).to.match(pattern);
		});
	});
}

function assertGenerator(method) {
	describe(`#${method}`, function() {
		const subject = () => factory[method]({ version });

		it(`returns a versioned id`, function() {
			expect(subject()).to.be.an.instanceOf(versioned_id_class);
		});

		it('always returns a different object', function() {
			expect(subject()).not.to.equal(subject());
		});

		it('throws without a version', function() {
			expect(() => factory[method]()).to.throw(UnsupportedVersion);
		});

		assertInjectsInstanceMethod('toCanonical', subject);
		assertInjectsInstanceMethod('toRaw', subject);
	});
}

function assertInjectsInstanceMethod(injected_method, generator) {
	describe(injected_method, function() {
		it(`is injected into the instance`, function() {
			const id = generator();

			expect(() => id[injected_method]()).not.to.throw();
			expect(id[injected_method]()).to.equal(factory[injected_method](id));
		});

		it('is only injected into the instance', function() {
			const id = generator();

			expect(new versioned_id_class()[injected_method]).to.be.undefined;
		});
	});
}

describe(described_class.name, function() {
	describe('#construct', function() {
		const subject = () => factory.construct(`some bytes vrsn:${version}`);

		it('returns a versioned id', function() {
			expect(subject()).to.be.an.instanceOf(versioned_id_class);
		});

		it('directly stores the bytes', function() {
			expect(subject()).to.have.property('bytes', `some bytes vrsn:${version}`);
		});

		it('returns an abstract id when the version is unsupported', function() {
			expect(factory.construct('some bytes vrsn:IDUNNO'))
				.to.be.an.instanceOf(abstract_id_class);
		});
	});

	describe('#name', function() {
		const subject = () => factory.name;

		it('returns the name of the abstract id for the factory', function() {
			expect(subject()).to.equal(abstract_id_class.name);
		});
	});

	describe('#versioned_ids', function() {
		const subject = () => factory.versioned_ids;

		it('returns all the versioned id classes the factory can generate', function() {
			expect(subject().map(id => id.name))
				.to.have.members(versioned_id_classes.map(id => id.name));
		});
	});

	assertGenerator('generate');
	assertGenerator('MIN');
	assertGenerator('MAX');

	assertDecoder('fromCanonical', `canonical_distrusted some_id vrsn:${version}`);
	assertDecoder('fromCanonicalTrusted', `canonical some_id vrsn:${version}`);
	assertDecoder('fromRaw', `raw_distrusted some_id vrsn:${version}`);
	assertDecoder('fromRawTrusted', `raw some_id vrsn:${version}`);

	assertEncoder('toCanonical', new RegExp(`^canonical id_\\d+ vrsn:${version}$`));
	assertEncoder('toRaw', new RegExp(`^raw id_\\d+ vrsn:${version}$`));
});




================================================
FILE: test/id/shared.js
================================================
'use strict';

const { expect } = require('chai');

const ByteArray = require('common/byte-array');
const Machine = require('common/machine');

const extractId = ([_, id]) => id;
const extractLabel = ([label, _]) => label;

function assertAccessorBytes(described_class) {
	describe('#bytes', function() {
		const subject = (bytes) => new described_class(bytes).bytes;

		it('returns the bytes given to the constructor', function() {
			[
				ByteArray.generateZeroFilled(),
				ByteArray.generateRandomFilled(),
				ByteArray.generateOneFilled(),
			].forEach((bytes) => expect(subject(bytes)).to.deep.equal(bytes));
		});
	});
}

function assertAccessorNode(described_class) {
	describe('#node', function() {
		const subject = (node) => described_class.generate({ node }).node;

		it('returns the mac address by default', function() {
			expect(subject()).to.deep.equal(Machine.mac_address);
		});

		it('returns the supplied node', function() {
			const node = Uint8Array.of(1, 2, 3, 4, 5, 6);
			expect(subject(node)).to.deep.equal(node);
		});
	});
}

function assertAccessorTime(described_class, labeled_times) {
	describe('#time', function() {
		const subject = (time) => described_class.generate({ time }).time;

		it('returns the time given to generate', function() {
			labeled_times.forEach(([label, time]) => {
				expect(subject(time), label).to.deep.equal(time)
			});
		});
	});
}

function assertCompareDemonstratesTotalOrder(labeled_ids) {
	describe('#compare', function() {
		const diagnose = (lhs, rhs) => `(${lhs}).compare(${rhs})`;

		labeled_ids.forEach(([lhs_label, lhs_id], lhs_idx) => {
			const subject = (other) => lhs_id.compare(other.clone());
			const prev_ids = labeled_ids.filter((_, idx) => (idx < lhs_idx));
			const next_ids = labeled_ids.filter((_, idx) => (idx > lhs_idx));

			describe(`given ${lhs_label}`, function() {
				if (lhs_idx === labeled_ids.length - 1) {
					it('has no subsequent ids', function() {
						expect(next_ids, `${lhs_label} should be the last id`).to.be.empty;
					});
				} else {
					it('returns -1 for all subsequent ids', function() {
						next_ids.forEach(([label, id]) => {
							expect(subject(id), diagnose(lhs_label, label)).to.equal(-1);
						});
					});
				}

				it('returns 0 for itself', function() {
					const [label, id] = labeled_ids[lhs_idx];
					expect(subject(id), label).to.equal(0);
				});

				if (lhs_idx === 0) {
					it('has no previous ids', function() {
						expect(prev_ids, `${lhs_label} should be the first id`).to.be.empty;
					});
				} else {
					it('returns 1 for all previous ids', function() {
						prev_ids.forEach(([label, id]) => {
							expect(subject(id), diagnose(lhs_label, label)).to.equal(1);
						});
					});
				}
			});
		});
	});
}

function assertDebuggable(described_class) {
	describe('when cast as a string', function() {
		const subject = () => '' + new described_class();

		it(`mentions the type ${described_class.name}`, function() {
			expect(subject()).to.contain.string(described_class.name);
		});
	});
}

function assertEqualDemonstratesSameness(labeled_ids) {
	describe('#equal', function() {
		const diagnose = (lhs, rhs) => `(${lhs}).equal(${rhs})`;

		labeled_ids.forEach(([lhs_label, lhs_id]) => {
			const subject = (other) => lhs_id.equal(other.clone());

			describe(`given ${lhs_label}`, function() {
				it('returns true for itself', function() {
					expect(subject(lhs_id)).to.be.true;
				});

				it('returns false for all others', function() {
					labeled_ids
						.filter((pair) => extractId(pair) !== lhs_id)
						.forEach(([label, id]) => {
							expect(subject(id), diagnose(lhs_label, label)).to.be.false
						});
				});
			});
		});
	});
}

function assertGenerateBasics(described_class) {
	describe('.generate', function() {
		const subject = () => described_class.generate();

		it(`returns a new ${described_class.name}`, function() {
			expect(subject()).to.be.an.instanceOf(described_class);
		});

		it(`returns an id with different bytes each time`, function() {
			// NOTE: given the nature of random and the bit entropy,
			// we're guarding against extreme misfortune
			this.retries(2);

			expect(subject().bytes).not.to.deep.equal(subject().bytes);
		});
	});
}

function assertUuidVariantVersion(described_class, variant, version) {
	const assertVariant = (subject) => it(`is variant ${variant}`, function() {
		expect(subject().variant).to.eql(variant);
	});
	const assertVersion = (subject) => it(`is version ${version}`, function() {
		expect(subject().version).to.eql(version);
	});

	describe('.generate variant/version', function() {
		const subject = () => described_class.generate();

		assertVariant(subject);
		assertVersion(subject);
	});

	describe('.MIN variant/version', function() {
		const subject = () => described_class.MIN();

		assertVariant(subject);
		assertVersion(subject);
	});

	describe('.MAX variant/version', function() {
		const subject = () => described_class.MAX();

		assertVariant(subject);
		assertVersion(subject);
	});
}

module.exports = {
	assertAccessorBytes,
	assertAccessorNode,
	assertAccessorTime,
	assertCompareDemonstratesTotalOrder,
	assertDebuggable,
	assertEqualDemonstratesSameness,
	assertGenerateBasics,
	assertUuidVariantVersion,
};


================================================
FILE: test/id/ulid-monotonic.js
================================================
'use strict';

const { expect } = require('chai');
const {
	assertAccessorBytes,
	assertCompareDemonstratesTotalOrder,
	assertDebuggable,
	assertEqualDemonstratesSameness,
	assertGenerateBasics,
} = require('./shared');

const ByteArray = require('common/byte-array');
const {
	ClockSequenceOverflow,
	InvalidEpoch,
} = require('common/exception');

const { UlidMonotonic: described_class } = require('id/ulid-monotonic');

const MAX_TIME = new Date(Math.pow(2, 48) - 1);
const MIN_TIME = new Date(0);

describe(described_class.name, function() {
	beforeEach(() => described_class.reset());
	after(() => described_class.reset());

	assertDebuggable(described_class);

	assertGenerateBasics(described_class);
	describe('.generate extended', function() {
		const subject = (time) => described_class.generate({ time });

		it('accepts epoch values', function() {
			[
				['start of epoch', MIN_TIME],
				['end of epoch', MAX_TIME],
			].forEach(([label, value]) => {
				expect(() => subject(value), label).not.to.throw(InvalidEpoch);
			});
		});

		it('rejects pre/post-epoch values', function() {
			[
				['prior to 1970', MIN_TIME - 1],
				['after late 10889', MAX_TIME + 1],
			].forEach(([label, value]) => {
				expect(() => subject(value), label).to.throw(InvalidEpoch);
			});
		});

		it('throws when the clock sequence overflows', function() {
			const overflow = 0x10001;
			let sequence = 0;

			subject(Date.now() + 24 * 60 * 60 * 1000);
			expect(() => {
				for (; sequence <= overflow; ++sequence) {
					subject();
				}
			}).to.throw(ClockSequenceOverflow);
			expect(sequence).to.be.above(overflow >> 1);
			expect(sequence).to.be.below(overflow);
		});
	});

	describe('.MIN', function() {
		const subject = () => described_class.MIN();

		it('has all 0-bits', function() {
			expect(subject().bytes).to.deep.equal(ByteArray.generateZeroFilled());
		});

		it('has the least allowed time', function() {
			expect(subject().time).to.deep.equal(MIN_TIME);
		});

		it('ignores monotonicity', function() {
			subject();
			expect(subject().bytes).to.deep.equal(ByteArray.generateZeroFilled());
		});
	});

	describe('.MAX', function() {
		const subject = () => described_class.MAX();

		it('has all 1-bits', function() {
			expect(subject().bytes).to.deep.equal(ByteArray.generateOneFilled());
		});

		it('has the greatest allowed time', function() {
			expect(subject().time).to.deep.equal(MAX_TIME);
		});

		it('ignores monotonicity', function() {
			subject();
			expect(subject().bytes).to.deep.equal(ByteArray.generateOneFilled());
		});
	});

	assertAccessorBytes(described_class);
	describe('#time', function() {
		const subject = (time) => described_class.generate({ time }).time;

		describe('given a future time', function() {
			it('returns the time given to generate', function() {
				[
					['min', MIN_TIME],
					['now', new Date()],
					['max', MAX_TIME],
				].forEach(([label, time]) => {
					expect(subject(time), label).to.deep.equal(time);
				});
			});
		});

		describe('given a past time', function() {
			let most_recent_time;
			beforeEach(() => (most_recent_time = subject(MAX_TIME)));

			it('returns the same time as the most recent id', function() {
				[
					['min', MIN_TIME],
					['now', new Date()],
					['max', MAX_TIME],
				].forEach(([label, time]) => {
					expect(subject(time), label).to.deep.equal(most_recent_time);
				});
			});
		});
	});

	assertCompareDemonstratesTotalOrder([
		['the min id', described_class.MIN()],
		['a min time id', described_class.generate({ time: MIN_TIME })],
		['a recent id', described_class.generate({ time: new Date })],
		['a max time id', described_class.generate({ time: MAX_TIME })],
		['an anachronistic id', described_class.generate({ time: new Date })],
		['the max id', described_class.MAX()],
	]);

	assertEqualDemonstratesSameness([
		['the min id', described_class.MIN()],
		['a min time id', described_class.generate({ time: MIN_TIME })],
		['a recent id', described_class.generate({ time: new Date() })],
		['a max time id', described_class.generate({ time: MAX_TIME })],
		['an anachronistic id', described_class.generate({ time: new Date() })],
		['the max id', described_class.MAX()],
	]);
});


================================================
FILE: test/id/ulid.js
================================================
'use strict';

const { expect } = require('chai');
const {
	assertAccessorBytes,
	assertAccessorTime,
	assertCompareDemonstratesTotalOrder,
	assertDebuggable,
	assertEqualDemonstratesSameness,
	assertGenerateBasics,
} = require('./shared');

const ByteArray = require('common/byte-array');
const { InvalidEpoch } = require('common/exception');

const { Ulid: described_class } = require('id/ulid');;

const MAX_TIME = new Date(Math.pow(2, 48) - 1);
const MIN_TIME = new Date(0);

describe(described_class.name, function() {
	assertDebuggable(described_class);

	assertGenerateBasics(described_class);
	describe('.generate extended', function() {
		const subject = (time) => described_class.generate({ time });

		it('accepts epoch values', function() {
			[
				['start of epoch', MIN_TIME],
				['end of epoch', MAX_TIME],
			].forEach(([label, value]) => {
				expect(() => subject(value), label).not.to.throw(InvalidEpoch);
			});
		});

		it('rejects pre/post-epoch values', function() {
			[
				['prior to 1970', MIN_TIME - 1],
				['after late 10889', MAX_TIME + 1],
			].forEach(([label, value]) => {
				expect(() => subject(value), label).to.throw(InvalidEpoch);
			});
		});
	});

	describe('.MIN', function() {
		const subject = () => described_class.MIN();

		it('has all 0-bits', function() {
			expect(subject().bytes).to.deep.equal(ByteArray.generateZeroFilled());
		});

		it('has the least allowed time', function() {
			expect(subject().time).to.deep.equal(MIN_TIME);
		});
	});

	describe('.MAX', function() {
		const subject = () => described_class.MAX();

		it('has all 1-bits', function() {
			expect(subject().bytes).to.deep.equal(ByteArray.generateOneFilled());
		});

		it('has the greatest allowed time', function() {
			expect(subject().time).to.deep.equal(MAX_TIME);
		});
	});

	assertAccessorBytes(described_class);
	assertAccessorTime(described_class, [
		['min', MIN_TIME],
		['now', new Date()],
		['max', MAX_TIME],
	]);

	assertCompareDemonstratesTotalOrder([
		['the min id', described_class.MIN()],
		['a min time id', described_class.generate({ time: MIN_TIME })],
		['a recent id', described_class.generate({ time: new Date })],
		['a max time id', described_class.generate({ time: MAX_TIME })],
		['the max id', described_class.MAX()],
	]);

	assertEqualDemonstratesSameness([
		['the min id', described_class.MIN()],
		['a min time id', described_class.generate({ time: MIN_TIME })],
		['a recent id', described_class.generate({ time: new Date })],
		['a max time id', described_class.generate({ time: MAX_TIME })],
		['the max id', described_class.MAX()],
	]);
});


================================================
FILE: test/id/uuid-1.js
================================================
'use strict';

const { expect } = require('chai');
const {
	assertAccessorBytes,
	assertAccessorNode,
	assertAccessorTime,
	assertCompareDemonstratesTotalOrder,
	assertDebuggable,
	assertEqualDemonstratesSameness,
	assertGenerateBasics,
	assertUuidVariantVersion,
} = require('./shared');

const ByteArray = require('common/byte-array');
const { InvalidEpoch } = require('common/exception');

const { Uuid1: described_class } = require('id/uuid-1');

const ORIGIN = Date.parse('1582-10-15Z');
const MAX_TIME = new Date(Math.pow(2, 48) - 1 + ORIGIN);
const MIN_TIME = new Date(ORIGIN);

describe(described_class.name, function() {
	beforeEach(() => described_class.reset());
	after(() => described_class.reset());

	assertDebuggable(described_class);
	assertGenerateBasics(described_class);
	describe('.generate extended', function() {
		const CLOCK_MAX = 0x3FFF;
		const HIRES_MAX = 0x0FFF;
		const subject = (time) => described_class.generate({ time });

		it('accepts epoch values', function() {
			[
				['start of epoch', MIN_TIME],
				['end of epoch', MAX_TIME],
			].forEach(([label, value]) => {
				expect(() => subject(value), label).not.to.throw(InvalidEpoch);
			});
		});

		it('rejects pre/post-epoch values', function() {
			[
				['prior to Gregorian calendar', MIN_TIME - 1],
				['after late 10502', MAX_TIME + 1],
			].forEach(([label, value]) => {
				expect(() => subject(value), label).to.throw(InvalidEpoch);
			});
		});

		context('when given a time in the past', function() {
			it('increments the hires timer', function() {
				const previous_id = subject();
				expect(subject(MIN_TIME).hires_time)
					.to.equal(previous_id.hires_time + 1);
			});

			it('increments the clock sequence', function() {
				// For the minor chance that the clock sequence starts at the top
				this.retries(1);

				const previous_id = subject();
				expect(subject(MIN_TIME).clock_sequence)
					.to.equal(previous_id.clock_sequence + 1);
			});

			context('when the clock sequence overflows', function() {
				function clockOverflow(time) {
					for (let count = 0; count < CLOCK_MAX; ++count) {
						subject(time);
					}
				}

				it('resets the clock sequence', function() {
					subject();
					clockOverflow(MIN_TIME);
					expect(subject(MIN_TIME).hires_time).to.equal(0);
				});
			});
		});

		context('when given the same time', function() {
			const time = Date.now();

			it('increments the hires timer', function() {
				const previous_id = subject(time);
				expect(subject(time).hires_time).to.equal(previous_id.hires_time + 1);
			});

			context('when the hires timer overflows', function() {
				function hiresOverflow(time) {
					for (let count = 0; count < HIRES_MAX; ++count) {
						subject(time);
					}
				}

				it('resets the hires timer', function() {
					subject();
					hiresOverflow(time);
					expect(subject(time).hires_time).to.equal(0);
				});

				it('increments the clock sequence', function() {
					// For the minor chance that the clock sequence starts at the top
					this.retries(1);

					const previous_id = subject(time);
					hiresOverflow(time);
					expect(subject(time).clock_sequence)
						.to.equal(previous_id.clock_sequence + 1);
				});
			});
		});

		context('when given a time in the future', function() {
			it('resets the hires timer', function() {
				subject();
				expect(subject(MAX_TIME).hires_time).to.equal(0);
			});

			it('retains the same clock sequence', function() {
				const previous_id = subject();
				expect(subject(MAX_TIME).clock_sequence)
					.to.equal(previous_id.clock_sequence);
			});
		});
	});

	describe('.MIN', function() {
		const subject = () => described_class.MIN();

		it('has all 0-bits other than variant/version', function() {
			const expected = ByteArray.generateZeroFilled();
			expected.set([0b00010000], 6);
			expected.set([0b10000000], 8);

			expect(subject().bytes).to.deep.equal(expected);
		});
	});

	describe('.MAX', function() {
		const subject = () => described_class.MAX();

		it('has all 1-bits other than variant/version', function() {
			const expected = ByteArray.generateOneFilled();
			expected.set([0b00011111], 6);
			expected.set([0b10111111], 8);

			expect(subject().bytes).to.deep.equal(expected);
		});
	});

	assertUuidVariantVersion(described_class, 1, 1);
	assertAccessorBytes(described_class);
	assertAccessorNode(described_class);
	assertAccessorTime(described_class, [
		['min', MIN_TIME],
		['origin', new Date(0)],
		['now', new Date()],
		['max', MAX_TIME],
	]);

	assertCompareDemonstratesTotalOrder([
		['the min id', described_class.MIN()],
		['a random id', described_class.generate()],
		['the max id', described_class.MAX()],
	]);

	assertEqualDemonstratesSameness([
		['the min id', described_class.MIN()],
		['a random id', described_class.generate()],
		['the max id', described_class.MAX()],
	]);
});



================================================
FILE: test/id/uuid-4.js
================================================
'use strict';

const { expect } = require('chai');
const {
	assertAccessorBytes,
	assertCompareDemonstratesTotalOrder,
	assertDebuggable,
	assertEqualDemonstratesSameness,
	assertGenerateBasics,
	assertUuidVariantVersion,
} = require('./shared');

const ByteArray = require('common/byte-array');

const { Uuid4: described_class } = require('id/uuid-4');

describe(described_class.name, function() {
	assertDebuggable(described_class);
	assertGenerateBasics(described_class);

	describe('.MIN', function() {
		const subject = () => described_class.MIN();

		it('has all 0-bits other than variant/version', function() {
			const expected = ByteArray.generateZeroFilled();
			expected.set([0b01000000], 6);
			expected.set([0b10000000], 8);

			expect(subject().bytes).to.deep.equal(expected);
		});
	});

	describe('.MAX', function() {
		const subject = () => described_class.MAX();

		it('has all 1-bits other than variant/version', function() {
			const expected = ByteArray.generateOneFilled();
			expected.set([0b01001111], 6);
			expected.set([0b10111111], 8);

			expect(subject().bytes).to.deep.equal(expected);
		});
	});

	assertUuidVariantVersion(described_class, 1, 4);
	assertAccessorBytes(described_class);

	assertCompareDemonstratesTotalOrder([
		['the min id', described_class.MIN()],
		['a random id', described_class.generate()],
		['the max id', described_class.MAX()],
	]);

	assertEqualDemonstratesSameness([
		['the min id', described_class.MIN()],
		['a random id', described_class.generate()],
		['the max id', described_class.MAX()],
	]);
});


================================================
FILE: test/id/uuid-6.js
================================================
'use strict';

const { expect } = require('chai');
const {
	assertAccessorBytes,
	assertAccessorNode,
	assertAccessorTime,
	assertCompareDemonstratesTotalOrder,
	assertDebuggable,
	assertEqualDemonstratesSameness,
	assertGenerateBasics,
	assertUuidVariantVersion,
} = require('./shared');

const ByteArray = require('common/byte-array');
const { InvalidEpoch } = require('common/exception');

const { Uuid6: described_class } = require('id/uuid-6');

const ORIGIN = Date.parse('1582-10-15Z');
const MAX_TIME = new Date(Math.pow(2, 48) - 1 + ORIGIN);
const MIN_TIME = new Date(ORIGIN);

describe(described_class.name, function() {
	beforeEach(() => described_class.reset());
	after(() => described_class.reset());

	assertDebuggable(described_class);
	assertGenerateBasics(described_class);
	describe('.generate extended', function() {
		const CLOCK_MAX = 0x3FFF;
		const HIRES_MAX = 0x0FFF;
		const subject = (time) => described_class.generate({ time });

		it('accepts epoch values', function() {
			[
				['start of epoch', MIN_TIME],
				['end of epoch', MAX_TIME],
			].forEach(([label, value]) => {
				expect(() => subject(value), label).not.to.throw(InvalidEpoch);
			});
		});

		it('rejects pre/post-epoch values', function() {
			[
				['prior to Gregorian calendar', MIN_TIME - 1],
				['after late 10502', MAX_TIME + 1],
			].forEach(([label, value]) => {
				expect(() => subject(value), label).to.throw(InvalidEpoch);
			});
		});

		context('when given a time in the past', function() {
			it('increments the hires timer', function() {
				const previous_id = subject();
				expect(subject(MIN_TIME).hires_time)
					.to.equal(previous_id.hires_time + 1);
			});

			it('increments the clock sequence', function() {
				// For the minor chance that the clock sequence starts at the top
				this.retries(1);

				const previous_id = subject();
				expect(subject(MIN_TIME).clock_sequence)
					.to.equal(previous_id.clock_sequence + 1);
			});

			context('when the clock sequence overflows', function() {
				function clockOverflow(time) {
					for (let count = 0; count < CLOCK_MAX; ++count) {
						subject(time);
					}
				}

				it('resets the clock sequence', function() {
					subject();
					clockOverflow(MIN_TIME);
					expect(subject(MIN_TIME).hires_time).to.equal(0);
				});
			});
		});

		context('when given the same time', function() {
			const time = Date.now();

			it('increments the hires timer', function() {
				const previous_id = subject(time);
				expect(subject(time).hires_time).to.equal(previous_id.hires_time + 1);
			});

			context('when the hires timer overflows', function() {
				function hiresOverflow(time) {
					for (let count = 0; count < HIRES_MAX; ++count) {
						subject(time);
					}
				}

				it('resets the hires timer', function() {
					subject();
					hiresOverflow(time);
					expect(subject(time).hires_time).to.equal(0);
				});

				it('increments the clock sequence', function() {
					// For the minor chance that the clock sequence starts at the top
					this.retries(1);

					const previous_id = subject(time);
					hiresOverflow(time);
					expect(subject(time).clock_sequence)
						.to.equal(previous_id.clock_sequence + 1);
				});
			});
		});

		context('when given a time in the future', function() {
			it('resets the hires timer', function() {
				subject();
				expect(subject(MAX_TIME).hires_time).to.equal(0);
			});

			it('retains the same clock sequence', function() {
				const previous_id = subject();
				expect(subject(MAX_TIME).clock_sequence)
					.to.equal(previous_id.clock_sequence);
			});
		});
	});

	describe('.MIN', function() {
		const subject = () => described_class.MIN();

		it('has all 0-bits other than variant/version', function() {
			const expected = ByteArray.generateZeroFilled();
			expected.set([0b01100000], 6);
			expected.set([0b10000000], 8);

			expect(subject().bytes).to.deep.equal(expected);
		});
	});

	describe('.MAX', function() {
		const subject = () => described_class.MAX();

		it('has all 1-bits other than variant/version', function() {
			const expected = ByteArray.generateOneFilled();
			expected.set([0b01101111], 6);
			expected.set([0b10111111], 8);

			expect(subject().bytes).to.deep.equal(expected);
		});
	});

	assertUuidVariantVersion(described_class, 1, 6);
	assertAccessorBytes(described_class);
	assertAccessorNode(described_class);
	assertAccessorTime(described_class, [
		['min', MIN_TIME],
		['origin', new Date(0)],
		['now', new Date()],
		['max', MAX_TIME],
	]);

	assertCompareDemonstratesTotalOrder([
		['the min id', described_class.MIN()],
		['a random id', described_class.generate()],
		['the max id', described_class.MAX()],
	]);

	assertEqualDemonstratesSameness([
		['the min id', described_class.MIN()],
		['a random id', described_class.generate()],
		['the max id', described_class.MAX()],
	]);
});



================================================
FILE: test/id/uuid-nil.js
================================================
'use strict';

const { expect } = require('chai');
const {
	assertAccessorBytes,
	assertDebuggable,
	assertUuidVariantVersion,
} = require('./shared');

const ByteArray = require('common/byte-array');

const { UuidNil: described_class } = require('id/uuid-nil');

describe(described_class.name, function() {
	assertDebuggable(described_class);

	describe('.generate', function() {
		const subject = () => described_class.generate();

		it(`returns a new ${described_class.name}`, function() {
			expect(subject()).to.be.an.instanceOf(described_class);
		});
	});

	describe('.MIN', function() {
		const subject = () => described_class.MIN();

		it('has all 0-bits', function() {
			const expected = ByteArray.generateZeroFilled();

			expect(subject().bytes).to.deep.equal(expected);
		});
	});

	describe('.MAX', function() {
		const subject = () => described_class.MAX();

		it('has all 0-bits', function() {
			const expected = ByteArray.generateZeroFilled();

			expect(subject().bytes).to.deep.equal(expected);
		});
	});

	assertUuidVariantVersion(described_class, 0, 0);
	assertAccessorBytes(described_class);

	describe('#compare', function() {
		const diagnose = (lhs, rhs) => `(${lhs}).compare(${rhs})`;

		const labeled_ids = [
			['the min id', described_class.MIN()],
			['a random id', described_class.generate()],
			['another random id', described_class.generate()],
			['the max id', described_class.MAX()],
		];

		labeled_ids.forEach(([lhs_label, lhs_id], lhs_idx) => {
			const subject = (other) => lhs_id.compare(other.clone());

			describe(`given ${lhs_label}`, function() {
				it('returns 0 for all ids', function() {
					labeled_ids.forEach(([label, id]) => {
						expect(subject(id), diagnose(lhs_label, label)).to.equal(0);
					});
				});
			});
		});
	});

	describe('#equal', function() {
		const diagnose = (lhs, rhs) => `(${lhs}).equal(${rhs})`;

		const labeled_ids = [
			['the min id', described_class.MIN()],
			['a random id', described_class.generate()],
			['another random id', described_class.generate()],
			['the max id', described_class.MAX()],
		];

		labeled_ids.forEach(([lhs_label, lhs_id]) => {
			const subject = (other) => lhs_id.equal(other.clone());

			describe(`given ${lhs_label}`, function() {
				it('returns true for all ids', function() {
					labeled_ids.forEach(([label, id]) => {
						expect(subject(id), diagnose(lhs_label, label)).to.be.true;
					});
				});
			});
		});
	});
});



================================================
FILE: test/id128.js
================================================
'use strict';

const { expect } = require('chai');

const Id128 = require('../');

function assertDebuggable(id_name, generator) {
	describe('when cast as a string', function() {
		const subject = () => '' + generator();

		it(`mentions the type ${id_name}`, function() {
			expect(subject()).to.contain.string(id_name);
		});
	});
}

function assertValidId128(id_name, factory, id_class, generator_args = {}) {
	describe('new', function() {
		it('is disabled', function() {
			expect(() => new factory).to.throw(TypeError);
		});
	});

	describe('.generate', function() {
		const subject = () => factory.generate(generator_args);

		it(`returns a ${id_name}`, function() {
			expect(subject()).to.be.an.instanceOf(id_class);
			expect(subject()).to.be.an.instanceOf(factory.type);
		});

		it('generates 128-bit id', function() {
			expect(subject().bytes).to.have.lengthOf(16);
		});

		assertDebuggable(id_name, subject);
	});

	describe('.MIN', function() {
		const subject = () => factory.MIN(generator_args);

		it(`returns a ${id_name}`, function() {
			expect(subject()).to.be.an.instanceOf(id_class);
		});

		it('generates 128-bit id', function() {
			expect(subject().bytes).to.have.lengthOf(16);
		});

		assertDebuggable(id_name, subject);
	});

	describe('.MAX', function() {
		const subject = () => factory.MAX(generator_args);

		it(`returns a ${id_name}`, function() {
			expect(subject()).to.be.an.instanceOf(id_class);
		});

		it('generates 128-bit id', function() {
			expect(subject().bytes).to.have.lengthOf(16);
		});

		assertDebuggable(id_name, subject);
	});

	describe('canonical', function() {
		const id = factory.generate(generator_args);

		it('encodes to a string', function() {
			expect(factory.toCanonical(id)).to.be.a('string');
		});

		it(`decodes to a ${id_name}`, function() {
			expect(factory.fromCanonical(factory.toCanonical(id)))
				.to.be.an.instanceOf(id_class);
		});

		it('converts symmetrically', function() {
			[
				['generated', id],
				['min', factory.MIN(generator_args)],
				['max', factory.MAX(generator_args)],
			].forEach(([label, test_id]) => {
				expect(factory.fromCanonical(factory.toCanonical(test_id)), label)
					.to.deep.equal(test_id);
			});
		});

		describe('when decoded', function() {
			assertDebuggable(id_name, () => factory.fromCanonical(id.toCanonical()));
		});
	});

	describe('raw', function() {
		const id = factory.generate(generator_args);

		it('encodes to a string', function() {
			expect(factory.toRaw(id)).to.be.a('string');
		});

		it(`decodes to a ${id_name}`, function() {
			expect(factory.fromRaw(factory.toRaw(id)))
				.to.be.an.instanceOf(id_class);
		});

		it('converts symmetrically', function() {
			[
				['generated', id],
				['min', factory.MIN(generator_args)],
				['max', factory.MAX(generator_args)],
			].forEach(([label, test_id]) => {
				expect(factory.fromRaw(factory.toRaw(test_id)), label)
					.to.deep.equal(test_id);
			});
		});

		describe('when decoded', function() {
			assertDebuggable(id_name, () => factory.fromRaw(id.toRaw()));
		});
	});
}

[
	'Ulid',
	'UlidMonotonic',
	'Uuid1',
	'Uuid4',
	'UuidNil',
].forEach((id_name) => describe(`${id_name} Factory`, function() {
	assertValidId128(
		id_name,
		Id128[id_name],
		Id128[id_name].type,
	);
}));

[
	['Uuid1', { version: 1 }],
	['Uuid4', { version: 4 }],
	['Uuid6', { version: 6 }],
	['UuidNil', { version: 0 }],
].forEach(([id_name, generator_args]) => {
	describe(`Uuid Factory generating ${id_name}`, function() {
		assertValidId128(
			id_name,
			Id128.Uuid,
			Id128[id_name].type,
			generator_args,
		);
	});
});


const all_ids = [
	'Ulid',
	'UlidMonotonic',
	'Uuid1',
	'Uuid4',
	'UuidNil',
].map((id_name) => Id128[id_name].generate())

describe('idCompare', function() {
	const subject = Id128.idCompare

	it('compares the same id of any type', function() {
		all_ids.forEach((id) => expect(subject(id, id), id.name).to.equal(0));
	});

	it('works with ids of any type', function() {
		all_ids.forEach((lhs) => {
			all_ids.forEach((rhs) => {
				expect(() => subject(lhs, rhs), `${lhs.name} and ${rhs.name}`)
					.not.to.throw();
			});
		});
	});
})

describe('idEqual', function() {
	const subject = Id128.idEqual

	it('equates the same id of any type', function() {
		all_ids.forEach((id) => expect(subject(id, id), id.name).to.equal(true));
	});

	it('works with ids of any type', function() {
		all_ids.forEach((lhs) => {
			all_ids.forEach((rhs) => {
				expect(() => subject(lhs, rhs), `${lhs.name} and ${rhs.name}`)
					.not.to.throw();
			});
		});
	});
})


================================================
FILE: types/test.ts
================================================
import {
	idCompare,
	idEqual,
	Exception,
	Ulid,
	UlidMonotonic,
	Uuid,
	Uuid1,
	Uuid4,
	Uuid6,
	UuidNil,
} from 'id128';

const bytes = new Uint8Array(16);
const encoded_id = "encoded-id-data";
const node = new Uint8Array([]);
const now = new Date();

const ulid = Ulid.MIN();
const ulid_monotonic = UlidMonotonic.MIN();
const uuid = Uuid.MIN({ version: 0 });
const uuid_1 = Uuid1.MIN();
const uuid_4 = Uuid4.MIN();
const uuid_6 = Uuid6.MIN();
const uuid_nil = UuidNil.MIN();

Ulid.MAX(); // $ExpectType Ulid
Ulid.MIN(); // $ExpectType Ulid
Ulid.construct(bytes); // $ExpectType Ulid
Ulid.fromCanonical(encoded_id); // $ExpectType Ulid
Ulid.fromCanonicalTrusted(encoded_id); // $ExpectType Ulid
Ulid.fromRaw(encoded_id); // $ExpectType Ulid
Ulid.fromRawTrusted(encoded_id); // $ExpectType Ulid
Ulid.generate(); // $ExpectType Ulid
Ulid.generate({ time: now }); // $ExpectType Ulid
Ulid.generate({}); // $ExpectType Ulid
Ulid.isCanonical(encoded_id); // $ExpectType boolean
Ulid.isRaw(encoded_id); // $ExpectType boolean
Ulid.name; // $ExpectType string
Ulid.type; // $ExpectType ConstructorOf<Ulid>
Ulid.toCanonical(ulid); // $ExpectType string
Ulid.toRaw(ulid); // $ExpectType string

UlidMonotonic.MAX(); // $ExpectType UlidMonotonic
UlidMonotonic.MIN(); // $ExpectType UlidMonotonic
UlidMonotonic.construct(bytes); // $ExpectType UlidMonotonic
UlidMonotonic.fromCanonical(encoded_id); // $ExpectType UlidMonotonic
UlidMonotonic.fromCanonicalTrusted(encoded_id); // $ExpectType UlidMonotonic
UlidMonotonic.fromRaw(encoded_id); // $ExpectType UlidMonotonic
UlidMonotonic.fromRawTrusted(encoded_id); // $ExpectType UlidMonotonic
UlidMonotonic.generate(); // $ExpectType UlidMonotonic
UlidMonotonic.generate({ time: now }); // $ExpectType UlidMonotonic
UlidMonotonic.generate({}); // $ExpectType UlidMonotonic
UlidMonotonic.isCanonical(encoded_id); // $ExpectType boolean
UlidMonotonic.isRaw(encoded_id); // $ExpectType boolean
UlidMonotonic.name; // $ExpectType string
UlidMonotonic.type; // $ExpectType ConstructorOf<UlidMonotonic>
UlidMonotonic.toCanonical(ulid_monotonic); // $ExpectType string
UlidMonotonic.toRaw(ulid_monotonic); // $ExpectType string

Uuid.MAX({ version: 0 }); // $ExpectType Uuid
Uuid.MAX({ version: 1 }); // $ExpectType Uuid
Uuid.MAX({ version: 4 }); // $ExpectType Uuid
Uuid.MAX({ version: 6 }); // $ExpectType Uuid
Uuid.MIN({ version: 0 }); // $ExpectType Uuid
Uuid.MIN({ version: 1 }); // $ExpectType Uuid
Uuid.MIN({ version: 4 }); // $ExpectType Uuid
Uuid.MIN({ version: 6 }); // $ExpectType Uuid
Uuid.fromCanonical(encoded_id); // $ExpectType Uuid
Uuid.fromCanonicalTrusted(encoded_id); // $ExpectType Uuid
Uuid.fromRaw(encoded_id); // $ExpectType Uuid
Uuid.fromRawTrusted(encoded_id); // $ExpectType Uuid
Uuid.generate({ node, time: now, version: 1 }); // $ExpectType Uuid
Uuid.generate({ node, time: now, version: 6 }); // $ExpectType Uuid
Uuid.generate({ version: 0 }); // $ExpectType Uuid
Uuid.generate({ version: 4 }); // $ExpectType Uuid
Uuid.isCanonical(encoded_id); // $ExpectType boolean
Uuid.isRaw(encoded_id); // $ExpectType boolean
Uuid.name; // $ExpectType string
Uuid.type; // $ExpectType ConstructorOf<Uuid>
Uuid.toCanonical(uuid); // $ExpectType string
Uuid.toCanonical(uuid_1); // $ExpectType string
Uuid.toCanonical(uuid_4); // $ExpectType string
Uuid.toCanonical(uuid_6); // $ExpectType string
Uuid.toCanonical(uuid_nil); // $ExpectType string
Uuid.toRaw(uuid); // $ExpectType string
Uuid.toRaw(uuid_1); // $ExpectType string
Uuid.toRaw(uuid_4); // $ExpectType string
Uuid.toRaw(uuid_6); // $ExpectType string
Uuid.toRaw(uuid_nil); // $ExpectType string
Uuid.versioned_ids; // $ExpectType IdFactory<Uuid>[]

Uuid1.MAX(); // $ExpectType Uuid1
Uuid1.MIN(); // $ExpectType Uuid1
Uuid1.construct(bytes); // $ExpectType Uuid1
Uuid1.fromCanonical(encoded_id); // $ExpectType Uuid1
Uuid1.fromCanonicalTrusted(encoded_id); // $ExpectType Uuid1
Uuid1.fromRaw(encoded_id); // $ExpectType Uuid1
Uuid1.fromRawTrusted(encoded_id); // $ExpectType Uuid1
Uuid1.generate(); // $ExpectType Uuid1
Uuid1.generate({ node, time: now }); // $ExpectType Uuid1
Uuid1.generate({}); // $ExpectType Uuid1
Uuid1.isCanonical(encoded_id); // $ExpectType boolean
Uuid1.isRaw(encoded_id); // $ExpectType boolean
Uuid1.name; // $ExpectType string
Uuid1.type; // $ExpectType ConstructorOf<Uuid1>
Uuid1.toCanonical(uuid_1); // $ExpectType string
Uuid1.toRaw(uuid_1); // $ExpectType string

Uuid4.MAX(); // $ExpectType Uuid4
Uuid4.MIN(); // $ExpectType Uuid4
Uuid4.construct(bytes); // $ExpectType Uuid4
Uuid4.fromCanonical(encoded_id); // $ExpectType Uuid4
Uuid4.fromCanonicalTrusted(encoded_id); // $ExpectType Uuid4
Uuid4.fromRaw(encoded_id); // $ExpectType Uuid4
Uuid4.fromRawTrusted(encoded_id); // $ExpectType Uuid4
Uuid4.generate(); // $ExpectType Uuid4
Uuid4.generate({}); // $ExpectType Uuid4
Uuid4.isCanonical(encoded_id); // $ExpectType boolean
Uuid4.isRaw(encoded_id); // $ExpectType boolean
Uuid4.name; // $ExpectType string
Uuid4.type; // $ExpectType ConstructorOf<Uuid4>
Uuid4.toCanonical(uuid_4); // $ExpectType string
Uuid4.toRaw(uuid_4); // $ExpectType string

Uuid6.MAX(); // $ExpectType Uuid6
Uuid6.MIN(); // $ExpectType Uuid6
Uuid6.construct(bytes); // $ExpectType Uuid6
Uuid6.fromCanonical(encoded_id); // $ExpectType Uuid6
Uuid6.fromCanonicalTrusted(encoded_id); // $ExpectType Uuid6
Uuid6.fromRaw(encoded_id); // $ExpectType Uuid6
Uuid6.fromRawTrusted(encoded_id); // $ExpectType Uuid6
Uuid6.generate(); // $ExpectType Uuid6
Uuid6.generate({ node, time: now }); // $ExpectType Uuid6
Uuid6.generate({}); // $ExpectType Uuid6
Uuid6.isCanonical(encoded_id); // $ExpectType boolean
Uuid6.isRaw(encoded_id); // $ExpectType boolean
Uuid6.name; // $ExpectType string
Uuid6.type; // $ExpectType ConstructorOf<Uuid6>
Uuid6.toCanonical(uuid_6); // $ExpectType string
Uuid6.toRaw(uuid_6); // $ExpectType string

UuidNil.MAX(); // $ExpectType UuidNil
UuidNil.MIN(); // $ExpectType UuidNil
UuidNil.construct(bytes); // $ExpectType UuidNil
UuidNil.fromCanonical(encoded_id); // $ExpectType UuidNil
UuidNil.fromCanonicalTrusted(encoded_id); // $ExpectType UuidNil
UuidNil.fromRaw(encoded_id); // $ExpectType UuidNil
UuidNil.fromRawTrusted(encoded_id); // $ExpectType UuidNil
UuidNil.generate(); // $ExpectType UuidNil
UuidNil.generate({}); // $ExpectType UuidNil
UuidNil.isCanonical(encoded_id); // $ExpectType boolean
UuidNil.isRaw(encoded_id); // $ExpectType boolean
UuidNil.name; // $ExpectType string
UuidNil.type; // $ExpectType ConstructorOf<UuidNil>
UuidNil.toCanonical(uuid_nil); // $ExpectType string
UuidNil.toRaw(uuid_nil); // $ExpectType string

ulid + ''; // $ExpectType string
ulid.bytes; // $ExpectType Uint8Array
ulid.clone(); // $ExpectType Ulid
ulid.compare(ulid); // $ExpectType number
ulid.equal(ulid); // $ExpectType boolean
ulid.time; // $ExpectType Date
ulid.toCanonical(); // $ExpectType string
ulid.toRaw(); // $ExpectType string
ulid instanceof Ulid.type; // $ExpectType boolean

ulid_monotonic + ''; // $ExpectType string
ulid_monotonic.bytes; // $ExpectType Uint8Array
ulid_monotonic.clone(); // $ExpectType UlidMonotonic
ulid_monotonic.compare(ulid_monotonic); // $ExpectType number
ulid_monotonic.equal(ulid_monotonic); // $ExpectType boolean
ulid_monotonic.time; // $ExpectType Date
ulid_monotonic.toCanonical(); // $ExpectType string
ulid_monotonic.toRaw(); // $ExpectType string
ulid_monotonic instanceof UlidMonotonic.type; // $ExpectType boolean

uuid_1 + ''; // $ExpectType string
uuid_1.bytes; // $ExpectType Uint8Array
uuid_1.clock_sequence; // $ExpectType number
uuid_1.clone(); // $ExpectType Uuid1
uuid_1.compare(uuid_1); // $ExpectType number
uuid_1.equal(uuid_1); // $ExpectType boolean
uuid_1.hires_time; // $ExpectType number
uuid_1.node; // $ExpectType Uint8Array
uuid_1.time; // $ExpectType Date
uuid_1.toCanonical(); // $ExpectType string
uuid_1.toRaw(); // $ExpectType string
uuid_1.variant; // $ExpectType number
uuid_1.version; // $ExpectType number
uuid_1 instanceof Uuid1.type; // $ExpectType boolean

uuid_4 + ''; // $ExpectType string
uuid_4.bytes; // $ExpectType Uint8Array
uuid_4.clone(); // $ExpectType Uuid4
uuid_4.compare(uuid_4); // $ExpectType number
uuid_4.equal(uuid_4); // $ExpectType boolean
uuid_4.toCanonical(); // $ExpectType string
uuid_4.toRaw(); // $ExpectType string
uuid_4.variant; // $ExpectType number
uuid_4.version; // $ExpectType number
uuid_4 instanceof Uuid4.type; // $ExpectType boolean

uuid_6 + ''; // $ExpectType string
uuid_6.bytes; // $ExpectType Uint8Array
uuid_6.clock_sequence; // $ExpectType number
uuid_6.clone(); // $ExpectType Uuid6
uuid_6.compare(uuid_6); // $ExpectType number
uuid_6.equal(uuid_6); // $ExpectType boolean
uuid_6.hires_time; // $ExpectType number
uuid_6.node; // $ExpectType Uint8Array
uuid_6.time; // $ExpectType Date
uuid_6.toCanonical(); // $ExpectType string
uuid_6.toRaw(); // $ExpectType string
uuid_6.variant; // $ExpectType number
uuid_6.version; // $ExpectType number
uuid_6 instanceof Uuid6.type; // $ExpectType boolean

uuid_nil + ''; // $ExpectType string
uuid_nil.bytes; // $ExpectType Uint8Array
uuid_nil.clone(); // $ExpectType UuidNil
uuid_nil.compare(uuid_nil); // $ExpectType number
uuid_nil.equal(uuid_nil); // $ExpectType boolean
uuid_nil.toCanonical(); // $ExpectType string
uuid_nil.toRaw(); // $ExpectType string
uuid_nil.variant; // $ExpectType number
uuid_nil.version; // $ExpectType number
uuid_nil instanceof UuidNil.type; // $ExpectType boolean

idCompare(ulid, uuid_nil); // $expectType number
idEqual(ulid, uuid_nil); // $expectType boolean

new Error() instanceof Exception.Id128Error; // $ExpectType boolean
new Error() instanceof Exception.ClockSequenceOverflow; // $ExpectType boolean
new Error() instanceof Exception.InvalidBytes; // $ExpectType boolean
new Error() instanceof Exception.InvalidEncoding; // $ExpectType boolean
new Error() instanceof Exception.InvalidEpoch; // $ExpectType boolean
new Error() instanceof Exception.UnsupportedVersion; // $ExpectType boolean


================================================
FILE: types/tsconfig.json
================================================
{
	"compilerOptions": {
		"lib": ["es6"],
		"module": "commonjs",
		"noEmit": true,
		"noImplicitAny": true,
		"noImplicitThis": true,
		"strictBindCallApply": true,
		"strictFunctionTypes": true,
		"strictNullChecks": true,
		"baseUrl": ".",
		"paths": { "id128": ["."] }
	}
}


================================================
FILE: types/tslint.json
================================================
{
	"extends": "dtslint/dtslint.json",
	"rules": {
		"indent": [true, "tabs", 2],
		"no-empty-interface": false
	}
}


================================================
FILE: utils.js
================================================
const { Ulid } = require('./src/id/ulid');
const { UlidMonotonic } = require('./src/id/ulid-monotonic');
const { Uuid } = require('./src/id/uuid');
const { Uuid1 } = require('./src/id/uuid-1');
const { Uuid4 } = require('./src/id/uuid-4');
const { Uuid6 } = require('./src/id/uuid-6');
const { UuidNil } = require('./src/id/uuid-nil');

const Crockford32Coder = require('./src/coder/crockford32');
const HexCoder = require('./src/coder/hex');
const UuidCoder = require('./src/coder/uuid');

const { IdFactory } = require('./src/factory/id');
const { VersionedIdFactory } = require('./src/factory/versioned-id');
const Exception = require('./src/common/exception');

module.exports = {
	Coder: {
		Crockford32: Crockford32Coder,
		Hex: HexCoder,
		Uuid: UuidCoder,
	},
	Exception,
	Id: {
		Ulid,
		UlidMonotonic,
		Uuid,
		Uuid1,
		Uuid4,
		Uuid6,
		UuidNil,
	},
	IdFactory,
	VersionedIdFactory,
};
Download .txt
gitextract_yj1hrjym/

├── .eslintrc.js
├── .gitignore
├── CHANGES
├── LICENSE
├── README.md
├── benchmark/
│   ├── basics.js
│   ├── factory-uuid.js
│   ├── memory.js
│   └── stats.js
├── index.d.ts
├── index.js
├── package.json
├── src/
│   ├── coder/
│   │   ├── base.js
│   │   ├── crockford32.js
│   │   ├── hex.js
│   │   └── uuid.js
│   ├── common/
│   │   ├── byte-array.js
│   │   ├── epoch-converter.js
│   │   ├── exception.js
│   │   ├── fake-machine.js
│   │   ├── machine.js
│   │   ├── random-bytes-browser.js
│   │   └── random-bytes.js
│   ├── factory/
│   │   ├── id.js
│   │   └── versioned-id.js
│   └── id/
│       ├── base.js
│       ├── ulid-monotonic.js
│       ├── ulid.js
│       ├── uuid-1.js
│       ├── uuid-4.js
│       ├── uuid-6.js
│       ├── uuid-nil.js
│       └── uuid.js
├── test/
│   ├── coder/
│   │   ├── crockford32.js
│   │   ├── hex.js
│   │   ├── shared.js
│   │   └── uuid.js
│   ├── common/
│   │   ├── byte-array.js
│   │   ├── epoch-converter.js
│   │   ├── fake-machine.js
│   │   └── machine.js
│   ├── factory/
│   │   ├── id.js
│   │   └── versioned-id.js
│   ├── id/
│   │   ├── shared.js
│   │   ├── ulid-monotonic.js
│   │   ├── ulid.js
│   │   ├── uuid-1.js
│   │   ├── uuid-4.js
│   │   ├── uuid-6.js
│   │   └── uuid-nil.js
│   └── id128.js
├── types/
│   ├── test.ts
│   ├── tsconfig.json
│   └── tslint.json
└── utils.js
Download .txt
SYMBOL INDEX (260 symbols across 34 files)

FILE: index.d.ts
  type ConstructorOf (line 6) | interface ConstructorOf<C> {
  type Id (line 12) | interface Id {
  type Uuid (line 25) | interface Uuid extends Id {
  type Ulid (line 30) | interface Ulid extends Id {
  type UlidMonotonic (line 34) | interface UlidMonotonic extends Id {
  type Uuid1 (line 38) | interface Uuid1 extends Uuid {
  type Uuid4 (line 45) | interface Uuid4 extends Uuid {}
  type Uuid6 (line 47) | interface Uuid6 extends Uuid {
  type UuidNil (line 54) | interface UuidNil extends Uuid {}
  type IdFactory (line 58) | interface IdFactory<T> {
  type VersionedIdFactory (line 82) | interface VersionedIdFactory<T> extends IdFactory<T> {
  type NodeOption (line 89) | interface NodeOption {
  type TimeOption (line 93) | interface TimeOption {
  type VersionOption (line 97) | interface VersionOption {
  type AnyIdFactory (line 101) | type AnyIdFactory = IdFactory<Id>;
  type UlidFactory (line 103) | interface UlidFactory extends IdFactory<Ulid> {
  type UlidMonotonicFactory (line 107) | interface UlidMonotonicFactory extends IdFactory<UlidMonotonic> {
  type UuidFactory (line 111) | interface UuidFactory extends VersionedIdFactory<Uuid> {
  type Uuid1Factory (line 115) | interface Uuid1Factory extends IdFactory<Uuid1> {
  type Uuid4Factory (line 119) | interface Uuid4Factory extends IdFactory<Uuid4> {
  type Uuid6Factory (line 123) | interface Uuid6Factory extends IdFactory<Uuid6> {
  type UuidNilFactory (line 127) | interface UuidNilFactory extends IdFactory<UuidNil> {
  type Id128Error (line 134) | interface Id128Error extends Function {
  type ClockSequenceOverflow (line 139) | interface ClockSequenceOverflow extends Id128Error {}
  type InvalidBytes (line 140) | interface InvalidBytes extends Id128Error {}
  type InvalidEncoding (line 141) | interface InvalidEncoding extends Id128Error {}
  type InvalidEpoch (line 142) | interface InvalidEpoch extends Id128Error {}
  type UnsupportedVersion (line 143) | interface UnsupportedVersion extends Id128Error {}

FILE: src/coder/base.js
  class BaseCoder (line 10) | class BaseCoder {
    method constructor (line 11) | constructor({
    method decode (line 17) | decode(encoding) {
    method decodeTrusted (line 26) | decodeTrusted(encoding) { return ByteArray.generateRandomFilled() }
    method encode (line 28) | encode(bytes) {
    method encodeTrusted (line 38) | encodeTrusted(bytes) { return '' }
    method isValidBytes (line 40) | isValidBytes(bytes) {
    method isValidEncoding (line 46) | isValidEncoding(encoding) {

FILE: src/coder/crockford32.js
  constant ALPHABET (line 5) | const ALPHABET = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';
  constant MAX_QUINTET (line 6) | const MAX_QUINTET = 0b11111;
  constant CHAR_TO_QUINTET (line 8) | const CHAR_TO_QUINTET = Array.from(ALPHABET).reduce(
  constant QUINTET_TO_CHAR (line 21) | const QUINTET_TO_CHAR = Array.from(ALPHABET);
  function _charToQuintet (line 23) | function _charToQuintet(chr) {
  function _quintetToChar (line 27) | function _quintetToChar(quintet) {
  class Crockford32Coder (line 31) | class Crockford32Coder extends BaseCoder {
    method constructor (line 32) | constructor() {
    method decodeTrusted (line 38) | decodeTrusted(encoding) {
    method encodeTrusted (line 70) | encodeTrusted(bytes) {

FILE: src/coder/hex.js
  constant ALPHABET (line 5) | const ALPHABET = '0123456789ABCDEF';
  constant BYTE_TO_HEX (line 7) | const BYTE_TO_HEX = Array
  constant HEX_TO_BYTE (line 15) | const HEX_TO_BYTE = Array.from(ALPHABET).reduce(
  class HexCoder (line 23) | class HexCoder extends BaseCoder {
    method constructor (line 24) | constructor() {
    method decodeTrusted (line 30) | decodeTrusted(encoding) {
    method encodeTrusted (line 54) | encodeTrusted(bytes) {

FILE: src/coder/uuid.js
  constant ALPHABET (line 5) | const ALPHABET = '0123456789ABCDEF';
  constant BYTE_TO_HEX (line 7) | const BYTE_TO_HEX = Array
  constant HEX_TO_BYTE (line 15) | const HEX_TO_BYTE = Array.from(ALPHABET).reduce(
  class UuidCoder (line 23) | class UuidCoder extends BaseCoder {
    method constructor (line 24) | constructor() {
    method decodeTrusted (line 30) | decodeTrusted(encoding) {
    method encodeTrusted (line 56) | encodeTrusted(bytes) {

FILE: src/common/byte-array.js
  constant MAX_BYTES (line 3) | const MAX_BYTES = 16;
  class ByteArray (line 5) | class ByteArray {
    method compare (line 6) | compare(lhs, rhs) {
    method generateOneFilled (line 13) | generateOneFilled() {
    method generateRandomFilled (line 17) | generateRandomFilled() {
    method generateZeroFilled (line 21) | generateZeroFilled() {

FILE: src/common/epoch-converter.js
  constant MIN_MS (line 3) | const MIN_MS = 0;
  constant MAX_MS (line 4) | const MAX_MS = Math.pow(2, 48);
  class EpochConverter (line 6) | class EpochConverter {
    method fromEpoch (line 7) | fromEpoch(origin_ms, epoch_ms) {
    method toEpoch (line 11) | toEpoch(origin_ms, time = null) {

FILE: src/common/exception.js
  class Id128Error (line 1) | class Id128Error extends Error {
    method name (line 2) | get name() { return this.constructor.name }
  class ClockSequenceOverflow (line 5) | class ClockSequenceOverflow extends Id128Error {}
  class InvalidBytes (line 6) | class InvalidBytes extends Id128Error {}
  class InvalidEncoding (line 7) | class InvalidEncoding extends Id128Error {}
  class InvalidEpoch (line 8) | class InvalidEpoch extends Id128Error {}
  class UnsupportedVersion (line 9) | class UnsupportedVersion extends Id128Error {}

FILE: src/common/fake-machine.js
  class FakeMachine (line 5) | class FakeMachine {
    method constructor (line 6) | constructor() {
    method mac_address (line 10) | get mac_address() {
    method reset (line 21) | reset() {

FILE: src/common/machine.js
  class Machine (line 6) | class Machine {
    method constructor (line 7) | constructor() {
    method mac_address (line 11) | get mac_address() {
    method reset (line 32) | reset() {

FILE: src/common/random-bytes-browser.js
  function randomBytes (line 3) | function randomBytes(size) {

FILE: src/common/random-bytes.js
  constant BUFFER_SIZE (line 3) | const BUFFER_SIZE = 4096 /* typical page size */ - 96 /* Empty buffer ov...
  function randomBytes (line 8) | function randomBytes(size) {

FILE: src/factory/id.js
  class IdFactory (line 7) | class IdFactory {
    method constructor (line 8) | constructor({
    method name (line 26) | get name() { return this[_id].name; }
    method type (line 27) | get type() { return this[_id][Symbol.species]; }
    method construct (line 31) | construct(bytes) {
    method generate (line 35) | generate() {
    method MIN (line 39) | MIN() {
    method MAX (line 43) | MAX() {
    method fromCanonical (line 49) | fromCanonical(canonical) {
    method fromCanonicalTrusted (line 53) | fromCanonicalTrusted(canonical) {
    method fromRaw (line 57) | fromRaw(raw) {
    method fromRawTrusted (line 61) | fromRawTrusted(raw) {
    method toCanonical (line 65) | toCanonical(id) {
    method toRaw (line 69) | toRaw(id) {
    method compare (line 75) | compare(lhs, rhs) {
    method equal (line 80) | equal(lhs, rhs) {
    method isCanonical (line 87) | isCanonical(canonical) {
    method isRaw (line 91) | isRaw(raw) {

FILE: src/factory/versioned-id.js
  function detect (line 8) | function detect(factory, { version } = {}) {
  class VersionedIdFactory (line 15) | class VersionedIdFactory extends IdFactory {
    method constructor (line 16) | constructor({
    method versioned_ids (line 40) | get versioned_ids() {
    method construct (line 46) | construct(bytes) {
    method generate (line 59) | generate() {
    method MIN (line 63) | MIN() {
    method MAX (line 67) | MAX() {

FILE: src/id/base.js
  class BaseId (line 7) | class BaseId {
    method constructor (line 10) | constructor(bytes) {
    method clone (line 14) | clone() {
    method bytes (line 20) | get bytes() {
    method compare (line 30) | compare(rhs) {
    method equal (line 34) | equal(rhs) {
  method [Symbol.toStringTag] (line 24) | get [Symbol.toStringTag]() {

FILE: src/id/ulid-monotonic.js
  constant TIME_OFFSET (line 6) | const TIME_OFFSET = 0;
  constant CLOCK_SEQUENCE_OFFSET (line 7) | const CLOCK_SEQUENCE_OFFSET = 6;
  constant RANDOM_OFFSET (line 8) | const RANDOM_OFFSET = 8;
  constant EPOCH_ORIGIN_MS (line 10) | const EPOCH_ORIGIN_MS = 0;
  function incrementClockSequence (line 15) | function incrementClockSequence(bytes) {
  function reserveClockSequence (line 34) | function reserveClockSequence(bytes) {
  function restoreClockSequence (line 38) | function restoreClockSequence(bytes) {
  class UlidMonotonic (line 44) | class UlidMonotonic extends Ulid {
    method reset (line 45) | static reset() {
    method generate (line 52) | static generate({ time } = {}) {

FILE: src/id/ulid.js
  constant TIME_OFFSET (line 5) | const TIME_OFFSET = 0;
  constant EPOCH_ORIGIN_MS (line 7) | const EPOCH_ORIGIN_MS = 0;
  constant UINT32_RADIX (line 8) | const UINT32_RADIX = Math.pow(2, 32);
  constant UINT8_MAX (line 9) | const UINT8_MAX = 0b11111111;
  function setTime (line 11) | function setTime(time, bytes) {
  class Ulid (line 24) | class Ulid extends BaseId {
    method generate (line 28) | static generate({ time } = {}) {
    method MIN (line 38) | static MIN() {
    method MAX (line 42) | static MAX() {
    method time (line 48) | get time() {

FILE: src/id/uuid-1.js
  constant TIME_OFFSET (line 12) | const TIME_OFFSET = 0;
  constant HIRES_TIME_OFFSET (line 13) | const HIRES_TIME_OFFSET = 2;
  constant CLOCK_SEQUENCE_OFFSET (line 14) | const CLOCK_SEQUENCE_OFFSET = 8;
  constant NODE_OFFSET (line 15) | const NODE_OFFSET = 10;
  constant CLOCK_SEQUENCE_RADIX (line 17) | const CLOCK_SEQUENCE_RADIX = Math.pow(2, 14);
  constant EPOCH_ORIGIN_MS (line 18) | const EPOCH_ORIGIN_MS = Date.parse('1582-10-15Z');
  constant HIRES_TIME_RADIX (line 19) | const HIRES_TIME_RADIX = Math.pow(2, 12);
  constant TIME_LOW_MS_RADIX (line 20) | const TIME_LOW_MS_RADIX = Math.pow(2, 20);
  constant UINT8_MAX (line 21) | const UINT8_MAX = 0b11111111;
  function incrementClockSequence (line 27) | function incrementClockSequence() {
  function setClockSequence (line 31) | function setClockSequence(time, bytes) {
  function setNode (line 49) | function setNode(node, bytes) {
  function setTime (line 55) | function setTime(time, bytes) {
  class Uuid1 (line 77) | class Uuid1 extends Uuid {
    method VARIANT (line 78) | static get VARIANT() { return 1 }
    method VERSION (line 79) | static get VERSION() { return 1 }
    method reset (line 81) | static reset() {
    method generate (line 89) | static generate({ node, time } = {}) {
    method clock_sequence (line 109) | get clock_sequence() {
    method hires_time (line 117) | get hires_time() {
    method node (line 125) | get node() {
    method time (line 129) | get time() {

FILE: src/id/uuid-4.js
  class Uuid4 (line 10) | class Uuid4 extends Uuid {
    method VARIANT (line 11) | static get VARIANT() { return 1 }
    method VERSION (line 12) | static get VERSION() { return 4 }
    method generate (line 14) | static generate() {

FILE: src/id/uuid-6.js
  constant TIME_OFFSET (line 12) | const TIME_OFFSET = 0;
  constant HIRES_TIME_OFFSET (line 13) | const HIRES_TIME_OFFSET = 6;
  constant CLOCK_SEQUENCE_OFFSET (line 14) | const CLOCK_SEQUENCE_OFFSET = 8;
  constant NODE_OFFSET (line 15) | const NODE_OFFSET = 10;
  constant CLOCK_SEQUENCE_RADIX (line 17) | const CLOCK_SEQUENCE_RADIX = Math.pow(2, 14);
  constant EPOCH_ORIGIN_MS (line 18) | const EPOCH_ORIGIN_MS = Date.parse('1582-10-15Z');
  constant HIRES_TIME_RADIX (line 19) | const HIRES_TIME_RADIX = Math.pow(2, 12);
  constant UINT32_RADIX (line 20) | const UINT32_RADIX = Math.pow(2, 32);
  constant UINT8_MAX (line 21) | const UINT8_MAX = 0b11111111;
  function incrementClockSequence (line 27) | function incrementClockSequence() {
  function setClockSequence (line 31) | function setClockSequence(time, bytes) {
  function setNode (line 49) | function setNode(node, bytes) {
  function setTime (line 55) | function setTime(time, bytes) {
  class Uuid6 (line 76) | class Uuid6 extends Uuid {
    method VARIANT (line 77) | static get VARIANT() { return 1 }
    method VERSION (line 78) | static get VERSION() { return 6 }
    method reset (line 80) | static reset() {
    method generate (line 88) | static generate({ node, time } = {}) {
    method clock_sequence (line 108) | get clock_sequence() {
    method hires_time (line 116) | get hires_time() {
    method node (line 124) | get node() {
    method time (line 128) | get time() {

FILE: src/id/uuid-nil.js
  class UuidNil (line 10) | class UuidNil extends Uuid {
    method VARIANT (line 11) | static get VARIANT() { return 0 }
    method VERSION (line 12) | static get VERSION() { return 0 }
    method generate (line 14) | static generate() {
    method MAX (line 23) | static MAX() {

FILE: src/id/uuid.js
  constant VARIANT_BYTE (line 6) | const VARIANT_BYTE = 8;
  constant VERSION_BYTE (line 7) | const VERSION_BYTE = 6;
  function setVariant (line 9) | function setVariant(variant, bytes) {
  function setVersion (line 14) | function setVersion(version, bytes) {
  class Uuid (line 19) | class Uuid extends BaseId {
    method MIN (line 20) | static MIN() {
    method MAX (line 29) | static MAX() {
    method variant (line 38) | get variant() {
    method version (line 49) | get version() {

FILE: test/coder/shared.js
  constant BYTES (line 13) | const BYTES = Object.freeze({
  constant ALPHABET (line 19) | const ALPHABET = Object.freeze({
  function describeNamespace (line 27) | function describeNamespace(described_namespace, encoding_any) {
  function makeBytes (line 32) | function makeBytes(length) {
  function makeString (line 36) | function makeString(length, alphabet) {
  function randomChar (line 41) | function randomChar(alphabet) {
  function assertDecode (line 48) | function assertDecode({
  function assertEncode (line 72) | function assertEncode({

FILE: test/coder/uuid.js
  function makeUuid (line 17) | function makeUuid(alphabet) {

FILE: test/common/byte-array.js
  function assertByteArray (line 7) | function assertByteArray(subject) {

FILE: test/common/machine.js
  function assertFaked (line 18) | function assertFaked() {

FILE: test/factory/id.js
  method generate (line 8) | static generate() { return new this(`id_${Date.now()}`) }
  method MIN (line 9) | static MIN() { return new this('\x00') }
  method MAX (line 10) | static MAX() { return new this('\xFF') }
  method constructor (line 11) | constructor(value) { this._bytes = value }
  method bytes (line 12) | get bytes() { return this._bytes }
  function assertDecoder (line 34) | function assertDecoder(method, encoding) {
  function assertEncoder (line 47) | function assertEncoder(method, pattern) {
  function assertGenerator (line 57) | function assertGenerator(method) {
  function assertInjectsInstanceMethod (line 74) | function assertInjectsInstanceMethod(injected_method, generator) {
  function assertVerifier (line 91) | function assertVerifier(method, validEncoding) {

FILE: test/factory/versioned-id.js
  method VERSION (line 9) | static get VERSION() { return version }
  method generate (line 10) | static generate() { return new this(`id_${Date.now()} vrsn:${this.VERSIO...
  method MIN (line 11) | static MIN() { return new this(`\x00 vrsn:${this.VERSION}`) }
  method MAX (line 12) | static MAX() { return new this(`\xFF vrsn:${this.VERSION}`) }
  method constructor (line 13) | constructor(value) { this._bytes = value }
  method bytes (line 14) | get bytes() { return this._bytes }
  method version (line 15) | get version() { return /vrsn:(\w+)/.exec(this._bytes)[1] }
  function assertDecoder (line 44) | function assertDecoder(method, encoding) {
  function assertEncoder (line 62) | function assertEncoder(method, pattern) {
  function assertGenerator (line 72) | function assertGenerator(method) {
  function assertInjectsInstanceMethod (line 93) | function assertInjectsInstanceMethod(injected_method, generator) {

FILE: test/id/shared.js
  function assertAccessorBytes (line 11) | function assertAccessorBytes(described_class) {
  function assertAccessorNode (line 25) | function assertAccessorNode(described_class) {
  function assertAccessorTime (line 40) | function assertAccessorTime(described_class, labeled_times) {
  function assertCompareDemonstratesTotalOrder (line 52) | function assertCompareDemonstratesTotalOrder(labeled_ids) {
  function assertDebuggable (line 95) | function assertDebuggable(described_class) {
  function assertEqualDemonstratesSameness (line 105) | function assertEqualDemonstratesSameness(labeled_ids) {
  function assertGenerateBasics (line 129) | function assertGenerateBasics(described_class) {
  function assertUuidVariantVersion (line 147) | function assertUuidVariantVersion(described_class, variant, version) {

FILE: test/id/ulid-monotonic.js
  constant MAX_TIME (line 20) | const MAX_TIME = new Date(Math.pow(2, 48) - 1);
  constant MIN_TIME (line 21) | const MIN_TIME = new Date(0);

FILE: test/id/ulid.js
  constant MAX_TIME (line 18) | const MAX_TIME = new Date(Math.pow(2, 48) - 1);
  constant MIN_TIME (line 19) | const MIN_TIME = new Date(0);

FILE: test/id/uuid-1.js
  constant ORIGIN (line 20) | const ORIGIN = Date.parse('1582-10-15Z');
  constant MAX_TIME (line 21) | const MAX_TIME = new Date(Math.pow(2, 48) - 1 + ORIGIN);
  constant MIN_TIME (line 22) | const MIN_TIME = new Date(ORIGIN);
  function clockOverflow (line 70) | function clockOverflow(time) {
  function hiresOverflow (line 93) | function hiresOverflow(time) {

FILE: test/id/uuid-6.js
  constant ORIGIN (line 20) | const ORIGIN = Date.parse('1582-10-15Z');
  constant MAX_TIME (line 21) | const MAX_TIME = new Date(Math.pow(2, 48) - 1 + ORIGIN);
  constant MIN_TIME (line 22) | const MIN_TIME = new Date(ORIGIN);
  function clockOverflow (line 70) | function clockOverflow(time) {
  function hiresOverflow (line 93) | function hiresOverflow(time) {

FILE: test/id128.js
  function assertDebuggable (line 7) | function assertDebuggable(id_name, generator) {
  function assertValidId128 (line 17) | function assertValidId128(id_name, factory, id_class, generator_args = {...
Condensed preview — 55 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (163K chars).
[
  {
    "path": ".eslintrc.js",
    "chars": 9276,
    "preview": "/* eslint max-lines: \"off\" */\n\nmodule.exports = {\n\tenv: {\n\t\tbrowser: true,\n\t\tcommonjs: true,\n\t\tes6: true,\n\t\tnode: true,\n"
  },
  {
    "path": ".gitignore",
    "chars": 44,
    "preview": ".node-version\nnode_modules/\nyarn.lock\n*.swp\n"
  },
  {
    "path": "CHANGES",
    "chars": 998,
    "preview": "- 0.1.0 : Move extraneous exports from index.js into utils.js.\n- 0.2.0 : Add browser support for Browserify/Webpack.\n- 0"
  },
  {
    "path": "LICENSE",
    "chars": 1075,
    "preview": "Copyright 2018 Aaron Cohen <aarondcohen@gmail.com>\n\nPermission is hereby granted, free of charge, to any person obtainin"
  },
  {
    "path": "README.md",
    "chars": 28939,
    "preview": "# Id128\n\nGenerate 128-bit unique identifiers for various specifications.  In particular:\n- [ULID](#ulid)\n- [Monotonic UL"
  },
  {
    "path": "benchmark/basics.js",
    "chars": 1447,
    "preview": "const Benchmarkify = require('benchmarkify');\nconst Id128 = require('../');\nconst { IdFactory } = require('../utils');\nc"
  },
  {
    "path": "benchmark/factory-uuid.js",
    "chars": 1212,
    "preview": "const Benchmarkify = require('benchmarkify');\nconst Id128 = require('../');\n\nconst benchmark = new Benchmarkify(\"UUID Pr"
  },
  {
    "path": "benchmark/memory.js",
    "chars": 621,
    "preview": "const ByteArray = require('common/byte-array');\n\nlet count = 0\nlet result = null;\nlet now = new Date;\ntry {\n\twhile (++co"
  },
  {
    "path": "benchmark/stats.js",
    "chars": 1805,
    "preview": "const Benchmarkify = require('benchmarkify');\nconst Id128 = require('../');\nconst { Uuid } = Id128;\n\nconst benchmark = n"
  },
  {
    "path": "index.d.ts",
    "chars": 3916,
    "preview": "/* eslint-disable @typescript-eslint/no-empty-interface */\nexport {};\n\n// Utility Types\n\ninterface ConstructorOf<C> {\n\tn"
  },
  {
    "path": "index.js",
    "chars": 1350,
    "preview": "const { Ulid } = require('./src/id/ulid');\nconst { UlidMonotonic } = require('./src/id/ulid-monotonic');\nconst { Uuid } "
  },
  {
    "path": "package.json",
    "chars": 1358,
    "preview": "{\n\t\"name\": \"id128\",\n\t\"description\": \"Collection of 128-bit Id generators\",\n\t\"version\": \"1.6.6\",\n\t\"author\": \"Aaron Cohen "
  },
  {
    "path": "src/coder/base.js",
    "chars": 1100,
    "preview": "'use strict';\n\nconst {\n\tInvalidEncoding,\n\tInvalidBytes,\n} = require('../common/exception');\n\nconst _valid_encoding_patte"
  },
  {
    "path": "src/coder/crockford32.js",
    "chars": 3116,
    "preview": "'use strict';\n\nconst { BaseCoder } = require('./base');\n\nconst ALPHABET = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';\nconst MAX_"
  },
  {
    "path": "src/coder/hex.js",
    "chars": 1167,
    "preview": "'use strict';\n\nconst { BaseCoder } = require('./base');\n\nconst ALPHABET = '0123456789ABCDEF';\n\nconst BYTE_TO_HEX = Array"
  },
  {
    "path": "src/coder/uuid.js",
    "chars": 1652,
    "preview": "'use strict';\n\nconst { BaseCoder } = require('./base');\n\nconst ALPHABET = '0123456789ABCDEF';\n\nconst BYTE_TO_HEX = Array"
  },
  {
    "path": "src/common/byte-array.js",
    "chars": 515,
    "preview": "const { randomBytes } = require('./random-bytes');\n\nconst MAX_BYTES = 16;\n\nclass ByteArray {\n\tcompare(lhs, rhs) {\n\t\tcons"
  },
  {
    "path": "src/common/epoch-converter.js",
    "chars": 834,
    "preview": "const { InvalidEpoch } = require('./exception');\n\nconst MIN_MS = 0;\nconst MAX_MS = Math.pow(2, 48);\n\nclass EpochConverte"
  },
  {
    "path": "src/common/exception.js",
    "chars": 433,
    "preview": "class Id128Error extends Error {\n\tget name() { return this.constructor.name }\n}\n\nclass ClockSequenceOverflow extends Id1"
  },
  {
    "path": "src/common/fake-machine.js",
    "chars": 437,
    "preview": "const { randomBytes } = require('./random-bytes');\n\nconst _mac_address = Symbol('mac-address');\n\nclass FakeMachine {\n\tco"
  },
  {
    "path": "src/common/machine.js",
    "chars": 731,
    "preview": "const Os = require('os');\nconst { randomBytes } = require('./random-bytes');\n\nconst _mac_address = Symbol('mac-address')"
  },
  {
    "path": "src/common/random-bytes-browser.js",
    "chars": 180,
    "preview": "const Crypto = self.crypto;\n\nfunction randomBytes(size) {\n\tconst bytes = new Uint8Array(size);\n\tCrypto.getRandomValues(b"
  },
  {
    "path": "src/common/random-bytes.js",
    "chars": 388,
    "preview": "const Crypto = require('crypto');\n\nconst BUFFER_SIZE = 4096 /* typical page size */ - 96 /* Empty buffer overhead */;\n\nc"
  },
  {
    "path": "src/factory/id.js",
    "chars": 1928,
    "preview": "'use strict';\n\nconst _id = Symbol('id');\nconst _canonical_coder = Symbol('canonical_coder');\nconst _raw_coder = Symbol('"
  },
  {
    "path": "src/factory/versioned-id.js",
    "chars": 1362,
    "preview": "'use strict';\n\nconst { IdFactory } = require('./id');\nconst { UnsupportedVersion } = require('../common/exception');\n\nco"
  },
  {
    "path": "src/id/base.js",
    "chars": 542,
    "preview": "'use strict';\n\nconst ByteArray = require('../common/byte-array');\n\nconst _bytes = Symbol('bytes');\n\nclass BaseId {\n\t//Co"
  },
  {
    "path": "src/id/ulid-monotonic.js",
    "chars": 1481,
    "preview": "const { Ulid, setTime } = require('./ulid');\nconst ByteArray = require('../common/byte-array');\nconst EpochConverter = r"
  },
  {
    "path": "src/id/ulid.js",
    "chars": 1546,
    "preview": "const ByteArray = require('../common/byte-array');\nconst EpochConverter = require('../common/epoch-converter');\nconst { "
  },
  {
    "path": "src/id/uuid-1.js",
    "chars": 3631,
    "preview": "'use strict';\n\nconst ByteArray = require('../common/byte-array');\nconst EpochConverter = require('../common/epoch-conver"
  },
  {
    "path": "src/id/uuid-4.js",
    "chars": 430,
    "preview": "'use strict';\n\nconst ByteArray = require('../common/byte-array');\nconst {\n\tUuid,\n\tsetVariant,\n\tsetVersion,\n} = require('"
  },
  {
    "path": "src/id/uuid-6.js",
    "chars": 3477,
    "preview": "'use strict';\n\nconst ByteArray = require('../common/byte-array');\nconst EpochConverter = require('../common/epoch-conver"
  },
  {
    "path": "src/id/uuid-nil.js",
    "chars": 596,
    "preview": "'use strict';\n\nconst ByteArray = require('../common/byte-array');\nconst {\n\tUuid,\n\tsetVariant,\n\tsetVersion,\n} = require('"
  },
  {
    "path": "src/id/uuid.js",
    "chars": 1088,
    "preview": "'use strict';\n\nconst { BaseId } = require('./base');\nconst ByteArray = require('../common/byte-array');\n\nconst VARIANT_B"
  },
  {
    "path": "test/coder/crockford32.js",
    "chars": 2224,
    "preview": "'use strict';\n\nconst { expect } = require('chai');\nconst {\n\tALPHABET,\n\tassertDecode,\n\tassertEncode,\n\tdescribeNamespace,\n"
  },
  {
    "path": "test/coder/hex.js",
    "chars": 1638,
    "preview": "'use strict';\n\nconst { expect } = require('chai');\nconst {\n\tALPHABET,\n\tassertDecode,\n\tassertEncode,\n\tdescribeNamespace,\n"
  },
  {
    "path": "test/coder/shared.js",
    "chars": 2860,
    "preview": "'use strict';\n\nconst { expect } = require('chai');\n\nconst ByteArray = require('common/byte-array');\nconst {\n\tInvalidByte"
  },
  {
    "path": "test/coder/uuid.js",
    "chars": 2135,
    "preview": "'use strict';\n\nconst { expect } = require('chai');\nconst {\n\tALPHABET,\n\tassertDecode,\n\tassertEncode,\n\tdescribeNamespace,\n"
  },
  {
    "path": "test/common/byte-array.js",
    "chars": 2423,
    "preview": "'use strict';\n\nconst { expect } = require('chai');\n\nconst described_namespace = require('common/byte-array');\n\nfunction "
  },
  {
    "path": "test/common/epoch-converter.js",
    "chars": 3039,
    "preview": "'use strict';\n\nconst { expect } = require('chai');\nconst { InvalidEpoch } = require('common/exception');\n\nconst describe"
  },
  {
    "path": "test/common/fake-machine.js",
    "chars": 906,
    "preview": "'use strict';\n\nconst { expect } = require('chai');\n\nconst described_singleton = require('common/fake-machine');\n\ndescrib"
  },
  {
    "path": "test/common/machine.js",
    "chars": 3238,
    "preview": "'use strict';\n\nconst { expect } = require('chai');\nconst Os = require('os') || {};\nconst Sinon = require('sinon');\nconst"
  },
  {
    "path": "test/factory/id.js",
    "chars": 4711,
    "preview": "'use strict';\n\nconst { expect } = require('chai');\n\nconst { IdFactory: described_class } = require('factory/id');\n\nconst"
  },
  {
    "path": "test/factory/versioned-id.js",
    "chars": 4914,
    "preview": "'use strict';\n\nconst { expect } = require('chai');\nconst { UnsupportedVersion } = require('common/exception');\n\nconst { "
  },
  {
    "path": "test/id/shared.js",
    "chars": 5270,
    "preview": "'use strict';\n\nconst { expect } = require('chai');\n\nconst ByteArray = require('common/byte-array');\nconst Machine = requ"
  },
  {
    "path": "test/id/ulid-monotonic.js",
    "chars": 4216,
    "preview": "'use strict';\n\nconst { expect } = require('chai');\nconst {\n\tassertAccessorBytes,\n\tassertCompareDemonstratesTotalOrder,\n\t"
  },
  {
    "path": "test/id/ulid.js",
    "chars": 2608,
    "preview": "'use strict';\n\nconst { expect } = require('chai');\nconst {\n\tassertAccessorBytes,\n\tassertAccessorTime,\n\tassertCompareDemo"
  },
  {
    "path": "test/id/uuid-1.js",
    "chars": 4867,
    "preview": "'use strict';\n\nconst { expect } = require('chai');\nconst {\n\tassertAccessorBytes,\n\tassertAccessorNode,\n\tassertAccessorTim"
  },
  {
    "path": "test/id/uuid-4.js",
    "chars": 1566,
    "preview": "'use strict';\n\nconst { expect } = require('chai');\nconst {\n\tassertAccessorBytes,\n\tassertCompareDemonstratesTotalOrder,\n\t"
  },
  {
    "path": "test/id/uuid-6.js",
    "chars": 4867,
    "preview": "'use strict';\n\nconst { expect } = require('chai');\nconst {\n\tassertAccessorBytes,\n\tassertAccessorNode,\n\tassertAccessorTim"
  },
  {
    "path": "test/id/uuid-nil.js",
    "chars": 2453,
    "preview": "'use strict';\n\nconst { expect } = require('chai');\nconst {\n\tassertAccessorBytes,\n\tassertDebuggable,\n\tassertUuidVariantVe"
  },
  {
    "path": "test/id128.js",
    "chars": 4571,
    "preview": "'use strict';\n\nconst { expect } = require('chai');\n\nconst Id128 = require('../');\n\nfunction assertDebuggable(id_name, ge"
  },
  {
    "path": "types/test.ts",
    "chars": 9943,
    "preview": "import {\n\tidCompare,\n\tidEqual,\n\tException,\n\tUlid,\n\tUlidMonotonic,\n\tUuid,\n\tUuid1,\n\tUuid4,\n\tUuid6,\n\tUuidNil,\n} from 'id128"
  },
  {
    "path": "types/tsconfig.json",
    "chars": 278,
    "preview": "{\n\t\"compilerOptions\": {\n\t\t\"lib\": [\"es6\"],\n\t\t\"module\": \"commonjs\",\n\t\t\"noEmit\": true,\n\t\t\"noImplicitAny\": true,\n\t\t\"noImplic"
  },
  {
    "path": "types/tslint.json",
    "chars": 116,
    "preview": "{\n\t\"extends\": \"dtslint/dtslint.json\",\n\t\"rules\": {\n\t\t\"indent\": [true, \"tabs\", 2],\n\t\t\"no-empty-interface\": false\n\t}\n}\n"
  },
  {
    "path": "utils.js",
    "chars": 898,
    "preview": "const { Ulid } = require('./src/id/ulid');\nconst { UlidMonotonic } = require('./src/id/ulid-monotonic');\nconst { Uuid } "
  }
]

About this extraction

This page contains the full source code of the aarondcohen/id128 GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 55 files (144.9 KB), approximately 42.4k tokens, and a symbol index with 260 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!