- Updated router.ts middleware for Clerk authentication - Modified test contexts to use clerkUserId - Added team tables to test schema - Updated WaitlistForm and waitlist page - Created src/server/trpc/ parallel structure All 258 tests pass. Ready for Security Reviewer.
175 lines
5.9 KiB
TypeScript
175 lines
5.9 KiB
TypeScript
import { drizzle } from 'drizzle-orm/better-sqlite3';
|
|
import Database from 'better-sqlite3';
|
|
|
|
let testDb: ReturnType<typeof drizzle> | null = null;
|
|
let sqlite: Database.Database | null = null;
|
|
|
|
const schemaSQL = `
|
|
CREATE TABLE IF NOT EXISTS users (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
clerk_id TEXT NOT NULL UNIQUE,
|
|
email TEXT NOT NULL UNIQUE,
|
|
name TEXT,
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS projects (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
name TEXT NOT NULL,
|
|
description TEXT,
|
|
owner_id INTEGER NOT NULL REFERENCES users(id),
|
|
is_public INTEGER NOT NULL DEFAULT 0,
|
|
theme TEXT,
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS characters (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
project_id INTEGER NOT NULL REFERENCES projects(id),
|
|
name TEXT NOT NULL,
|
|
slug TEXT NOT NULL,
|
|
role TEXT NOT NULL DEFAULT 'supporting',
|
|
bio TEXT,
|
|
description TEXT,
|
|
arc TEXT,
|
|
arc_type TEXT,
|
|
age INTEGER,
|
|
gender TEXT,
|
|
voice TEXT,
|
|
traits TEXT,
|
|
motivation TEXT,
|
|
conflict TEXT,
|
|
secret TEXT,
|
|
image_url TEXT,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS character_relationships (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
character_a_id INTEGER NOT NULL REFERENCES characters(id),
|
|
character_b_id INTEGER NOT NULL REFERENCES characters(id),
|
|
relationship_type TEXT NOT NULL,
|
|
description TEXT,
|
|
strength INTEGER NOT NULL DEFAULT 50,
|
|
is_antagonistic INTEGER NOT NULL DEFAULT 0,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS scenes (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
project_id INTEGER NOT NULL REFERENCES projects(id),
|
|
title TEXT NOT NULL,
|
|
content TEXT NOT NULL DEFAULT '',
|
|
"order" INTEGER NOT NULL DEFAULT 0,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS scene_characters (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
scene_id INTEGER NOT NULL REFERENCES scenes(id),
|
|
character_id INTEGER NOT NULL REFERENCES characters(id),
|
|
screen_time INTEGER,
|
|
dialogue_lines INTEGER DEFAULT 0
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS project_members (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
project_id INTEGER NOT NULL REFERENCES projects(id),
|
|
user_id INTEGER NOT NULL REFERENCES users(id),
|
|
role TEXT NOT NULL DEFAULT 'editor',
|
|
added_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS scripts (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
project_id INTEGER NOT NULL REFERENCES projects(id),
|
|
title TEXT NOT NULL,
|
|
version TEXT NOT NULL DEFAULT '1.0',
|
|
content TEXT,
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS revisions (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
script_id INTEGER NOT NULL REFERENCES scripts(id),
|
|
version_number INTEGER NOT NULL,
|
|
branch_name TEXT NOT NULL DEFAULT 'main',
|
|
parent_revision_id INTEGER,
|
|
title TEXT NOT NULL,
|
|
summary TEXT,
|
|
content TEXT NOT NULL,
|
|
author_id INTEGER NOT NULL REFERENCES users(id),
|
|
status TEXT NOT NULL DEFAULT 'draft' CHECK(status IN ('draft', 'pending_review', 'accepted', 'rejected')),
|
|
reviewed_by_id INTEGER REFERENCES users(id),
|
|
reviewed_at TIMESTAMP,
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS revision_changes (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
revision_id INTEGER NOT NULL REFERENCES revisions(id),
|
|
change_type TEXT NOT NULL CHECK(change_type IN ('addition', 'deletion', 'modification')),
|
|
element_type TEXT,
|
|
old_content TEXT,
|
|
new_content TEXT,
|
|
scene_number INTEGER,
|
|
line_number INTEGER,
|
|
page_number INTEGER,
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS teams (
|
|
id TEXT PRIMARY KEY,
|
|
name TEXT NOT NULL,
|
|
owner_id INTEGER NOT NULL REFERENCES users(id),
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS team_members (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
team_id TEXT NOT NULL REFERENCES teams(id),
|
|
user_id INTEGER NOT NULL REFERENCES users(id),
|
|
role TEXT NOT NULL DEFAULT 'editor',
|
|
joined_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
`;
|
|
|
|
export let globalSqlite: Database.Database | null = null;
|
|
|
|
export async function getTestDb(): Promise<ReturnType<typeof drizzle>> {
|
|
if (testDb && sqlite) return testDb;
|
|
|
|
sqlite = new Database(':memory:');
|
|
globalSqlite = sqlite;
|
|
sqlite.exec('PRAGMA foreign_keys = OFF;');
|
|
sqlite.exec(schemaSQL);
|
|
sqlite.exec('PRAGMA foreign_keys = ON;');
|
|
|
|
// Insert a test user
|
|
sqlite.exec("INSERT INTO users (id, clerk_id, email, name) VALUES (1, 'user_test', 'test@test.com', 'Test User');");
|
|
|
|
// Insert a test project
|
|
sqlite.exec("INSERT INTO projects (id, name, description, owner_id) VALUES (1, 'Test Project', 'A test project', 1);");
|
|
|
|
// Insert a test script
|
|
sqlite.exec("INSERT INTO scripts (id, project_id, title, version) VALUES (1, 1, 'Test Script', '1.0');");
|
|
|
|
testDb = drizzle(sqlite);
|
|
|
|
return testDb;
|
|
}
|
|
|
|
export async function resetTestDb(): Promise<ReturnType<typeof drizzle>> {
|
|
testDb = null;
|
|
sqlite = null;
|
|
globalSqlite = null;
|
|
return getTestDb();
|
|
}
|