refactor packages, env, db and auth (prev commit)

This commit is contained in:
Maze Winther 2025-11-26 10:12:40 +01:00
parent 811491ba9c
commit 2da84e7132
25 changed files with 202 additions and 158 deletions

View File

@ -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;

View File

@ -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"
}
}
}

View File

@ -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}

View File

@ -1,6 +1,6 @@
import { createAuthClient } from "better-auth/react";
import { env } from "@opencut/env";
import { toolsEnv } from "@opencut/env/tools";
export const { signIn, signUp, useSession } = createAuthClient({
baseURL: env.NEXT_PUBLIC_SITE_URL,
baseURL: toolsEnv.NEXT_PUBLIC_SITE_URL,
});

View File

@ -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;

View File

@ -1,13 +1,13 @@
import { drizzle } from "drizzle-orm/postgres-js";
import postgres from "postgres";
import * as schema from "./schema";
import { env } from "@opencut/env";
import { toolsEnv } from "@opencut/env/tools";
let _db: ReturnType<typeof drizzle> | null = null;
function getDb() {
if (!_db) {
const client = postgres(env.DATABASE_URL);
const client = postgres(toolsEnv.DATABASE_URL);
_db = drizzle(client, { schema });
}
@ -17,17 +17,3 @@ function getDb() {
export const db = getDb();
export * from "./schema";
export {
eq,
and,
or,
not,
isNull,
isNotNull,
inArray,
notInArray,
exists,
notExists,
sql,
} from "drizzle-orm";

View File

@ -1,9 +1,9 @@
import type { Config } from "drizzle-kit";
import * as dotenv from "dotenv";
import { env } from "@opencut/env";
import { webEnv } from "@opencut/env/web";
// Load the right env file based on environment
if (env.NODE_ENV === "production") {
if (webEnv.NODE_ENV === "production") {
dotenv.config({ path: ".env.production" });
} else {
dotenv.config({ path: ".env.local" });
@ -16,8 +16,8 @@ export default {
table: "drizzle_migrations",
},
dbCredentials: {
url: env.DATABASE_URL,
url: webEnv.DATABASE_URL,
},
out: "./migrations",
strict: env.NODE_ENV === "production",
strict: webEnv.NODE_ENV === "production",
} satisfies Config;

View File

@ -21,8 +21,6 @@
"@ffmpeg/util": "^0.12.2",
"@hello-pangea/dnd": "^18.0.1",
"@hookform/resolvers": "^3.9.1",
"@opencut/auth": "workspace:*",
"@opencut/db": "workspace:*",
"@opencut/env": "workspace:*",
"@opencut/ui": "workspace:*",
"@radix-ui/react-separator": "^1.1.7",
@ -36,8 +34,8 @@
"clsx": "^2.1.1",
"cmdk": "^1.0.0",
"dayjs": "^1.11.13",
"dotenv": "^16.5.0",
"drizzle-orm": "^0.44.2",
"postgres": "^3.4.5",
"embla-carousel-react": "^8.5.1",
"eventemitter3": "^5.0.1",
"feed": "^5.1.0",
@ -85,6 +83,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",
@ -92,4 +91,4 @@
"tsx": "^4.7.1",
"typescript": "^5.8.3"
}
}
}

View File

