// Schema for the {{projectName}} SaaS backend. // // Two tenant-scoped domain tables — `projects` and `invites`. The plugins // contribute their OWN tables automatically (auth uses the in-process // `memoryUserStore`; billing adds `_voltro_billing_*`), so you don't declare // those here. `actors` + `tenants` are the framework's core tables the audit / // tenant mixins reference. import { databaseHandle, id, table, text, timestamp, type InferRow, } from '@voltro/database' import { tenant } from '@voltro/plugin-multitenancy' // ---------- Core tables (required by the audit / tenant mixins) ---------- export const actors = table('actors', { id: id(), kind: text().oneOf(['user', 'serviceAccount', 'apiKey', 'system']), displayName: text().nullable(), createdAt: timestamp().default('now'), }) export const tenants = table('tenants', { id: id(), name: text(), createdAt: timestamp().default('now'), }) // ---------- Application tables ---------- // Creating a project spends the billing `projects` entitlement (free = 3) — // see mutations/projects.create. export const projects = table('projects', { id: id({ prefix: 'proj' }), name: text(), }) // tenant() pulls audit() transitively → tenantId + createdAt / updatedAt / // createdBy / updatedBy (auto-stamped by the runtime). .with(tenant()) // Inviting a teammate spends the billing `seats` entitlement (free = 1) — see // mutations/invites.create. export const invites = table('invites', { id: id({ prefix: 'inv' }), email: text(), status: text().oneOf(['pending', 'accepted', 'revoked']), }) .with(tenant()) export type Project = InferRow export type Invite = InferRow export const database = databaseHandle({ actors, tenants, projects, invites })