Skip to content

Commit

Permalink
feat: creates orbitkit/db package
Browse files Browse the repository at this point in the history
Summary of commit:

- creates `@orbitkit/db` package and uses drizzle orm and kit
- uses the db package in `apps/web`

Details of changes:

- Needed environment variables handling and validation so went
with t3 env and dotenv-cli to target `apps/web` env files in `packages/db`
- Caches the drizzle kit scripts using turborepo except the migration drop
script as that turborepo doesn't like questions and inputs in commands
(plus you can't cache that anyways).
- imports the env.mjs file in db package in next.config.js file in `apps/web`
so that we get env vars validation.

TODO:

Need to figure out a good workflow for integrating neon db branching with pull
requests, my thinking is the following workflows.

pull request created:

- create a neon db branch that will be used for all ci pipelines of that pr
- when pr is merged to main, delete the created branch and apply migrations on main branch
- if pr is closed, just delete the neon branch.
  • Loading branch information
ixahmedxi committed Jan 24, 2024
1 parent 5526fec commit 77d5a63
Show file tree
Hide file tree
Showing 21 changed files with 1,331 additions and 12 deletions.
4 changes: 3 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
pnpm-lock.yaml
pnpm-lock.yaml
drizzle/
.prettierignore
6 changes: 5 additions & 1 deletion apps/web/next.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import '@orbitkit/db/env';

/** @type {import('next').NextConfig} */
const nextConfig = {};
const nextConfig = {
transpilePackages: ['@orbitkit/db'],
};

export default nextConfig;
1 change: 1 addition & 0 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"typecheck": "tsc --noEmit --tsBuildInfoFile .tsbuildinfo"
},
"dependencies": {
"@orbitkit/db": "workspace:^",
"geist": "^1.2.1",
"next": "14.1.0",
"next-themes": "^0.2.1",
Expand Down
6 changes: 5 additions & 1 deletion apps/web/src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import { ThemeSwitcher } from '@/components/ThemeSwitcher';
import { db } from '@orbitkit/db';

export default async function Home() {
const users = await db.query.userTable.findMany();

export default function Home() {
return (
<main className="container mx-auto">
<h1>Hello World</h1>
{JSON.stringify(users)}
<ThemeSwitcher />
</main>
);
Expand Down
4 changes: 3 additions & 1 deletion cspell.config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ ignorePaths:
words:
- astro
- commitlint
- esbenp
- ianvs
- lockb
- neondatabase
- nextjs
- orbitkit
- packagejson
- tailwindcss
- tsbuildinfo
- turborepo
- typecheck
- esbenp
7 changes: 7 additions & 0 deletions packages/db/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/** @type {import('eslint').Linter.Config} */
const config = {
root: true,
extends: ['orbitkit/base'],
};

module.exports = config;
12 changes: 12 additions & 0 deletions packages/db/drizzle.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type { Config } from 'drizzle-kit';

import { env } from './src/env.mjs';

export default {
schema: './src/schema/index.ts',
out: './drizzle',
dbCredentials: {
connectionString: env.DATABASE_URL,
},
driver: 'pg',
} satisfies Config;
15 changes: 15 additions & 0 deletions packages/db/drizzle/0000_married_arachne.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
CREATE TABLE IF NOT EXISTS "user" (
"id" text PRIMARY KEY NOT NULL
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "session" (
"id" text PRIMARY KEY NOT NULL,
"user_id" text NOT NULL,
"expires_at" timestamp with time zone NOT NULL
);
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "session" ADD CONSTRAINT "session_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "user"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
73 changes: 73 additions & 0 deletions packages/db/drizzle/meta/0000_snapshot.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
{
"id": "53aefb64-3f60-400a-87ef-485bddb3be55",
"prevId": "00000000-0000-0000-0000-000000000000",
"version": "5",
"dialect": "pg",
"tables": {
"user": {
"name": "user",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"session": {
"name": "session",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"user_id": {
"name": "user_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"expires_at": {
"name": "expires_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {
"session_user_id_user_id_fk": {
"name": "session_user_id_user_id_fk",
"tableFrom": "session",
"tableTo": "user",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
}
},
"enums": {},
"schemas": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}
13 changes: 13 additions & 0 deletions packages/db/drizzle/meta/_journal.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"version": "5",
"dialect": "pg",
"entries": [
{
"idx": 0,
"version": "5",
"when": 1706041191201,
"tag": "0000_married_arachne",
"breakpoints": true
}
]
}
21 changes: 21 additions & 0 deletions packages/db/migrate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { drizzle } from 'drizzle-orm/postgres-js';
import { migrate } from 'drizzle-orm/postgres-js/migrator';
import postgres from 'postgres';

import { env } from './src/env.mjs';

const sql = postgres(env.DATABASE_URL, { max: 1 });
const db = drizzle(sql);

const main = async () => {
try {
await migrate(db, { migrationsFolder: 'drizzle' });
await sql.end();
console.log(`🚀 Successfully migrated database!`);
} catch (err) {
console.error('😪 Error migrating database:', err);
process.exit(1);
}
};

void main();
41 changes: 41 additions & 0 deletions packages/db/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"name": "@orbitkit/db",
"version": "0.1.0",
"private": true,
"description": "A database package utilizing drizzle orm.",
"license": "MIT",
"author": "OrbitKit",
"type": "module",
"exports": {
".": "./src/index.ts",
"./schema": "./src/schema/index.ts",
"./env": "./src/env.mjs"
},
"scripts": {
"db:check": "dotenv -e ../../apps/web/.env.local drizzle-kit check:pg",
"db:generate": "dotenv -e ../../apps/web/.env.local drizzle-kit generate:pg",
"db:migrate": "dotenv -e ../../apps/web/.env.local tsx migrate.ts",
"db:migrate:drop": "dotenv -e ../../apps/web/.env.local drizzle-kit drop",
"db:pull": "dotenv -e ../../apps/web/.env.local drizzle-kit introspect:pg",
"db:push": "dotenv -e ../../apps/web/.env.local drizzle-kit push:pg",
"db:studio": "dotenv -e ../../apps/web/.env.local drizzle-kit studio",
"db:up": "dotenv -e ../../apps/web/.env.local drizzle-kit up:pg",
"lint": "eslint . --cache --max-warnings 0",
"typecheck": "tsc --noEmit --tsBuildInfoFile .tsbuildinfo"
},
"dependencies": {
"@neondatabase/serverless": "^0.7.2",
"@t3-oss/env-nextjs": "^0.7.3",
"drizzle-orm": "^0.29.3",
"pg": "^8.11.3",
"postgres": "^3.4.3",
"zod": "^3.22.4"
},
"devDependencies": {
"@orbitkit/tsconfig": "workspace:*",
"dotenv-cli": "^7.3.0",
"drizzle-kit": "^0.20.13",
"eslint-config-orbitkit": "workspace:*",
"tsx": "^4.7.0"
}
}
12 changes: 12 additions & 0 deletions packages/db/src/env.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { createEnv } from '@t3-oss/env-nextjs';
import { z } from 'zod';

export const env = createEnv({
server: {
DATABASE_URL: z.string().url(),
},
client: {},
runtimeEnv: {
DATABASE_URL: process.env['DATABASE_URL'],
},
});
9 changes: 9 additions & 0 deletions packages/db/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { neon } from '@neondatabase/serverless';
import { drizzle } from 'drizzle-orm/neon-http';

import { env } from './env.mjs';
import * as schema from './schema';

const sql = neon(env.DATABASE_URL);

export const db = drizzle(sql, { schema });
2 changes: 2 additions & 0 deletions packages/db/src/schema/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './user';
export * from './session';
14 changes: 14 additions & 0 deletions packages/db/src/schema/session.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { pgTable, text, timestamp } from 'drizzle-orm/pg-core';

import { userTable } from './user';

export const sessionTable = pgTable('session', {
id: text('id').primaryKey(),
userId: text('user_id')
.notNull()
.references(() => userTable.id),
expiresAt: timestamp('expires_at', {
withTimezone: true,
mode: 'date',
}).notNull(),
});
5 changes: 5 additions & 0 deletions packages/db/src/schema/user.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { pgTable, text } from 'drizzle-orm/pg-core';

export const userTable = pgTable('user', {
id: text('id').primaryKey(),
});
4 changes: 4 additions & 0 deletions packages/db/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"extends": ["@orbitkit/tsconfig/base.json"],
"include": ["**/*.ts", ".eslintrc.cjs"],
}
33 changes: 33 additions & 0 deletions packages/db/turbo.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"$schema": "https://turbo.build/schema.json",
"extends": ["//"],
"pipeline": {
"db:check": {
"cache": true,
"inputs": ["src/**", "drizzle/**", "drizzle.config.ts"]
},
"db:generate": {
"cache": true,
"outputs": ["drizzle/**"],
"inputs": ["src/**", "drizzle/**", "drizzle.config.ts"]
},
"db:migrate": {
"cache": true,
"inputs": ["src/**", "drizzle/**", "drizzle.config.ts", "migrate.ts"]
},
"db:pull": {
"cache": false
},
"db:push": {
"cache": true,
"inputs": ["src/**"]
},
"db:studio": {
"cache": false,
"persistent": true
},
"db:up": {
"cache": false
}
}
}
Loading

0 comments on commit 77d5a63

Please sign in to comment.