142 lines
4.1 KiB
JavaScript

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 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 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)
`)
}