nehoid
Version:
Advanced unique ID generation utility with multi-layer encoding, collision detection, and context-aware features
120 lines • 4.06 kB
JavaScript
export class Validator {
static validate(id, options = {}) {
const { checkFormat = true } = options;
if (!id || typeof id !== 'string') {
return false;
}
if (checkFormat) {
// Basic format validation
if (id.length < 8) {
return false;
}
// Check for invalid characters
if (/[^A-Za-z0-9_-]/.test(id)) {
return false;
}
}
return true;
}
static validateBatch(ids, options = {}) {
const result = {
valid: [],
invalid: [],
duplicates: [],
};
const seen = new Set();
for (const id of ids) {
if (!this.validate(id, options)) {
result.invalid.push(id);
continue;
}
if (options.checkCollisions && seen.has(id)) {
result.duplicates.push(id);
continue;
}
result.valid.push(id);
seen.add(id);
}
return result;
}
static healthCheck(id) {
const score = this.calculateHealthScore(id);
const entropy = this.calculateEntropy(id);
const predictability = this.assessPredictability(id);
const recommendations = this.generateRecommendations(score, entropy, id.length);
return {
score,
entropy: entropy > 0.75 ? 'high' : entropy > 0.5 ? 'medium' : 'low',
predictability: predictability < 0.3 ? 'low' : predictability < 0.6 ? 'medium' : 'high',
recommendations,
};
}
static calculateHealthScore(id) {
let score = 1.0;
// Length check
if (id.length < 8)
score *= 0.5;
if (id.length > 32)
score *= 0.9;
// Character variety
const hasUpper = /[A-Z]/.test(id);
const hasLower = /[a-z]/.test(id);
const hasNumber = /[0-9]/.test(id);
const hasSpecial = /[^A-Za-z0-9]/.test(id);
if (!hasUpper)
score *= 0.9;
if (!hasLower)
score *= 0.9;
if (!hasNumber)
score *= 0.9;
if (!hasSpecial)
score *= 0.95;
return Math.min(1, Math.max(0, score));
}
static calculateEntropy(id) {
const charFreq = new Map();
for (const char of id) {
charFreq.set(char, (charFreq.get(char) || 0) + 1);
}
let entropy = 0;
const length = id.length;
for (const freq of charFreq.values()) {
const probability = freq / length;
entropy -= probability * Math.log2(probability);
}
return entropy / Math.log2(charFreq.size);
}
static assessPredictability(id) {
let predictability = 0;
// Check for patterns
const hasRepeatingPattern = /(.+?)\1+/.test(id);
if (hasRepeatingPattern)
predictability += 0.3;
// Check for sequential characters
const hasSequential = /(?:abc|123|xyz)/i.test(id);
if (hasSequential)
predictability += 0.2;
// Check for common words
const hasCommonWords = /(?:test|admin|user|temp)/i.test(id);
if (hasCommonWords)
predictability += 0.4;
return Math.min(1, predictability);
}
static generateRecommendations(score, entropy, length) {
const recommendations = [];
if (score < 0.8) {
if (length < 12)
recommendations.push('increase_length');
if (entropy < 0.6)
recommendations.push('increase_complexity');
}
if (length > 50)
recommendations.push('consider_shorter');
if (entropy < 0.4)
recommendations.push('add_more_variety');
return recommendations;
}
}
Validator.UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
Validator.NANO_REGEX = /^[A-Za-z0-9_-]+$/;
//# sourceMappingURL=validator.js.map