feat(api): add activities + work_sessions domain schema and shared contracts

This commit is contained in:
Bas van Rossem
2026-06-17 15:29:14 +02:00
parent 40a2512dfd
commit 57809985fd
6 changed files with 732 additions and 0 deletions

View File

@@ -109,3 +109,45 @@ export const accountRelations = relations(account, ({ one }) => ({
references: [user.id],
}),
}));
// ---- SoleLog domain tables (Phase 1) ----
export const activities = sqliteTable('activities', {
id: integer('id').primaryKey({ autoIncrement: true }),
name: text('name').notNull(),
// subset of 'Kurk' | 'Berk' | '3D' — stored as a JSON string by libsql.
insoleTypes: text('insole_types', { mode: 'json' })
.$type<string[]>()
.notNull()
.default(['Kurk', 'Berk', '3D']),
createdAt: integer('created_at', { mode: 'timestamp_ms' })
.default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`)
.notNull(),
});
export const workSessions = sqliteTable(
'work_sessions',
{
id: integer('id').primaryKey({ autoIncrement: true }),
userId: text('user_id')
.notNull()
.references(() => user.id, { onDelete: 'cascade' }),
activityId: integer('activity_id')
.notNull()
.references(() => activities.id),
insoleType: text('insole_type'),
pairCount: integer('pair_count').notNull().default(2),
startTime: integer('start_time', { mode: 'timestamp_ms' }).notNull(),
endTime: integer('end_time', { mode: 'timestamp_ms' }), // null = active
durationSeconds: integer('duration_seconds'),
status: text('status').notNull().default('active'), // 'active' | 'completed' | 'discarded'
source: text('source').notNull().default('app'), // 'app' | 'manual'
notes: text('notes'),
createdAt: integer('created_at', { mode: 'timestamp_ms' })
.default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`)
.notNull(),
},
(table) => ({
workSessionsUserIdIdx: index('work_sessions_userId_idx').on(table.userId),
workSessionsStartTimeIdx: index('work_sessions_startTime_idx').on(table.startTime),
})
);