puid
Version:
Generate an unique ID for use in a distributed environment.
144 lines (103 loc) • 3.96 kB
JavaScript
var os = require('os');
var crypto = require('crypto');
var Puid = function Piud(options) {
"use strict";
this.config = {
"nlen": options === void 0 ? 6 : 2, // machine identifier for long or short puid,
"plen": 4, // process id
"tlen": options === void 0 ? 8 : 12, // timestamp length for long or short puid
"clen": 6, // counter/hrtime for long puid
"epoch": "1999-06-07 03:00:00 pm GMT" // epoch start for short puid
};
if (options === void 0) {
// long puid
this.type = "long";
this.nodeId = this.getNodeId();
this.processId = this.getProcessId();
} else {
// short puid
this.type = "short";
if (typeof options === 'string' && options.length <= 2) {
this.nodeId = options;
} else {
if (typeof options === 'object') {
if (options.nodeId !== void 0 && typeof options.nodeId === 'string' && options.nodeId.length <= 2) {
this.nodeId = options.nodeId;
}
if (options.epoch !== void 0 && typeof options.epoch === 'string' && options.epoch.length >= 4) {
if (isNaN(Date.parse(options.epoch))) {
throw new Error("epoch date format error");
}
this.config.epoch = options.epoch;
}
}
}
// random nodeId
if (options !== true && this.nodeId === void 0) {
this.nodeId = this.toBase36String(parseInt(Math.random() * (Math.pow(36, 2) - 1), 10), this.config.nlen);
} else {
if (options === true) {
this.nodeId = '';
}
}
this.nodeId = this.nodeId && this.nodeId.toLowerCase()
.trim();
}
};
Puid.prototype.generate = function generate() {
if (this.type[0] === "l") {
return this.getTimestamp() + this.processId + this.nodeId + this.getCounter();
} else {
return this.getNanos() + this.nodeId;
}
};
Puid.prototype.getTimestamp = function getTimestamp() {
return this.toBase36String(Date.now(), this.config.tlen);
};
Puid.prototype.getNanos = function getNanos() {
var hrt = '' + process.hrtime()[1];
while (hrt.length < 9) {
hrt = "0" + hrt;
}
var time = parseInt(Date.now() / 1000, 10) - parseInt(Date.parse(this.config.epoch) / 1000, 10);
return this.toBase36String(time + '' + hrt, this.config.tlen);
};
Puid.prototype.getNodeId = function getNodeId(networkInterfaces, fallback) {
var i, v, value;
networkInterfaces = networkInterfaces || os.networkInterfaces() || {};
if (!fallback) {
/* jshint -W015: true */
interfaces: for (i in networkInterfaces) {
for (v in i) {
if (networkInterfaces[i][v] && networkInterfaces[i][v].address.length && !networkInterfaces[i][v].internal) {
value = networkInterfaces[i][v].address;
break interfaces;
}
}
}
}
return crypto.createHash('md5')
.update(fallback || value || os.hostname(), 'utf8')
.digest('hex')
.slice(-this.config.nlen);
};
Puid.prototype.getProcessId = function getProcessId() {
return this.toBase36String(process.pid, this.config.plen);
};
Puid.prototype.getCounter = function getCounter() {
return this.toBase36String(process.hrtime()[1], this.config.clen);
};
Puid.prototype.toBase36String = function toBase36String(value, padding) {
if (isNaN(value)) {
throw new Error('error in toBase36String: value is NaN: \"' + value + '\"');
}
padding = padding && !isNaN(padding) ? padding : 2;
var hex = Number(Math.abs(value))
.toString(36);
while (hex.length < padding) {
hex = "0" + hex;
}
return hex.substr(0, padding);
};
module.exports = exports = Puid;
//