Files
petfeed/prisma/seed.ts
T
admin 4daac56bfe feat(species): add Chinchilla and Aquarium (Gitea #25)
Chinchilla joins the small-pet species as its own Species (breeds are
color varieties: Standard Grey, Beige, Black Velvet, etc.).

Aquarium models the tank/setup as the pet identity rather than an
individual fish, matching how aquarists actually showcase their hobby —
Breed is the predominant fish species kept (Betta, Guppy, Discus, Koi,
etc.), same pattern as Bird covering many bird types via Breed. Pure
seed-data addition, no schema/code changes needed.
2026-08-15 12:13:48 +02:00

497 lines
12 KiB
TypeScript

import { PrismaClient } from "@prisma/client";
import { PrismaPg } from "@prisma/adapter-pg";
import { Pool } from "pg";
/**
* Seed script for the PawFeed database.
* Seeds Species (Dog, Cat, Bird) and Breed taxonomy idempotently.
* Uses upsert so it is safe to run multiple times.
*
* Run: npx tsx prisma/seed.ts
* Or: npx prisma db seed
*/
const databaseUrl = process.env.DATABASE_URL;
if (!databaseUrl) {
throw new Error(
"DATABASE_URL is not set. Please add it to .env.local first."
);
}
const adapter = new PrismaPg(new Pool({ connectionString: databaseUrl }));
const prisma = new PrismaClient({ adapter });
const DOG_BREEDS = [
"Labrador Retriever",
"Golden Retriever",
"German Shepherd",
"French Bulldog",
"Bulldog",
"Poodle",
"Beagle",
"Rottweiler",
"German Shorthaired Pointer",
"Dachshund",
"Pembroke Welsh Corgi",
"Australian Shepherd",
"Yorkshire Terrier",
"Boxer",
"Cavalier King Charles Spaniel",
"Doberman Pinscher",
"Great Dane",
"Miniature Schnauzer",
"Siberian Husky",
"Border Collie",
];
const CAT_BREEDS = [
"Domestic Shorthair",
"Domestic Longhair",
"Maine Coon",
"Ragdoll",
"Siamese",
"Persian",
"Bengal",
"British Shorthair",
"Sphynx",
"Scottish Fold",
"American Shorthair",
"Abyssinian",
"Norwegian Forest Cat",
"Birman",
"Russian Blue",
];
const BIRD_BREEDS = [
"Budgerigar (Budgie)",
"Cockatiel",
"Lovebird",
"African Grey Parrot",
"Cockatoo",
"Conure",
"Macaw",
"Canary",
"Finch",
"Amazon Parrot",
];
const HORSE_BREEDS = [
"Arabian Horse",
"Icelandic Horse",
"Shetland Pony",
"Haflinger",
"Friesian",
"Andalusian",
"Quarter Horse",
"Thoroughbred",
"Warmblood",
"Welsh Pony",
"Trakehner",
"Hanoverian",
];
const RABBIT_BREEDS = [
"Netherland Dwarf",
"Holland Lop",
"Lionhead Rabbit",
"Rex Rabbit",
"Angora Rabbit",
"Flemish Giant",
"Mini Rex",
"Dutch Rabbit",
];
const GUINEA_PIG_BREEDS = [
"American Guinea Pig",
"Abyssinian Guinea Pig",
"Peruvian Guinea Pig",
"Silkie Guinea Pig",
"Teddy Guinea Pig",
"Skinny Pig",
];
const HAMSTER_BREEDS = [
"Syrian Hamster",
"Roborovski Hamster",
"Campbell's Dwarf Hamster",
"Winter White Hamster",
"Chinese Hamster",
];
const MOUSE_BREEDS = [
"Fancy Mouse",
"Satin Mouse",
"Long-Haired Mouse",
"Hairless Mouse",
];
const RAT_BREEDS = [
"Standard Rat",
"Dumbo Rat",
"Hairless Rat",
"Rex Rat",
"Satin Rat",
];
const SNAKE_BREEDS = [
"Corn Snake",
"Ball Python",
"Boa Constrictor",
"King Snake",
"Milk Snake",
"Garter Snake",
];
const LIZARD_BREEDS = [
"Bearded Dragon",
"Green Iguana",
"Blue-Tongued Skink",
"Chameleon",
"Monitor Lizard",
];
const TURTLE_BREEDS = [
"Red-Eared Slider",
"Greek Tortoise",
"Hermann's Tortoise",
"Box Turtle",
"African Sulcata Tortoise",
];
const GECKO_BREEDS = [
"Leopard Gecko",
"Crested Gecko",
"Tokay Gecko",
"Day Gecko",
"Gargoyle Gecko",
];
const SPIDER_BREEDS = [
"Chilean Rose Tarantula",
"Mexican Red Knee Tarantula",
"Curly Hair Tarantula",
"Pink Toe Tarantula",
"Goliath Birdeater",
"Brazilian Black Tarantula",
];
const CHINCHILLA_BREEDS = [
"Standard Grey",
"Beige",
"White",
"Black Velvet",
"Violet",
"Sapphire",
"Ebony",
];
// The Species is the aquarium/tank as a whole (matches how aquarists
// actually showcase their hobby), not one profile per individual fish —
// "breed" here means the predominant fish species kept, same pattern as
// Bird covering many bird types via Breed.
const AQUARIUM_BREEDS = [
"Betta (Siamese Fighting Fish)",
"Guppy",
"Neon Tetra",
"Goldfish",
"Angelfish",
"Discus",
"Koi",
"Molly",
"Platy",
"Cichlid",
"Corydoras Catfish",
"Zebra Danio",
];
const SPECIES_DE: Record<string, string> = {
"Dog": "Hund",
"Cat": "Katze",
"Bird": "Vogel",
"Horse": "Pferd",
"Rabbit": "Kaninchen",
"Guinea Pig": "Meerschweinchen",
"Hamster": "Hamster",
"Mouse": "Maus",
"Rat": "Ratte",
"Snake": "Schlange",
"Lizard": "Echse",
"Turtle": "Schildkröte",
"Gecko": "Gecko",
"Spider": "Spinne",
"Chinchilla": "Chinchilla",
"Aquarium": "Aquarium",
};
const DOG_BREEDS_DE: Record<string, string> = {
"Labrador Retriever": "Labrador Retriever",
"Golden Retriever": "Golden Retriever",
"German Shepherd": "Deutscher Schäferhund",
"French Bulldog": "Französische Bulldogge",
"Bulldog": "Bulldogge",
"Poodle": "Pudel",
"Beagle": "Beagle",
"Rottweiler": "Rottweiler",
"German Shorthaired Pointer": "Deutsch Kurzhaar",
"Dachshund": "Dackel",
"Pembroke Welsh Corgi": "Pembroke Welsh Corgi",
"Australian Shepherd": "Australian Shepherd",
"Yorkshire Terrier": "Yorkshire Terrier",
"Boxer": "Boxer",
"Cavalier King Charles Spaniel": "Cavalier King Charles Spaniel",
"Doberman Pinscher": "Dobermann",
"Great Dane": "Deutsche Dogge",
"Miniature Schnauzer": "Zwergschnauzer",
"Siberian Husky": "Sibirischer Husky",
"Border Collie": "Border Collie",
};
const CAT_BREEDS_DE: Record<string, string> = {
"Domestic Shorthair": "Europäisch Kurzhaar",
"Domestic Longhair": "Europäisch Langhaar",
"Maine Coon": "Maine Coon",
"Ragdoll": "Ragdoll",
"Siamese": "Siamkatze",
"Persian": "Perserkatze",
"Bengal": "Bengalkatze",
"British Shorthair": "Britisch Kurzhaar",
"Sphynx": "Sphynx",
"Scottish Fold": "Scottish Fold",
"American Shorthair": "Amerikanisch Kurzhaar",
"Abyssinian": "Abessinier",
"Norwegian Forest Cat": "Norwegische Waldkatze",
"Birman": "Heilige Birma",
"Russian Blue": "Russisch Blau",
};
const BIRD_BREEDS_DE: Record<string, string> = {
"Budgerigar (Budgie)": "Wellensittich",
"Cockatiel": "Nymphensittich",
"Lovebird": "Unzertrennliche",
"African Grey Parrot": "Graupapagei",
"Cockatoo": "Kakadu",
"Conure": "Sittich",
"Macaw": "Ara",
"Canary": "Kanarienvogel",
"Finch": "Fink",
"Amazon Parrot": "Amazone",
};
const HORSE_BREEDS_DE: Record<string, string> = {
"Arabian Horse": "Araber",
"Icelandic Horse": "Islandpferd",
"Shetland Pony": "Shetlandpony",
"Haflinger": "Haflinger",
"Friesian": "Friese",
"Andalusian": "Andalusier",
"Quarter Horse": "Quarter Horse",
"Thoroughbred": "Englisches Vollblut",
"Warmblood": "Warmblut",
"Welsh Pony": "Welsh Pony",
"Trakehner": "Trakehner",
"Hanoverian": "Hannoveraner",
};
const RABBIT_BREEDS_DE: Record<string, string> = {
"Netherland Dwarf": "Hollandzwerg",
"Holland Lop": "Widderkaninchen",
"Lionhead Rabbit": "Löwenkopfkaninchen",
"Rex Rabbit": "Rex-Kaninchen",
"Angora Rabbit": "Angorakaninchen",
"Flemish Giant": "Deutscher Riese",
"Mini Rex": "Mini Rex",
"Dutch Rabbit": "Holländer",
};
const GUINEA_PIG_BREEDS_DE: Record<string, string> = {
"American Guinea Pig": "Glatthaarmeerschweinchen",
"Abyssinian Guinea Pig": "Rosettenmeerschweinchen",
"Peruvian Guinea Pig": "Perumeerschweinchen",
"Silkie Guinea Pig": "Silkie",
"Teddy Guinea Pig": "Teddymeerschweinchen",
"Skinny Pig": "Skinny Pig",
};
const HAMSTER_BREEDS_DE: Record<string, string> = {
"Syrian Hamster": "Goldhamster",
"Roborovski Hamster": "Roborowski-Zwerghamster",
"Campbell's Dwarf Hamster": "Campbell-Zwerghamster",
"Winter White Hamster": "Dsungarischer Zwerghamster",
"Chinese Hamster": "Chinesischer Streifenhamster",
};
const MOUSE_BREEDS_DE: Record<string, string> = {
"Fancy Mouse": "Farbmaus",
"Satin Mouse": "Satinmaus",
"Long-Haired Mouse": "Langhaarmaus",
"Hairless Mouse": "Nacktmaus",
};
const RAT_BREEDS_DE: Record<string, string> = {
"Standard Rat": "Standardratte",
"Dumbo Rat": "Dumbo-Ratte",
"Hairless Rat": "Nacktratte",
"Rex Rat": "Rex-Ratte",
"Satin Rat": "Satin-Ratte",
};
const SNAKE_BREEDS_DE: Record<string, string> = {
"Corn Snake": "Kornnatter",
"Ball Python": "Königspython",
"Boa Constrictor": "Abgottschlange",
"King Snake": "Königsnatter",
"Milk Snake": "Milchschlange",
"Garter Snake": "Strumpfbandnatter",
};
const LIZARD_BREEDS_DE: Record<string, string> = {
"Bearded Dragon": "Bartagame",
"Green Iguana": "Grüner Leguan",
"Blue-Tongued Skink": "Blauzungenskink",
"Chameleon": "Chamäleon",
"Monitor Lizard": "Waran",
};
const TURTLE_BREEDS_DE: Record<string, string> = {
"Red-Eared Slider": "Rotwangen-Schmuckschildkröte",
"Greek Tortoise": "Griechische Landschildkröte",
"Hermann's Tortoise": "Griechische Landschildkröte (Testudo hermanni)",
"Box Turtle": "Dosenschildkröte",
"African Sulcata Tortoise": "Spornschildkröte",
};
const GECKO_BREEDS_DE: Record<string, string> = {
"Leopard Gecko": "Leopardgecko",
"Crested Gecko": "Kronengecko",
"Tokay Gecko": "Tokeh",
"Day Gecko": "Taggecko",
"Gargoyle Gecko": "Gargoyle-Gecko",
};
const SPIDER_BREEDS_DE: Record<string, string> = {
"Chilean Rose Tarantula": "Chilenische Rosenhaarvogelspinne",
"Mexican Red Knee Tarantula": "Mexikanische Rotknievogelspinne",
"Curly Hair Tarantula": "Lockenhaarvogelspinne",
"Pink Toe Tarantula": "Antillen-Baumvogelspinne",
"Goliath Birdeater": "Goliath-Vogelspinne",
"Brazilian Black Tarantula": "Brasilianische Schwarze Vogelspinne",
};
const CHINCHILLA_BREEDS_DE: Record<string, string> = {
"Standard Grey": "Standardgrau",
"Beige": "Beige",
"White": "Weiß",
"Black Velvet": "Black Velvet",
"Violet": "Violett",
"Sapphire": "Saphir",
"Ebony": "Ebony",
};
const AQUARIUM_BREEDS_DE: Record<string, string> = {
"Betta (Siamese Fighting Fish)": "Kampffisch",
"Guppy": "Guppy",
"Neon Tetra": "Neonsalmler",
"Goldfish": "Goldfisch",
"Angelfish": "Skalar",
"Discus": "Diskusfisch",
"Koi": "Koi",
"Molly": "Molly",
"Platy": "Platy",
"Cichlid": "Buntbarsch",
"Corydoras Catfish": "Panzerwels",
"Zebra Danio": "Zebrabärbling",
};
const BREED_DE_BY_SPECIES: Record<string, Record<string, string>> = {
"Dog": DOG_BREEDS_DE,
"Cat": CAT_BREEDS_DE,
"Bird": BIRD_BREEDS_DE,
"Horse": HORSE_BREEDS_DE,
"Rabbit": RABBIT_BREEDS_DE,
"Guinea Pig": GUINEA_PIG_BREEDS_DE,
"Hamster": HAMSTER_BREEDS_DE,
"Mouse": MOUSE_BREEDS_DE,
"Rat": RAT_BREEDS_DE,
"Snake": SNAKE_BREEDS_DE,
"Lizard": LIZARD_BREEDS_DE,
"Turtle": TURTLE_BREEDS_DE,
"Gecko": GECKO_BREEDS_DE,
"Spider": SPIDER_BREEDS_DE,
"Chinchilla": CHINCHILLA_BREEDS_DE,
"Aquarium": AQUARIUM_BREEDS_DE,
};
async function main() {
console.log("Seeding species...");
const speciesData = [
{ name: "Dog", breeds: DOG_BREEDS },
{ name: "Cat", breeds: CAT_BREEDS },
{ name: "Bird", breeds: BIRD_BREEDS },
{ name: "Horse", breeds: HORSE_BREEDS },
{ name: "Rabbit", breeds: RABBIT_BREEDS },
{ name: "Guinea Pig", breeds: GUINEA_PIG_BREEDS },
{ name: "Hamster", breeds: HAMSTER_BREEDS },
{ name: "Mouse", breeds: MOUSE_BREEDS },
{ name: "Rat", breeds: RAT_BREEDS },
{ name: "Snake", breeds: SNAKE_BREEDS },
{ name: "Lizard", breeds: LIZARD_BREEDS },
{ name: "Turtle", breeds: TURTLE_BREEDS },
{ name: "Gecko", breeds: GECKO_BREEDS },
{ name: "Spider", breeds: SPIDER_BREEDS },
{ name: "Chinchilla", breeds: CHINCHILLA_BREEDS },
{ name: "Aquarium", breeds: AQUARIUM_BREEDS },
];
for (const s of speciesData) {
const species = await prisma.species.upsert({
where: { name: s.name },
update: {},
create: { name: s.name },
});
console.log(` Upserted species: ${species.name} (${species.id})`);
const deSpeciesName = SPECIES_DE[s.name];
if (deSpeciesName) {
await prisma.speciesTranslation.upsert({
where: { speciesId_locale: { speciesId: species.id, locale: "de" } },
update: { name: deSpeciesName },
create: { speciesId: species.id, locale: "de", name: deSpeciesName },
});
}
console.log(` Seeding ${s.breeds.length} breeds for ${species.name}...`);
const breedDeMap = BREED_DE_BY_SPECIES[s.name] ?? {};
for (const breedName of s.breeds) {
const breed = await prisma.breed.upsert({
where: { speciesId_name: { speciesId: species.id, name: breedName } },
update: {},
create: { speciesId: species.id, name: breedName },
});
const deBreedName = breedDeMap[breedName];
if (deBreedName) {
await prisma.breedTranslation.upsert({
where: { breedId_locale: { breedId: breed.id, locale: "de" } },
update: { name: deBreedName },
create: { breedId: breed.id, locale: "de", name: deBreedName },
});
}
console.log(` Upserted breed: ${breed.name}`);
}
}
console.log("Seeding complete.");
}
main()
.catch((e) => {
console.error(e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});