import { index, jsonb, primaryKey, text, timestamp } from 'drizzle-orm/pg-core'; import { cardsSchema } from './_schema.ts'; import { decks } from './decks.ts'; /** * Karten. `fields` ist ein generischer JSONB-Slot, der je nach `type` * unterschiedliche Felder enthält: * * - basic / basic-reverse: { front, back } * - cloze: { text, extra? } * - type-in: { question, expected } * - image-occlusion: { image_ref, mask_regions: [...] } * * MVP unterstützt nur `basic` und `basic-reverse`. * * `tags` ist ein eigener Tag-Mapping-Layer (siehe `tags.ts` + `cardTags`), * NICHT in dieser Tabelle gespeichert. */ export const cards = cardsSchema.table( 'cards', { id: text('id').primaryKey(), deckId: text('deck_id') .notNull() .references(() => decks.id, { onDelete: 'cascade' }), userId: text('user_id').notNull(), type: text('type').notNull(), fields: jsonb('fields').notNull(), mediaRefs: jsonb('media_refs').notNull().$type().default([]), contentHash: text('content_hash'), createdAt: timestamp('created_at', { withTimezone: true, mode: 'date' }) .notNull() .defaultNow(), updatedAt: timestamp('updated_at', { withTimezone: true, mode: 'date' }) .notNull() .defaultNow(), }, (t) => ({ deckIdx: index('cards_deck_idx').on(t.deckId), userIdx: index('cards_user_idx').on(t.userId), }) ); export type CardRow = typeof cards.$inferSelect; export type CardInsert = typeof cards.$inferInsert; /** * Card↔Tag-Mapping. PK ist (card_id, tag_id) — kein eigenes id-Feld nötig. */ export const cardTags = cardsSchema.table( 'card_tags', { cardId: text('card_id') .notNull() .references(() => cards.id, { onDelete: 'cascade' }), tagId: text('tag_id').notNull(), }, (t) => ({ pk: primaryKey({ columns: [t.cardId, t.tagId] }), }) ); export type CardTagRow = typeof cardTags.$inferSelect; export type CardTagInsert = typeof cardTags.$inferInsert;