All files / web/src/db/schema euclid-creations.ts

100% Statements 61/61
100% Branches 1/1
100% Functions 0/0
100% Lines 61/61

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 622x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 39x 39x 39x 39x 39x 39x 2x 2x 2x 2x  
import { createId } from '@paralleldrive/cuid2'
import { index, integer, sqliteTable, text } from 'drizzle-orm/sqlite-core'
import type { PostCompletionAction } from '../../components/toys/euclid/engine/replayConstruction'
import type { SerializedElement, SerializedEqualityFact } from '../../components/toys/euclid/types'
 
export interface CreationData {
  /** Positions of given points at save time (e.g. pt-A) */
  givenPoints: Array<{ id: string; x: number; y: number }>
  /** All post-completion actions (circles, segments, free points, macros) */
  actions: PostCompletionAction[]
  /** Viewport state at save time */
  viewport?: { centerX: number; centerY: number; ppu: number }
  /** Full given element definitions (admin constructions with custom givens) */
  givenElements?: SerializedElement[]
  /** Equality constraints declared during given-setup */
  givenFacts?: SerializedEqualityFact[]
}
 
export const euclidCreations = sqliteTable(
  'euclid_creations',
  {
    id: text('id')
      .primaryKey()
      .$defaultFn(() => createId()),
 
    /** User who created this (guests included — every visitor has a userId) */
    userId: text('user_id'),
 
    /** Player (kid) who created this — null when playing without a selected player */
    playerId: text('player_id'),
 
    /** Serialized construction state */
    data: text('data', { mode: 'json' }).$type<CreationData>().notNull(),
 
    /** Downsampled JPEG data URL for gallery display */
    thumbnail: text('thumbnail'),
 
    /** User-facing title for the creation */
    title: text('title'),
 
    /** Whether this appears in the public gallery */
    isPublic: integer('is_public', { mode: 'boolean' }).notNull().default(false),
 
    createdAt: integer('created_at', { mode: 'timestamp' })
      .notNull()
      .$defaultFn(() => new Date()),
 
    /** Last update timestamp (null for legacy rows) */
    updatedAt: integer('updated_at', { mode: 'timestamp' }),
  },
  (table) => ({
    userIdIdx: index('euclid_creations_user_id_idx').on(table.userId),
    publicCreatedIdx: index('euclid_creations_public_created_idx').on(
      table.isPublic,
      table.createdAt
    ),
  })
)
 
export type EuclidCreation = typeof euclidCreations.$inferSelect
export type NewEuclidCreation = typeof euclidCreations.$inferInsert