diff options
| author | Maze Winther <mazewinther@gmail.com> | 2026-03-29 14:15:21 +0200 |
|---|---|---|
| committer | Maze Winther <mazewinther@gmail.com> | 2026-03-29 15:58:46 +0200 |
| commit | 220ec757d42b54f498d031436e5b4b03931b165c (patch) | |
| tree | 931a9b147c692b1fa5fcdc17ec568dea6bd437b2 /apps/web/src/lib | |
| parent | 585e28d49b853155c34a3eba03388722e2049cb7 (diff) | |
| download | opencut-220ec757d42b54f498d031436e5b4b03931b165c.tar.gz | |
refactor: move packages sub-folders into web app
Diffstat (limited to 'apps/web/src/lib')
| -rw-r--r-- | apps/web/src/lib/auth/client.ts | 12 | ||||
| -rw-r--r-- | apps/web/src/lib/auth/server.ts | 86 | ||||
| -rw-r--r-- | apps/web/src/lib/db/index.ts | 2 | ||||
| -rw-r--r-- | apps/web/src/lib/env/web.ts | 34 | ||||
| -rw-r--r-- | apps/web/src/lib/rate-limit.ts | 42 |
5 files changed, 105 insertions, 71 deletions
diff --git a/apps/web/src/lib/auth/client.ts b/apps/web/src/lib/auth/client.ts index a4380e54..3bec5072 100644 --- a/apps/web/src/lib/auth/client.ts +++ b/apps/web/src/lib/auth/client.ts @@ -1,6 +1,6 @@ -import { createAuthClient } from "better-auth/react";
-import { webEnv } from "@opencut/env/web";
-
-export const { signIn, signUp, useSession } = createAuthClient({
- baseURL: webEnv.NEXT_PUBLIC_SITE_URL,
-});
+import { createAuthClient } from "better-auth/react"; +import { webEnv } from "@/lib/env/web"; + +export const { signIn, signUp, useSession } = createAuthClient({ + baseURL: webEnv.NEXT_PUBLIC_SITE_URL, +}); diff --git a/apps/web/src/lib/auth/server.ts b/apps/web/src/lib/auth/server.ts index aaca7936..39fce38f 100644 --- a/apps/web/src/lib/auth/server.ts +++ b/apps/web/src/lib/auth/server.ts @@ -1,43 +1,43 @@ -import { betterAuth, type RateLimit } from "better-auth";
-import { drizzleAdapter } from "better-auth/adapters/drizzle";
-import { Redis } from "@upstash/redis";
-import { db } from "@/lib/db";
-import { webEnv } from "@opencut/env/web";
-
-const redis = new Redis({
- url: webEnv.UPSTASH_REDIS_REST_URL,
- token: webEnv.UPSTASH_REDIS_REST_TOKEN,
-});
-
-export const auth = betterAuth({
- database: drizzleAdapter(db, {
- provider: "pg",
- usePlural: true,
- }),
- secret: webEnv.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: webEnv.NEXT_PUBLIC_SITE_URL,
- appName: "OpenCut",
- trustedOrigins: [webEnv.NEXT_PUBLIC_SITE_URL],
-});
-
-export type Auth = typeof auth;
+import { betterAuth, type RateLimit } from "better-auth"; +import { drizzleAdapter } from "better-auth/adapters/drizzle"; +import { Redis } from "@upstash/redis"; +import { db } from "@/lib/db"; +import { webEnv } from "@/lib/env/web"; + +const redis = new Redis({ + url: webEnv.UPSTASH_REDIS_REST_URL, + token: webEnv.UPSTASH_REDIS_REST_TOKEN, +}); + +export const auth = betterAuth({ + database: drizzleAdapter(db, { + provider: "pg", + usePlural: true, + }), + secret: webEnv.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: webEnv.NEXT_PUBLIC_SITE_URL, + appName: "OpenCut", + trustedOrigins: [webEnv.NEXT_PUBLIC_SITE_URL], +}); + +export type Auth = typeof auth; diff --git a/apps/web/src/lib/db/index.ts b/apps/web/src/lib/db/index.ts index 290e7c2a..b1ffd119 100644 --- a/apps/web/src/lib/db/index.ts +++ b/apps/web/src/lib/db/index.ts @@ -1,7 +1,7 @@ import { drizzle } from "drizzle-orm/postgres-js"; import postgres from "postgres"; import * as schema from "./schema"; -import { webEnv } from "@opencut/env/web"; +import { webEnv } from "@/lib/env/web"; let _db: ReturnType<typeof drizzle> | null = null; diff --git a/apps/web/src/lib/env/web.ts b/apps/web/src/lib/env/web.ts new file mode 100644 index 00000000..4e8b550e --- /dev/null +++ b/apps/web/src/lib/env/web.ts @@ -0,0 +1,34 @@ +import { z } from "zod"; + +const webEnvSchema = z.object({ + // Node + NODE_ENV: z.enum(["development", "production", "test"]), + ANALYZE: z.string().optional(), + NEXT_RUNTIME: z.enum(["nodejs", "edge"]).optional(), + + // Public + NEXT_PUBLIC_SITE_URL: z.url().default("http://localhost:3000"), + NEXT_PUBLIC_MARBLE_API_URL: z.url(), + + // Server + DATABASE_URL: z + .string() + .startsWith("postgres://") + .or(z.string().startsWith("postgresql://")), + + BETTER_AUTH_SECRET: z.string(), + UPSTASH_REDIS_REST_URL: z.url(), + UPSTASH_REDIS_REST_TOKEN: z.string(), + MARBLE_WORKSPACE_KEY: z.string(), + FREESOUND_CLIENT_ID: z.string(), + FREESOUND_API_KEY: z.string(), + CLOUDFLARE_ACCOUNT_ID: z.string(), + R2_ACCESS_KEY_ID: z.string(), + R2_SECRET_ACCESS_KEY: z.string(), + R2_BUCKET_NAME: z.string(), + MODAL_TRANSCRIPTION_URL: z.url(), +}); + +export type WebEnv = z.infer<typeof webEnvSchema>; + +export const webEnv = webEnvSchema.parse(process.env); diff --git a/apps/web/src/lib/rate-limit.ts b/apps/web/src/lib/rate-limit.ts index 6b59c473..234bf48f 100644 --- a/apps/web/src/lib/rate-limit.ts +++ b/apps/web/src/lib/rate-limit.ts @@ -1,21 +1,21 @@ -import { Ratelimit } from "@upstash/ratelimit";
-import { Redis } from "@upstash/redis";
-import { webEnv } from "@opencut/env/web";
-
-const redis = new Redis({
- url: webEnv.UPSTASH_REDIS_REST_URL,
- token: webEnv.UPSTASH_REDIS_REST_TOKEN,
-});
-
-export const baseRateLimit = new Ratelimit({
- redis,
- limiter: Ratelimit.slidingWindow(100, "1 m"), // 100 requests per minute
- analytics: true,
- prefix: "rate-limit",
-});
-
-export async function checkRateLimit({ request }: { request: Request }) {
- const ip = request.headers.get("x-forwarded-for") ?? "anonymous";
- const { success } = await baseRateLimit.limit(ip);
- return { success, limited: !success };
-}
+import { Ratelimit } from "@upstash/ratelimit"; +import { Redis } from "@upstash/redis"; +import { webEnv } from "@/lib/env/web"; + +const redis = new Redis({ + url: webEnv.UPSTASH_REDIS_REST_URL, + token: webEnv.UPSTASH_REDIS_REST_TOKEN, +}); + +export const baseRateLimit = new Ratelimit({ + redis, + limiter: Ratelimit.slidingWindow(100, "1 m"), // 100 requests per minute + analytics: true, + prefix: "rate-limit", +}); + +export async function checkRateLimit({ request }: { request: Request }) { + const ip = request.headers.get("x-forwarded-for") ?? "anonymous"; + const { success } = await baseRateLimit.limit(ip); + return { success, limited: !success }; +} |
