New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

ifid

Package Overview
Dependencies
Maintainers
1
Versions
26
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ifid - npm Package Compare versions

Comparing version 0.0.1 to 0.0.2

tsdist/index.js

3

package.json
{
"name": "ifid",
"version": "0.0.1",
"version": "0.0.2",
"description": "A package to generate Interactive Fiction Identifiers.",

@@ -26,3 +26,2 @@ "main": "tsdist/index.js",

"@types/node": "^8.0.55",
"tiny-uuid": "^1.0.0",
"typescript": "^2.6.2"

@@ -29,0 +28,0 @@ },

@@ -1,53 +0,148 @@

/* An RFC-4112 UUID generator for generating IFIDs, or Interactive Fiction
/* An RFC 4112 UUID generator for generating IFIDs, or Interactive Fiction
* Identifiers. */
import {
randomBytes,
} from 'crypto';
import {
readFileSync,
} from 'fs';
import {
networkInterfaces,
} from 'os';
const isNode: boolean = typeof module !== 'undefined' && module.exports;
const isNode: boolean = typeof window === 'undefined';
type TIndexableObject = { [key: string]: string, };
export const strings = {
ENDIANNESS_INVALID:
'The endianness of the host machine could not be detected as ' +
'little-endian or big-endian. This is almost certainly a problem with ' +
'the ifid package rather than the host machine.',
declare const window: TIndexableObject;
UUID_VERSION_INVALID:
'The version argument was not a valid UUID version.',
export interface IIFIDOptions {
version: TUUIDVersion;
nodeIdGetter?: Function;
};
RANDOM_GENERATOR_INVALID:
'A suitable random number generator could not be found.',
export class IFIDOptions implements IIFIDOptions {
version: TUUIDVersion = '4';
RANDOM_BYTES_COUNT_INVALID:
'The num argument, representing the number of random bytes to generate, ' +
'was not an integer greater than or equal to 1.',
constructor(version: TUUIDVersion) {
if (!isUUIDVersion(version)) {
throw new Error(strings.INVALID_UUID_VERSION);
}
TIMESTAMP_GENERATION_FAILED:
'The random number generator did not produce an acceptable value for ' +
'the random number used in place of a stable timestamp.',
this.version = version;
TIMESTAMP_INVALID:
'The timestamp property of the UUID object is malformed.',
CLOCK_SEQUENCE_INVALID:
'The clockSequence property of the UUID object is malformed.',
CLOCK_SEQUENCE_GENERATION_FAILED:
'The random number generator did not produce an acceptable value for ' +
'the random number used in place of a stable clock sequence.',
CLOCK_SEQUENCE_LOW_INVALID:
'The clockSequenceLow property of the UUID object is malformed.',
CLOCK_SEQUENCE_HIGH_INVALID:
'The clockSequenceHigh property of the UUID object is malformed.',
CLOCK_HIGH_AND_RESERVED_INVALID:
'The clockSequenceHighAndReserved property of the UUID object is ' +
'malformed.',
MAC_ADDRESS_UNAVAILABLE:
'The MAC address is unavailable, which makes creating the version 1 ' +
'node ID impossible.',
MAC_ADDRESS_INVALID:
'The MAC address was found, but it was malformed.',
UUID_STRING_INVALID:
'The text argument passed to UUID.parse was malformed.',
UUID_OPTIONS_INVALID:
'The options argument passed to one of the UUID methods did not meet ' +
'the isUUIDOptions type guard.',
TIME_LOW_INVALID:
'The timestamp property did not produce a valid low portion of the ' +
'timestamp.',
TIME_MID_INVALID:
'The timestamp property did not produce a valid mid portion of the ' +
'timestamp.',
TIME_HIGH_INVALID:
'The timestamp property did not produce a valid high portion of the ' +
'timestamp.',
TIME_HIGH_AND_VERSION_INVALID:
'The timestamp property did not produce a valid high-and-version ' +
'multiplex.',
NODE_IDENTIFIER_INVALID:
'The nodeIdentifier property of the UUID object was malformed.',
};
const endianness = ((): 'LE' | 'BE' => {
const arrayBuffer = new ArrayBuffer(2);
const uint8 = new Uint8Array(arrayBuffer);
const uint16 = new Uint16Array(arrayBuffer);
uint8[0] = 0x00;
uint8[1] = 0x01;
if (uint16[0] === 0x1000) {
return 'LE';
} else if (uint16[0] === 0x0001) {
return 'BE';
} else {
throw new Error(strings.ENDIANNESS_INVALID);
}
})();
timeValueGetter() {
if (isNode) {
} else {
}
const randomBytesGenerator = (() => {
let func: Function;
if (isNode) {
func = randomBytes;
} else if (typeof window.crypto === 'object' &&
window.crypto &&
typeof window.crypto.randomBytes === 'function')
{
func = window.crypto.randomBytes;
} else {
throw new Error(strings.RANDOM_GENERATOR_INVALID);
}
nodeIdGetter(): TSixHexOctet {
if (this.version === '1') { /* Create the node ID from the system time. */
return (num: number): Buffer | Uint8Array => {
if (!(num >= 1 && num % 1 === 0)) {
throw new Error(strings.RANDOM_BYTES_COUNT_INVALID);
}
return <TSixHexOctet>sixOctet;
} else if (this.version === '3') {
return func(num);
};
})();
} else if (this.version === '4') {
declare const window: { [key: string]: any; };
} else if (this.version === '5') {
export interface IIFIDLastResults {
node: TSixBytesInHex;
timestamp: TSixtyBitsInHex;
clockSequence: TFourteenBitsInHex;
}
} else {
throw new Error('The version')
}
}
export function isValidLastResults(maybe: any): maybe is IIFIDLastResults {
return typeof maybe === 'object' &&
maybe &&
isTwoBytesInHex(maybe.node) &&
isSixtyBitsInHex(maybe.timestamp) &&
isFourteenBitsInHex(maybe.clockSequence);
}
export interface IIFID {
id: IUUID;
version: TUUIDVersion;
toString(): string;
}
export class IFID implements IIFID {

@@ -62,3 +157,10 @@ readonly id: IUUID;

static parse(text: string): IIFID {
const id = UUID.parse(text);
const version = id.version;
const obj = {
id,
version,
};
return Object.assign(IFID, obj);
}

@@ -76,18 +178,20 @@

export interface IIFIDOptions extends IUUIDOptions {}
/* The formal Augmented Backus-Naur Form grammar for UUIDs is as follows,
* courtesy RFC-4112:
* The formal definition of the UUID string representation is
* provided by the following ABNF [7]:
* provided by the following ABNF:
*
* UUID = time-low "-" time-mid "-"
* time-high-and-version "-"
* clock-seq-and-reserved
* clock-seq-low "-" node
* time-low = 4hexOctet
* time-mid = 2hexOctet
* time-high-and-version = 2hexOctet
* clock-seq-and-reserved = hexOctet
* clock-seq-low = hexOctet
* node = 6hexOctet
* hexOctet = hexDigit hexDigit
* UUID = time-low "-" time-mid "-"
* time-high-and-version "-"
* clock-seq-high-and-reserved
* clock-seq-low "-" node
* time-low = 4hexOctet
* time-mid = 2hexOctet
* time-high-and-version = 2hexOctet
* clock-seq-high-and-reserved = hexOctet
* clock-seq-low = hexOctet
* node = 6hexOctet
* hexOctet = hexDigit hexDigit
* hexDigit =

@@ -100,38 +204,195 @@ * "0" / "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9" /

export interface IUUID {
version: TUUIDVersion;
timeLow: TFourHexOctet;
timeMid: TTwoHexOctet;
timeHigh: THexOctet;
timeHighAndVersion: TTwoHexOctet;
clockSeqAndReserved: THexOctet;
clockSeqLow: THexOctet;
node: TSixHexOctet;
toString(): string;
readonly version: TUUIDVersion;
readonly timestamp: TSixtyBitsInHex;
readonly timeLow: TFourBytesInHex;
readonly timeMid: TTwoBytesInHex;
readonly timeHigh: TOneByteInHex;
readonly timeHighAndVersion: TTwoBytesInHex;
readonly clockSequence: TFourteenBitsInHex;
readonly clockSequenceHighAndReserved: TOneByteInHex;
readonly clockSequenceLow: TOneByteInHex;
readonly nodeIdentifier: TSixBytesInHex;
toString(): string;
}
export class UUID implements IUUID {
version: TUUIDVersion;
timeLow: TFourHexOctet;
timeMid: TTwoHexOctet;
timeHigh: THexOctet;
timeHighAndVersion: TTwoHexOctet;
clockSeqAndReserved: THexOctet;
clockSeqLow: THexOctet;
node: TSixHexOctet;
private __version: TUUIDVersion;
get version(): TUUIDVersion {
return this.__version;
}
constructor(version: TUUIDVersion) {
this.version = version;
if (version === '1') {
private __timestamp: TSixtyBitsInHex;
get timestamp(): TSixtyBitsInHex {
return this.__timestamp;
}
} else if (version === '3') {
get timeLow(): TFourBytesInHex {
const low = parseInt(this.timestamp.join(''), 16) & 0xFFFFFFFF;
const timeLow = <TFourBytesInHex>low.toString(16).split('');
if (!isFourBytesInHex(timeLow)) {
throw new Error(strings.TIME_LOW_INVALID);
}
} else if (version === '4') {
return timeLow;
}
} else if (version === '5') {
get timeMid(): TTwoBytesInHex {
const mid = (parseInt(this.timestamp.join(''), 16) >> 32) & 0xFFFF;
const timeMid = <TTwoBytesInHex>mid.toString(16).split('');
if (!isTwoBytesInHex(timeMid)) {
throw new Error(strings.TIME_MID_INVALID);
}
} else {
throw new Error(strings.INVALID_UUID_VERSION);
return timeMid;
}
get timeHigh(): TOneByteInHex {
const high = (parseInt(this.timestamp.join('')) >> 48) & 0x0FFF;
const timeHigh = <TOneByteInHex>high.toString(16).split('');
if (!isOneByteInHex(timeHigh)) {
throw new Error(strings.TIME_HIGH_INVALID);
}
return timeHigh;
}
get timeHighAndVersion(): TTwoBytesInHex {
const _timeHigh = parseInt(this.timeHigh.join(''), 16);
const _version = parseInt(this.version, 16) << 12;
const high = _timeHigh | _version;
const timeHigh = <TTwoBytesInHex>high.toString(16).split('');
if (!isTwoBytesInHex(timeHigh)) {
throw new Error(strings.TIME_HIGH_AND_VERSION_INVALID);
}
return timeHigh;
}
private __clockSequence: TFourteenBitsInHex;
get clockSequence(): TFourteenBitsInHex {
return this.__clockSequence;
}
get clockSequenceLow(): TOneByteInHex {
const low = parseInt(this.clockSequence.join(''), 16) >> 8;
const clockSequenceLow = <TOneByteInHex>low.toString(16).split('');
if (!isOneByteInHex(clockSequenceLow)) {
throw new Error(strings.CLOCK_SEQUENCE_LOW_INVALID);
}
return clockSequenceLow;
}
get clockSequenceHigh(): TOneByteInHex {
const high = (parseInt(this.clockSequence.join('')) & 0x3F00) >> 8;
const clockHigh = <TOneByteInHex>high.toString(16).split('');
if (!isOneByteInHex(clockHigh)) {
throw new Error(strings.CLOCK_SEQUENCE_HIGH_INVALID);
}
return clockHigh;
}
get reserved(): [ '8', '0' ] {
return [ '8', '0', ];
}
get clockSequenceHighAndReserved(): TOneByteInHex {
const _clockHigh = parseInt(this.clockSequenceHigh.join(''), 16);
const _reserved = parseInt(this.reserved.join(''), 16);
const high = _clockHigh | _reserved;
const clockHigh = <TOneByteInHex>high.toString(16).split('');
if (!isOneByteInHex(clockHigh)) {
throw new Error(strings.CLOCK_HIGH_AND_RESERVED_INVALID);
}
return clockHigh;
}
private __nodeIdentifier: TSixBytesInHex;
get nodeIdentifier(): TSixBytesInHex {
return this.__nodeIdentifier;
}
static parse(text: string): IUUID {
const split = text.split('-');
if (split.length !== 5) {
throw new Error(strings.UUID_STRING_INVALID);
}
const version = <TUUIDVersion>parseInt(split[2], 16).toString();
if (!isUUIDVersion(version)) {
throw new Error(strings.UUID_VERSION_INVALID);
}
const tsNum = parseInt(split[0] + split[1] + split[2], 16);
const num = (tsNum >> 64);
const ts = 0 |
((num & 0x0000000000000fff) << 48) |
((num & 0x00000000ffff0000) << 16) |
((num & 0xffffffff00000000) >> 32);
const timestamp = <TSixBytesInHex>ts.toString(16).split('');
if (!isSixBytesInHex(timestamp)) {
throw new Error(strings.TIMESTAMP_INVALID);
}
const csHighReserved = parseInt(split[3].slice(0, split[3].length / 2), 16);
const csLow = parseInt(split[3].slice(split[3].length / 2), 16);
const cs = (csHighReserved << 8) | csLow;
const clockSequence = <TFourteenBitsInHex>cs.toString(2).split('');
if (!isFourteenBitsInHex(clockSequence)) {
throw new Error(strings.CLOCK_SEQUENCE_INVALID);
}
const nodeIdentifier = <TSixBytesInHex>split[4].split('');
if (!isSixBytesInHex(nodeIdentifier)) {
throw new Error(strings.NODE_IDENTIFIER_INVALID);
}
const uuid = new UUID({
skipCreation: true,
version,
timestampGetter: () => {},
clockSequenceGetter: () => {},
nodeIdentifierGetter: () => {},
});
return Object.assign(uuid, {
__version: version,
__timestamp: timestamp,
__clockSequence: clockSequence,
__nodeIdentifier: nodeIdentifier,
});
}
constructor(options: IUUIDOptions) {
if (options.skipCreation === true) {
return;
}
if (!isUUIDOptions(options)) {
throw new Error(strings.UUID_OPTIONS_INVALID);
}
const version = options.version;
if (!isUUIDVersion(version)) {
throw new Error(strings.UUID_VERSION_INVALID);
}
const timestamp = options.timestampGetter();
if (!isSixtyBitsInHex(timestamp)) {
throw new Error(strings.TIMESTAMP_GENERATION_FAILED);
}
this.__timestamp = timestamp;
const nodeIdentifier = options.nodeIdentifierGetter();
if (!isSixBytesInHex(nodeIdentifier)) {
throw new Error(strings.NODE_IDENTIFIER_INVALID);
}
this.__nodeIdentifier = nodeIdentifier;
}
toString(): string {

@@ -144,10 +405,161 @@ return this.timeLow.join('') +

'-' +
this.clockSeqAndReserved.join('') +
this.clockSequenceHighAndReserved.join('') +
this.clockSequenceLow.join('') +
'-' +
this.clockSeqLow.join('') +
'-' +
this.node.join('');
this.nodeIdentifier.join('');
}
}
export interface IUUIDOptions {
skipCreation: boolean;
version: TUUIDVersion;
nodeIdentifierGetter: Function;
timestampGetter: Function;
clockSequenceGetter: Function;
};
export function isUUIDOptions(maybe: any): maybe is IUUIDOptions {
return typeof maybe === 'object' &&
maybe &&
isUUIDVersion(maybe.version) &&
typeof maybe.nodeIdGetter === 'function' &&
typeof maybe.timestampGetter === 'function' &&
typeof maybe.clockSequenceGetter === 'function';
}
export class UUIDOptions implements IUUIDOptions {
skipCreation = false;
version: TUUIDVersion = '4';
private __lastResults: IIFIDLastResults | null = null;
constructor(version?: TUUIDVersion) {
if (typeof version !== 'undefined' && !isUUIDVersion(version)) {
throw new Error(strings.UUID_VERSION_INVALID);
}
this.version = version || this.version;
if (version === '1') {
if (!isNode) {
throw new Error(strings.MAC_ADDRESS_UNAVAILABLE);
}
try {
const resultsObj = JSON.parse(readFileSync('~/ifid', 'utf8'));
if (isValidLastResults(resultsObj)) {
this.__lastResults = resultsObj;
}
} catch (e) {
/* Do nothing. */
}
}
}
timestampGetter(): TSixtyBitsInHex {
if (this.version === '1' &&
this.__lastResults &&
isSixtyBitsInHex(this.__lastResults.timestamp))
{
const lts = this.__lastResults.timestamp.join('');
const lastTimestamp = parseInt(lts, 16);
if (lastTimestamp > getHundredsOfNanosecondsSinceGregorianReform() &&
isFourteenBitsInHex(this.__lastResults.clockSequence))
{
const cs = this.__lastResults.clockSequence.join('');
let csNum = parseInt(cs, 16);
csNum += 1;
const bin = csNum.toString(2);
this.__lastResults.clockSequence = <TFourteenBitsInHex>bin.split('');
}
/* Get the last known timestamp. */
return this.__lastResults.timestamp;
} else {
const bufferOrArray = randomBytesGenerator(8);
let binStr = bufferOrArray.join('');
if (endianness === 'LE') {
binStr = binStr.split('').reverse().join('');
}
if (binStr.length < 60) {
throw new Error(strings.RANDOM_BYTES_COUNT_INVALID);
}
const values = parseInt(binStr, 8).toString(2).slice(0, 60);
const hexDigits: Array<THexDigit> = [];
for (let ii = 0; ii < values.length; ii += 4) {
const slice = values.slice(ii, ii + 4);
if (slice.split('').filter((aa: string) => isBit(aa)).length !== 4) {
throw new Error(strings.TIMESTAMP_GENERATION_FAILED);
}
const hexDigit = <THexDigit>parseInt(slice, 2).toString(16);
hexDigits.push(hexDigit);
}
return <TSixtyBitsInHex>hexDigits;
}
}
nodeIdentifierGetter(): TSixBytesInHex {
if (this.version === '1') { /* Create the node ID from the system time. */
if (!Array.isArray(networkInterfaces) ||
!('0' in networkInterfaces) ||
!('mac' in networkInterfaces[0]))
{
throw new Error(strings.MAC_ADDRESS_UNAVAILABLE);
}
const rawId = networkInterfaces[0].mac;
const octets = rawId.split(':');
if (!isTwoBytesInHex(octets)) {
throw new Error(strings.MAC_ADDRESS_INVALID);
}
/* TODO: set cast bit to multicast (1). */
return <TSixBytesInHex>octets;
} else if (/3|4|5/.test(this.version)) {
const bytes = randomBytesGenerator(6);
const hex = parseInt(bytes.join(''), 8).toString(16).split('');
return <TSixBytesInHex>hex;
} else {
throw new Error(strings.UUID_VERSION_INVALID);
}
}
clockSequenceGetter(): TFourteenBitsInHex {
if (isNode && this.__lastResults) {
const clockSequence = this.__lastResults.clockSequence;
if (isFourteenBitsInHex(clockSequence)) {
return clockSequence;
}
}
const values = <Buffer | Uint8Array>randomBytesGenerator(2);
const bits: Array<TBit> = [];
let counter = 0;
for (let value of values) {
if (counter >= 14) {
break;
}
const _bits = value.toString(2).split('');
for (let bit of _bits) {
bits.push(<TBit>bit);
counter += 1;
if (counter >= 14) {
break;
}
}
}
if (bits.filter((aa) => isBit(aa)).length !== 14) {
throw new Error(strings.CLOCK_SEQUENCE_GENERATION_FAILED);
}
return <TFourteenBitsInHex>bits;
}
}
export class IFIDOptions extends UUIDOptions {}
export type TUUIDVersion = '1' | '3' | '4' | '5';

