feat(19-01): update Zod schemas, types, and seed script for reference model

- Add globalItemId and purchasePriceCents to createItemSchema
- Add globalItemId to createCandidateSchema
- Add tags param to searchGlobalItemsSchema
- Remove linkItemSchema from schemas and types
- Replace ItemGlobalLink with Tag and GlobalItemTag types
- Convert seedGlobalItems to async, add seedTags with 30 curated tags
This commit is contained in:
2026-04-05 20:27:51 +02:00
parent 5df513c138
commit e9baa8d7e0
3 changed files with 67 additions and 21 deletions

View File

@@ -1,27 +1,73 @@
import seedData from "./global-items-seed.json";
import { db as prodDb } from "./index.ts";
import { globalItems } from "./schema.ts";
import { globalItems, tags } from "./schema.ts";
type Db = typeof prodDb;
const SEED_TAGS = [
"handlebar-bag",
"framebag",
"saddlebag",
"top-tube-bag",
"stem-bag",
"fork-bag",
"hip-pack",
"backpack",
"tent",
"bivy",
"tarp",
"hammock",
"sleeping-bag",
"sleeping-pad",
"quilt",
"pillow",
"stove",
"cookware",
"water-filter",
"water-bottle",
"headlamp",
"bike-light",
"ultralight",
"waterproof",
"budget",
"premium",
"bikepacking",
"hiking",
"camping",
"touring",
];
/**
* Seed curated tags for outdoor/adventure gear.
* Idempotent: skips if any tags already exist.
*/
export async function seedTags(db: Db = prodDb) {
const existing = await db.select().from(tags).limit(1);
if (existing.length > 0) return;
for (const name of SEED_TAGS) {
await db.insert(tags).values({ name });
}
}
/**
* Seed the global items table with initial bikepacking gear data.
* Idempotent: skips if any rows already exist.
*/
export function seedGlobalItems(db: Db = prodDb) {
const existing = db.select().from(globalItems).limit(1).all();
export async function seedGlobalItems(db: Db = prodDb) {
const existing = await db.select().from(globalItems).limit(1);
if (existing.length > 0) return;
for (const item of seedData) {
db.insert(globalItems)
.values({
brand: item.brand,
model: item.model,
category: item.category ?? null,
weightGrams: item.weightGrams ?? null,
priceCents: item.priceCents ?? null,
description: item.description ?? null,
})
.run();
await db.insert(globalItems).values({
brand: item.brand,
model: item.model,
category: item.category ?? null,
weightGrams: item.weightGrams ?? null,
priceCents: item.priceCents ?? null,
description: item.description ?? null,
});
}
await seedTags(db);
}