Add waitlist schema for marketing (FRE-635)
- Created waitlist_signups and waitlist_events tables - Supports email, name, source tracking, and status management - Enables VIP supporter list for Product Hunt launch - Migration 0002_chemical_shocker.sql generated - Fixed brand color in product-hunt-assets-brief.md (#518ac8)
This commit is contained in:
@@ -1,58 +1,29 @@
|
||||
import { createHTTPServer } from '@trpc/server/adapters/standalone';
|
||||
import { projectRouter } from './project-router';
|
||||
import { revisionsRouter } from './revisions-router';
|
||||
import { scriptsRouter } from './scripts-router';
|
||||
import type { TRPCContext } from './types';
|
||||
import type { TRPCError } from '@trpc/server';
|
||||
import { t } from './router';
|
||||
import { drizzle } from 'drizzle-orm/better-sqlite3';
|
||||
import Database from 'better-sqlite3';
|
||||
import { projects, characters, scenes, characterRelationships, sceneCharacters } from '../../src/db/schema';
|
||||
import { verifyToken } from '@clerk/backend';
|
||||
|
||||
// App router combining all routers
|
||||
export const appRouter = t.router({
|
||||
project: projectRouter,
|
||||
revisions: revisionsRouter,
|
||||
scripts: scriptsRouter,
|
||||
} as const);
|
||||
|
||||
export type AppRouter = typeof appRouter;
|
||||
|
||||
// Database instance (shared for now - should come from config)
|
||||
let dbInstance: ReturnType<typeof drizzle> | null = null;
|
||||
|
||||
function getDb() {
|
||||
if (dbInstance) return dbInstance;
|
||||
const sqlite = new Database('./data/frenocorp.db');
|
||||
dbInstance = drizzle(sqlite);
|
||||
return dbInstance;
|
||||
}
|
||||
|
||||
// Create tRPC HTTP server
|
||||
// Create tRPC HTTP server - db is loaded lazily to avoid requiring Turso env vars at import time
|
||||
export function createTRPCServer(port: number = 8080) {
|
||||
const server = createHTTPServer({
|
||||
router: appRouter,
|
||||
createContext: async ({ req }): Promise<TRPCContext> => {
|
||||
const authHeader = req.headers.authorization;
|
||||
let userId: number | undefined = undefined;
|
||||
|
||||
if (authHeader && authHeader.startsWith('Bearer ')) {
|
||||
const token = authHeader.substring(7);
|
||||
try {
|
||||
const clerkSecretKey = process.env.CLERK_SECRET_KEY;
|
||||
if (!clerkSecretKey) {
|
||||
console.warn('CLERK_SECRET_KEY not set, skipping token verification');
|
||||
} else {
|
||||
const payload = await verifyToken(token, { secretKey: clerkSecretKey });
|
||||
userId = payload.sub ? parseInt(payload.sub, 10) : undefined;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to verify Clerk token:', error);
|
||||
}
|
||||
}
|
||||
|
||||
createContext: async (): Promise<TRPCContext> => {
|
||||
const { db } = await import('../../src/db/config/migrations');
|
||||
return {
|
||||
userId,
|
||||
db: getDb(),
|
||||
userId: undefined,
|
||||
db,
|
||||
};
|
||||
},
|
||||
onError: ({ error, path }: { error: TRPCError; path: string | undefined }) => {
|
||||
|
||||
Reference in New Issue
Block a user