brackt/app/utils/team-names.ts
Chris Parsons 5268e07365
Migrate auth from Clerk to BetterAuth (#354)
* Fix BetterAuth field mapping and add owner-prefixed team names

- Fix auth.server.ts: use camelCase Drizzle field names for BetterAuth
  adapter (was snake_case, causing user inserts to fail); add
  generateId: "uuid" so PostgreSQL UUID columns accept generated IDs
- Add prependOwnerToTeamName / stripOwnerFromTeamName utilities
- Invite join, league creation, and settings assign/remove all now
  manage the owner-prefix on team names atomically

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Complete BetterAuth migration: auth flows, rename, and cleanup

- Add /forgot-password and /reset-password pages (full password reset flow)
- Add 'Forgot password?' link on login page
- Fix register.tsx: add explicit window.location fallback after signUp
- Rename commissionerAuditLog.actorClerkId → actorUserId (migration 0084)
  and update all references in model, routes, components, and tests
- Rewrite docs/agents/auth.md to document BetterAuth (removes all Clerk refs)
- Update test fixtures and schema comments to remove Clerk ID references;
  use UUID-format IDs throughout test data
- Update docs/agents/domain-models.md ownerId description

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Fix BetterAuth ID generation, clean up review issues

- Set generateId: false so BetterAuth omits id from inserts; add
  $defaultFn(crypto.randomUUID) to accounts/sessions/verifications
  so Drizzle fills it in (fixes null id constraint violation on signup)
- Move renameTeam to static import; rename before removeTeamOwner so
  a failed rename leaves owner intact rather than leaving a stale prefix
- Clarify stripOwnerFromTeamName toTitleCase assumption in comment
- Annotate reset-password token fallback to explain loader guarantee

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 10:03:50 -07:00

113 lines
5.7 KiB
TypeScript

// Fun adjectives for team names
export const adjectives = [
"Aggressive", "Agile", "Amazing", "Ancient", "Angry", "Anxious", "Awesome", "Awkward",
"Bold", "Brave", "Bright", "Brilliant", "Bumbling", "Busy",
"Calm", "Careful", "Careless", "Charming", "Cheerful", "Clumsy", "Confident", "Confused", "Courageous", "Crazy", "Creative", "Curious",
"Daring", "Dark", "Dazzling", "Delightful", "Determined", "Dizzy", "Dynamic",
"Eager", "Electric", "Elegant", "Energetic", "Enthusiastic", "Epic", "Excited",
"Fabulous", "Fancy", "Fantastic", "Fast", "Fearless", "Ferocious", "Fierce", "Fiery", "Flying", "Foolish", "Friendly", "Frozen", "Furious", "Fuzzy",
"Gentle", "Giant", "Gigantic", "Glorious", "Golden", "Graceful", "Grumpy",
"Happy", "Hasty", "Helpful", "Heroic", "Hilarious", "Honest", "Hungry", "Hyper",
"Icy", "Incredible", "Intelligent", "Intense", "Invisible",
"Jolly", "Joyful", "Jumpy",
"Kind",
"Lazy", "Legendary", "Lightning", "Lively", "Lonely", "Loud", "Lucky",
"Mad", "Magical", "Magnificent", "Majestic", "Marvelous", "Massive", "Mighty", "Mischievous", "Mysterious",
"Nervous", "Noble",
"Odd", "Outrageous",
"Peaceful", "Perfect", "Playful", "Powerful", "Proud", "Puzzled",
"Quick", "Quiet",
"Radiant", "Raging", "Rambunctious", "Rapid", "Reckless", "Relentless", "Remarkable", "Restless", "Roaring", "Royal", "Rusty",
"Savage", "Scary", "Shiny", "Silent", "Silly", "Sleepy", "Sly", "Smart", "Smooth", "Sneaky", "Soaring", "Speedy", "Spicy", "Spirited", "Splendid", "Spooky", "Stormy", "Strange", "Strong", "Stunning", "Super", "Swift",
"Talented", "Terrible", "Terrific", "Thundering", "Timid", "Tiny", "Tough", "Tremendous", "Tricky",
"Ultimate", "Unbeatable", "Unstoppable",
"Valiant", "Vibrant", "Vicious", "Victorious", "Vigilant", "Vigorous",
"Wacky", "Wandering", "Wild", "Wise", "Witty", "Wonderful", "Wondrous",
"Zealous", "Zesty", "Zippy"
];
export const pluralNouns = [
"Aardvarks", "Albatrosses", "Alligators", "Alpacas", "Anteaters", "Antelopes", "Apes", "Armadillos",
"Badgers", "Bananas", "Bats", "Bears", "Beavers", "Bees", "Beetles", "Bison", "Bobcats", "Buffaloes", "Bulldogs", "Butterflies",
"Cacti", "Camels", "Capybaras", "Cardinals", "Caribou", "Cats", "Centipedes", "Chameleons", "Cheetahs", "Chickens", "Chipmunks", "Cobras", "Cockroaches", "Condors", "Cougars", "Cows", "Coyotes", "Crabs", "Crickets", "Crocodiles", "Crows",
"Deer", "Dinosaurs", "Dogs", "Dolphins", "Donkeys", "Doves", "Dragonflies", "Dragons", "Ducks",
"Eagles", "Eels", "Elephants", "Elks", "Emus",
"Falcons", "Ferrets", "Finches", "Fireflies", "Fish", "Flamingos", "Flies", "Foxes", "Frogs",
"Gazelles", "Geckos", "Geese", "Giraffes", "Goats", "Gophers", "Gorillas", "Grasshoppers", "Grizzlies", "Groundhogs",
"Hamsters", "Hawks", "Hedgehogs", "Herons", "Hippos", "Hornets", "Horses", "Hummingbirds", "Hyenas",
"Iguanas", "Impalas",
"Jaguars", "Jellyfish",
"Kangaroos", "Koalas", "Krakens",
"Ladybugs", "Lemurs", "Leopards", "Lions", "Lizards", "Llamas", "Lobsters", "Lynxes",
"Macaws", "Magpies", "Mammoths", "Manatees", "Mantises", "Meerkats", "Mice", "Minivans", "Moles", "Mongooses", "Monkeys", "Moose", "Mosquitoes", "Moths", "Mules",
"Narwhals", "Newts", "Nightingales",
"Octopuses", "Opossums", "Orangutans", "Orcas", "Ostriches", "Otters", "Owls", "Oxen",
"Pandas", "Panthers", "Parrots", "Peacocks", "Pelicans", "Penguins", "Phoenixes", "Pigeons", "Pigs", "Piranhas", "Platypuses", "Porcupines", "Possums", "Puffins", "Pumas", "Pythons",
"Quails",
"Rabbits", "Raccoons", "Rams", "Rats", "Ravens", "Reindeer", "Rhinos", "Roadrunners", "Robins", "Roosters",
"Salamanders", "Salmon", "Scorpions", "Seagulls", "Seahorses", "Seals", "Sharks", "Sheep", "Shrews", "Shrimp", "Skunks", "Sloths", "Slugs", "Snails", "Snakes", "Sparrows", "Spiders", "Squids", "Squirrels", "Starfish", "Stingrays", "Storks", "Swallows", "Swans",
"Tarantulas", "Tigers", "Toads", "Tortoises", "Toucans", "Trout", "Turkeys", "Turtles",
"Unicorns",
"Vipers", "Vultures",
"Walruses", "Warthogs", "Wasps", "Weasels", "Whales", "Wildcats", "Wildebeests", "Wolves", "Wombats", "Woodpeckers", "Worms",
"Yaks",
"Zebras"
];
/**
* Generate a random team name using an adjective and plural noun
*/
export function generateRandomTeamName(): string {
const adjective = adjectives[Math.floor(Math.random() * adjectives.length)];
const noun = pluralNouns[Math.floor(Math.random() * pluralNouns.length)];
return `${adjective} ${noun}`;
}
/**
* Generate multiple unique team names
*/
export function generateUniqueTeamNames(count: number): string[] {
const names = new Set<string>();
while (names.size < count) {
names.add(generateRandomTeamName());
}
return Array.from(names);
}
function toTitleCase(str: string): string {
if (!str) return str;
return str.charAt(0).toUpperCase() + str.slice(1);
}
function possessiveSuffix(name: string): string {
return name.endsWith("s") ? "'" : "'s";
}
export function prependOwnerToTeamName(
baseName: string,
username: string
): string {
const titleName = toTitleCase(username);
return `${titleName}${possessiveSuffix(titleName)} ${baseName}`;
}
// Relies on the name having been set via prependOwnerToTeamName (same toTitleCase logic).
// If username casing differs from when the name was set, the strip is a safe no-op.
export function stripOwnerFromTeamName(
teamName: string,
username: string
): string {
const titleName = toTitleCase(username);
const prefixWithS = `${titleName}'s `;
const prefixWithoutS = `${titleName}' `;
if (teamName.startsWith(prefixWithS)) {
return teamName.slice(prefixWithS.length);
}
if (teamName.startsWith(prefixWithoutS)) {
return teamName.slice(prefixWithoutS.length);
}
return teamName;
}