diff options
| author | Maze <167211895+mazeincoding@users.noreply.github.com> | 2026-01-31 00:20:04 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-01-31 00:20:04 +0100 |
| commit | 7bf0984698e43b9aa2dd879f65951318ed410390 (patch) | |
| tree | ccf2cd590a47d550152afc07129cb55c71a9ec35 /packages | |
| parent | 0173db99448d1c4c6415dcf15272e17551b48b04 (diff) | |
| download | opencut-7bf0984698e43b9aa2dd879f65951318ed410390.tar.gz | |
codebase overhaul (#697)
Diffstat (limited to 'packages')
| -rw-r--r-- | packages/auth/package.json | 22 | ||||
| -rw-r--r-- | packages/auth/src/client.ts | 8 | ||||
| -rw-r--r-- | packages/auth/src/index.ts | 8 | ||||
| -rw-r--r-- | packages/auth/src/keys.ts | 20 | ||||
| -rw-r--r-- | packages/auth/src/server.ts | 50 | ||||
| -rw-r--r-- | packages/db/drizzle.config.ts | 25 | ||||
| -rw-r--r-- | packages/db/migrations/0000_brainy_saracen.sql | 62 | ||||
| -rw-r--r-- | packages/db/migrations/meta/0000_snapshot.json | 344 | ||||
| -rw-r--r-- | packages/db/migrations/meta/_journal.json | 13 | ||||
| -rw-r--r-- | packages/db/package.json | 30 | ||||
| -rw-r--r-- | packages/db/src/index.ts | 38 | ||||
| -rw-r--r-- | packages/db/src/keys.ts | 19 | ||||
| -rw-r--r-- | packages/db/src/schema.ts | 70 | ||||
| -rw-r--r-- | packages/env/package.json | 21 | ||||
| -rw-r--r-- | packages/env/src/tools.ts | 29 | ||||
| -rw-r--r-- | packages/env/src/types/node-env.d.ts | 1 | ||||
| -rw-r--r-- | packages/env/src/web.ts | 34 | ||||
| -rw-r--r-- | packages/ui/package.json | 19 | ||||
| -rw-r--r-- | packages/ui/src/icons/brand.tsx | 67 | ||||
| -rw-r--r-- | packages/ui/src/icons/index.tsx | 2 | ||||
| -rw-r--r-- | packages/ui/src/icons/ui.tsx | 32 | ||||
| -rw-r--r-- | packages/ui/tsconfig.json | 20 |
22 files changed, 225 insertions, 709 deletions
diff --git a/packages/auth/package.json b/packages/auth/package.json deleted file mode 100644 index f76a2303..00000000 --- a/packages/auth/package.json +++ /dev/null @@ -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", - "./keys": "./src/keys.ts" - }, - "dependencies": { - "@opencut/db": "workspace:*", - "@t3-oss/env-nextjs": "^0.13.8", - "better-auth": "^1.1.1", - "zod": "^4.0.5" - }, - "devDependencies": { - "@types/node": "^22.10.2" - } -} diff --git a/packages/auth/src/client.ts b/packages/auth/src/client.ts deleted file mode 100644 index 2676fb0d..00000000 --- a/packages/auth/src/client.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { createAuthClient } from "better-auth/react"; -import { keys } from "./keys"; - -const { NEXT_PUBLIC_BETTER_AUTH_URL } = keys(); - -export const { signIn, signUp, useSession } = createAuthClient({ - baseURL: NEXT_PUBLIC_BETTER_AUTH_URL, -}); diff --git a/packages/auth/src/index.ts b/packages/auth/src/index.ts deleted file mode 100644 index 1209c39f..00000000 --- a/packages/auth/src/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -// Re-export server auth -export * from "./server"; - -// Re-export client auth -export * from "./client"; - -// Re-export keys -export * from "./keys"; diff --git a/packages/auth/src/keys.ts b/packages/auth/src/keys.ts deleted file mode 100644 index 3ac528f4..00000000 --- a/packages/auth/src/keys.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { createEnv } from "@t3-oss/env-nextjs"; -import { z } from "zod"; - -export const keys = () => - createEnv({ - server: { - BETTER_AUTH_SECRET: z.string(), - UPSTASH_REDIS_REST_URL: z.string().url(), - UPSTASH_REDIS_REST_TOKEN: z.string(), - }, - client: { - NEXT_PUBLIC_BETTER_AUTH_URL: z.string().url(), - }, - runtimeEnv: { - NEXT_PUBLIC_BETTER_AUTH_URL: process.env.NEXT_PUBLIC_BETTER_AUTH_URL, - BETTER_AUTH_SECRET: process.env.BETTER_AUTH_SECRET, - UPSTASH_REDIS_REST_URL: process.env.UPSTASH_REDIS_REST_URL, - UPSTASH_REDIS_REST_TOKEN: process.env.UPSTASH_REDIS_REST_TOKEN, - }, - }); diff --git a/packages/auth/src/server.ts b/packages/auth/src/server.ts deleted file mode 100644 index 84b91b39..00000000 --- a/packages/auth/src/server.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { betterAuth, RateLimit } from "better-auth"; -import { drizzleAdapter } from "better-auth/adapters/drizzle"; -import { db } from "@opencut/db"; -import { keys } from "./keys"; -import { Redis } from "@upstash/redis"; - -const { - NEXT_PUBLIC_BETTER_AUTH_URL, - BETTER_AUTH_SECRET, - UPSTASH_REDIS_REST_URL, - UPSTASH_REDIS_REST_TOKEN, -} = keys(); - -const redis = new Redis({ - url: UPSTASH_REDIS_REST_URL, - token: UPSTASH_REDIS_REST_TOKEN, -}); - -export const auth = betterAuth({ - database: drizzleAdapter(db, { - provider: "pg", - usePlural: true, - }), - secret: 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: NEXT_PUBLIC_BETTER_AUTH_URL, - appName: "OpenCut", - trustedOrigins: ["http://localhost:3000"], -}); - -export type Auth = typeof auth; diff --git a/packages/db/drizzle.config.ts b/packages/db/drizzle.config.ts deleted file mode 100644 index d661c455..00000000 --- a/packages/db/drizzle.config.ts +++ /dev/null @@ -1,25 +0,0 @@ -import type { Config } from "drizzle-kit"; -import * as dotenv from "dotenv"; -import { keys } from "./src/keys"; - -const { NODE_ENV, DATABASE_URL } = keys(); - -// Load the right env file based on environment -if (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: DATABASE_URL, - }, - out: "./migrations", - strict: NODE_ENV === "production", -} satisfies Config; diff --git a/packages/db/migrations/0000_brainy_saracen.sql b/packages/db/migrations/0000_brainy_saracen.sql deleted file mode 100644 index 2c6ab2b2..00000000 --- a/packages/db/migrations/0000_brainy_saracen.sql +++ /dev/null @@ -1,62 +0,0 @@ -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;
\ No newline at end of file diff --git a/packages/db/migrations/meta/0000_snapshot.json b/packages/db/migrations/meta/0000_snapshot.json deleted file mode 100644 index 8d505274..00000000 --- a/packages/db/migrations/meta/0000_snapshot.json +++ /dev/null @@ -1,344 +0,0 @@ -{ - "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": {} - } -} diff --git a/packages/db/migrations/meta/_journal.json b/packages/db/migrations/meta/_journal.json deleted file mode 100644 index c7d30f16..00000000 --- a/packages/db/migrations/meta/_journal.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "version": "7", - "dialect": "postgresql", - "entries": [ - { - "idx": 0, - "version": "7", - "when": 1750753385927, - "tag": "0000_brainy_saracen", - "breakpoints": true - } - ] -} diff --git a/packages/db/package.json b/packages/db/package.json deleted file mode 100644 index aebbbc90..00000000 --- a/packages/db/package.json +++ /dev/null @@ -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", - "./keys": "./src/keys.ts" - }, - "scripts": { - "db:generate": "drizzle-kit generate", - "db:migrate": "drizzle-kit migrate", - "db:push": "drizzle-kit push", - "db:studio": "drizzle-kit studio" - }, - "dependencies": { - "@t3-oss/env-nextjs": "^0.13.8", - "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" - } -} diff --git a/packages/db/src/index.ts b/packages/db/src/index.ts deleted file mode 100644 index 9b395ab6..00000000 --- a/packages/db/src/index.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { drizzle } from "drizzle-orm/postgres-js"; -import postgres from "postgres"; -import * as schema from "./schema"; -import { keys } from "./keys"; - -const { DATABASE_URL } = keys(); -// Create a lazy database instance that only initializes when accessed -let _db: ReturnType<typeof drizzle> | null = null; - -function getDb() { - if (!_db) { - const client = postgres(DATABASE_URL); - _db = drizzle(client, { schema }); - } - - return _db; -} - -// Export a proxy that forwards all calls to the actual db instance -export const db = getDb(); - -// Re-export schema for convenience -export * from "./schema"; - -// Re-export drizzle-orm functions to ensure version consistency -export { - eq, - and, - or, - not, - isNull, - isNotNull, - inArray, - notInArray, - exists, - notExists, - sql, -} from "drizzle-orm"; diff --git a/packages/db/src/keys.ts b/packages/db/src/keys.ts deleted file mode 100644 index 65983416..00000000 --- a/packages/db/src/keys.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { createEnv } from "@t3-oss/env-nextjs"; -import { z } from "zod"; - -export const keys = () => - createEnv({ - server: { - NODE_ENV: z - .enum(["development", "production", "test"]) - .default("development"), - DATABASE_URL: z - .string() - .startsWith("postgres://") - .or(z.string().startsWith("postgresql://")), - }, - runtimeEnv: { - NODE_ENV: process.env.NODE_ENV, - DATABASE_URL: process.env.DATABASE_URL, - }, - }); diff --git a/packages/db/src/schema.ts b/packages/db/src/schema.ts deleted file mode 100644 index a1a69e6d..00000000 --- a/packages/db/src/schema.ts +++ /dev/null @@ -1,70 +0,0 @@ -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(); diff --git a/packages/env/package.json b/packages/env/package.json new file mode 100644 index 00000000..0b794ef4 --- /dev/null +++ b/packages/env/package.json @@ -0,0 +1,21 @@ +{ + "name": "@opencut/env", + "version": "0.0.0", + "description": "Environment package for OpenCut", + "main": "./src/index.ts", + "types": "./src/index.ts", + "exports": { + ".": "./src/index.ts", + "./web": "./src/web.ts", + "./tools": "./src/tools.ts" + }, + "dependencies": { + "zod": "^4.0.5" + }, + "devDependencies": { + "dotenv": "^16.4.7", + "@types/bun": "latest", + "@types/node": "^24.2.1", + "typescript": "^5.8.3" + } +} diff --git a/packages/env/src/tools.ts b/packages/env/src/tools.ts new file mode 100644 index 00000000..625e3d71 --- /dev/null +++ b/packages/env/src/tools.ts @@ -0,0 +1,29 @@ +import { z } from "zod"; + +const toolsEnvSchema = 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"), + + // 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(), + CLOUDFLARE_ACCOUNT_ID: z.string(), + R2_ACCESS_KEY_ID: z.string(), + R2_SECRET_ACCESS_KEY: z.string(), + R2_BUCKET_NAME: z.string(), +}); + +export type ToolsEnv = z.infer<typeof toolsEnvSchema>; + +export const toolsEnv = toolsEnvSchema.parse(process.env); diff --git a/packages/env/src/types/node-env.d.ts b/packages/env/src/types/node-env.d.ts new file mode 100644 index 00000000..7e3a61cb --- /dev/null +++ b/packages/env/src/types/node-env.d.ts @@ -0,0 +1 @@ +/// <reference types="node" /> diff --git a/packages/env/src/web.ts b/packages/env/src/web.ts new file mode 100644 index 00000000..4e8b550e --- /dev/null +++ b/packages/env/src/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/packages/ui/package.json b/packages/ui/package.json new file mode 100644 index 00000000..81dbae68 --- /dev/null +++ b/packages/ui/package.json @@ -0,0 +1,19 @@ +{ + "name": "@opencut/ui", + "version": "0.0.0", + "description": "UI package for OpenCut", + "main": "./src/index.ts", + "types": "./src/index.ts", + "exports": { + "./icons": "./src/icons/index.tsx" + }, + "dependencies": { + "@iconify/react": "^6.0.2", + "@types/react": "^19.2.7", + "react": "^19.2.0" + }, + "devDependencies": { + "@types/bun": "latest", + "typescript": "^5.8.3" + } +} diff --git a/packages/ui/src/icons/brand.tsx b/packages/ui/src/icons/brand.tsx new file mode 100644 index 00000000..26aabf86 --- /dev/null +++ b/packages/ui/src/icons/brand.tsx @@ -0,0 +1,67 @@ +export function OcVercelIcon({ className }: { className?: string }) { + return ( + <svg + className={className} + width="20" + height="18" + viewBox="0 0 76 65" + fill="none" + xmlns="http://www.w3.org/2000/svg" + > + <title>Vercel</title> + <path d="M37.5274 0L75.0548 65H0L37.5274 0Z" fill="currentColor" /> + </svg> + ); +} + +export function OcMarbleIcon({ + className = "", + size = 32, +}: { + className?: string; + size?: number; +}) { + return ( + <svg + xmlns="http://www.w3.org/2000/svg" + width={size} + height={size} + className={className} + fill="none" + viewBox="0 0 256 256" + > + <title>Marble</title> + <path fill="#202027" d="M0 0h256v256H0z" /> + <path + fill="#fff" + d="M116.032 94.016q1.408.256 6.272 9.856 4.856 9.472 11.904 24.576l4.096 8.576a42.4 42.4 0 0 0 4.992-6.784q2.304-3.96 5.76-10.624 3.96-7.56 5.504-9.728 6.144-9.344 13.312-19.84.896-1.408 3.2-1.92a4.8 4.8 0 0 1 1.28-.128q3.072 0 6.784 2.56 3.84 2.56 4.992 5.248a4.8 4.8 0 0 1 .256 1.92q0 1.28-.128 1.92l-.64 2.944q-.256 1.664-.512 3.968a3200 3200 0 0 0-5.888 46.848 56 56 0 0 0-.512 8.064l-.256 4.096a32 32 0 0 0-.128 2.944q0 1.672-.384 2.304-.384.64-1.408.64-.768 0-2.304-.384-4.096-.896-6.272-3.2-2.176-2.432-2.432-6.656-.128-2.176-.128-6.784 0-4.736.256-14.464l.128-7.04.256-10.112q-1.152 1.024-5.888 8.064a328 328 0 0 0-9.088 14.464q-4.48 7.56-5.888 11.648-1.28 3.2-2.56 4.736-1.152 1.536-2.816 1.536-1.536 0-3.968-1.408-6.912-4.224-8.448-11.648a336 336 0 0 0-6.016-23.68 40 40 0 0 0-2.56-6.272q-1.792-3.968-2.304-4.992l-1.664-3.328q-18.68 24.832-25.344 45.568-1.28 4.352-2.432 6.272-1.152 1.792-2.688 1.792-2.432 0-6.912-4.352Q72 158.144 72 154.304q0-2.04.768-4.096a108 108 0 0 1 16-30.08l3.968-5.248a432 432 0 0 0 12.16-16.64q3.072-4.48 8.192-4.48.896 0 2.944.256" + /> + </svg> + ); +} + +export function OcDataBuddyIcon({ + className = "", + size = 32, +}: { + className?: string; + size?: number; +}) { + return ( + <svg + xmlns="http://www.w3.org/2000/svg" + width={size} + height={size} + className={className} + viewBox="0 0 8 8" + shapeRendering="crispEdges" + > + <title>Data Buddy</title> + <path d="M0 0h8v8H0z" /> + <path + fill="#fff" + d="M1 1h1v6H1zm1 0h4v1H2zm4 1h1v1H6zm0 1h1v1H6zm0 1h1v1H6zm0 1h1v1H6zM2 6h4v1H2zm1-3h1v1H3zm1 1h1v1H4z" + /> + </svg> + ); +} diff --git a/packages/ui/src/icons/index.tsx b/packages/ui/src/icons/index.tsx new file mode 100644 index 00000000..2203b633 --- /dev/null +++ b/packages/ui/src/icons/index.tsx @@ -0,0 +1,2 @@ +export * from "./brand"; +export * from "./ui"; diff --git a/packages/ui/src/icons/ui.tsx b/packages/ui/src/icons/ui.tsx new file mode 100644 index 00000000..60231c33 --- /dev/null +++ b/packages/ui/src/icons/ui.tsx @@ -0,0 +1,32 @@ +export function OcVideoIcon({ + className = "", + size = 32, +}: { + className?: string; + size?: number; +}) { + return ( + <svg + width={size} + height={size} + className={className} + viewBox="0 0 29 24" + fill="none" + xmlns="http://www.w3.org/2000/svg" + > + <title>Video</title> + <path + d="M2.41667 11C2.41667 7.70017 2.41667 6.05025 3.65537 5.02513C4.89405 4 6.88771 4 10.875 4H12.0833C16.0706 4 18.0642 4 19.303 5.02513C20.5417 6.05025 20.5417 7.70017 20.5417 11V13C20.5417 16.2998 20.5417 17.9497 19.303 18.9749C18.0642 20 16.0706 20 12.0833 20H10.875C6.88771 20 4.89405 20 3.65537 18.9749C2.41667 17.9497 2.41667 16.2998 2.41667 13V11Z" + stroke="currentColor" + strokeWidth="1.5" + strokeLinecap="round" + /> + <path + d="M20.5417 8.90585L20.6938 8.80196C23.2504 7.05623 24.5287 6.18336 25.556 6.60482C26.5833 7.02628 26.5833 8.42355 26.5833 11.2181V12.7819C26.5833 15.5765 26.5833 16.9737 25.556 17.3952C24.5287 17.8166 23.2504 16.9438 20.6938 15.198L20.5417 15.0941" + stroke="currentColor" + strokeWidth="1.5" + strokeLinecap="round" + /> + </svg> + ); +} diff --git a/packages/ui/tsconfig.json b/packages/ui/tsconfig.json new file mode 100644 index 00000000..d179b7d1 --- /dev/null +++ b/packages/ui/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "ES2020", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules"] +} |
