Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/drizzle #62

Merged
merged 7 commits into from
Jan 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM mcr.microsoft.com/devcontainers/javascript-node:0-20
FROM mcr.microsoft.com/devcontainers/javascript-node:1-20-bullseye

# Install MongoDB command line tools - though mongo-database-tools not available on arm64
ARG MONGO_TOOLS_VERSION=6.0
Expand All @@ -20,6 +20,3 @@ RUN . /etc/os-release \

# [Optional] Uncomment if you want to install more global node modules
# RUN su node -c "npm install -g <your-package-list-here>"



21 changes: 8 additions & 13 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/javascript-node-mongo
// README at: https://github.com/devcontainers/templates/tree/main/src/javascript-node-postgres
{
"name": "Node.js & Mongo DB",
"name": "Node.js & PostgreSQL",
"dockerComposeFile": "docker-compose.yml",
"service": "app",
"workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",

// Features to add to the dev container. More info: https://containers.dev/features.
// "features": {},

// Use 'forwardPorts' to make a list of ports inside the container available locally.
// This can be used to network with other containers or with the host.
// "forwardPorts": [3000, 5432],
// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "yarn install",
// Configure tool-specific properties.
"customizations": {
"vscode": {
"extensions": [
"mongodb.mongodb-vscode",
"GitHub.copilot-chat",
"WallabyJs.console-ninja",
"bradlc.vscode-tailwindcss",
Expand All @@ -22,13 +24,6 @@
]
}
}

// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [3000, 27017],

// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "yarn install",

// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
// "remoteUser": "root"
}
}
34 changes: 19 additions & 15 deletions .devcontainer/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,36 +1,40 @@
version: '3.8'
version: "3.8"

services:
app:
build:
build:
context: .
dockerfile: Dockerfile

volumes:
- ../..:/workspaces:cached

# Overrides default command so things don't shut down after the process ends.
command: sleep infinity

# Runs app on the same network as the database container, allows "forwardPorts" in devcontainer.json function.
network_mode: service:db
# network_mode: service:db

# Use "forwardPorts" in **devcontainer.json** to forward an app port locally.
# Use "forwardPorts" in **devcontainer.json** to forward an app port locally.
# (Adding the "ports" property to this file will not forward from a Codespace.)

db:
image: mongo:latest
db-postgres:
image: postgres:latest
restart: unless-stopped
volumes:
- mongodb-data:/data/db

# Uncomment to change startup options
# environment:
# MONGO_INITDB_ROOT_USERNAME: root
# MONGO_INITDB_ROOT_PASSWORD: example
# MONGO_INITDB_DATABASE: your-database-here
- postgres-data:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: postgres
POSTGRES_USER: postgres
POSTGRES_DB: postgres

# Add "forwardPorts": ["27017"] to **devcontainer.json** to forward MongoDB locally.
# Add "forwardPorts": ["5432"] to **devcontainer.json** to forward PostgreSQL locally.
# (Adding the "ports" property to this file will not forward from a Codespace.)
db-mongo:
image: mongo:latest
restart: unless-stopped
volumes:
- mongodb-data:/data/db

volumes:
mongodb-data:
postgres-data:
7 changes: 7 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ build:
start: build
@cd app && npm run start

## Drizzle ## drizzle-kit is a tool to manage database migrations
# see: https://orm.drizzle.team/kit-docs/overview#prototyping-with-db-push
db-push:
cd app && npx drizzle-kit push:pg
# see: https://orm.drizzle.team/kit-docs/overview#schema-updates
db-generate:
cd app && npx drizzle-kit generate:pg
clean:
@cd app && rm -rf .next

Expand Down
5 changes: 3 additions & 2 deletions app/.env.sample
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
AUTH_42_SCHOOL_CLIENT_ID=
AUTH_42_SCHOOL_CLIENT_SECRET=
AUTH_URL=http://localhost:3000
AUTH_SECRET=SWsskyjBb9I4v2j3edbB8Q89j6T60flzrCbLNw0Omlc=
MONGODB_URI=mongodb://localhost:27017
AUTH_SECRET=`openssl rand -base64 32`
POSTGRES_URI=postgresql://postgres:postgres@db-postgres:5432
MONGODB_URI=mongodb://db-mongo:27017
37 changes: 19 additions & 18 deletions app/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,37 +4,38 @@
*/
import NextAuth from "next-auth";
import FortyTwoProvider from "next-auth/providers/42-school";
import { DrizzleAdapter } from "@auth/drizzle-adapter";
import { db } from "@/lib/db/db";
import { profiles } from "./drizzle/accounts/profiles";

