feat(18-01): add globalItems, itemGlobalLinks tables and user profile/setup visibility columns

- Add globalItems table with brand, model, category, weightGrams, priceCents, imageUrl, description
- Add itemGlobalLinks junction table linking user items to global items (unique per item)
- Add displayName, avatarUrl, bio nullable columns to users table
- Add isPublic boolean column to setups table (default false)
- Import boolean from drizzle-orm/pg-core
- Generate migration 0001_tough_boomerang.sql
This commit is contained in:
2026-04-05 12:57:49 +02:00
parent 37d5711475
commit 82657038cc
4 changed files with 1157 additions and 0 deletions

View File

@@ -0,0 +1,25 @@
CREATE TABLE "global_items" (
"id" serial PRIMARY KEY NOT NULL,
"brand" text NOT NULL,
"model" text NOT NULL,
"category" text,
"weight_grams" double precision,
"price_cents" integer,
"image_url" text,
"description" text,
"created_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE "item_global_links" (
"id" serial PRIMARY KEY NOT NULL,
"item_id" integer NOT NULL,
"global_item_id" integer NOT NULL,
CONSTRAINT "item_global_links_item_id_unique" UNIQUE("item_id")
);
--> statement-breakpoint
ALTER TABLE "setups" ADD COLUMN "is_public" boolean DEFAULT false NOT NULL;--> statement-breakpoint
ALTER TABLE "users" ADD COLUMN "display_name" text;--> statement-breakpoint
ALTER TABLE "users" ADD COLUMN "avatar_url" text;--> statement-breakpoint
ALTER TABLE "users" ADD COLUMN "bio" text;--> statement-breakpoint
ALTER TABLE "item_global_links" ADD CONSTRAINT "item_global_links_item_id_items_id_fk" FOREIGN KEY ("item_id") REFERENCES "public"."items"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "item_global_links" ADD CONSTRAINT "item_global_links_global_item_id_global_items_id_fk" FOREIGN KEY ("global_item_id") REFERENCES "public"."global_items"("id") ON DELETE cascade ON UPDATE no action;

File diff suppressed because it is too large Load Diff

View File

@@ -8,6 +8,13 @@
"when": 1775377947759, "when": 1775377947759,
"tag": "0000_thankful_loners", "tag": "0000_thankful_loners",
"breakpoints": true "breakpoints": true
},
{
"idx": 1,
"version": "7",
"when": 1775386658636,
"tag": "0001_tough_boomerang",
"breakpoints": true
} }
] ]
} }

View File

@@ -1,4 +1,5 @@
import { import {
boolean,
doublePrecision, doublePrecision,
integer, integer,
pgTable, pgTable,
@@ -14,6 +15,9 @@ import {
export const users = pgTable("users", { export const users = pgTable("users", {
id: serial("id").primaryKey(), id: serial("id").primaryKey(),
logtoSub: text("logto_sub").notNull().unique(), logtoSub: text("logto_sub").notNull().unique(),
displayName: text("display_name"),
avatarUrl: text("avatar_url"),
bio: text("bio"),
createdAt: timestamp("created_at").defaultNow().notNull(), createdAt: timestamp("created_at").defaultNow().notNull(),
}); });
@@ -105,6 +109,7 @@ export const setups = pgTable("setups", {
userId: integer("user_id") userId: integer("user_id")
.notNull() .notNull()
.references(() => users.id), .references(() => users.id),
isPublic: boolean("is_public").notNull().default(false),
createdAt: timestamp("created_at").defaultNow().notNull(), createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at").defaultNow().notNull(), updatedAt: timestamp("updated_at").defaultNow().notNull(),
}); });
@@ -122,6 +127,33 @@ export const setupItems = pgTable("setup_items", {
classification: text("classification").notNull().default("base"), classification: text("classification").notNull().default("base"),
}); });
// ── Global Items ────────────────────────────────────────────────────
export const globalItems = pgTable("global_items", {
id: serial("id").primaryKey(),
brand: text("brand").notNull(),
model: text("model").notNull(),
category: text("category"),
weightGrams: doublePrecision("weight_grams"),
priceCents: integer("price_cents"),
imageUrl: text("image_url"),
description: text("description"),
createdAt: timestamp("created_at").defaultNow().notNull(),
});
// ── Item Global Links ───────────────────────────────────────────────
export const itemGlobalLinks = pgTable("item_global_links", {
id: serial("id").primaryKey(),
itemId: integer("item_id")
.notNull()
.references(() => items.id, { onDelete: "cascade" })
.unique(),
globalItemId: integer("global_item_id")
.notNull()
.references(() => globalItems.id, { onDelete: "cascade" }),
});
// ── Settings ──────────────────────────────────────────────────────── // ── Settings ────────────────────────────────────────────────────────
export const settings = pgTable( export const settings = pgTable(