@@ -162,5 +574,7 @@

export interface IIFID {
id: IUUID;
toString(): string;
/* Expresses the storage of a single bit. */
export type TBit = '0' | '1';
export function isBit(maybe: any): maybe is TBit {
return maybe === '0' || maybe === '1';
}

@@ -194,10 +608,42 @@

export function isHexDigit(maybe: any): maybe is THexDigit {
return /^0123456789abcdef$/i.test(maybe);
}
/* Expresses the storage of one byte, or eight bits. */
export type THexOctet = [
THexDigit, /* 1 */
THexDigit /* 2 */
export type TOneByteInHex = [
THexDigit, /* 1 */
THexDigit /* 2 */
];
export function isOneByteInHex(maybe: any): maybe is TOneByteInHex {
return Array.isArray(maybe) &&
maybe.filter((aa) => isHexDigit(aa)).length === 2;
}
/* Expresses the storage of 14 bits, or 1.75 bytes. */
export type TFourteenBitsInHex = [
TBit, /* 1 */
TBit, /* 2 */
TBit, /* 3 */
TBit, /* 4 */
TBit, /* 5 */
TBit, /* 6 */
TBit, /* 7 */
TBit, /* 8 */
TBit, /* 9 */
TBit, /* 10 */
TBit, /* 11 */
TBit, /* 12 */
TBit, /* 13 */
TBit /* 14 */
];
export function isFourteenBitsInHex(maybe: any): maybe is TFourteenBitsInHex {
return Array.isArray(maybe) &&
maybe.filter((aa) => isBit(aa)).length === 14;
}
/* Expresses the storage of two bytes, or 16 bits. */
export type TTwoHexOctet = [
export type TTwoBytesInHex = [
THexDigit, /* 1 */

@@ -209,4 +655,9 @@ THexDigit, /* 2 */

export function isTwoBytesInHex(maybe: any): maybe is TTwoBytesInHex {
return Array.isArray(maybe) &&
maybe.filter((aa) => isHexDigit(aa)).length === 4;
}
/* Expresses the storage of four bytes, or 32 bits. */
export type TFourHexOctet = [
export type TFourBytesInHex = [
THexDigit, /* 1 */

@@ -222,4 +673,9 @@ THexDigit, /* 2 */

export function isFourBytesInHex(maybe: any): maybe is TFourBytesInHex {
return Array.isArray(maybe) &&
maybe.filter((aa) => isHexDigit(aa)).length === 8;
}
/* Expresses the storage of six bytes, or 48 bits. */
export type TSixHexOctet = [
export type TSixBytesInHex = [
THexDigit, /* 1 */

@@ -239,11 +695,36 @@ THexDigit, /* 2 */

export const strings = {
INVALID_UUID_VERSION:
'The version argument was not a valid UUID version.',
};
export function isSixBytesInHex(maybe: any): maybe is TSixBytesInHex {
return Array.isArray(maybe) &&
maybe.filter((aa) => isHexDigit(aa)).length === 12;
}
/* Expresses the storage of 15 hex digits, 7.5 bytes, or 60 bits. */
export type TSixtyBitsInHex = [
THexDigit, /* 1 */
THexDigit, /* 2 */
THexDigit, /* 3 */
THexDigit, /* 4 */
THexDigit, /* 5 */
THexDigit, /* 6 */
THexDigit, /* 7 */
THexDigit, /* 8 */
THexDigit, /* 9 */
THexDigit, /* 10 */
THexDigit, /* 11 */
THexDigit, /* 13 */
THexDigit, /* 14 */
THexDigit /* 15 */
];
export function isSixtyBitsInHex(maybe: any): maybe is TSixtyBitsInHex {
return Array.isArray(maybe) &&
maybe.filter((aa) => isHexDigit(aa)).length === 15;
}
export function getHundredsOfNanosecondsSinceGregorianReform(): number {
/* Javascript returns only microseconds, so the value has to be increased
* an order of magnitude. */
return (new Date().getTime() - new Date(1582, 10, 15).getTime()) * 10;
/* Months start at 0, so 9 is October. */
return (new Date().getTime() - new Date(1582, 9, 15).getTime()) *
/* Javascript returns only microseconds, so the value has to be increased
* an order of magnitude. */
10;
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc