hybrid-id-generator
Version:
A powerful hybrid ID generator that combines timestamps, machine IDs, random bits, and sequence numbers to create globally unique identifiers. Features collision prevention, Base62 encoding, and optional ID expiry tracking, ideal for distributed systems a
146 lines (145 loc) • 5.8 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MachineIDProviderFactory = exports.RandomMachineIDProvider = exports.NetworkMachineIDProvider = exports.EnvMachineIDProvider = void 0;
//src/MachineIDProvider.ts
const os_1 = __importDefault(require("os"));
const crypto_1 = __importDefault(require("crypto"));
/**
* Environment-based machine ID provider.
* Retrieves the machine ID from a specified environment variable and caches it.
*/
class EnvMachineIDProvider {
constructor(envVarName = 'MACHINE_ID') {
this.cachedMachineId = null; // Cache variable for the machine ID
this.envVarName = envVarName;
}
getMachineId() {
// Return cached value if available
if (this.cachedMachineId !== null) {
return this.cachedMachineId;
}
const machineIdStr = process.env[this.envVarName];
if (!machineIdStr) {
throw new Error(`Environment variable ${this.envVarName} is not defined`);
}
const machineId = parseInt(machineIdStr, 10);
if (isNaN(machineId) || machineId < 0) {
throw new Error(`Invalid MACHINE_ID from environment variable: ${this.envVarName}`);
}
// Cache the retrieved machine ID
this.cachedMachineId = machineId;
return machineId;
}
}
exports.EnvMachineIDProvider = EnvMachineIDProvider;
/**
* Network-based machine ID provider.
* Generates a machine ID based on the MAC address of the network interface and caches it.
* This provider can handle multiple MAC addresses and offers configuration options.
*/
class NetworkMachineIDProvider {
/**
* @param interfaceName Optional name of the network interface to use.
* If not provided, the first valid MAC address found will be used.
*/
constructor(interfaceName) {
this.cachedMachineId = null; // Cache variable for the machine ID
this.interfaceName = interfaceName;
}
getMachineId() {
// Return cached value if available
if (this.cachedMachineId !== null) {
return this.cachedMachineId;
}
const interfaces = os_1.default.networkInterfaces();
let mac;
if (this.interfaceName) {
// Look for the specified interface name
const iface = interfaces[this.interfaceName];
if (iface) {
mac = this.getValidMac(iface);
}
}
else {
// If no specific interface, search all interfaces for a valid MAC
for (const iface of Object.values(interfaces)) {
if (iface) {
mac = this.getValidMac(iface);
if (mac)
break; // Stop once a valid MAC is found
}
}
}
if (!mac) {
throw new Error("Unable to determine machine ID based on network interface");
}
// Cache the generated machine ID
this.cachedMachineId = this.hashMacToMachineId(mac);
return this.cachedMachineId;
}
getValidMac(iface) {
for (const { mac } of iface) {
if (mac && mac !== '00:00:00:00:00:00') {
return mac; // Return the first valid MAC address found
}
}
return undefined; // No valid MAC found
}
hashMacToMachineId(mac) {
// Simplified hash to convert MAC address to machine ID (limited to a range)
return parseInt(mac.replace(/:/g, ''), 16) % 1024;
}
}
exports.NetworkMachineIDProvider = NetworkMachineIDProvider;
/**
* Random machine ID provider.
* Generates a random machine ID within a specified range.
* This implementation uses cryptographic random values to improve security and reduce predictability.
*/
class RandomMachineIDProvider {
/**
* @param maxMachineId Maximum value for the machine ID. Defaults to 1023.
*/
constructor(maxMachineId = 1023) {
this.maxMachineId = maxMachineId;
}
getMachineId() {
return this.generateRandomMachineId();
}
generateRandomMachineId() {
const randomValue = this.getCryptographicRandomValue(4); // Get a random 4-byte value
return randomValue % (this.maxMachineId + 1); // Ensure it stays within the maxMachineId range
}
getCryptographicRandomValue(byteSize) {
const buffer = crypto_1.default.randomBytes(byteSize); // Generate cryptographic random bytes
return buffer.readUInt32BE(0); // Convert first 4 bytes to an unsigned 32-bit integer
}
}
exports.RandomMachineIDProvider = RandomMachineIDProvider;
/**
* Factory for creating MachineIDProvider based on strategy.
*/
class MachineIDProviderFactory {
/**
* Create a MachineIDProvider based on the strategy and a single var that is interpreted based on the strategy.
* - If the strategy is 'env', the var is treated as envVarName.
* - If the strategy is 'random', the var is treated as maxMachineId.
* - 'network' strategy doesn't require an additional var.
*/
static createMachineIDProvider(strategy, value) {
switch (strategy) {
case 'env':
return new EnvMachineIDProvider(value); // Use value as envVarName
case 'network':
return new NetworkMachineIDProvider(); // No additional value needed
case 'random':
return new RandomMachineIDProvider(value); // Use value as maxMachineId
default:
throw new Error(`Invalid machine ID strategy: ${strategy}`);
}
}
}
exports.MachineIDProviderFactory = MachineIDProviderFactory;