export const {
handlers: { GET, POST },
auth
} = NextAuth({
adapter: DrizzleAdapter(db),
providers: [
FortyTwoProvider({
clientId: process.env.AUTH_42_SCHOOL_CLIENT_ID,
clientSecret: process.env.AUTH_42_SCHOOL_CLIENT_SECRET
})
],
callbacks: {
async jwt({ token, trigger, profile }) {
if (profile && trigger === "signIn") {
return {
...token,
user: {
login: profile.login,
isStaff: profile["staff?"]
}
};
}
return token;
},
async session({ session, token }) {
session.user = {
...session.user,
login: token.user.login,
isStaff: token.user.isStaff
};
async session({ session, user }) {
session.user.id = user.id;
return session;
}
},
events: {
async linkAccount({ user }) {
// Create a profile for the user if it doesn't exist
if (user) {
await db
.insert(profiles)
.values({
userId: user.id
})
.onConflictDoNothing();
}
}
}
});
11 changes: 11 additions & 0 deletions app/drizzle.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { defineConfig } from "drizzle-kit";
export default defineConfig({
out: "./migrations",
schema: "./drizzle/*/**",
driver: "pg",
dbCredentials: {
connectionString: `${process.env.POSTGRES_URI}`
},
verbose: true,
strict: true
});
63 changes: 63 additions & 0 deletions app/drizzle/accounts/authjs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/**
* AuthJS's schema, do not edit. Create another table (and make 1-1 relationship) if you need to store extra user data.
*/
import type { AdapterAccount } from "@auth/core/adapters";
import {
integer,
pgTable,
primaryKey,
text,
timestamp
} from "drizzle-orm/pg-core";

export const users = pgTable("user", {
id: text("id").notNull().primaryKey(),
name: text("name"),
email: text("email").notNull(),
emailVerified: timestamp("emailVerified", { mode: "date" }),
image: text("image")
});

export const accounts = pgTable(
"account",
{
userId: text("userId")
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
type: text("type").$type<AdapterAccount["type"]>().notNull(),
provider: text("provider").notNull(),
providerAccountId: text("providerAccountId").notNull(),
refresh_token: text("refresh_token"),
access_token: text("access_token"),
expires_at: integer("expires_at"),
token_type: text("token_type"),
scope: text("scope"),
id_token: text("id_token"),
session_state: text("session_state")
},
(account) => ({
compoundKey: primaryKey({
columns: [account.provider, account.providerAccountId]
})
})
);

export const sessions = pgTable("session", {
sessionToken: text("sessionToken").notNull().primaryKey(),
userId: text("userId")
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
expires: timestamp("expires", { mode: "date" }).notNull()
});

export const verificationTokens = pgTable(
"verificationToken",
{
identifier: text("identifier").notNull(),
token: text("token").notNull(),
expires: timestamp("expires", { mode: "date" }).notNull()
},
(vt) => ({
compoundKey: primaryKey({ columns: [vt.identifier, vt.token] })
})
);
21 changes: 21 additions & 0 deletions app/drizzle/accounts/profiles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* User's profile, you can add more fields here
*/

import { relations } from "drizzle-orm";
import { boolean, pgTable, text, uuid } from "drizzle-orm/pg-core";
import { users } from "./authjs";

export const profiles = pgTable("profile", {
id: uuid("id").defaultRandom().primaryKey(),
isStaff: boolean("isStaff").notNull().default(false),
isResumePublic: boolean("isResumePublic").notNull().default(false),
userId: text("userId")
.unique()
.notNull()
.references(() => users.id, { onDelete: "cascade" })
});

export const profilesRelations = relations(profiles, ({ one }) => ({
userId: one(users)
}));
5 changes: 3 additions & 2 deletions app/instrumentation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ function envManager() {
"AUTH_42_SCHOOL_CLIENT_SECRET",
"AUTH_URL",
"AUTH_SECRET",
"MONGODB_URI"
"POSTGRES_URI"
];
let errs: any[] = [];
const errs: any[] = [];
ENVS.forEach((env) => {
if (!process.env[env]) {
errs.push(env);
Expand All @@ -23,6 +23,7 @@ function envManager() {
if (errs.length) {
throw new Error(`Missing ENVs: ${errs.join(", ")}`);
} else {
// eslint-disable-next-line no-console
console.log("ENVs Check OK");
}
}
Expand Down
10 changes: 10 additions & 0 deletions app/lib/db/db.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { Db, MongoClient } from "mongodb";
import { drizzle } from "drizzle-orm/postgres-js";
import postgres from "postgres";

// TODO: to be removed
/**
* Returns a connected MongoDB client.
*
Expand All @@ -17,3 +20,10 @@ export async function getDb(): Promise<Db> {
throw error;
}
}

/**
* Single client is instantiated and shared across the application.
* This Postgres client is used by Drizzle ORM.
*/
const queryClient = postgres(`${process.env.POSTGRES_URI}`);
export const db = drizzle(queryClient);
10 changes: 10 additions & 0 deletions app/migrate.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* This file is used to migrate the database on cloud deployments
*/
import { drizzle } from "drizzle-orm/postgres-js";
import { migrate } from "drizzle-orm/postgres-js/migrator";
import postgres from "postgres";
const sql = postgres(`${process.env.POSTGRES_URI}`, { max: 1 });
const db = drizzle(sql);
await migrate(db, { migrationsFolder: "migrations" });
await sql.end();
Loading