Skip to content

Commit

Permalink
Merge pull request #110 from TigerAppsOrg/staging
Browse files Browse the repository at this point in the history
Begin drizzle setup
  • Loading branch information
joshuamotoaki authored Oct 31, 2024
2 parents d05b5ac + 4874c3f commit 6ddc796
Show file tree
Hide file tree
Showing 27 changed files with 210 additions and 1,724 deletions.
8 changes: 8 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"recommendations": [
"bocovo.dbml-erd-visualizer",
"1yib.svelte-bundle",
"oven.bun-vscode",
"bradlc.vscode-tailwindcss",
]
}
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"editor.formatOnSave": true
"editor.formatOnSave": true,
"dbmlERDPreviewer.preferredTheme": "dark"
}
6 changes: 6 additions & 0 deletions apps/database/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
PUBLIC_SUPABASE_URL=
PUBLIC_SUPABASE_ANON_KEY=
REDIS_PASSWORD=
API_ACCESS_TOKEN=
SERVICE_ROLE_KEY=
DATABASE_URL=
9 changes: 9 additions & 0 deletions apps/server/.gitignore → apps/database/.gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore

# User Additions

# This is not sensitive info, but it's just to help the developer
# To recreate it, run `bun run db:schema` in the root of the project
schema.dbml

# We are using Bun, so this should be ignored in case someone runs npm install
package-lock.json

# Logs

logs
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
pnpm-lock.yaml
package-lock.json
package.json
yarn.lock
*.config.*
*.json
Expand Down
File renamed without changes.
9 changes: 9 additions & 0 deletions apps/database/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# TigerJunction Database

This is where the Drizzle database schema is defined and where the scripts that update the course data are located. This is separated from the main web app in order to maintain a clean separation of concerns. Additionally, as we are migrating off Supabase, this will keep the migration process as clean and simple as possible.

## Getting Started

Make sure to have [Bun](https://bun.sh) installed and the environment variables set according to the `.env.example` file. Run `bun install` to install the dependencies. Check the `package.json` file for the available scripts.

There are 2 main directories. `db` contains the Drizzle database schema. `scripts` contains a collection of scripts used to keep course data up to date.
Binary file added apps/database/bun.lockb
Binary file not shown.
10 changes: 10 additions & 0 deletions apps/database/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
services:
db:
image: postgres
restart: always
ports:
- 5432:5432
environment:
POSTGRES_USER: root
POSTGRES_PASSWORD: mysecretpassword
POSTGRES_DB: local
13 changes: 13 additions & 0 deletions apps/database/drizzle.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { defineConfig } from "drizzle-kit";

if (!process.env.DATABASE_URL) throw new Error("DATABASE_URL is not set");

export default defineConfig({
dialect: "postgresql",
schema: "./src/db/schema.ts",
dbCredentials: {
url: process.env.DATABASE_URL
},
verbose: true,
strict: true
});
File renamed without changes.
36 changes: 36 additions & 0 deletions apps/database/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"name": "tiger-junction-server",
"module": "index.ts",
"type": "module",
"scripts": {
"lint": "prettier --check . && eslint src/",
"format": "prettier --write .",
"update-supabase": "bun src/scripts/supabase/index.ts",
"ratings-supabase": "bun src/scripts/supabase/ratings.ts",
"db:start": "docker compose up",
"db:schema": "bun src/db/generate-dbml.ts",
"db:push": "drizzle-kit push",
"db:migrate": "drizzle-kit migrate",
"db:studio": "drizzle-kit studio"
},
"devDependencies": {
"@types/jsdom": "^21.1.7",
"bun-types": "latest",
"drizzle-kit": "^0.27.0",
"eslint": "^9.9.0",
"eslint-config-prettier": "^9.1.0",
"prettier": "^3.3.3",
"typescript-eslint": "^8.2.0"
},
"peerDependencies": {
"typescript": "^5.0.0"
},
"dependencies": {
"@supabase/supabase-js": "^2.45.1",
"drizzle-dbml-generator": "^0.9.0",
"drizzle-orm": "^0.36.0",
"jsdom": "^25.0.1",
"postgres": "^3.4.5",
"redis": "^4.7.0"
}
}
16 changes: 16 additions & 0 deletions apps/database/src/db/generate-dbml.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* @file db/generate-dbml.ts
* @description Used to create a schema.dbml file from the Drizzle ORM schema.
* This is useful for visualization. The schema.dbml file can be opened with
* the VSCode extension "bocovo.dbml-erd-visualizer"
* @link https://github.com/drizzle-team/drizzle-orm/discussions/1480
*/

import * as schema from "./schema";
import { pgGenerate } from "drizzle-dbml-generator";

const out = "./schema.dbml";
const relational = true;

