54 lines
4.0 KiB
TypeScript
54 lines
4.0 KiB
TypeScript
import { index, integer, sqliteTable, text } from "drizzle-orm/sqlite-core";
|
|
|
|
export const users = sqliteTable("users", {
|
|
id: text("id").primaryKey(),
|
|
discordId: text("discord_id").notNull().unique(),
|
|
username: text("username").notNull(),
|
|
globalName: text("global_name"),
|
|
avatarHash: text("avatar_hash"),
|
|
timezone: text("timezone").notNull().default("UTC"),
|
|
createdAt: integer("created_at").notNull(),
|
|
updatedAt: integer("updated_at").notNull(),
|
|
});
|
|
|
|
export const sessions = sqliteTable("sessions", {
|
|
tokenHash: text("token_hash").primaryKey(),
|
|
userId: text("user_id").notNull().references(() => users.id, { onDelete: "cascade" }),
|
|
createdAt: integer("created_at").notNull(),
|
|
expiresAt: integer("expires_at").notNull(),
|
|
}, table => [
|
|
index("sessions_user_id_idx").on(table.userId),
|
|
index("sessions_expires_at_idx").on(table.expiresAt),
|
|
]);
|
|
|
|
// Revisions are append-only, including multiple edits on the same local date.
|
|
export const habits = sqliteTable('habits', {
|
|
id: text('id').primaryKey(), userId: text('user_id').notNull().references(() => users.id),
|
|
createdDate: text('created_date').notNull(), materializedThrough: text('materialized_through'), createdAt: integer('created_at').notNull(),
|
|
}, t => [index('habits_user_idx').on(t.userId)]);
|
|
export const habitRevisions = sqliteTable('habit_revisions', {
|
|
id: integer('id').primaryKey({ autoIncrement: true }), habitId: text('habit_id').notNull().references(() => habits.id),
|
|
effectiveDate: text('effective_date').notNull(), config: text('config', { mode: 'json' }).$type<import('../habits/contracts').HabitConfig>().notNull(), createdAt: integer('created_at').notNull(),
|
|
}, t => [index('habit_revisions_date_idx').on(t.habitId, t.effectiveDate, t.id)]);
|
|
export const habitDays = sqliteTable('habit_days', {
|
|
id: integer('id').primaryKey({ autoIncrement: true }), habitId: text('habit_id').notNull().references(() => habits.id),
|
|
revisionId: integer('revision_id').notNull().references(() => habitRevisions.id), date: text('date').notNull(),
|
|
timezone: text('timezone').notNull(), endsAt: integer('ends_at').notNull(), countSet: integer('count_set', { mode: 'boolean' }).notNull().default(false), count: integer('count').notNull().default(0), done: integer('done', { mode: 'boolean' }).notNull().default(false),
|
|
}, t => [index('habit_days_lookup_idx').on(t.habitId, t.date, t.revisionId)]);
|
|
export const taskOccurrences = sqliteTable('task_occurrences', {
|
|
id: text('id').primaryKey(), dayId: integer('day_id').notNull().references(() => habitDays.id), taskId: text('task_id').notNull(), name: text('name').notNull(),
|
|
done: integer('done', { mode: 'boolean' }).notNull().default(false), expiredAt: integer('expired_at'), closedAt: integer('closed_at'), updatedAt: integer('updated_at').notNull(),
|
|
}, t => [index('task_occurrences_day_idx').on(t.dayId)]);
|
|
export const progressEvents = sqliteTable('progress_events', {
|
|
id: integer('id').primaryKey({ autoIncrement: true }), dayId: integer('day_id').notNull().references(() => habitDays.id), occurrenceId: text('occurrence_id'),
|
|
before: text('before', { mode: 'json' }).$type<unknown>().notNull(), after: text('after', { mode: 'json' }).$type<unknown>().notNull(), createdAt: integer('created_at').notNull(),
|
|
}, t => [index('progress_events_day_idx').on(t.dayId)]);
|
|
export const habitCalendarSettings = sqliteTable('habit_calendar_settings', {
|
|
habitId: text('habit_id').primaryKey().references(() => habits.id), settings: text('settings', { mode: 'json' }).$type<import('../habits/contracts').CalendarSettings>().notNull(),
|
|
});
|
|
export const combinedCharts = sqliteTable('combined_charts', {
|
|
id: text('id').primaryKey(), userId: text('user_id').notNull().references(() => users.id), name: text('name').notNull(),
|
|
habitIds: text('habit_ids', { mode: 'json' }).$type<string[]>().notNull(), settings: text('settings', { mode: 'json' }).$type<import('../habits/contracts').CalendarSettings>().notNull(),
|
|
createdAt: integer('created_at').notNull(), updatedAt: integer('updated_at').notNull(),
|
|
}, t => [index('combined_charts_user_idx').on(t.userId)]);
|