Files
trackevery-day/lib/auth/tokens.ts
2025-07-15 18:58:21 +02:00

168 lines
2.3 KiB
TypeScript

import { customAlphabet } from 'nanoid';
// Word lists for generating memorable tokens
const adjectives = [
'quick',
'lazy',
'happy',
'brave',
'bright',
'calm',
'clever',
'eager',
'gentle',
'kind',
'lively',
'proud',
'silly',
'witty',
'bold',
'cool',
'fair',
'fine',
'glad',
'good',
'neat',
'nice',
'rare',
'safe',
'warm',
'wise',
'fresh',
'clean',
'clear',
'crisp',
'sweet',
'smooth',
];
const colors = [
'red',
'blue',
'green',
'yellow',
'purple',
'orange',
'pink',
'black',
'white',
'gray',
'brown',
'cyan',
'lime',
'navy',
'teal',
'gold',
'silver',
'coral',
'salmon',
'indigo',
'violet',
'crimson',
'azure',
'jade',
];
const animals = [
'cat',
'dog',
'bird',
'fish',
'bear',
'lion',
'wolf',
'fox',
'deer',
'owl',
'hawk',
'duck',
'goat',
'seal',
'crab',
'moth',
'bee',
'ant',
'bat',
'cow',
'pig',
'hen',
'ram',
'rat',
'eel',
'cod',
'jay',
'yak',
'ox',
'pug',
'doe',
'hog',
];
const nouns = [
'moon',
'star',
'cloud',
'river',
'mountain',
'ocean',
'forest',
'desert',
'island',
'valley',
'meadow',
'garden',
'bridge',
'castle',
'tower',
'light',
'shadow',
'dream',
'hope',
'wish',
'song',
'dance',
'smile',
'laugh',
'gift',
'pearl',
'jewel',
'crown',
'shield',
'sword',
'arrow',
'bow',
];
// Generate a 4-digit number suffix for uniqueness
const generateNumber = customAlphabet('0123456789', 4);
function getRandomElement<T>(array: T[]): T {
return array[Math.floor(Math.random() * array.length)];
}
export function generateMemorableToken(): string {
const parts = [
getRandomElement(adjectives),
getRandomElement(colors),
getRandomElement(animals),
generateNumber(),
];
return parts.join('-');
}
export function generateShortToken(): string {
const parts = [getRandomElement(colors), getRandomElement(nouns), generateNumber()];
return parts.join('-');
}
// Validate token format
export function isValidToken(token: string): boolean {
// Check if token matches our format (word-word-word-4digits or word-word-4digits)
const longFormat = /^[a-z]+-[a-z]+-[a-z]+-\d{4}$/;
const shortFormat = /^[a-z]+-[a-z]+-\d{4}$/;
return longFormat.test(token) || shortFormat.test(token);
}