feat: seed manufacturers list, update seedGlobalItems to resolve by name
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,81 +1,59 @@
|
||||
import seedData from "./global-items-seed.json";
|
||||
import { db as prodDb } from "./index.ts";
|
||||
import { globalItems, tags } from "./schema.ts";
|
||||
import { globalItems, manufacturers, tags } from "./schema.ts";
|
||||
|
||||
type Db = typeof prodDb;
|
||||
|
||||
const SEED_TAGS = [
|
||||
// Hobby / activity tags (used by onboarding hobby picker)
|
||||
"bikepacking",
|
||||
"cycling",
|
||||
"hiking",
|
||||
"backpacking",
|
||||
"camping",
|
||||
"climbing",
|
||||
"mountaineering",
|
||||
"road-cycling",
|
||||
"gravel",
|
||||
"running",
|
||||
"trail-running",
|
||||
// Bag types
|
||||
"handlebar-bag",
|
||||
"framebag",
|
||||
"saddlebag",
|
||||
"top-tube-bag",
|
||||
"stem-bag",
|
||||
"fork-bag",
|
||||
"feed-bag",
|
||||
"dry-bag",
|
||||
"stuff-sack",
|
||||
// Bike bags (parent)
|
||||
"bike-bag",
|
||||
// Shelter
|
||||
"tent",
|
||||
"bivy",
|
||||
"tarp",
|
||||
"hammock",
|
||||
// Sleep system
|
||||
"sleeping-bag",
|
||||
"sleeping-pad",
|
||||
"quilt",
|
||||
"pillow",
|
||||
// Cooking
|
||||
"stove",
|
||||
"cookware",
|
||||
"mug",
|
||||
"utensils",
|
||||
// Water
|
||||
"water-filter",
|
||||
"water-bottle",
|
||||
// Lighting
|
||||
"headlamp",
|
||||
"bike-light",
|
||||
"lantern",
|
||||
// Navigation & electronics
|
||||
"gps",
|
||||
"bike-computer",
|
||||
"power-bank",
|
||||
"solar-panel",
|
||||
// Tools & repair
|
||||
"multi-tool",
|
||||
"pump",
|
||||
"repair-kit",
|
||||
"lock",
|
||||
// Clothing
|
||||
"rain-jacket",
|
||||
"base-layer",
|
||||
"gloves",
|
||||
"shoe",
|
||||
export const SEED_MANUFACTURERS = [
|
||||
{ name: "Revelate Designs", slug: "revelate-designs", website: "https://revelatedesigns.com", country: "US", tier: 1 },
|
||||
{ name: "Apidura", slug: "apidura", website: "https://apidura.com", country: "GB", tier: 1 },
|
||||
{ name: "Ortlieb", slug: "ortlieb", website: "https://ortlieb.com", country: "DE", tier: 1 },
|
||||
{ name: "Big Agnes", slug: "big-agnes", website: "https://bigagnes.com", country: "US", tier: 1 },
|
||||
{ name: "Tarptent", slug: "tarptent", website: "https://tarptent.com", country: "US", tier: 1 },
|
||||
{ name: "Zpacks", slug: "zpacks", website: "https://zpacks.com", country: "US", tier: 1 },
|
||||
{ name: "Sea to Summit", slug: "sea-to-summit", website: "https://seatosummit.com", country: "AU", tier: 1 },
|
||||
{ name: "Western Mountaineering", slug: "western-mountaineering", website: "https://westernmountaineering.com", country: "US", tier: 1 },
|
||||
{ name: "MSR", slug: "msr", website: "https://msrgear.com", country: "US", tier: 1 },
|
||||
{ name: "BioLite", slug: "biolite", website: "https://bioliteenergy.com", country: "US", tier: 1 },
|
||||
{ name: "Petzl", slug: "petzl", website: "https://petzl.com", country: "FR", tier: 1 },
|
||||
{ name: "Black Diamond", slug: "black-diamond", website: "https://blackdiamondequipment.com", country: "US", tier: 1 },
|
||||
{ name: "Garmin", slug: "garmin", website: "https://garmin.com", country: "US", tier: 1 },
|
||||
{ name: "Wahoo", slug: "wahoo", website: "https://wahoofitness.com", country: "US", tier: 1 },
|
||||
{ name: "Sawyer", slug: "sawyer", website: "https://sawyerproducts.com", country: "US", tier: 1 },
|
||||
{ name: "Canyon", slug: "canyon", website: "https://canyon.com", country: "DE", tier: 1 },
|
||||
{ name: "Specialized", slug: "specialized", website: "https://specialized.com", country: "US", tier: 1 },
|
||||
{ name: "Trek", slug: "trek", website: "https://trekbikes.com", country: "US", tier: 1 },
|
||||
{ name: "Salsa Cycles", slug: "salsa-cycles", website: "https://salsacycles.com", country: "US", tier: 1 },
|
||||
{ name: "Surly", slug: "surly", website: "https://surlybikes.com", country: "US", tier: 1 },
|
||||
];
|
||||
|
||||
/**
|
||||
* Seed curated tags for outdoor/adventure gear.
|
||||
* Idempotent: inserts only tags that don't already exist.
|
||||
*/
|
||||
const SEED_TAGS = [
|
||||
"bikepacking", "cycling", "hiking", "backpacking", "camping", "climbing",
|
||||
"mountaineering", "road-cycling", "gravel", "running", "trail-running",
|
||||
"handlebar-bag", "framebag", "saddlebag", "top-tube-bag", "stem-bag",
|
||||
"fork-bag", "feed-bag", "dry-bag", "stuff-sack", "bike-bag",
|
||||
"tent", "bivy", "tarp", "hammock",
|
||||
"sleeping-bag", "sleeping-pad", "quilt", "pillow",
|
||||
"stove", "cookware", "mug", "utensils",
|
||||
"water-filter", "water-bottle",
|
||||
"headlamp", "bike-light", "lantern",
|
||||
"gps", "bike-computer", "power-bank", "solar-panel",
|
||||
"multi-tool", "pump", "repair-kit", "lock",
|
||||
"rain-jacket", "base-layer", "gloves", "shoe",
|
||||
];
|
||||
|
||||
export async function seedManufacturers(db: Db = prodDb) {
|
||||
for (const m of SEED_MANUFACTURERS) {
|
||||
await db
|
||||
.insert(manufacturers)
|
||||
.values(m)
|
||||
.onConflictDoNothing();
|
||||
}
|
||||
}
|
||||
|
||||
export async function seedTags(db: Db = prodDb) {
|
||||
const existing = await db.select().from(tags);
|
||||
const existingNames = new Set(existing.map((t) => t.name));
|
||||
|
||||
for (const name of SEED_TAGS) {
|
||||
if (!existingNames.has(name)) {
|
||||
await db.insert(tags).values({ name });
|
||||
@@ -83,17 +61,21 @@ export async function seedTags(db: Db = prodDb) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Seed the global items table with initial bikepacking gear data.
|
||||
* Idempotent: skips if any rows already exist.
|
||||
*/
|
||||
export async function seedGlobalItems(db: Db = prodDb) {
|
||||
await seedManufacturers(db);
|
||||
|
||||
const existing = await db.select().from(globalItems).limit(1);
|
||||
if (existing.length > 0) return;
|
||||
|
||||
const allManufacturers = await db.select().from(manufacturers);
|
||||
const mfByName = new Map(allManufacturers.map((m) => [m.name, m.id]));
|
||||
|
||||
for (const item of seedData) {
|
||||
const manufacturerId = mfByName.get(item.brand);
|
||||
if (!manufacturerId) continue;
|
||||
|
||||
await db.insert(globalItems).values({
|
||||
brand: item.brand,
|
||||
manufacturerId,
|
||||
model: item.model,
|
||||
category: item.category ?? null,
|
||||
weightGrams: item.weightGrams ?? null,
|
||||
|
||||
Reference in New Issue
Block a user