pgGenerate({ schema, out, relational });
console.log("Successfully created the schema.dbml file.");
66 changes: 66 additions & 0 deletions apps/database/src/db/schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/**
* @file db/schema.ts
* @description This file contains the Drizzle ORM schema for the database.
* @author Joshua Lau
*/

import { relations } from "drizzle-orm";
import {
pgTable,
text,
smallint,
integer,
real,
pgEnum,
boolean,
serial
} from "drizzle-orm/pg-core";

//----------------------------------------------------------------------
// Enums
//----------------------------------------------------------------------

export const statusEnum = pgEnum("status", ["open", "closed", "cancelled"]);

//----------------------------------------------------------------------
// Tables
//----------------------------------------------------------------------

export const listings = pgTable("listings", {
id: text("id").notNull().primaryKey(),
code: text("code").notNull(),
title: text("title").notNull(),
aka: text("aka").array(),
recentTerm: smallint("recent_term"),
terms: smallint("terms").array()
});

export const listingsRelations = relations(listings, ({ many }) => ({
courses: many(courses)
}));

export const courses = pgTable("courses", {
id: serial("id").primaryKey().notNull(),
listingId: text("listing_id")
.notNull()
.references(() => listings.id, {
onDelete: "cascade"
}),
term: smallint("term").notNull(),
code: text("code").notNull(),
title: text("title").notNull(),
gradingBasis: text("grading_basis").notNull(),
dists: text("dists").array(),
rating: real("rating"),
status: statusEnum("status").notNull().default("open"),
numEvals: integer("num_evals"),
instructors: text("instructors").array(),
hasFinal: boolean("has_final")
});

export const coursesRelations = relations(courses, ({ one }) => ({
listing: one(listings, {
fields: [courses.listingId],
references: [listings.id]
})
}));
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
// Functions to fetch course data from the registrar API
/**
* @file scripts/reg-fetchers.ts
* @description Functions for fetching course listings and details from
* the registrar API.
* @author Joshua Lau
*/

import type { RegCourseDetails, RegDeptCourses, RegListings } from "./types";
import type {
RegCourseDetails,
RegDeptCourses,
RegListings
} from "./reg-types";

//----------------------------------------------------------------------
// Helpers and Constants
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
/**
* @file scripts/reg-types.ts
* @description This file contains types for the registrar API data.
* I pray this does not change anytime in the near future.
* @author Joshua Lau
*/

export type StringBoolean = "Y" | "N";

export type RegListings = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import {
fetchRegCourseDetails,
fetchRegDeptCourses,
fetchRegListings
} from "./fetchers";
} from "../reg-fetchers";
import { supabase } from "./shared";
import type { RegDeptCourses } from "./types";
import type { RegDeptCourses } from "../reg-types";

//----------------------------------------------------------------------
// Types
Expand Down Expand Up @@ -352,7 +352,7 @@ export const populateCourses = async (

const { data: supaSections, error: sectionError } = await supabase
.from("sections")
.select("id,course_id,num")
.select("id,course_id,num,start_time,days")
.eq("term", term);

if (sectionError) {
Expand Down Expand Up @@ -382,7 +382,16 @@ export const populateCourses = async (
for (const newSection of courseSections) {
const matchingSectionIndices: number[] = [];
for (let i = 0; i < supaCourseSections.length; i++) {
if (supaCourseSections[i].num === newSection.num) {
const supaSection = supaCourseSections[i];
// All of these conditions have to be checked
// because there are edge cases where there's a
// section with multiple times or days, which
// requires multiple db rows (sadly)
const numMatch = supaSection.num === newSection.num;
const timeMatch =
supaSection.start_time === newSection.start_time;
const dayMatch = supaSection.days === newSection.days;
if (numMatch && timeMatch && dayMatch) {
matchingSectionIndices.push(i);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import { populateListings } from "./listings";
import { populateCourses } from "./courses";
import { redisTransfer } from "./transfer";
import { redisTransfer } from "./redis";
import { TERMS } from "./shared";

const args = process.argv.slice(2);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { fetchRegListings } from "./fetchers";
import { fetchRegListings } from "../reg-fetchers";
import { supabase } from "./shared";
import type { RegListings } from "./types";
import type { RegListings } from "../reg-types";

type FormattedListing = {
id: string;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { supabase, TERMS } from "./shared";
import { JSDOM } from "jsdom";
import { redisTransfer } from "./transfer";
import { redisTransfer } from "./redis";

type IdPair = {
listingId: string;
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
15 changes: 0 additions & 15 deletions apps/server/README.md

This file was deleted.

Binary file removed apps/server/bun.lockb
Binary file not shown.
Loading

0 comments on commit 6ddc796

Please sign in to comment.