From 3494876abbae659761f310f628390be884ff72e0 Mon Sep 17 00:00:00 2001 From: Bradley Shellnut Date: Fri, 2 Feb 2024 17:56:31 -0800 Subject: [PATCH] Migrating to drizzle schemas. --- package.json | 1 + pnpm-lock.yaml | 13 +- src/lib/drizzle.ts | 13 ++ src/lib/server/auth.ts | 7 +- src/schema.ts | 304 +++++++++++++++++++++++++++++++++++++++-- 5 files changed, 320 insertions(+), 18 deletions(-) create mode 100644 src/lib/drizzle.ts diff --git a/package.json b/package.json index 48920c0..eb85754 100644 --- a/package.json +++ b/package.json @@ -104,6 +104,7 @@ "lucia": "3.0.1", "lucide-svelte": "^0.298.0", "mysql2": "^3.9.1", + "nanoid": "^5.0.5", "open-props": "^1.6.18", "oslo": "^1.0.3", "radix-svelte": "^0.9.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 835f2d4..fd92865 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -89,6 +89,9 @@ dependencies: mysql2: specifier: ^3.9.1 version: 3.9.1 + nanoid: + specifier: ^5.0.5 + version: 5.0.5 open-props: specifier: ^1.6.18 version: 1.6.18 @@ -1713,7 +1716,7 @@ packages: '@internationalized/date': 3.5.1 dequal: 2.0.3 focus-trap: 7.5.4 - nanoid: 5.0.4 + nanoid: 5.0.5 svelte: 4.2.9 dev: false @@ -1727,7 +1730,7 @@ packages: '@internationalized/date': 3.5.0 dequal: 2.0.3 focus-trap: 7.5.4 - nanoid: 5.0.4 + nanoid: 5.0.5 svelte: 4.2.9 dev: true @@ -3420,7 +3423,7 @@ packages: dependencies: '@internationalized/date': 3.5.1 '@melt-ui/svelte': 0.68.0(svelte@4.2.9) - nanoid: 5.0.4 + nanoid: 5.0.5 svelte: 4.2.9 dev: false @@ -5264,8 +5267,8 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - /nanoid@5.0.4: - resolution: {integrity: sha512-vAjmBf13gsmhXSgBrtIclinISzFFy22WwCYoyilZlsrRXNIHSwgFQ1bEdjRwMT3aoadeIF6HMuDRlOxzfXV8ig==} + /nanoid@5.0.5: + resolution: {integrity: sha512-/Veqm+QKsyMY3kqi4faWplnY1u+VuKO3dD2binyPIybP31DRO29bPF+1mszgLnrR2KqSLceFLBNw0zmvDzN1QQ==} engines: {node: ^18 || >=20} hasBin: true diff --git a/src/lib/drizzle.ts b/src/lib/drizzle.ts new file mode 100644 index 0000000..15d2cd4 --- /dev/null +++ b/src/lib/drizzle.ts @@ -0,0 +1,13 @@ +import { drizzle } from "drizzle-orm/planetscale-serverless"; +import { connect } from "@planetscale/database"; + +// create the connection +const connection = connect({ + host: process.env["DATABASE_HOST"], + username: process.env["DATABASE_USERNAME"], + password: process.env["DATABASE_PASSWORD"], +}); + +const db = drizzle(connection); + +export default db; \ No newline at end of file diff --git a/src/lib/server/auth.ts b/src/lib/server/auth.ts index 4fde8d7..21f848b 100644 --- a/src/lib/server/auth.ts +++ b/src/lib/server/auth.ts @@ -1,10 +1,11 @@ // lib/server/lucia.ts import { Lucia, TimeSpan } from 'lucia'; -import { PrismaAdapter } from '@lucia-auth/adapter-prisma'; +import { DrizzleMySQLAdapter } from "@lucia-auth/adapter-drizzle"; import { dev } from '$app/environment'; -import prisma_client from '$lib/prisma'; +import db from '$lib/drizzle'; +import { sessionTable, userTable } from '../../schema'; -const adapter = new PrismaAdapter(prisma_client.session, prisma_client.user); +const adapter = new DrizzleMySQLAdapter(db, sessionTable, userTable); export const lucia = new Lucia(adapter, { getSessionAttributes: (attributes) => { diff --git a/src/schema.ts b/src/schema.ts index 6e9369d..f10bfb8 100644 --- a/src/schema.ts +++ b/src/schema.ts @@ -1,27 +1,311 @@ -import { DrizzleMySQLAdapter } from "@lucia-auth/adapter-drizzle"; -import mysql from "mysql2/promise"; -import { int, mysqlEnum, mysqlTable, uniqueIndex, datetime, varchar, serial } from 'drizzle-orm/mysql-core'; -import { drizzle } from "drizzle-orm/mysql2"; +import { sql } from 'drizzle-orm'; +import { mysqlTable, datetime, varchar, boolean, timestamp } from 'drizzle-orm/mysql-core'; +import { nanoid } from 'nanoid'; -const connection = await mysql.createConnection(); -const db = drizzle(connection); +model User { + id String @id @default(cuid()) + username String @unique + hashed_password String? + email String? @unique + firstName String? + lastName String? + roles UserRole[] + verified Boolean @default(false) + receiveEmail Boolean @default(false) + collection Collection? + wishlist Wishlist? + list List[] + theme String @default("system") + created_at DateTime @default(now()) @db.Timestamp(6) + updated_at DateTime @updatedAt @db.Timestamp(6) + sessions Session[] -const userTable = mysqlTable("user", { + @@map("users") +} + +export const userTable = mysqlTable("users", { id: varchar("id", { length: 255 }).primaryKey() + .$defaultFn(() => nanoid()), + username: varchar("username", { + length: 255 + }).unique(), + hashedPassword: varchar("hashed_password", { + length: 255 + }), + email: varchar("email", { + length: 255 + }).unique(), + firstName: varchar("first_name", { + length: 255 + }), + lastName: varchar("last_name", { + length: 255 + }), + verified: boolean("verified").default(false), + receiveEmail: boolean("receive_email").default(false), + theme: varchar("theme", { + length: 255 + }).default("system"), + createdAt: timestamp("created_at").default(sql`(now(6))`), + updatedAt: timestamp("updated_at").default(sql`(now(6))`) }); -const sessionTable = mysqlTable("session", { +// model Session { +// id String @id @unique +// userId String +// ip_country String +// ip_address String +// expiresAt DateTime +// user User @relation(references: [id], fields: [userId], onDelete: Cascade) + +// @@index([userId]) +// @@map("sessions") +// } + +export const sessionTable = mysqlTable("sessions", { id: varchar("id", { length: 255 - }).primaryKey(), + }).primaryKey() + .$defaultFn(() => nanoid()), userId: varchar("user_id", { length: 255 }) .notNull() .references(() => userTable.id), + ipCountry: varchar("ip_country", { + length: 255 + }), + ipAddress: varchar("ip_address", { + length: 255 + }), expiresAt: datetime("expires_at").notNull() }); -const adapter = new DrizzleMySQLAdapter(db, sessionTable, userTable); +model Role { + id String @id @default(cuid()) + name String @unique + userRoles UserRole[] + + @@map("roles") +} + +model UserRole { + id String @id @default(cuid()) + user User @relation(fields: [user_id], references: [id]) + user_id String + role Role @relation(fields: [role_id], references: [id]) + role_id String + created_at DateTime @default(now()) @db.Timestamp(6) + updated_at DateTime @updatedAt @db.Timestamp(6) + + @@unique([user_id, role_id]) + @@index([user_id]) + @@index([role_id]) + @@map("user_roles") +} + +model Collection { + id String @id @default(cuid()) + user_id String @unique + user User @relation(references: [id], fields: [user_id]) + items CollectionItem[] + + @@index([user_id]) + @@map("collections") +} + +model CollectionItem { + id String @id @default(cuid()) + collection_id String + collection Collection @relation(references: [id], fields: [collection_id], onDelete: Cascade) + game_id String @unique + game Game @relation(references: [id], fields: [game_id]) + times_played Int + + @@index([game_id, collection_id]) + @@index([game_id]) + @@index([collection_id]) + @@map("collection_items") +} + +model Wishlist { + id String @id @default(cuid()) + user_id String @unique + user User @relation(references: [id], fields: [user_id]) + items WishlistItem[] + + @@index([user_id]) + @@map("wishlists") +} + +model WishlistItem { + id String @id @default(cuid()) + wishlist_id String + wishlist Wishlist @relation(references: [id], fields: [wishlist_id], onDelete: Cascade) + game_id String @unique + game Game @relation(references: [id], fields: [game_id]) + created_at DateTime @default(now()) @db.Timestamp(6) + updated_at DateTime @updatedAt @db.Timestamp(6) + + @@index([game_id, wishlist_id]) + @@index([game_id]) + @@index([wishlist_id]) + @@map("wishlist_items") +} + +model List { + id String @id @default(cuid()) + name String + user_id String @unique + user User @relation(references: [id], fields: [user_id]) + items ListItem[] + + @@index([user_id]) + @@map("lists") +} + +model ListItem { + id String @id @default(cuid()) + list_id String + list List @relation(references: [id], fields: [list_id], onDelete: Cascade) + game_id String @unique + game Game @relation(references: [id], fields: [game_id]) + created_at DateTime @default(now()) @db.Timestamp(6) + updated_at DateTime @updatedAt @db.Timestamp(6) + + @@index([game_id, list_id]) + @@index([game_id]) + @@index([list_id]) + @@map("list_items") +} + +model Game { + id String @id @default(cuid()) + name String + slug String + description String? @db.LongText + year_published Int? @db.Year + min_players Int? + max_players Int? + playtime Int? + min_playtime Int? + max_playtime Int? + min_age Int? + image_url String? + thumb_url String? + url String? + rules_url String? + categories Category[] + mechanics Mechanic[] + designers Designer[] + publishers Publisher[] + artists Artist[] + names GameName[] + expansions Expansion[] @relation("BaseToExpansion") + expansion_of Expansion[] @relation("ExpansionToBase") + collection_items CollectionItem[] + wishlist_items WishlistItem[] + list_items ListItem[] + external_id Int @unique + last_sync_at DateTime? @db.Timestamp(6) + created_at DateTime @default(now()) @db.Timestamp(6) + updated_at DateTime @updatedAt @db.Timestamp(6) + + @@fulltext([name]) + @@fulltext([slug]) + @@map("games") +} + +model GameName { + id String @id @default(cuid()) + name String + slug String + game_id String + game Game @relation(references: [id], fields: [game_id]) + created_at DateTime @default(now()) @db.Timestamp(6) + updated_at DateTime @updatedAt @db.Timestamp(6) + + @@index([game_id]) + @@map("game_names") +} + +model Publisher { + id String @id @default(cuid()) + name String + slug String + external_id Int @unique + games Game[] + created_at DateTime @default(now()) @db.Timestamp(6) + updated_at DateTime @updatedAt @db.Timestamp(6) + + @@fulltext([name]) + @@map("publishers") +} + +model Category { + id String @id @default(cuid()) + name String + slug String + games Game[] + external_id Int @unique + created_at DateTime @default(now()) @db.Timestamp(6) + updated_at DateTime @updatedAt @db.Timestamp(6) + + @@fulltext([name]) + @@map("categories") +} + +model Mechanic { + id String @id @default(cuid()) + name String + slug String + games Game[] + external_id Int @unique + created_at DateTime @default(now()) @db.Timestamp(6) + updated_at DateTime @updatedAt @db.Timestamp(6) + + @@fulltext([name]) + @@map("mechanics") +} + +model Designer { + id String @id @default(cuid()) + name String + slug String + external_id Int @unique + games Game[] + created_at DateTime @default(now()) @db.Timestamp(6) + updated_at DateTime @updatedAt @db.Timestamp(6) + + @@fulltext([name]) + @@map("designers") +} + +model Artist { + id String @id @default(cuid()) + name String + slug String @unique + external_id Int @unique + games Game[] + created_at DateTime @default(now()) @db.Timestamp(6) + updated_at DateTime @updatedAt @db.Timestamp(6) + + @@fulltext([name]) + @@map("artists") +} + +model Expansion { + id String @id @default(cuid()) + base_game Game @relation(name: "BaseToExpansion", fields: [base_game_id], references: [id]) + base_game_id String + game Game @relation(name: "ExpansionToBase", fields: [game_id], references: [id]) + game_id String + created_at DateTime @default(now()) @db.Timestamp(6) + updated_at DateTime @updatedAt @db.Timestamp(6) + + @@index([base_game_id]) + @@index([game_id]) + @@map("expansions") +} \ No newline at end of file