- Add pros/cons nullable TEXT columns to threadCandidates schema - Generate and apply Drizzle migration (0004_soft_synch.sql) - Mirror pros/cons columns in test helper CREATE TABLE - createCandidate: pass pros/cons to values() object - updateCandidate: add pros/cons to Partial type - getThreadWithCandidates: include pros/cons in select projection - createCandidateSchema: add optional pros/cons string fields
98 lines
3.1 KiB
TypeScript
98 lines
3.1 KiB
TypeScript
import { integer, real, sqliteTable, text } from "drizzle-orm/sqlite-core";
|
|
|
|
export const categories = sqliteTable("categories", {
|
|
id: integer("id").primaryKey({ autoIncrement: true }),
|
|
name: text("name").notNull().unique(),
|
|
icon: text("icon").notNull().default("package"),
|
|
createdAt: integer("created_at", { mode: "timestamp" })
|
|
.notNull()
|
|
.$defaultFn(() => new Date()),
|
|
});
|
|
|
|
export const items = sqliteTable("items", {
|
|
id: integer("id").primaryKey({ autoIncrement: true }),
|
|
name: text("name").notNull(),
|
|
weightGrams: real("weight_grams"),
|
|
priceCents: integer("price_cents"),
|
|
categoryId: integer("category_id")
|
|
.notNull()
|
|
.references(() => categories.id),
|
|
notes: text("notes"),
|
|
productUrl: text("product_url"),
|
|
imageFilename: text("image_filename"),
|
|
createdAt: integer("created_at", { mode: "timestamp" })
|
|
.notNull()
|
|
.$defaultFn(() => new Date()),
|
|
updatedAt: integer("updated_at", { mode: "timestamp" })
|
|
.notNull()
|
|
.$defaultFn(() => new Date()),
|
|
});
|
|
|
|
export const threads = sqliteTable("threads", {
|
|
id: integer("id").primaryKey({ autoIncrement: true }),
|
|
name: text("name").notNull(),
|
|
status: text("status").notNull().default("active"),
|
|
resolvedCandidateId: integer("resolved_candidate_id"),
|
|
categoryId: integer("category_id")
|
|
.notNull()
|
|
.references(() => categories.id),
|
|
createdAt: integer("created_at", { mode: "timestamp" })
|
|
.notNull()
|
|
.$defaultFn(() => new Date()),
|
|
updatedAt: integer("updated_at", { mode: "timestamp" })
|
|
.notNull()
|
|
.$defaultFn(() => new Date()),
|
|
});
|
|
|
|
export const threadCandidates = sqliteTable("thread_candidates", {
|
|
id: integer("id").primaryKey({ autoIncrement: true }),
|
|
threadId: integer("thread_id")
|
|
.notNull()
|
|
.references(() => threads.id, { onDelete: "cascade" }),
|
|
name: text("name").notNull(),
|
|
weightGrams: real("weight_grams"),
|
|
priceCents: integer("price_cents"),
|
|
categoryId: integer("category_id")
|
|
.notNull()
|
|
.references(() => categories.id),
|
|
notes: text("notes"),
|
|
productUrl: text("product_url"),
|
|
imageFilename: text("image_filename"),
|
|
status: text("status").notNull().default("researching"),
|
|
pros: text("pros"),
|
|
cons: text("cons"),
|
|
createdAt: integer("created_at", { mode: "timestamp" })
|
|
.notNull()
|
|
.$defaultFn(() => new Date()),
|
|
updatedAt: integer("updated_at", { mode: "timestamp" })
|
|
.notNull()
|
|
.$defaultFn(() => new Date()),
|
|
});
|
|
|
|
export const setups = sqliteTable("setups", {
|
|
id: integer("id").primaryKey({ autoIncrement: true }),
|
|
name: text("name").notNull(),
|
|
createdAt: integer("created_at", { mode: "timestamp" })
|
|
.notNull()
|
|
.$defaultFn(() => new Date()),
|
|
updatedAt: integer("updated_at", { mode: "timestamp" })
|
|
.notNull()
|
|
.$defaultFn(() => new Date()),
|
|
});
|
|
|
|
export const setupItems = sqliteTable("setup_items", {
|
|
id: integer("id").primaryKey({ autoIncrement: true }),
|
|
setupId: integer("setup_id")
|
|
.notNull()
|
|
.references(() => setups.id, { onDelete: "cascade" }),
|
|
itemId: integer("item_id")
|
|
.notNull()
|
|
.references(() => items.id, { onDelete: "cascade" }),
|
|
classification: text("classification").notNull().default("base"),
|
|
});
|
|
|
|
export const settings = sqliteTable("settings", {
|
|
key: text("key").primaryKey(),
|
|
value: text("value").notNull(),
|
|
});
|