@ -8,7 +8,7 @@ import { StorageProvider } from "../components/storage-provider";
import { ScenesMigrator } from "../components/providers/migrators/scenes-migrator";
import { baseMetaData } from "./metadata";
import { BotIdClient } from "botid/client";
import { env } from "@opencut/env";
import { webEnv } from "@opencut/env/web";
import { Inter } from "next/font/google";
const siteFont = Inter({ subsets: ["latin"] });
@ -45,7 +45,7 @@ export default function RootLayout({
strategy="afterInteractive"
async
data-client-id="UP-Wcoy5arxFeK7oyjMMZ"
data-disabled={env.NODE_ENV === "development"}
data-disabled={webEnv.NODE_ENV === "development"}
data-track-attributes={false}
data-track-errors={true}
data-track-outgoing-links={false}

View File

@ -1,6 +1,6 @@
import { createAuthClient } from "better-auth/react";
import { env } from "@opencut/env";
import { webEnv } from "@opencut/env/web";
export const { signIn, signUp, useSession } = createAuthClient({
baseURL: env.NEXT_PUBLIC_SITE_URL,
baseURL: webEnv.NEXT_PUBLIC_SITE_URL,
});

View File

@ -1,12 +1,12 @@
import { betterAuth, RateLimit } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { Redis } from "@upstash/redis";
import { db } from "@opencut/db";
import { env } from "@opencut/env";
import { db } from "@/lib/db";
import { webEnv } from "@opencut/env/web";
const redis = new Redis({
url: env.UPSTASH_REDIS_REST_URL,
token: env.UPSTASH_REDIS_REST_TOKEN,
url: webEnv.UPSTASH_REDIS_REST_URL,
token: webEnv.UPSTASH_REDIS_REST_TOKEN,
});
export const auth = betterAuth({
@ -14,7 +14,7 @@ export const auth = betterAuth({
provider: "pg",
usePlural: true,
}),
secret: env.BETTER_AUTH_SECRET,
secret: webEnv.BETTER_AUTH_SECRET,
user: {
deleteUser: {
enabled: true,
@ -35,9 +35,9 @@ export const auth = betterAuth({
},
},
},
baseURL: env.NEXT_PUBLIC_SITE_URL,
baseURL: webEnv.NEXT_PUBLIC_SITE_URL,
appName: "OpenCut",
trustedOrigins: ["http://localhost:3000"],
trustedOrigins: [webEnv.NEXT_PUBLIC_SITE_URL],
});
export type Auth = typeof auth;

View File

@ -0,0 +1,19 @@
import { drizzle } from "drizzle-orm/postgres-js";
import postgres from "postgres";
import * as schema from "./schema";
import { webEnv } from "@opencut/env/web";
let _db: ReturnType<typeof drizzle> | null = null;
function getDb() {
if (!_db) {
const client = postgres(webEnv.DATABASE_URL);
_db = drizzle(client, { schema });
}
return _db;
}
export const db = getDb();
export * from "./schema";

View File

@ -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();

View File

@ -29,6 +29,7 @@
"clsx": "^2.1.1",
"cmdk": "^1.0.0",
"dotenv": "^16.5.0",
"drizzle-orm": "^0.44.2",
"embla-carousel-react": "^8.5.1",
"input-otp": "^1.4.1",
"lucide-react": "^0.468.0",
@ -38,6 +39,7 @@
"next": "^15.5.3",
"next-themes": "^0.4.4",
"pg": "^8.16.2",
"postgres": "^3.4.5",
"radix-ui": "^1.4.2",
"react": "^18.2.0",
"react-day-picker": "^8.10.1",
@ -69,6 +71,7 @@
"@types/react": "^18.2.48",
"@types/react-dom": "^18.2.18",
"cross-env": "^7.0.3",
"dotenv": "^16.5.0",
"drizzle-kit": "^0.31.4",
"postcss": "^8",
"prettier": "^3.6.2",
@ -87,8 +90,6 @@
"@ffmpeg/util": "^0.12.2",
"@hello-pangea/dnd": "^18.0.1",
"@hookform/resolvers": "^3.9.1",
"@opencut/auth": "workspace:*",
"@opencut/db": "workspace:*",
"@opencut/env": "workspace:*",
"@opencut/ui": "workspace:*",
"@radix-ui/react-separator": "^1.1.7",
@ -102,7 +103,6 @@
"clsx": "^2.1.1",
"cmdk": "^1.0.0",
"dayjs": "^1.11.13",
"dotenv": "^16.5.0",
"drizzle-orm": "^0.44.2",
"embla-carousel-react": "^8.5.1",
"eventemitter3": "^5.0.1",
@ -115,6 +115,7 @@
"next": "^15.5.3",
"next-themes": "^0.4.4",
"pg": "^8.16.2",
"postgres": "^3.4.5",
"radix-ui": "^1.4.2",
"react": "^18.2.0",
"react-country-flag": "^3.1.0",
@ -150,6 +151,7 @@
"@types/react": "^18.2.48",
"@types/react-dom": "^18.2.18",
"cross-env": "^7.0.3",
"dotenv": "^16.5.0",
"drizzle-kit": "^0.31.4",
"postcss": "^8",
"prettier": "^3.6.2",
@ -159,35 +161,6 @@
"typescript": "^5.8.3",
},
},
"packages/auth": {
"name": "@opencut/auth",
"version": "0.0.0",
"dependencies": {
"@opencut/db": "workspace:*",
"@opencut/env": "workspace:*",
"@upstash/redis": "^1.35.4",
"better-auth": "^1.1.1",
"zod": "^4.0.5",
},
"devDependencies": {
"@types/node": "^22.10.2",
},
},
"packages/db": {
"name": "@opencut/db",
"version": "0.0.0",
"dependencies": {
"@opencut/env": "workspace:*",
"drizzle-orm": "^0.44.2",
"postgres": "^3.4.5",
"zod": "^4.0.5",
},
"devDependencies": {
"@types/pg": "^8.11.10",
"dotenv": "^16.4.7",
"drizzle-kit": "^0.31.1",
},
},
"packages/env": {
"name": "@opencut/env",
"version": "0.0.0",
@ -406,10 +379,6 @@
"@noble/hashes": ["@noble/hashes@1.8.0", "", {}, "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="],
"@opencut/auth": ["@opencut/auth@workspace:packages/auth"],
"@opencut/db": ["@opencut/db@workspace:packages/db"],
"@opencut/env": ["@opencut/env@workspace:packages/env"],
"@opencut/tools": ["@opencut/tools@workspace:apps/tools"],
@ -622,7 +591,7 @@
"@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="],
"@types/node": ["@types/node@22.16.5", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-bJFoMATwIGaxxx8VJPeM8TonI8t579oRvgAuT8zFugJsJZgzqv0Fu8Mhp68iecjzG7cnN3mO2dJQ5uUM2EFrgQ=="],
"@types/node": ["@types/node@24.2.1", "", { "dependencies": { "undici-types": "~7.10.0" } }, "sha512-DRh5K+ka5eJic8CjH7td8QpYEV6Zo10gfRkjHCO3weqZHWDtAaSTFtl4+VMqOJ4N5jcuhZ9/l+yy8rVgw7BQeQ=="],
"@types/pg": ["@types/pg@8.15.4", "", { "dependencies": { "@types/node": "*", "pg-protocol": "*", "pg-types": "^2.2.0" } }, "sha512-I6UNVBAoYbvuWkkU3oosC8yxqH21f4/Jc4DK71JLG3dT2mdlGe1z+ep/LQGXaKaOgcvUrsQoPRqfgtMcvZiJhg=="],
@ -662,7 +631,7 @@
"buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="],
"bun-types": ["bun-types@1.2.19", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-uAOTaZSPuYsWIXRpj7o56Let0g/wjihKCkeRqUBhlLVM/Bt+Fj9xTo+LhC1OV1XDaGkz4hNC80et5xgy+9KTHQ=="],
"bun-types": ["bun-types@1.3.3", "", { "dependencies": { "@types/node": "*" } }, "sha512-z3Xwlg7j2l9JY27x5Qn3Wlyos8YAp0kKRlrePAOjgjMGS5IG6E7Jnlx736vH9UVI4wUICwwhC9anYL++XeOgTQ=="],
"caniuse-lite": ["caniuse-lite@1.0.30001727", "", {}, "sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q=="],
@ -1160,7 +1129,7 @@
"uncrypto": ["uncrypto@0.1.3", "", {}, "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q=="],
"undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
"undici-types": ["undici-types@7.10.0", "", {}, "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag=="],
"unified": ["unified@11.0.5", "", { "dependencies": { "@types/unist": "^3.0.0", "bail": "^2.0.0", "devlop": "^1.0.0", "extend": "^3.0.0", "is-plain-obj": "^4.0.0", "trough": "^2.0.0", "vfile": "^6.0.0" } }, "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA=="],
@ -1214,10 +1183,6 @@
"@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="],
"@opencut/env/@types/node": ["@types/node@24.2.1", "", { "dependencies": { "undici-types": "~7.10.0" } }, "sha512-DRh5K+ka5eJic8CjH7td8QpYEV6Zo10gfRkjHCO3weqZHWDtAaSTFtl4+VMqOJ4N5jcuhZ9/l+yy8rVgw7BQeQ=="],
"@opencut/tools/@types/node": ["@types/node@24.2.1", "", { "dependencies": { "undici-types": "~7.10.0" } }, "sha512-DRh5K+ka5eJic8CjH7td8QpYEV6Zo10gfRkjHCO3weqZHWDtAaSTFtl4+VMqOJ4N5jcuhZ9/l+yy8rVgw7BQeQ=="],
"@opencut/tools/next": ["next@15.5.3", "", { "dependencies": { "@next/env": "15.5.3", "@swc/helpers": "0.5.15", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "15.5.3", "@next/swc-darwin-x64": "15.5.3", "@next/swc-linux-arm64-gnu": "15.5.3", "@next/swc-linux-arm64-musl": "15.5.3", "@next/swc-linux-x64-gnu": "15.5.3", "@next/swc-linux-x64-musl": "15.5.3", "@next/swc-win32-arm64-msvc": "15.5.3", "@next/swc-win32-x64-msvc": "15.5.3", "sharp": "^0.34.3" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-r/liNAx16SQj4D+XH/oI1dlpv9tdKJ6cONYPwwcCC46f2NjpaRWY+EKCzULfgQYV6YKXjHBchff2IZBSlZmJNw=="],
"@opencut/tools/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
@ -1226,8 +1191,6 @@
"@opencut/ui/react": ["react@19.2.0", "", {}, "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ=="],
"@opencut/web/@types/node": ["@types/node@24.2.1", "", { "dependencies": { "undici-types": "~7.10.0" } }, "sha512-DRh5K+ka5eJic8CjH7td8QpYEV6Zo10gfRkjHCO3weqZHWDtAaSTFtl4+VMqOJ4N5jcuhZ9/l+yy8rVgw7BQeQ=="],
"@opencut/web/next": ["next@15.5.3", "", { "dependencies": { "@next/env": "15.5.3", "@swc/helpers": "0.5.15", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "15.5.3", "@next/swc-darwin-x64": "15.5.3", "@next/swc-linux-arm64-gnu": "15.5.3", "@next/swc-linux-arm64-musl": "15.5.3", "@next/swc-linux-x64-gnu": "15.5.3", "@next/swc-linux-x64-musl": "15.5.3", "@next/swc-win32-arm64-msvc": "15.5.3", "@next/swc-win32-x64-msvc": "15.5.3", "sharp": "^0.34.3" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-r/liNAx16SQj4D+XH/oI1dlpv9tdKJ6cONYPwwcCC46f2NjpaRWY+EKCzULfgQYV6YKXjHBchff2IZBSlZmJNw=="],
"@opencut/web/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
@ -1244,7 +1207,7 @@
"@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
"@types/bun/bun-types": ["bun-types@1.3.3", "", { "dependencies": { "@types/node": "*" } }, "sha512-z3Xwlg7j2l9JY27x5Qn3Wlyos8YAp0kKRlrePAOjgjMGS5IG6E7Jnlx736vH9UVI4wUICwwhC9anYL++XeOgTQ=="],
"@types/pg/@types/node": ["@types/node@22.16.5", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-bJFoMATwIGaxxx8VJPeM8TonI8t579oRvgAuT8zFugJsJZgzqv0Fu8Mhp68iecjzG7cnN3mO2dJQ5uUM2EFrgQ=="],
"@upstash/core-analytics/@upstash/redis": ["@upstash/redis@1.35.1", "", { "dependencies": { "uncrypto": "^0.1.3" } }, "sha512-sIMuAMU9IYbE2bkgDby8KLoQKRiBMXn0moXxqLvUmQ7VUu2CvulZLtK8O0x3WQZFvvZhU5sRC2/lOVZdGfudkA=="],
@ -1304,10 +1267,6 @@
"@esbuild-kit/core-utils/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.18.20", "", { "os": "win32", "cpu": "x64" }, "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ=="],
"@opencut/env/@types/node/undici-types": ["undici-types@7.10.0", "", {}, "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag=="],
"@opencut/tools/@types/node/undici-types": ["undici-types@7.10.0", "", {}, "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag=="],
"@opencut/tools/next/@next/env": ["@next/env@15.5.3", "", {}, "sha512-RSEDTRqyihYXygx/OJXwvVupfr9m04+0vH8vyy0HfZ7keRto6VX9BbEk0J2PUk0VGy6YhklJUSrgForov5F9pw=="],
"@opencut/tools/next/@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@15.5.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-nzbHQo69+au9wJkGKTU9lP7PXv0d1J5ljFpvb+LnEomLtSbJkbZyEs6sbF3plQmiOB2l9OBtN2tNSvCH1nQ9Jg=="],
@ -1330,8 +1289,6 @@
"@opencut/ui/@types/react/csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="],
"@opencut/web/@types/node/undici-types": ["undici-types@7.10.0", "", {}, "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag=="],
"@opencut/web/next/@next/env": ["@next/env@15.5.3", "", {}, "sha512-RSEDTRqyihYXygx/OJXwvVupfr9m04+0vH8vyy0HfZ7keRto6VX9BbEk0J2PUk0VGy6YhklJUSrgForov5F9pw=="],
"@opencut/web/next/@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@15.5.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-nzbHQo69+au9wJkGKTU9lP7PXv0d1J5ljFpvb+LnEomLtSbJkbZyEs6sbF3plQmiOB2l9OBtN2tNSvCH1nQ9Jg=="],
@ -1354,14 +1311,12 @@
"@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime/@tybys/wasm-util": ["@tybys/wasm-util@0.10.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ=="],
"@types/bun/bun-types/@types/node": ["@types/node@24.2.1", "", { "dependencies": { "undici-types": "~7.10.0" } }, "sha512-DRh5K+ka5eJic8CjH7td8QpYEV6Zo10gfRkjHCO3weqZHWDtAaSTFtl4+VMqOJ4N5jcuhZ9/l+yy8rVgw7BQeQ=="],
"@types/pg/@types/node/undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
"next/postcss/nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
"@opencut/tools/next/postcss/nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
"@opencut/web/next/postcss/nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
"@types/bun/bun-types/@types/node/undici-types": ["undici-types@7.10.0", "", {}, "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag=="],
}
}

View File

@ -10,11 +10,7 @@
"build:web": "turbo run build --filter=@opencut/web",
"dev:tools": "turbo run dev --filter=@opencut/tools",
"build:tools": "turbo run build --filter=@opencut/tools",
"start:tools": "turbo run start --filter=@opencut/tools",
"db:generate": "turbo run db:generate --filter=@opencut/db",
"db:migrate": "turbo run db:migrate --filter=@opencut/db",
"db:push:local": "turbo run db:push:local --filter=@opencut/db",
"db:push:prod": "turbo run db:push:prod --filter=@opencut/db"
"start:tools": "turbo run start --filter=@opencut/tools"
},
"dependencies": {
"next": "^15.3.4"

View File

@ -1,22 +0,0 @@
{
"name": "@opencut/auth",
"version": "0.0.0",
"description": "Authentication package for OpenCut",
"main": "./src/index.ts",
"types": "./src/index.ts",
"exports": {
".": "./src/index.ts",
"./client": "./src/client.ts",
"./server": "./src/server.ts"
},
"dependencies": {
"@opencut/db": "workspace:*",
"@opencut/env": "workspace:*",
"better-auth": "^1.1.1",
"zod": "^4.0.5",
"@upstash/redis": "^1.35.4"
},
"devDependencies": {
"@types/node": "^22.10.2"
}
}

View File

@ -1 +0,0 @@
export * from "./react";

View File

@ -1,2 +0,0 @@
export * from "./server";
export * from "./clients/index";

View File

@ -1,30 +0,0 @@
{
"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": "bun --env-file=../../.env run drizzle-kit generate",
"db:migrate": "bun --env-file=../../.env run drizzle-kit migrate",
"db:push:local": "cross-env NODE_ENV=development bun --env-file=../../.env run drizzle-kit push",
"db:push:prod": "cross-env NODE_ENV=production bun --env-file=../../.env run drizzle-kit push"
},
"dependencies": {
"@opencut/env": "workspace:*",
"drizzle-orm": "^0.44.2",
"postgres": "^3.4.5",
"zod": "^4.0.5"
},
"devDependencies": {
"drizzle-kit": "^0.31.1",
"dotenv": "^16.4.7",
"@types/pg": "^8.11.10"
}
}

View File

@ -5,7 +5,9 @@
"main": "./src/index.ts",
"types": "./src/index.ts",
"exports": {
".": "./src/index.ts"
".": "./src/index.ts",
"./web": "./src/web.ts",
"./tools": "./src/tools.ts"
},
"dependencies": {
"zod": "^4.0.5"

View File

@ -8,7 +8,6 @@ const toolsEnvSchema = z.object({
// Public
NEXT_PUBLIC_SITE_URL: z.url().default("http://localhost:3000"),
NEXT_PUBLIC_MARBLE_API_URL: z.url(),
// Server
DATABASE_URL: z