use sqlx::{sqlite::SqlitePool, Row};
pub async fn init(pool: &SqlitePool) -> Result<(), sqlx::Error> {
sqlx::query(
r#"
CREATE TABLE IF NOT EXISTS users (
id TEXT PRIMARY KEY,
email TEXT NOT NULL UNIQUE,
username TEXT NOT NULL UNIQUE,
password_hash TEXT NOT NULL,
tier TEXT NOT NULL DEFAULT 'free',
stripe_customer_id TEXT,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
)
"#,
)
.execute(pool)
.await?;
sqlx::query(
r#"
CREATE TABLE IF NOT EXISTS api_keys (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL,
key_hash TEXT NOT NULL UNIQUE,
name TEXT NOT NULL,
expires_at TEXT,
last_used TEXT,
active BOOLEAN NOT NULL DEFAULT 1,
created_at TEXT NOT NULL,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
)
"#,
)
.execute(pool)
.await?;
sqlx::query(
r#"
CREATE TABLE IF NOT EXISTS subscriptions (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL UNIQUE,
tier TEXT NOT NULL,
stripe_subscription_id TEXT,
status TEXT NOT NULL DEFAULT 'active',
current_period_start TEXT NOT NULL,
current_period_end TEXT NOT NULL,
cancel_at_period_end BOOLEAN NOT NULL DEFAULT 0,
created_at TEXT NOT NULL,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
)
"#,
)
.execute(pool)
.await?;
sqlx::query(
r#"
CREATE TABLE IF NOT EXISTS payments (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL,
stripe_payment_id TEXT,
amount_cents INTEGER NOT NULL,
currency TEXT NOT NULL DEFAULT 'usd',
status TEXT NOT NULL DEFAULT 'pending',
description TEXT,
created_at TEXT NOT NULL,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
)
"#,
)
.execute(pool)
.await?;
sqlx::query(
r#"
CREATE TABLE IF NOT EXISTS invoices (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL,
stripe_invoice_id TEXT,
amount_cents INTEGER NOT NULL,
status TEXT NOT NULL DEFAULT 'draft',
issued_at TEXT NOT NULL,
due_at TEXT NOT NULL,
paid_at TEXT,
created_at TEXT NOT NULL,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
)
"#,
)
.execute(pool)
.await?;
sqlx::query(
r#"
CREATE TABLE IF NOT EXISTS usage_events (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL,
operation TEXT NOT NULL,
cost INTEGER NOT NULL,
created_at TEXT NOT NULL,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
)
"#,
)
.execute(pool)
.await?;
sqlx::query(
r#"
CREATE TABLE IF NOT EXISTS webhook_events (
id TEXT PRIMARY KEY,
stripe_event_id TEXT NOT NULL UNIQUE,
event_type TEXT NOT NULL,
data TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'pending',
created_at TEXT NOT NULL
)
"#,
)
.execute(pool)
.await?;
sqlx::query("CREATE INDEX IF NOT EXISTS idx_api_keys_user ON api_keys(user_id)")
.execute(pool)
.await?;
sqlx::query("CREATE INDEX IF NOT EXISTS idx_payments_user ON payments(user_id)")
.execute(pool)
.await?;
sqlx::query("CREATE INDEX IF NOT EXISTS idx_invoices_user ON invoices(user_id)")
.execute(pool)
.await?;
sqlx::query("CREATE INDEX IF NOT EXISTS idx_usage_events_user ON usage_events(user_id)")
.execute(pool)
.await?;
Ok(())
}