chore(turborepo): initial setup and config, move db to package

This commit is contained in:
Hyteq
2025-06-24 11:23:40 +03:00
parent 65bff0d2da
commit 140880a444
15 changed files with 614 additions and 6701 deletions

6
.gitignore vendored
View File

@ -22,3 +22,9 @@
# asdf version management
.tool-versions
node_modules
.cursorignore
.turbo
*.env

2
apps/web/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
# Turborepo
.turbo

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,8 @@
{
"name": "next-template",
"name": "opencut",
"version": "0.1.0",
"private": true,
"packageManager": "bun@1.2.2",
"packageManager": "bun@1.2.17",
"scripts": {
"dev": "next dev --turbopack",
"build": "next build",

BIN
bun.lockb Normal file

Binary file not shown.

6
package-lock.json generated
View File

@ -1,6 +0,0 @@
{
"name": "OpenCut",
"lockfileVersion": 3,
"requires": true,
"packages": {}
}

17
package.json Normal file
View File

@ -0,0 +1,17 @@
{
"packageManager": "bun@1.2.17",
"devDependencies": {
"turbo": "^2.5.4"
},
"workspaces": [
"apps/*",
"packages/*"
],
"scripts": {
"dev": "turbo run dev",
"build": "turbo run build",
"check-types": "turbo run check-types",
"lint": "turbo run lint",
"format": "turbo run format"
}
}

View File

@ -0,0 +1,26 @@
import type { Config } from "drizzle-kit";
import * as dotenv from "dotenv";
// Load the right env file based on environment
if (process.env.NODE_ENV === "production") {
dotenv.config({ path: ".env.production" });
} else {
dotenv.config({ path: ".env.local" });
}
if (!process.env.DATABASE_URL) {
throw new Error("DATABASE_URL is not set");
}
export default {
schema: "./src/schema.ts",
dialect: "postgresql",
migrations: {
table: "drizzle_migrations",
},
dbCredentials: {
url: process.env.DATABASE_URL,
},
out: "./migrations",
strict: process.env.NODE_ENV === "production",
} satisfies Config;

View File

@ -0,0 +1,62 @@
CREATE TABLE "accounts" (
"id" text PRIMARY KEY NOT NULL,
"account_id" text NOT NULL,
"provider_id" text NOT NULL,
"user_id" text NOT NULL,
"access_token" text,
"refresh_token" text,
"id_token" text,
"access_token_expires_at" timestamp,
"refresh_token_expires_at" timestamp,
"scope" text,
"password" text,
"created_at" timestamp NOT NULL,
"updated_at" timestamp NOT NULL
);
--> statement-breakpoint
ALTER TABLE "accounts" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint
CREATE TABLE "sessions" (
"id" text PRIMARY KEY NOT NULL,
"expires_at" timestamp NOT NULL,
"token" text NOT NULL,
"created_at" timestamp NOT NULL,
"updated_at" timestamp NOT NULL,
"ip_address" text,
"user_agent" text,
"user_id" text NOT NULL,
CONSTRAINT "sessions_token_unique" UNIQUE("token")
);
--> statement-breakpoint
ALTER TABLE "sessions" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint
CREATE TABLE "users" (
"id" text PRIMARY KEY NOT NULL,
"name" text NOT NULL,
"email" text NOT NULL,
"email_verified" boolean NOT NULL,
"image" text,
"created_at" timestamp NOT NULL,
"updated_at" timestamp NOT NULL,
CONSTRAINT "users_email_unique" UNIQUE("email")
);
--> statement-breakpoint
ALTER TABLE "users" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint
CREATE TABLE "verifications" (
"id" text PRIMARY KEY NOT NULL,
"identifier" text NOT NULL,
"value" text NOT NULL,
"expires_at" timestamp NOT NULL,
"created_at" timestamp,
"updated_at" timestamp
);
--> statement-breakpoint
ALTER TABLE "verifications" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint
CREATE TABLE "waitlist" (
"id" text PRIMARY KEY NOT NULL,
"email" text NOT NULL,
"created_at" timestamp NOT NULL,
CONSTRAINT "waitlist_email_unique" UNIQUE("email")
);
--> statement-breakpoint
ALTER TABLE "waitlist" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint
ALTER TABLE "accounts" ADD CONSTRAINT "accounts_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "sessions" ADD CONSTRAINT "sessions_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;

View File

@ -0,0 +1,358 @@
{
"id": "33a6742f-89da-4ac5-958f-421aa1cf9bd6",
"prevId": "00000000-0000-0000-0000-000000000000",
"version": "7",
"dialect": "postgresql",
"tables": {
"public.accounts": {
"name": "accounts",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"account_id": {
"name": "account_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"provider_id": {
"name": "provider_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"user_id": {
"name": "user_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"access_token": {
"name": "access_token",
"type": "text",
"primaryKey": false,
"notNull": false
},
"refresh_token": {
"name": "refresh_token",
"type": "text",
"primaryKey": false,
"notNull": false
},
"id_token": {
"name": "id_token",
"type": "text",
"primaryKey": false,
"notNull": false
},
"access_token_expires_at": {
"name": "access_token_expires_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"refresh_token_expires_at": {
"name": "refresh_token_expires_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"scope": {
"name": "scope",
"type": "text",
"primaryKey": false,
"notNull": false
},
"password": {
"name": "password",
"type": "text",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {
"accounts_user_id_users_id_fk": {
"name": "accounts_user_id_users_id_fk",
"tableFrom": "accounts",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": true
},
"public.sessions": {
"name": "sessions",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"expires_at": {
"name": "expires_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true
},
"token": {
"name": "token",
"type": "text",
"primaryKey": false,
"notNull": true
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true
},
"ip_address": {
"name": "ip_address",
"type": "text",
"primaryKey": false,
"notNull": false
},
"user_agent": {
"name": "user_agent",
"type": "text",
"primaryKey": false,
"notNull": false
},
"user_id": {
"name": "user_id",
"type": "text",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {
"sessions_user_id_users_id_fk": {
"name": "sessions_user_id_users_id_fk",
"tableFrom": "sessions",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"sessions_token_unique": {
"name": "sessions_token_unique",
"nullsNotDistinct": false,
"columns": [
"token"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": true
},
"public.users": {
"name": "users",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"email": {
"name": "email",
"type": "text",
"primaryKey": false,
"notNull": true
},
"email_verified": {
"name": "email_verified",
"type": "boolean",
"primaryKey": false,
"notNull": true
},
"image": {
"name": "image",
"type": "text",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"users_email_unique": {
"name": "users_email_unique",
"nullsNotDistinct": false,
"columns": [
"email"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": true
},
"public.verifications": {
"name": "verifications",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"identifier": {
"name": "identifier",
"type": "text",
"primaryKey": false,
"notNull": true
},
"value": {
"name": "value",
"type": "text",
"primaryKey": false,
"notNull": true
},
"expires_at": {
"name": "expires_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": true
},
"public.waitlist": {
"name": "waitlist",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"email": {
"name": "email",
"type": "text",
"primaryKey": false,
"notNull": true
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"waitlist_email_unique": {
"name": "waitlist_email_unique",
"nullsNotDistinct": false,
"columns": [
"email"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": true
}
},
"enums": {},
"schemas": {},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}

View File

@ -0,0 +1,13 @@
{
"version": "7",
"dialect": "postgresql",
"entries": [
{
"idx": 0,
"version": "7",
"when": 1750753385927,
"tag": "0000_brainy_saracen",
"breakpoints": true
}
]
}

27
packages/db/package.json Normal file
View File

@ -0,0 +1,27 @@
{
"name": "@opencut/db",
"version": "0.0.0",
"description": "Database package for OpenCut",
"main": "./src/index.ts",
"types": "./src/index.ts",
"exports": {
".": "./src/index.ts",
"./schema": "./src/schema.ts",
"./drizzle.config": "./drizzle.config.ts"
},
"scripts": {
"db:generate": "drizzle-kit generate",
"db:migrate": "drizzle-kit migrate",
"db:push": "drizzle-kit push",
"db:studio": "drizzle-kit studio"
},
"dependencies": {
"drizzle-orm": "^0.36.4",
"postgres": "^3.4.5"
},
"devDependencies": {
"drizzle-kit": "^0.30.0",
"dotenv": "^16.4.7",
"@types/pg": "^8.11.10"
}
}

16
packages/db/src/index.ts Normal file
View File

@ -0,0 +1,16 @@
import { drizzle } from "drizzle-orm/postgres-js";
import postgres from "postgres";
import * as schema from "./schema";
if (!process.env.DATABASE_URL) {
throw new Error("DATABASE_URL is not set");
}
// Create the postgres client
const client = postgres(process.env.DATABASE_URL);
// Create the drizzle instance
export const db = drizzle(client, { schema });
// Re-export schema for convenience
export * from "./schema";

69
packages/db/src/schema.ts Normal file
View File

@ -0,0 +1,69 @@
import { pgTable, text, timestamp, boolean } from "drizzle-orm/pg-core";
export const users = pgTable("users", {
id: text("id").primaryKey(),
name: text("name").notNull(),
email: text("email").notNull().unique(),
emailVerified: boolean("email_verified")
.$defaultFn(() => false)
.notNull(),
image: text("image"),
createdAt: timestamp("created_at")
.$defaultFn(() => /* @__PURE__ */ new Date())
.notNull(),
updatedAt: timestamp("updated_at")
.$defaultFn(() => /* @__PURE__ */ new Date())
.notNull(),
}).enableRLS();
export const sessions = pgTable("sessions", {
id: text("id").primaryKey(),
expiresAt: timestamp("expires_at").notNull(),
token: text("token").notNull().unique(),
createdAt: timestamp("created_at").notNull(),
updatedAt: timestamp("updated_at").notNull(),
ipAddress: text("ip_address"),
userAgent: text("user_agent"),
userId: text("user_id")
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
}).enableRLS();
export const accounts = pgTable("accounts", {
id: text("id").primaryKey(),
accountId: text("account_id").notNull(),
providerId: text("provider_id").notNull(),
userId: text("user_id")
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
accessToken: text("access_token"),
refreshToken: text("refresh_token"),
idToken: text("id_token"),
accessTokenExpiresAt: timestamp("access_token_expires_at"),
refreshTokenExpiresAt: timestamp("refresh_token_expires_at"),
scope: text("scope"),
password: text("password"),
createdAt: timestamp("created_at").notNull(),
updatedAt: timestamp("updated_at").notNull(),
}).enableRLS();
export const verifications = pgTable("verifications", {
id: text("id").primaryKey(),
identifier: text("identifier").notNull(),
value: text("value").notNull(),
expiresAt: timestamp("expires_at").notNull(),
createdAt: timestamp("created_at").$defaultFn(
() => /* @__PURE__ */ new Date()
),
updatedAt: timestamp("updated_at").$defaultFn(
() => /* @__PURE__ */ new Date()
),
}).enableRLS();
export const waitlist = pgTable("waitlist", {
id: text("id").primaryKey(),
email: text("email").notNull().unique(),
createdAt: timestamp("created_at")
.$defaultFn(() => /* @__PURE__ */ new Date())
.notNull(),
}).enableRLS();

16
turbo.json Normal file
View File

@ -0,0 +1,16 @@
{
"$schema": "https://turborepo.com/schema.json",
"tasks": {
"build": {
"dependsOn": ["^build"],
"outputs": [".next/**", "!.next/cache/**"]
},
"check-types": {
"dependsOn": ["^check-types"]
},
"dev": {
"persistent": true,
"cache": false
}
}
}