Files
STTracker/packages/db/src/schema.ts
T
Lucas WintherandClaude Opus 5.5 e3a759d768 fix(core): soft-delete source connections with deleted_at
Migration 0003 adds source_connections.deleted_at. deleteConnection sets it; listing, lookups,
updates, the scheduler and the sync handler ignore deleted connections, so a paused
credential-less connection stays visible and can be resumed.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 21:25:59 +01:00

367 lines
8.3 KiB
TypeScript

/**
* Kysely table types. snake_case columns; timestamps are ISO-8601 text; JSON columns are text
* (use `toJson`/`fromJson`); booleans are integer 0/1. All IDs come from app code (`newId()`),
* so nothing here is `Generated<>`.
*/
export type Role = "admin" | "member";
export type EntryStatus = "planned" | "in_progress" | "paused" | "completed" | "dropped" | "none";
export type Visibility = "private" | "friends" | "public";
export type TokenScope = "read" | "write" | "ingest";
export type CustomFieldLevel = "entry" | "engagement" | "copy";
export type ListKind = "list" | "grouping" | "thread";
export type AttachmentEntity = "entry" | "engagement" | "copy" | "list" | "work";
export type SuggestionStatus = "pending" | "accepted" | "rejected";
export type ConnectionStatus = "active" | "paused" | "error";
export type RunMode = "full" | "changes" | "file";
export type RunStatus = "running" | "ok" | "failed";
export type ChangeType = "added" | "changed" | "removed" | "merged" | "conflict";
export type ChangeStatus = "pending" | "auto_applied" | "accepted" | "ignored" | "kept_mine";
export type JobStatus = "queued" | "running" | "done" | "failed";
export interface UsersTable {
id: string;
username: string;
display_name: string;
password_hash: string;
role: Role;
preferences: string;
created_at: string;
updated_at: string;
}
export interface SessionsTable {
id: string;
user_id: string;
token_hash: string;
expires_at: string;
created_at: string;
}
export interface InvitesTable {
id: string;
code_hash: string;
created_by: string;
used_by: string | null;
expires_at: string;
created_at: string;
}
export interface AppTokensTable {
id: string;
user_id: string;
name: string;
token_hash: string;
/** JSON `TokenScope[]`. */
scopes: string;
last_used_at: string | null;
revoked_at: string | null;
created_at: string;
}
export interface WorksTable {
id: string;
media_type: string;
title: string;
original_title: string;
year: number | null;
release_date: string | null;
creators: string;
description: string;
cover_url: string;
cover_attachment_id: string | null;
metadata: string;
parent_id: string | null;
position: string | null;
owner_user_id: string | null;
merged_into_id: string | null;
created_at: string;
updated_at: string;
}
export interface ExternalIdsTable {
id: string;
work_id: string;
namespace: string;
value: string;
}
export interface WorkAliasesTable {
id: string;
user_id: string;
from_work_id: string;
to_work_id: string;
}
export interface WorkHistoryTable {
id: string;
work_id: string;
before: string;
after: string;
actor: string;
created_at: string;
}
export interface EntriesTable {
id: string;
user_id: string;
work_id: string;
status: EntryStatus;
rating: number | null;
review: string | null;
private_notes: string | null;
/** 0 or 1. */
favorite: number;
tags: string;
custom_fields: string;
visibility: Visibility;
overrides: string;
media_type_override: string | null;
field_sources: string;
created_at: string;
updated_at: string;
deleted_at: string | null;
}
export interface EngagementsTable {
id: string;
entry_id: string;
started_at: string | null;
started_precision: string;
finished_at: string | null;
finished_precision: string;
progress: string;
platform: string | null;
rating: number | null;
notes: string | null;
custom_fields: string;
field_sources: string;
created_at: string;
updated_at: string;
deleted_at: string | null;
}
export interface EngagementSourcesTable {
id: string;
engagement_id: string;
connection_id: string;
record_key: string;
}
export interface ListensTable {
id: string;
user_id: string;
listened_at: string;
artist: string;
track: string;
album: string | null;
duration_ms: number | null;
mbids: string;
work_id: string | null;
source: string;
source_key: string;
created_at: string;
}
export interface ListsTable {
id: string;
user_id: string;
name: string;
description: string;
kind: ListKind;
visibility: Visibility;
rating: number | null;
review: string | null;
created_at: string;
updated_at: string;
deleted_at: string | null;
}
export interface ListItemsTable {
id: string;
list_id: string;
work_id: string;
position: number;
note: string | null;
}
export interface CustomFieldDefinitionsTable {
id: string;
user_id: string;
name: string;
type: string;
options: string;
/** JSON `MediaType[] | "all"`. */
applies_to: string;
level: CustomFieldLevel;
created_at: string;
}
export interface CopiesTable {
id: string;
user_id: string;
work_id: string | null;
title_hint: string | null;
format: string | null;
acquired_from: string | null;
acquired_at: string | null;
acquired_precision: string;
price_cents: number | null;
currency: string | null;
notes: string | null;
custom_fields: string;
source_ref: string | null;
created_at: string;
updated_at: string;
deleted_at: string | null;
}
export interface AttachmentsTable {
id: string;
user_id: string;
sha256: string;
mime: string;
size: number;
filename: string;
caption: string | null;
taken_at: string | null;
visibility: Visibility | null;
created_at: string;
}
export interface AttachmentLinksTable {
id: string;
attachment_id: string;
entity: AttachmentEntity;
entity_id: string;
}
export interface UserHistoryTable {
id: string;
user_id: string;
entity: string;
entity_id: string;
before: string;
after: string;
actor: string;
created_at: string;
}
export interface MatchSuggestionsTable {
id: string;
user_id: string;
work_id: string;
candidate_work_id: string;
score: number;
status: SuggestionStatus;
created_at: string;
}
export interface SourceConnectionsTable {
id: string;
user_id: string;
plugin_id: string;
name: string;
config: string;
credentials_enc: string | null;
schedule_minutes: number | null;
cursor: string | null;
status: ConnectionStatus;
last_run_at: string | null;
created_at: string;
/** Set by `deleteConnection`; deleted connections are hidden, never scheduled and never synced. */
deleted_at: string | null;
}
export interface SourceRunsTable {
id: string;
connection_id: string;
mode: RunMode;
started_at: string;
finished_at: string | null;
status: RunStatus;
counts: string;
log: string;
error: string | null;
}
export interface SourceRecordsTable {
id: string;
connection_id: string;
key: string;
kind: string;
current_hash: string;
first_seen: string;
last_seen: string;
deleted_at: string | null;
merged_into_key: string | null;
target_entity: string | null;
target_id: string | null;
}
export interface SourceRecordVersionsTable {
id: string;
record_id: string;
hash: string;
/** Base64 of gzipped raw record. */
raw_gz: string;
seen_at: string;
}
export interface ChangeEventsTable {
id: string;
user_id: string;
connection_id: string | null;
run_id: string | null;
record_id: string | null;
type: ChangeType;
target_entity: string;
target_id: string | null;
payload: string;
status: ChangeStatus;
created_at: string;
resolved_at: string | null;
}
export interface JobsTable {
id: string;
type: string;
payload: string;
run_at: string;
status: JobStatus;
attempts: number;
last_error: string | null;
locked_at: string | null;
lock_key: string | null;
created_at: string;
}
export interface Database {
users: UsersTable;
sessions: SessionsTable;
invites: InvitesTable;
app_tokens: AppTokensTable;
works: WorksTable;
external_ids: ExternalIdsTable;
work_aliases: WorkAliasesTable;
work_history: WorkHistoryTable;
entries: EntriesTable;
engagements: EngagementsTable;
engagement_sources: EngagementSourcesTable;
listens: ListensTable;
lists: ListsTable;
list_items: ListItemsTable;
custom_field_definitions: CustomFieldDefinitionsTable;
copies: CopiesTable;
attachments: AttachmentsTable;
attachment_links: AttachmentLinksTable;
user_history: UserHistoryTable;
match_suggestions: MatchSuggestionsTable;
source_connections: SourceConnectionsTable;
source_runs: SourceRunsTable;
source_records: SourceRecordsTable;
source_record_versions: SourceRecordVersionsTable;
change_events: ChangeEventsTable;
jobs: JobsTable;
}