diff --git a/.gitignore b/.gitignore index 2971a0b..5c718fb 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ # database /prisma/db.sqlite /prisma/db.sqlite-journal +/drizzle # next.js /.next/ diff --git a/README.md b/README.md index 5377a3d..0683437 100644 --- a/README.md +++ b/README.md @@ -10,10 +10,8 @@ Built with [`create-t3-app`](https://create.t3.gg/). ### Backend -- Create a Profile model that includes - - clerkId - - currentCourse - - courseHistory +- Database modelling +- Lightweight CMS ### Frontend diff --git a/drizzle.config.ts b/drizzle.config.ts index 85c5e47..04b6bf9 100644 --- a/drizzle.config.ts +++ b/drizzle.config.ts @@ -9,4 +9,5 @@ export default { connectionString: env.DATABASE_URL, }, tablesFilter: ["flurry_*"], + out: "./drizzle", } satisfies Config; diff --git a/package.json b/package.json index 0b82ac9..431e8cf 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "scripts": { "build": "next build", "db:push": "dotenv drizzle-kit push:mysql", + "db:generate": "dotenv drizzle-kit generate:mysql", "db:studio": "dotenv drizzle-kit studio", "dev": "next dev", "lint": "next lint", diff --git a/src/server/db/schema.ts b/src/server/db/schema.ts index 6afab59..cd0d500 100644 --- a/src/server/db/schema.ts +++ b/src/server/db/schema.ts @@ -1,34 +1,80 @@ -// Example model schema from the Drizzle docs -// https://orm.drizzle.team/docs/sql-schema-declaration - -import { sql } from "drizzle-orm"; +import { relations } from "drizzle-orm"; import { - bigint, - index, mysqlTableCreator, - timestamp, + text, varchar, + serial, + int, + bigint, } from "drizzle-orm/mysql-core"; -/** - * This is an example of how to use the multi-project schema feature of Drizzle ORM. Use the same - * database instance for multiple projects. - * - * @see https://orm.drizzle.team/docs/goodies#multi-project-schema - */ export const mysqlTable = mysqlTableCreator((name) => `flurry_${name}`); -export const posts = mysqlTable( - "post", - { - id: bigint("id", { mode: "number" }).primaryKey().autoincrement(), - name: varchar("name", { length: 256 }), - createdAt: timestamp("created_at") - .default(sql`CURRENT_TIMESTAMP`) - .notNull(), - updatedAt: timestamp("updatedAt").onUpdateNow(), - }, - (example) => ({ - nameIndex: index("name_idx").on(example.name), +// Foreign keys: https://planetscale.com/blog/working-with-related-data-using-drizzle-and-planetscale + +// === Tables ========================================================= + +export const user = mysqlTable("user", { + userId: varchar("userId", { length: 255 }).unique().primaryKey(), + activeLanguageId: bigint("activeLanguageId", { mode: "bigint" }).notNull(), + // .references(() => language.languageId), +}); + +export const language = mysqlTable("language", { + languageId: serial("languageId").primaryKey(), + name: varchar("name", { length: 255 }), + abbreviation: varchar("abbreviation", { length: 2 }), +}); + +export const course = mysqlTable("course", { + courseId: serial("courseId").primaryKey(), + languageId: bigint("languageId", { mode: "bigint" }).notNull(), + // .references(() => language.languageId), + name: varchar("name", { length: 255 }), + description: text("description"), +}); + +export const progress = mysqlTable("progress", { + // Probably need to explicitly make a composite key + userId: varchar("userId", { length: 255 }), + // .references(() => user.userId), + languageId: bigint("languageId", { mode: "bigint" }).notNull(), + // .references(() => language.languageId), + interactions: int("interactions"), + successes: int("successes"), +}); + +export const content = mysqlTable("content", { + contentId: serial("contentId").primaryKey(), + courseId: bigint("courseId", { mode: "bigint" }).notNull(), + // .references(() => course.courseId), + content: text("content"), +}); + +// === Relations ========================================================= + +export const userRelations = relations(user, ({ one }) => ({ + language: one(language, { + fields: [user.activeLanguageId], + references: [language.languageId], }), -); +})); + +export const courseRelations = relations(course, ({ one }) => ({ + language: one(language, { + fields: [course.languageId], + references: [language.languageId], + }), +})); + +export const progressRelations = relations(progress, ({ many }) => ({ + language: many(language), + user: many(user), +})); + +export const contentRelations = relations(content, ({ one }) => ({ + course: one(course, { + fields: [content.courseId], + references: [course.courseId], + }), +}));