Files
taptapp/src/lib/server/db/schema.js
2025-07-24 22:38:28 +02:00

94 lines
3.5 KiB
JavaScript

import { sqliteTable, integer, text, blob, real } from 'drizzle-orm/sqlite-core';
import { isNull } from 'drizzle-orm';
export const user = sqliteTable('user', {
id: text('id').primaryKey(),
age: integer('age'),
username: text('username').notNull().unique(),
passwordHash: text('password_hash').notNull()
});
export const session = sqliteTable('session', {
id: text('id').primaryKey(),
userId: text('user_id')
.notNull()
.references(() => user.id),
expiresAt: integer('expires_at', { mode: 'timestamp' }).notNull()
});
export const audioFile = sqliteTable('audio_file', {
id: text('id').primaryKey(),
filename: text('filename').notNull(),
contentType: text('content_type').notNull(),
data: blob('data').default(null), // Temporarily keep for migration
s3Key: text('s3_key'), // Temporarily optional for migration
duration: real('duration'),
fileSize: integer('file_size'),
createdAt: integer('created_at', { mode: 'timestamp' }).notNull(),
deletedAt: integer('deleted_at', { mode: 'timestamp' }) // Soft delete for audio files
});
export const inviteLink = sqliteTable('invite_link', {
id: text('id').primaryKey(),
token: text('token').notNull().unique(),
participantName: text('participant_name'),
isUsed: integer('is_used', { mode: 'boolean' }).notNull().default(false),
createdAt: integer('created_at', { mode: 'timestamp' }).notNull(),
usedAt: integer('used_at', { mode: 'timestamp' }),
deletedAt: integer('deleted_at', { mode: 'timestamp' })
});
export const participant = sqliteTable('participant', {
id: text('id').primaryKey(),
inviteToken: text('invite_token')
.notNull()
.references(() => inviteLink.token),
sessionId: text('session_id'),
createdAt: integer('created_at', { mode: 'timestamp' }).notNull(),
deletedAt: integer('deleted_at', { mode: 'timestamp' })
});
export const rating = sqliteTable('rating', {
id: text('id').primaryKey(),
participantId: text('participant_id')
.notNull()
.references(() => participant.id),
audioFileId: text('audio_file_id')
.notNull()
.references(() => audioFile.id),
timestamp: real('timestamp').notNull(),
value: real('value').notNull(),
isCompleted: integer('is_completed', { mode: 'boolean' }).notNull().default(false),
timeseriesData: text('timeseries_data'), // JSON string of all rating changes (for completed ratings)
createdAt: integer('created_at', { mode: 'timestamp' }).notNull(),
deletedAt: integer('deleted_at', { mode: 'timestamp' }) // Soft delete for redos
});
export const participantProgress = sqliteTable('participant_progress', {
id: text('id').primaryKey(),
participantId: text('participant_id')
.notNull()
.references(() => participant.id),
audioFileId: text('audio_file_id')
.notNull()
.references(() => audioFile.id),
isCompleted: integer('is_completed', { mode: 'boolean' }).notNull().default(false),
lastPosition: real('last_position').default(0),
maxReachedTime: real('max_reached_time').default(0),
updatedAt: integer('updated_at', { mode: 'timestamp' }).notNull()
});
export const overallRating = sqliteTable('overall_rating', {
id: text('id').primaryKey(),
participantId: text('participant_id')
.notNull()
.references(() => participant.id),
audioFileId: text('audio_file_id')
.notNull()
.references(() => audioFile.id),
value: real('value').notNull(), // 0-100 rating value
createdAt: integer('created_at', { mode: 'timestamp' }).notNull(),
updatedAt: integer('updated_at', { mode: 'timestamp' }).notNull(),
deletedAt: integer('deleted_at', { mode: 'timestamp' }) // Soft delete for potential redos
});