Files
bricktrack/drizzle/0000_clean_sumo.sql
T
unknownandClaude Opus 5 06268bcfd6 feat(db): drizzle-schema, db-client und initiale migration
Vollstaendiges Datenmodell: Katalog (manufacturer, theme, set, tag,
instruction), Besitz (collection_item, location, missing_part, photo),
Wunschlisten (wishlist, wishlist_item) und die Auth-Tabellen von
better-auth inklusive passkey und invite.

Kernregel: ein set ist ein Katalogeintrag, ein collection_item die
Verknuepfung mit dem tatsaechlichen Besitz. Preise liegen als Cent in
INTEGER-Spalten, damit Summen exakt bleiben.

SQLite laeuft mit WAL, foreign_keys=ON und busy_timeout.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-06 22:25:22 +02:00

271 lines
10 KiB
SQL

CREATE TABLE `account` (
`id` text PRIMARY KEY NOT NULL,
`accountId` text NOT NULL,
`providerId` text NOT NULL,
`userId` text NOT NULL,
`accessToken` text,
`refreshToken` text,
`idToken` text,
`accessTokenExpiresAt` integer,
`refreshTokenExpiresAt` integer,
`scope` text,
`password` text,
`createdAt` integer NOT NULL,
`updatedAt` integer NOT NULL,
FOREIGN KEY (`userId`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE cascade
);
--> statement-breakpoint
CREATE INDEX `account_user_idx` ON `account` (`userId`);--> statement-breakpoint
CREATE TABLE `invite` (
`id` text PRIMARY KEY NOT NULL,
`token_hash` text NOT NULL,
`email` text,
`role` text DEFAULT 'member' NOT NULL,
`created_by_user_id` text NOT NULL,
`expires_at` integer NOT NULL,
`used_at` integer,
`used_by_user_id` text,
`created_at` integer NOT NULL,
FOREIGN KEY (`created_by_user_id`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE cascade,
FOREIGN KEY (`used_by_user_id`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE set null
);
--> statement-breakpoint
CREATE UNIQUE INDEX `invite_token_hash_unique` ON `invite` (`token_hash`);--> statement-breakpoint
CREATE TABLE `passkey` (
`id` text PRIMARY KEY NOT NULL,
`name` text,
`publicKey` text NOT NULL,
`userId` text NOT NULL,
`credentialID` text NOT NULL,
`counter` integer NOT NULL,
`deviceType` text NOT NULL,
`backedUp` integer NOT NULL,
`transports` text,
`aaguid` text,
`createdAt` integer,
FOREIGN KEY (`userId`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE cascade
);
--> statement-breakpoint
CREATE UNIQUE INDEX `passkey_credentialID_unique` ON `passkey` (`credentialID`);--> statement-breakpoint
CREATE INDEX `passkey_user_idx` ON `passkey` (`userId`);--> statement-breakpoint
CREATE TABLE `rateLimit` (
`id` text PRIMARY KEY NOT NULL,
`key` text,
`count` integer,
`lastRequest` integer
);
--> statement-breakpoint
CREATE TABLE `session` (
`id` text PRIMARY KEY NOT NULL,
`token` text NOT NULL,
`userId` text NOT NULL,
`expiresAt` integer NOT NULL,
`ipAddress` text,
`userAgent` text,
`createdAt` integer NOT NULL,
`updatedAt` integer NOT NULL,
FOREIGN KEY (`userId`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE cascade
);
--> statement-breakpoint
CREATE UNIQUE INDEX `session_token_unique` ON `session` (`token`);--> statement-breakpoint
CREATE INDEX `session_user_idx` ON `session` (`userId`);--> statement-breakpoint
CREATE TABLE `user` (
`id` text PRIMARY KEY NOT NULL,
`name` text NOT NULL,
`email` text NOT NULL,
`emailVerified` integer DEFAULT false NOT NULL,
`image` text,
`role` text DEFAULT 'member' NOT NULL,
`createdAt` integer NOT NULL,
`updatedAt` integer NOT NULL
);
--> statement-breakpoint
CREATE UNIQUE INDEX `user_email_unique` ON `user` (`email`);--> statement-breakpoint
CREATE TABLE `verification` (
`id` text PRIMARY KEY NOT NULL,
`identifier` text NOT NULL,
`value` text NOT NULL,
`expiresAt` integer NOT NULL,
`createdAt` integer NOT NULL,
`updatedAt` integer NOT NULL
);
--> statement-breakpoint
CREATE INDEX `verification_identifier_idx` ON `verification` (`identifier`);--> statement-breakpoint
CREATE TABLE `instruction` (
`id` text PRIMARY KEY NOT NULL,
`set_id` text NOT NULL,
`kind` text NOT NULL,
`file_path` text,
`url` text,
`label` text,
`page_count` integer,
`file_size_bytes` integer,
`sort_order` integer DEFAULT 0 NOT NULL,
`created_at` integer NOT NULL,
FOREIGN KEY (`set_id`) REFERENCES `set`(`id`) ON UPDATE no action ON DELETE cascade,
CONSTRAINT "instruction_source" CHECK(("instruction"."kind" = 'pdf_upload' AND "instruction"."file_path" IS NOT NULL AND "instruction"."url" IS NULL)
OR ("instruction"."kind" = 'external_url' AND "instruction"."url" IS NOT NULL AND "instruction"."file_path" IS NULL))
);
--> statement-breakpoint
CREATE INDEX `instruction_set_idx` ON `instruction` (`set_id`);--> statement-breakpoint
CREATE TABLE `manufacturer` (
`id` text PRIMARY KEY NOT NULL,
`name` text NOT NULL,
`slug` text NOT NULL,
`website` text,
`created_at` integer NOT NULL,
`updated_at` integer NOT NULL
);
--> statement-breakpoint
CREATE UNIQUE INDEX `manufacturer_slug_unique` ON `manufacturer` (`slug`);--> statement-breakpoint
CREATE TABLE `set` (
`id` text PRIMARY KEY NOT NULL,
`manufacturer_id` text NOT NULL,
`theme_id` text,
`set_number` text NOT NULL,
`name` text NOT NULL,
`year` integer,
`piece_count` integer,
`minifig_count` integer,
`ean` text,
`age_range` text,
`image_url` text,
`image_path` text,
`retail_price_cents` integer,
`external_ids` text,
`notes` text,
`created_at` integer NOT NULL,
`updated_at` integer NOT NULL,
FOREIGN KEY (`manufacturer_id`) REFERENCES `manufacturer`(`id`) ON UPDATE no action ON DELETE restrict,
FOREIGN KEY (`theme_id`) REFERENCES `theme`(`id`) ON UPDATE no action ON DELETE set null
);
--> statement-breakpoint
CREATE UNIQUE INDEX `set_manufacturer_number_unique` ON `set` (`manufacturer_id`,`set_number`);--> statement-breakpoint
CREATE INDEX `set_name_idx` ON `set` (`name`);--> statement-breakpoint
CREATE INDEX `set_ean_idx` ON `set` (`ean`);--> statement-breakpoint
CREATE INDEX `set_theme_idx` ON `set` (`theme_id`);--> statement-breakpoint
CREATE INDEX `set_year_idx` ON `set` (`year`);--> statement-breakpoint
CREATE TABLE `set_tag` (
`set_id` text NOT NULL,
`tag_id` text NOT NULL,
PRIMARY KEY(`set_id`, `tag_id`),
FOREIGN KEY (`set_id`) REFERENCES `set`(`id`) ON UPDATE no action ON DELETE cascade,
FOREIGN KEY (`tag_id`) REFERENCES `tag`(`id`) ON UPDATE no action ON DELETE cascade
);
--> statement-breakpoint
CREATE TABLE `tag` (
`id` text PRIMARY KEY NOT NULL,
`name` text NOT NULL,
`slug` text NOT NULL
);
--> statement-breakpoint
CREATE UNIQUE INDEX `tag_slug_unique` ON `tag` (`slug`);--> statement-breakpoint
CREATE TABLE `theme` (
`id` text PRIMARY KEY NOT NULL,
`manufacturer_id` text NOT NULL,
`parent_theme_id` text,
`name` text NOT NULL,
`created_at` integer NOT NULL,
`updated_at` integer NOT NULL,
FOREIGN KEY (`manufacturer_id`) REFERENCES `manufacturer`(`id`) ON UPDATE no action ON DELETE cascade,
FOREIGN KEY (`parent_theme_id`) REFERENCES `theme`(`id`) ON UPDATE no action ON DELETE set null
);
--> statement-breakpoint
CREATE INDEX `theme_manufacturer_idx` ON `theme` (`manufacturer_id`);--> statement-breakpoint
CREATE UNIQUE INDEX `theme_unique_name` ON `theme` (`manufacturer_id`,`name`);--> statement-breakpoint
CREATE TABLE `collection_item` (
`id` text PRIMARY KEY NOT NULL,
`set_id` text NOT NULL,
`status` text DEFAULT 'owned' NOT NULL,
`completeness` text DEFAULT 'unknown' NOT NULL,
`condition` text,
`location_id` text,
`acquired_at` integer,
`acquired_price_cents` integer,
`acquired_from` text,
`gifted_by` text,
`lent_out_to` text,
`notes` text,
`created_at` integer NOT NULL,
`updated_at` integer NOT NULL,
FOREIGN KEY (`set_id`) REFERENCES `set`(`id`) ON UPDATE no action ON DELETE cascade,
FOREIGN KEY (`location_id`) REFERENCES `location`(`id`) ON UPDATE no action ON DELETE set null
);
--> statement-breakpoint
CREATE INDEX `collection_item_set_idx` ON `collection_item` (`set_id`);--> statement-breakpoint
CREATE INDEX `collection_item_status_idx` ON `collection_item` (`status`);--> statement-breakpoint
CREATE INDEX `collection_item_location_idx` ON `collection_item` (`location_id`);--> statement-breakpoint
CREATE TABLE `location` (
`id` text PRIMARY KEY NOT NULL,
`name` text NOT NULL,
`parent_location_id` text,
`created_at` integer NOT NULL,
`updated_at` integer NOT NULL,
FOREIGN KEY (`parent_location_id`) REFERENCES `location`(`id`) ON UPDATE no action ON DELETE set null
);
--> statement-breakpoint
CREATE TABLE `missing_part` (
`id` text PRIMARY KEY NOT NULL,
`collection_item_id` text NOT NULL,
`part_number` text,
`color_name` text,
`quantity` integer DEFAULT 1 NOT NULL,
`resolved` integer DEFAULT false NOT NULL,
`notes` text,
`created_at` integer NOT NULL,
FOREIGN KEY (`collection_item_id`) REFERENCES `collection_item`(`id`) ON UPDATE no action ON DELETE cascade
);
--> statement-breakpoint
CREATE INDEX `missing_part_item_idx` ON `missing_part` (`collection_item_id`);--> statement-breakpoint
CREATE TABLE `photo` (
`id` text PRIMARY KEY NOT NULL,
`set_id` text,
`collection_item_id` text,
`file_path` text NOT NULL,
`thumbnail_path` text,
`caption` text,
`sort_order` integer DEFAULT 0 NOT NULL,
`created_at` integer NOT NULL,
FOREIGN KEY (`set_id`) REFERENCES `set`(`id`) ON UPDATE no action ON DELETE cascade,
FOREIGN KEY (`collection_item_id`) REFERENCES `collection_item`(`id`) ON UPDATE no action ON DELETE cascade,
CONSTRAINT "photo_single_owner" CHECK(("photo"."set_id" IS NOT NULL) <> ("photo"."collection_item_id" IS NOT NULL))
);
--> statement-breakpoint
CREATE INDEX `photo_set_idx` ON `photo` (`set_id`);--> statement-breakpoint
CREATE INDEX `photo_item_idx` ON `photo` (`collection_item_id`);--> statement-breakpoint
CREATE TABLE `wishlist` (
`id` text PRIMARY KEY NOT NULL,
`owner_user_id` text NOT NULL,
`title` text NOT NULL,
`occasion` text DEFAULT 'other' NOT NULL,
`event_date` integer,
`share_token` text NOT NULL,
`is_public` integer DEFAULT false NOT NULL,
`surprise_mode` integer DEFAULT false NOT NULL,
`note` text,
`created_at` integer NOT NULL,
`updated_at` integer NOT NULL,
FOREIGN KEY (`owner_user_id`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE cascade
);
--> statement-breakpoint
CREATE UNIQUE INDEX `wishlist_share_token_unique` ON `wishlist` (`share_token`);--> statement-breakpoint
CREATE INDEX `wishlist_owner_idx` ON `wishlist` (`owner_user_id`);--> statement-breakpoint
CREATE TABLE `wishlist_item` (
`id` text PRIMARY KEY NOT NULL,
`wishlist_id` text NOT NULL,
`set_id` text NOT NULL,
`priority` integer DEFAULT 2 NOT NULL,
`note` text,
`sort_order` integer DEFAULT 0 NOT NULL,
`reserved_by_name` text,
`reserved_at` integer,
`reservation_token_hash` text,
`fulfilled_at` integer,
`created_at` integer NOT NULL,
FOREIGN KEY (`wishlist_id`) REFERENCES `wishlist`(`id`) ON UPDATE no action ON DELETE cascade,
FOREIGN KEY (`set_id`) REFERENCES `set`(`id`) ON UPDATE no action ON DELETE cascade,
CONSTRAINT "wishlist_item_priority" CHECK("wishlist_item"."priority" BETWEEN 1 AND 3)
);
--> statement-breakpoint
CREATE UNIQUE INDEX `wishlist_item_unique` ON `wishlist_item` (`wishlist_id`,`set_id`);--> statement-breakpoint
CREATE INDEX `wishlist_item_list_idx` ON `wishlist_item` (`wishlist_id`,`sort_order`);