Files
aris/apps/aelis-backend/src/db/schema.ts
Kenneth 61c1ade631 feat(backend): add DB persistence layer (#79)
* feat(backend): add DB persistence layer

Replace raw pg Pool with Drizzle ORM backed by Bun.sql.
Add per-user source configuration table (user_sources).
Migrate Better Auth to drizzle-adapter.
Add AES-256-GCM credential encryption.

Co-authored-by: Ona <no-reply@ona.com>

* fix(backend): set updatedAt explicitly in all mutations

onConflictDoUpdate bypasses Drizzle's $onUpdate hook.
Set updatedAt explicitly in all mutation methods.

Co-authored-by: Ona <no-reply@ona.com>

* fix(backend): add composite index on user_sources

Add (user_id, enabled) index for the enabled() query path.

Co-authored-by: Ona <no-reply@ona.com>

---------

Co-authored-by: Ona <no-reply@ona.com>
2026-03-16 01:30:02 +00:00

63 lines
1.6 KiB
TypeScript

import {
boolean,
customType,
index,
jsonb,
pgTable,
text,
timestamp,
unique,
uuid,
} from "drizzle-orm/pg-core"
// ---------------------------------------------------------------------------
// Better Auth core tables
// Re-exported from CLI-generated schema.
// Regenerate with: bunx --bun auth@latest generate --config auth.ts --output src/db/auth-schema.ts
// ---------------------------------------------------------------------------
export {
user,
session,
account,
verification,
userRelations,
sessionRelations,
accountRelations,
} from "./auth-schema.ts"
import { user } from "./auth-schema.ts"
// ---------------------------------------------------------------------------
// AELIS — per-user source configuration
// ---------------------------------------------------------------------------
const bytea = customType<{ data: Buffer }>({
dataType() {
return "bytea"
},
})
export const userSources = pgTable(
"user_sources",
{
id: uuid("id").primaryKey().defaultRandom(),
userId: text("user_id")
.notNull()
.references(() => user.id, { onDelete: "cascade" }),
sourceId: text("source_id").notNull(),
enabled: boolean("enabled").notNull().default(true),
config: jsonb("config").default({}),
credentials: bytea("credentials"),
createdAt: timestamp("created_at").notNull().defaultNow(),
updatedAt: timestamp("updated_at")
.notNull()
.defaultNow()
.$onUpdate(() => new Date()),
},
(t) => [
unique("user_sources_user_id_source_id_unique").on(t.userId, t.sourceId),
index("user_sources_user_id_enabled_idx").on(t.userId, t.enabled),
],
)