From dca6ffd84d05a3cdb8114212ac79caa2a03ec3ea Mon Sep 17 00:00:00 2001 From: Jonatan Granqvist Date: Sun, 22 Feb 2026 13:54:44 +0100 Subject: [PATCH] add timeline schema --- package.json | 1 + packages/auth/package.json | 1 + packages/auth/src/index.ts | 5 ++++ packages/db/src/schema/auth.ts | 31 +++++++++++++++----- packages/db/src/schema/index.ts | 2 +- packages/db/src/schema/shared.ts | 18 ++++++++++++ packages/db/src/schema/timeline.ts | 47 ++++++++++++++++++++++++++++++ turbo.json | 3 ++ 8 files changed, 99 insertions(+), 9 deletions(-) create mode 100644 packages/db/src/schema/shared.ts create mode 100644 packages/db/src/schema/timeline.ts diff --git a/package.json b/package.json index 9343eed..817be47 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "check-types": "turbo check-types", "dev:native": "turbo -F native dev", "dev:web": "turbo -F web dev", + "auth:generate": "turbo -F @zendegi/auth auth:generate", "db:push": "turbo -F @zendegi/db db:push", "db:studio": "turbo -F @zendegi/db db:studio", "db:generate": "turbo -F @zendegi/db db:generate", diff --git a/packages/auth/package.json b/packages/auth/package.json index b486158..1145737 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -10,6 +10,7 @@ } }, "scripts": { + "auth:generate": "DOTENV_CONFIG_PATH=../../apps/web/.env pnpx @better-auth/cli generate --config src/index.ts --output ../db/src/schema/auth.ts", "check-types": "tsc --noEmit", "lint": "eslint ." }, diff --git a/packages/auth/src/index.ts b/packages/auth/src/index.ts index e976357..bcd382d 100644 --- a/packages/auth/src/index.ts +++ b/packages/auth/src/index.ts @@ -16,4 +16,9 @@ export const auth = betterAuth({ enabled: true, }, plugins: [tanstackStartCookies()], + advanced: { + database: { + generateId: "uuid", + }, + }, }); diff --git a/packages/db/src/schema/auth.ts b/packages/db/src/schema/auth.ts index a3e4c61..e2a996b 100644 --- a/packages/db/src/schema/auth.ts +++ b/packages/db/src/schema/auth.ts @@ -1,8 +1,17 @@ -import { relations } from "drizzle-orm"; -import { boolean, index, pgTable, text, timestamp } from "drizzle-orm/pg-core"; +import { relations, sql } from "drizzle-orm"; +import { + boolean, + index, + pgTable, + text, + timestamp, + uuid, +} from "drizzle-orm/pg-core"; export const user = pgTable("user", { - id: text("id").primaryKey(), + id: uuid("id") + .default(sql`pg_catalog.gen_random_uuid()`) + .primaryKey(), name: text("name").notNull(), email: text("email").notNull().unique(), emailVerified: boolean("email_verified").default(false).notNull(), @@ -17,7 +26,9 @@ export const user = pgTable("user", { export const session = pgTable( "session", { - id: text("id").primaryKey(), + id: uuid("id") + .default(sql`pg_catalog.gen_random_uuid()`) + .primaryKey(), expiresAt: timestamp("expires_at").notNull(), token: text("token").notNull().unique(), createdAt: timestamp("created_at").defaultNow().notNull(), @@ -26,7 +37,7 @@ export const session = pgTable( .notNull(), ipAddress: text("ip_address"), userAgent: text("user_agent"), - userId: text("user_id") + userId: uuid("user_id") .notNull() .references(() => user.id, { onDelete: "cascade" }), }, @@ -36,10 +47,12 @@ export const session = pgTable( export const account = pgTable( "account", { - id: text("id").primaryKey(), + id: uuid("id") + .default(sql`pg_catalog.gen_random_uuid()`) + .primaryKey(), accountId: text("account_id").notNull(), providerId: text("provider_id").notNull(), - userId: text("user_id") + userId: uuid("user_id") .notNull() .references(() => user.id, { onDelete: "cascade" }), accessToken: text("access_token"), @@ -60,7 +73,9 @@ export const account = pgTable( export const verification = pgTable( "verification", { - id: text("id").primaryKey(), + id: uuid("id") + .default(sql`pg_catalog.gen_random_uuid()`) + .primaryKey(), identifier: text("identifier").notNull(), value: text("value").notNull(), expiresAt: timestamp("expires_at").notNull(), diff --git a/packages/db/src/schema/index.ts b/packages/db/src/schema/index.ts index d9d31ea..8c4a2c6 100644 --- a/packages/db/src/schema/index.ts +++ b/packages/db/src/schema/index.ts @@ -1,2 +1,2 @@ export * from "./auth"; -export {}; +export * from "./timeline"; diff --git a/packages/db/src/schema/shared.ts b/packages/db/src/schema/shared.ts new file mode 100644 index 0000000..83b504a --- /dev/null +++ b/packages/db/src/schema/shared.ts @@ -0,0 +1,18 @@ +import { text, timestamp } from "drizzle-orm/pg-core"; +import { sql } from "drizzle-orm"; + +export const id = { + id: text("id") + .default(sql`pg_catalog.gen_random_uuid()`) + .primaryKey(), +}; + +export const timestamps = { + createdAt: timestamp("created_at", { withTimezone: true }) + .defaultNow() + .notNull(), + updatedAt: timestamp("updated_at", { withTimezone: true }) + .defaultNow() + .$onUpdate(() => new Date()) + .notNull(), +}; diff --git a/packages/db/src/schema/timeline.ts b/packages/db/src/schema/timeline.ts new file mode 100644 index 0000000..1281da1 --- /dev/null +++ b/packages/db/src/schema/timeline.ts @@ -0,0 +1,47 @@ +import { relations } from "drizzle-orm"; +import { integer, pgEnum, pgTable, text, timestamp } from "drizzle-orm/pg-core"; +import { user } from "./auth"; +import { id, timestamps } from "./shared"; + +export const visibility = pgEnum("visibility", ["private", "public"]); + +export const timeline = pgTable("timeline", { + ...id, + ownerId: text("owner_id") + .notNull() + .references(() => user.id, { onDelete: "cascade" }), + title: text("title").notNull(), + visibility: visibility().notNull().default("public"), + ...timestamps, +}); + +export const timelineGroup = pgTable("timeline_group", { + ...id, + title: text("title").notNull(), + sortOrder: integer().notNull().default(0), + timelineId: text("timeline_id") + .notNull() + .references(() => timeline.id, { onDelete: "cascade" }), + ...timestamps, +}); + +export const timelineItem = pgTable("timeline_item", { + ...id, + timelineGroupId: text("timeline_group_id") + .notNull() + .references(() => timelineGroup.id, { onDelete: "cascade" }), + title: text("title").notNull(), + description: text("description").notNull().default(""), + start: timestamp("start", { withTimezone: true }).notNull().defaultNow(), + // Allow null to denote a event without duration + end: timestamp("end", { withTimezone: true }), + ...timestamps, +}); + +export const timelineRelations = relations(timeline, ({ many }) => ({ + groups: many(timelineGroup), +})); + +export const groupRelations = relations(timelineGroup, ({ many }) => ({ + items: many(timelineItem), +})); diff --git a/turbo.json b/turbo.json index b1ed9f6..d3a6dd9 100644 --- a/turbo.json +++ b/turbo.json @@ -20,6 +20,9 @@ "cache": false, "persistent": true }, + "auth:generate": { + "cache": false + }, "db:push": { "cache": false },