@usex/key-fleur
Version:
Generate beautiful, memorable, and poetic API keys and unique identifiers for your applications.
613 lines (607 loc) • 11.8 kB
JavaScript
;
const THEMES = {
haiku: [
"nyrae",
"soliv",
"virel",
"ethae",
"omura",
"lyr",
"aeli",
"sirune",
"nuvia",
"evara",
"halen",
"ilari",
"tyrel",
"elune",
"kairi",
"syrel",
"narun",
"velia",
"orune",
"faeli"
],
nocturnal: [
"luna",
"night",
"star",
"owl",
"dusk",
"twilight",
"midnight",
"shade",
"echo",
"eclipse",
"gloom",
"moth",
"raven",
"void",
"mist",
"sleep",
"howl",
"nova",
"quiet",
"shiver",
"dark",
"silence",
"phantom",
"crescent",
"hollow",
"dream",
"veil",
"crypt",
"umbra",
"noir"
],
sunny: [
"sol",
"sun",
"ray",
"bright",
"day",
"dawn",
"shine",
"gold",
"beam",
"sky",
"flare",
"light",
"summer",
"glow",
"warmth",
"clear",
"zenith",
"haze",
"amber",
"bliss",
"gleam",
"glint",
"sunrise",
"radiant",
"beam",
"halo",
"lucid",
"fire",
"flare",
"glory"
],
floreal: [
"rose",
"lily",
"petal",
"bloom",
"ivy",
"orchid",
"daisy",
"violet",
"primrose",
"stem",
"pollen",
"sprout",
"bud",
"blossom",
"flora",
"camellia",
"garden",
"leaf",
"nectar",
"thistle",
"lavender",
"tulip",
"clover",
"hyacinth",
"marigold",
"chrysant",
"wisteria",
"magnolia",
"peony",
"fern"
],
oceanic: [
"wave",
"coral",
"foam",
"drift",
"deep",
"pearl",
"tide",
"gull",
"salt",
"whale",
"kelp",
"abyss",
"current",
"surf",
"ocean",
"marina",
"shoal",
"siren",
"lagoon",
"shell",
"reef",
"seastar",
"nautilus",
"spray",
"undertow",
"isle",
"brine",
"anchor",
"swell",
"ripple"
],
crystalline: [
"crystal",
"gem",
"shard",
"opal",
"quartz",
"glint",
"ice",
"snow",
"frost",
"facet",
"prism",
"glass",
"clear",
"gleam",
"diamond",
"shine",
"mirror",
"spark",
"flake",
"glow",
"glacier",
"amethyst",
"glisten",
"translucent",
"silica",
"bismuth",
"halo",
"chime",
"lucent",
"citrine"
],
mythic: [
"aether",
"wyrm",
"oracle",
"sigil",
"blade",
"fable",
"mythos",
"grimoire",
"phoenix",
"echo",
"titan",
"nymph",
"elysium",
"lore",
"rune",
"arcane",
"wyrd",
"hero",
"legend",
"shade",
"sphinx",
"hydra",
"oblivion",
"divine",
"hex",
"omen",
"ritual",
"saga",
"daemon",
"prophecy"
],
forest: [
"moss",
"bark",
"deer",
"grove",
"tree",
"fern",
"owl",
"leaf",
"fox",
"thicket",
"pine",
"birch",
"root",
"sap",
"fungus",
"log",
"trail",
"wild",
"branch",
"meadow",
"cedar",
"acorn",
"willow",
"glade",
"lichen",
"bluff",
"elm",
"spruce",
"hedge",
"nest"
],
desert: [
"sand",
"dune",
"mirage",
"sun",
"dry",
"camel",
"cactus",
"arid",
"scorch",
"salt",
"wind",
"dust",
"stone",
"haze",
"burn",
"sol",
"flame",
"crack",
"barren",
"sizzle",
"ember",
"serpent",
"blister",
"parch",
"ash",
"glare",
"mesa",
"quartz",
"sirocco",
"ridge"
],
celestial: [
"nova",
"orbit",
"comet",
"moon",
"star",
"sol",
"galaxy",
"void",
"pulse",
"flare",
"venus",
"eclipse",
"plasma",
"space",
"light",
"sphere",
"sky",
"drift",
"saturn",
"zero",
"nebula",
"equinox",
"zenith",
"meteor",
"lunar",
"solstice",
"mercury",
"aster",
"axis",
"horizon"
],
library: [
"scroll",
"ink",
"book",
"page",
"shelf",
"quiet",
"dust",
"study",
"read",
"verse",
"prose",
"codex",
"folio",
"scribe",
"script",
"glyph",
"letter",
"note",
"pen",
"volume",
"archive",
"index",
"library",
"margin",
"annotation",
"spine",
"binding",
"tome",
"quill",
"text"
],
decay: [
"rot",
"rust",
"moss",
"mold",
"crack",
"fade",
"peel",
"dust",
"crumble",
"ash",
"time",
"void",
"wilt",
"droop",
"filth",
"wear",
"flaw",
"scratch",
"stain",
"dull",
"brittle",
"smudge",
"erode",
"fracture",
"debris",
"decay",
"fester",
"grime",
"soot",
"relic"
],
steampunk: [
"gear",
"steam",
"cog",
"brass",
"pipe",
"gauge",
"valve",
"weld",
"bolt",
"clock",
"spark",
"smoke",
"engine",
"vane",
"dial",
"joint",
"helm",
"rivets",
"boiler",
"coil",
"piston",
"frame",
"rotor",
"socket",
"vent",
"torque",
"copper",
"chrono",
"lever",
"mech"
]
};
const SOFT_CONS = "flmnrschv";
const VOWELS = "aeiouy";
function syllable() {
return getRandomChar(SOFT_CONS) + getRandomChar(VOWELS);
}
function getRandomChar(chars) {
return chars.charAt(Math.floor(Math.random() * chars.length));
}
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function getRandomElement(array) {
return array[Math.floor(Math.random() * array.length)];
}
function estimateSyllables(word) {
if (!word || typeof word !== "string") {
return 0;
}
word = word.toLowerCase();
const vowels = "aeiouy";
let count = 0;
let prevChar = "";
for (const char of word) {
if (vowels.includes(char) && !vowels.includes(prevChar)) {
count++;
}
prevChar = char;
}
if (word.endsWith("e") && count > 1) {
count--;
}
return Math.max(1, count);
}
const RUNES = ["now+1d", "now-2h", "dawn", "midnight", "solstice", "infinite", "epoch"];
function haiku(theme) {
const allWords = Object.values(THEMES[theme]).flat().filter((word) => word);
const shuffledWords = [...allWords].sort(() => Math.random() - 0.5);
const usedWords = /* @__PURE__ */ new Set();
function findWords(targetSyllables) {
const result = [];
let total = 0;
for (const word of shuffledWords) {
if (!word || usedWords.has(word)) {
continue;
}
const syll = estimateSyllables(word);
if (syll === 0) {
continue;
}
if (total + syll <= targetSyllables) {
result.push(word.charAt(0).toUpperCase() + word.slice(1));
usedWords.add(word);
total += syll;
if (total === targetSyllables) {
break;
}
}
}
return total === targetSyllables ? result : [];
}
const line1 = findWords(5);
const line2 = findWords(7);
const line3 = findWords(5);
if (!line1.length || !line2.length || !line3.length) {
return "incomplete-haiku";
}
return [line1.join(""), line2.join(""), line3.join("")].join("-");
}
function lace(theme) {
const roots = THEMES[theme] || THEMES["haiku"];
const word = getRandomElement(roots);
const mid = syllable();
return `${word}${mid}-${mid.split("").reverse().join("")}${word.split("").reverse().join("")}`;
}
function mirrora(_) {
const s = syllable();
return `${s.split("").reverse().join("")}-${s}`;
}
function runeKey(theme) {
const base = haiku(theme).charAt(0).toUpperCase() + haiku(theme).slice(1);
const rune = getRandomElement(RUNES);
return `${base}_${rune}`;
}
function sonnet(theme) {
const roots = THEMES[theme] || THEMES["haiku"];
const firstWord = getRandomElement(roots);
const secondWord = getRandomElement(roots);
const firstSyll = syllable().slice(0, 2);
const secondSyll = syllable().slice(0, 2);
return `${firstWord.charAt(0).toUpperCase() + firstWord.slice(1)}${firstSyll}-${secondWord.charAt(0).toUpperCase() + secondWord.slice(1)}${secondSyll}`;
}
function sigil(theme) {
const roots = THEMES[theme] || THEMES["haiku"];
const firstWord = getRandomElement(roots);
const secondWord = getRandomElement(roots);
return `${firstWord.charAt(0).toUpperCase() + firstWord.slice(1)}-${getRandomInt(100, 999)}-${secondWord.charAt(0).toUpperCase() + secondWord.slice(1)}`;
}
function seed(theme) {
const roots = THEMES[theme] || THEMES["haiku"];
const word = getRandomElement(roots);
const wordPrefix = word.slice(0, 4);
const randomHex = getRandomInt(4096, 39321).toString(16);
return `${wordPrefix.charAt(0).toUpperCase() + wordPrefix.slice(1)}-${randomHex}`;
}
function mantra(theme) {
const roots = THEMES[theme] || THEMES["haiku"];
const word = getRandomElement(roots);
const secondWord = getRandomElement(roots);
return `${word.charAt(0).toUpperCase() + word.slice(1)}-${word.charAt(0).toUpperCase() + word.slice(1)}-${secondWord.charAt(0).toUpperCase() + secondWord.slice(1)}`;
}
function quartz(theme) {
const roots = THEMES[theme] || THEMES["haiku"];
const root = getRandomElement(roots);
const capitalized = root.charAt(0).toUpperCase() + root.slice(1);
const rev = capitalized.split("").reverse().join("").slice(0, 4);
const num = getRandomInt(10, 99).toString();
return `${capitalized}${num}.${num}${rev}`;
}
const MODES = {
haiku,
lace,
mirrora,
rune: runeKey,
sonnet,
sigil,
seed,
mantra,
quartz
};
function poeticKey(mode = "haiku", theme = "haiku") {
const func = MODES[mode] || MODES["haiku"];
return func(theme);
}
function generateKeyFleur(options = {}) {
const { mode = "haiku", theme = "haiku", count = 1 } = options;
if (!MODES[mode]) {
throw new Error(`Invalid mode: ${mode}. Available modes: ${Object.keys(MODES).join(", ")}`);
}
if (!THEMES[theme]) {
throw new Error(`Invalid theme: ${theme}. Available themes: ${Object.keys(THEMES).join(", ")}`);
}
if (count < 1 || count > 100) {
throw new Error("Count must be between 1 and 100");
}
if (count === 1) {
return poeticKey(mode, theme);
}
return Array.from({ length: count }, () => poeticKey(mode, theme));
}
function isValidKeyFleur(key, mode) {
if (!key || typeof key !== "string") {
return { valid: false, reason: "Key must be a non-empty string" };
}
const patterns = {
haiku: /^[A-Z][a-z]+-[A-Z][a-z]+-[A-Z][a-z]+$/,
lace: /^[a-z]+[a-z]{2}-[a-z]{2}[a-z]+$/,
mirrora: /^[a-z]{2}-[a-z]{2}$/,
rune: /^[A-Z][a-z]+-[A-Z][a-z]+-[A-Z][a-z]+_(now\+1d|now-2h|dawn|midnight|solstice|infinite|epoch)$/,
sonnet: /^[A-Z][a-z]+[a-z]{2}-[A-Z][a-z]+[a-z]{2}$/,
sigil: /^[A-Z][a-z]+-\d{3}-[A-Z][a-z]+$/,
seed: /^[A-Z][a-z]{1,3}-[a-f0-9]{4}$/,
mantra: /^[A-Z][a-z]+-[A-Z][a-z]+-[A-Z][a-z]+$/,
quartz: /^[A-Z][a-z]+\d{2}\.\d{2}[A-Z][a-z]*$/
};
if (mode) {
const pattern = patterns[mode];
if (!pattern) {
return { valid: false, reason: `Unknown mode: ${mode}` };
}
const valid = pattern.test(key);
return {
valid,
mode: valid ? mode : void 0,
reason: valid ? void 0 : `Key does not match ${mode} pattern`,
parts: valid ? key.split(/[-_.]/) : void 0
};
}
for (const [modeName, pattern] of Object.entries(patterns)) {
if (pattern.test(key)) {
return {
valid: true,
mode: modeName,
parts: key.split(/[-_.]/)
};
}
}
return {
valid: false,
reason: "Key does not match any known KeyFleur pattern"
};
}
exports.MODES = MODES;
exports.THEMES = THEMES;
exports.generateKeyFleur = generateKeyFleur;
exports.isValidKeyFleur = isValidKeyFleur;
exports.poeticKey = poeticKey;