import pg from 'pg' const { Pool } = pg let pool export function getPool() { if (!pool) { if (!process.env.DATABASE_URL) throw new Error('DATABASE_URL is required') pool = new Pool({ connectionString: process.env.DATABASE_URL, max: 10, ssl: process.env.DATABASE_SSL === 'true' ? { rejectUnauthorized: false } : undefined }) } return pool } export async function initDb() { const db = getPool() await db.query(` CREATE TABLE IF NOT EXISTS templates ( id text PRIMARY KEY, tenant_id text NOT NULL, template_key text, name text NOT NULL, type text NOT NULL CHECK (type IN ('email', 'report')), status text NOT NULL DEFAULT 'draft', draft_document jsonb NOT NULL, sample_data jsonb NOT NULL DEFAULT '{}'::jsonb, published_version integer, created_by text, updated_by text, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now() ) `) await db.query(`ALTER TABLE templates ADD COLUMN IF NOT EXISTS template_key text`) await db.query(` UPDATE templates SET template_key = 'template-' || substr(replace(id, '-', ''), 1, 12) WHERE template_key IS NULL `) await db.query(`ALTER TABLE templates ALTER COLUMN template_key SET NOT NULL`) await db.query(` CREATE TABLE IF NOT EXISTS folders ( id text PRIMARY KEY, tenant_id text NOT NULL, name text NOT NULL, parent_id text REFERENCES folders(id) ON DELETE CASCADE, created_by text, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now() ) `) await db.query(`ALTER TABLE templates ADD COLUMN IF NOT EXISTS folder_id text REFERENCES folders(id) ON DELETE SET NULL`) await db.query(` CREATE TABLE IF NOT EXISTS template_versions ( id text PRIMARY KEY, template_id text NOT NULL REFERENCES templates(id) ON DELETE CASCADE, version integer NOT NULL, document jsonb NOT NULL, sample_data jsonb NOT NULL DEFAULT '{}'::jsonb, created_by text, created_at timestamptz NOT NULL DEFAULT now(), UNIQUE(template_id, version) ) `) await db.query(` CREATE TABLE IF NOT EXISTS template_assets ( id text PRIMARY KEY, tenant_id text NOT NULL, template_id text NOT NULL REFERENCES templates(id) ON DELETE CASCADE, asset_key text NOT NULL, filename text NOT NULL, mime_type text NOT NULL, byte_size integer NOT NULL, public_token text NOT NULL UNIQUE, data bytea NOT NULL, created_at timestamptz NOT NULL DEFAULT now(), UNIQUE(template_id, asset_key) ) `) await db.query(` CREATE TABLE IF NOT EXISTS themes ( id text PRIMARY KEY, tenant_id text NOT NULL, name text NOT NULL, applies_to text NOT NULL DEFAULT 'all' CHECK (applies_to IN ('all', 'report', 'email')), theme jsonb NOT NULL, created_by text, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now() ) `) await db.query(` CREATE TABLE IF NOT EXISTS theme_assets ( id text PRIMARY KEY, tenant_id text NOT NULL, theme_id text NOT NULL REFERENCES themes(id) ON DELETE CASCADE, asset_key text NOT NULL, filename text NOT NULL, mime_type text NOT NULL, byte_size integer NOT NULL, public_token text NOT NULL UNIQUE, data bytea NOT NULL, created_at timestamptz NOT NULL DEFAULT now(), UNIQUE(theme_id, asset_key) ) `) await db.query(` CREATE TABLE IF NOT EXISTS api_keys ( id text PRIMARY KEY, tenant_id text NOT NULL, name text NOT NULL, key_prefix text NOT NULL, key_hash text NOT NULL UNIQUE, created_by text, created_at timestamptz NOT NULL DEFAULT now(), last_used_at timestamptz, revoked_at timestamptz ) `) await db.query(` CREATE INDEX IF NOT EXISTS templates_tenant_updated_idx ON templates (tenant_id, updated_at DESC) `) await db.query(` CREATE INDEX IF NOT EXISTS templates_folder_idx ON templates (tenant_id, folder_id, updated_at DESC) `) await db.query(` CREATE INDEX IF NOT EXISTS folders_parent_idx ON folders (tenant_id, parent_id, name) `) await db.query(` CREATE UNIQUE INDEX IF NOT EXISTS folders_unique_sibling_name_idx ON folders (tenant_id, COALESCE(parent_id, ''), lower(name)) `) await db.query(` CREATE UNIQUE INDEX IF NOT EXISTS templates_tenant_key_idx ON templates (tenant_id, template_key) `) await db.query(` CREATE INDEX IF NOT EXISTS api_keys_tenant_created_idx ON api_keys (tenant_id, created_at DESC) `) await db.query(` CREATE INDEX IF NOT EXISTS template_assets_template_idx ON template_assets (template_id) `) await db.query(` CREATE INDEX IF NOT EXISTS themes_tenant_created_idx ON themes (tenant_id, created_at DESC) `) await db.query(` CREATE INDEX IF NOT EXISTS theme_assets_theme_idx ON theme_assets (theme_id) `) }