mirror of
https://github.com/OpenCut-app/OpenCut.git
synced 2026-07-13 21:52:53 +02:00
refactor packages, env, db and auth (prev commit)
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
import type { Config } from "drizzle-kit";
|
||||
import * as dotenv from "dotenv";
|
||||
import { toolsEnv } from "@opencut/env/tools";
|
||||
|
||||
// Load the right env file based on environment
|
||||
if (toolsEnv.NODE_ENV === "production") {
|
||||
dotenv.config({ path: ".env.production" });
|
||||
} else {
|
||||
dotenv.config({ path: ".env.local" });
|
||||
}
|
||||
|
||||
export default {
|
||||
schema: "./src/schema.ts",
|
||||
dialect: "postgresql",
|
||||
migrations: {
|
||||
table: "drizzle_migrations",
|
||||
},
|
||||
dbCredentials: {
|
||||
url: toolsEnv.DATABASE_URL,
|
||||
},
|
||||
out: "./migrations",
|
||||
strict: toolsEnv.NODE_ENV === "production",
|
||||
} satisfies Config;
|
||||
@@ -9,7 +9,11 @@
|
||||
"start": "next start --port 3001",
|
||||
"lint": "biome check src/",
|
||||
"lint:fix": "biome check src/ --write",
|
||||
"format": "biome format src/ --write"
|
||||
"format": "biome format src/ --write",
|
||||
"db:generate": "drizzle-kit generate",
|
||||
"db:migrate": "drizzle-kit migrate",
|
||||
"db:push:local": "cross-env NODE_ENV=development drizzle-kit push",
|
||||
"db:push:prod": "cross-env NODE_ENV=production drizzle-kit push"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hookform/resolvers": "^3.9.1",
|
||||
@@ -20,6 +24,8 @@
|
||||
"@upstash/redis": "^1.35.4",
|
||||
"aws4fetch": "^1.0.20",
|
||||
"better-auth": "^1.2.7",
|
||||
"drizzle-orm": "^0.44.2",
|
||||
"postgres": "^3.4.5",
|
||||
"botid": "^1.4.2",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
@@ -66,6 +72,7 @@
|
||||
"@types/react-dom": "^18.2.18",
|
||||
"cross-env": "^7.0.3",
|
||||
"drizzle-kit": "^0.31.4",
|
||||
"dotenv": "^16.5.0",
|
||||
"postcss": "^8",
|
||||
"prettier": "^3.6.2",
|
||||
"prettier-plugin-tailwindcss": "^0.6.14",
|
||||
@@ -73,4 +80,4 @@
|
||||
"tsx": "^4.7.1",
|
||||
"typescript": "^5.8.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import { Toaster } from "../components/ui/sonner";
|
||||
import { TooltipProvider } from "../components/ui/tooltip";
|
||||
import { baseMetaData } from "./metadata";
|
||||
import { BotIdClient } from "botid/client";
|
||||
import { env } from "@opencut/env";
|
||||
import { toolsEnv } from "@opencut/env/tools";
|
||||
import { Inter } from "next/font/google";
|
||||
|
||||
const siteFont = Inter({ subsets: ["latin"] });
|
||||
@@ -39,7 +39,7 @@ export default function RootLayout({
|
||||
strategy="afterInteractive"
|
||||
async
|
||||
data-client-id="Apo7VtbtH8QvYfCn-NLXX"
|
||||
data-disabled={env.NODE_ENV === "development"}
|
||||
data-disabled={toolsEnv.NODE_ENV === "development"}
|
||||
data-track-attributes={false}
|
||||
data-track-errors={true}
|
||||
data-track-outgoing-links={false}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
import { createAuthClient } from "better-auth/react";
|
||||
import { toolsEnv } from "@opencut/env/tools";
|
||||
|
||||
export const { signIn, signUp, useSession } = createAuthClient({
|
||||
baseURL: toolsEnv.NEXT_PUBLIC_SITE_URL,
|
||||
});
|
||||
@@ -0,0 +1,43 @@
|
||||
import { betterAuth, RateLimit } from "better-auth";
|
||||
import { drizzleAdapter } from "better-auth/adapters/drizzle";
|
||||
import { Redis } from "@upstash/redis";
|
||||
import { db } from "@/lib/db";
|
||||
import { toolsEnv } from "@opencut/env/tools";
|
||||
|
||||
const redis = new Redis({
|
||||
url: toolsEnv.UPSTASH_REDIS_REST_URL,
|
||||
token: toolsEnv.UPSTASH_REDIS_REST_TOKEN,
|
||||
});
|
||||
|
||||
export const auth = betterAuth({
|
||||
database: drizzleAdapter(db, {
|
||||
provider: "pg",
|
||||
usePlural: true,
|
||||
}),
|
||||
secret: toolsEnv.BETTER_AUTH_SECRET,
|
||||
user: {
|
||||
deleteUser: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
emailAndPassword: {
|
||||
enabled: true,
|
||||
},
|
||||
rateLimit: {
|
||||
storage: "secondary-storage",
|
||||
customStorage: {
|
||||
get: async (key) => {
|
||||
const value = await redis.get(key);
|
||||
return value as RateLimit | undefined;
|
||||
},
|
||||
set: async (key, value) => {
|
||||
await redis.set(key, value);
|
||||
},
|
||||
},
|
||||
},
|
||||
baseURL: toolsEnv.NEXT_PUBLIC_SITE_URL,
|
||||
appName: "OpenCut Tools",
|
||||
trustedOrigins: [toolsEnv.NEXT_PUBLIC_SITE_URL],
|
||||
});
|
||||
|
||||
export type Auth = typeof auth;
|
||||
@@ -0,0 +1,19 @@
|
||||
import { drizzle } from "drizzle-orm/postgres-js";
|
||||
import postgres from "postgres";
|
||||
import * as schema from "./schema";
|
||||
import { toolsEnv } from "@opencut/env/tools";
|
||||
|
||||
let _db: ReturnType<typeof drizzle> | null = null;
|
||||
|
||||
function getDb() {
|
||||
if (!_db) {
|
||||
const client = postgres(toolsEnv.DATABASE_URL);
|
||||
_db = drizzle(client, { schema });
|
||||
}
|
||||
|
||||
return _db;
|
||||
}
|
||||
|
||||
export const db = getDb();
|
||||
|
||||
export * from "./schema";
|
||||
@@ -0,0 +1,70 @@
|
||||
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").default(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 exportWaitlist = pgTable("export_waitlist", {
|
||||
id: text("id").primaryKey(),
|
||||
email: text("email").notNull().unique(),
|
||||
createdAt: timestamp("created_at")
|
||||
.$defaultFn(() => /* @__PURE__ */ new Date())
|
||||
.notNull(),
|
||||
updatedAt: timestamp("updated_at")
|
||||
.$defaultFn(() => /* @__PURE__ */ new Date())
|
||||
.notNull(),
|
||||
}).enableRLS();
|
||||
Reference in New Issue
Block a user