adapter-sqlite: all repo implementations + wire fn + migrations copy
This commit is contained in:
11
migrations_sqlite/20240101000000_init_users.sql
Normal file
11
migrations_sqlite/20240101000000_init_users.sql
Normal file
@@ -0,0 +1,11 @@
|
||||
-- Create users table
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id TEXT PRIMARY KEY NOT NULL,
|
||||
subject TEXT NOT NULL,
|
||||
email TEXT NOT NULL,
|
||||
password_hash TEXT,
|
||||
created_at TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_users_subject ON users(subject);
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_users_email ON users(email);
|
||||
59
migrations_sqlite/20240102000000_init_channels.sql
Normal file
59
migrations_sqlite/20240102000000_init_channels.sql
Normal file
@@ -0,0 +1,59 @@
|
||||
-- Channels: user-defined broadcast channels with their schedule template
|
||||
CREATE TABLE IF NOT EXISTS channels (
|
||||
id TEXT PRIMARY KEY NOT NULL,
|
||||
owner_id TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
description TEXT,
|
||||
timezone TEXT NOT NULL DEFAULT 'UTC',
|
||||
-- JSON-encoded ScheduleConfig (the shareable/exportable template)
|
||||
schedule_config TEXT NOT NULL DEFAULT '{"blocks":[]}',
|
||||
-- JSON-encoded RecyclePolicy
|
||||
recycle_policy TEXT NOT NULL DEFAULT '{"cooldown_days":30,"cooldown_generations":null,"min_available_ratio":0.2}',
|
||||
created_at TEXT NOT NULL,
|
||||
updated_at TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_channels_owner ON channels(owner_id);
|
||||
|
||||
-- Generated 48-hour schedules (resolved from a channel's template)
|
||||
CREATE TABLE IF NOT EXISTS generated_schedules (
|
||||
id TEXT PRIMARY KEY NOT NULL,
|
||||
channel_id TEXT NOT NULL,
|
||||
valid_from TEXT NOT NULL,
|
||||
valid_until TEXT NOT NULL,
|
||||
generation INTEGER NOT NULL,
|
||||
FOREIGN KEY (channel_id) REFERENCES channels(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
-- Composite index supports both "find active at time T" and "find latest"
|
||||
CREATE INDEX IF NOT EXISTS idx_schedules_channel_valid
|
||||
ON generated_schedules(channel_id, valid_from DESC);
|
||||
|
||||
-- Individual scheduled slots within a generated schedule.
|
||||
-- The MediaItem snapshot is stored as JSON so the EPG survives library changes.
|
||||
CREATE TABLE IF NOT EXISTS scheduled_slots (
|
||||
id TEXT PRIMARY KEY NOT NULL,
|
||||
schedule_id TEXT NOT NULL,
|
||||
start_at TEXT NOT NULL,
|
||||
end_at TEXT NOT NULL,
|
||||
-- JSON-encoded MediaItem (metadata snapshot at generation time)
|
||||
item TEXT NOT NULL,
|
||||
source_block_id TEXT NOT NULL,
|
||||
FOREIGN KEY (schedule_id) REFERENCES generated_schedules(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_slots_schedule_start
|
||||
ON scheduled_slots(schedule_id, start_at);
|
||||
|
||||
-- Playback history for the recycle policy engine
|
||||
CREATE TABLE IF NOT EXISTS playback_records (
|
||||
id TEXT PRIMARY KEY NOT NULL,
|
||||
channel_id TEXT NOT NULL,
|
||||
item_id TEXT NOT NULL,
|
||||
played_at TEXT NOT NULL,
|
||||
generation INTEGER NOT NULL,
|
||||
FOREIGN KEY (channel_id) REFERENCES channels(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_playback_channel_date
|
||||
ON playback_records(channel_id, played_at DESC);
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE channels ADD COLUMN auto_schedule INTEGER NOT NULL DEFAULT 0;
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE channels ADD COLUMN access_mode TEXT NOT NULL DEFAULT 'public';
|
||||
ALTER TABLE channels ADD COLUMN access_password_hash TEXT;
|
||||
@@ -0,0 +1,3 @@
|
||||
ALTER TABLE channels ADD COLUMN logo TEXT;
|
||||
ALTER TABLE channels ADD COLUMN logo_position TEXT NOT NULL DEFAULT 'top_right';
|
||||
ALTER TABLE channels ADD COLUMN logo_opacity REAL NOT NULL DEFAULT 1.0;
|
||||
10
migrations_sqlite/20260314000000_add_local_files_index.sql
Normal file
10
migrations_sqlite/20260314000000_add_local_files_index.sql
Normal file
@@ -0,0 +1,10 @@
|
||||
CREATE TABLE IF NOT EXISTS local_files_index (
|
||||
id TEXT PRIMARY KEY,
|
||||
rel_path TEXT NOT NULL UNIQUE,
|
||||
title TEXT NOT NULL,
|
||||
duration_secs INTEGER NOT NULL DEFAULT 0,
|
||||
year INTEGER,
|
||||
tags TEXT NOT NULL DEFAULT '[]',
|
||||
top_dir TEXT NOT NULL DEFAULT '',
|
||||
scanned_at TEXT NOT NULL
|
||||
);
|
||||
@@ -0,0 +1,5 @@
|
||||
CREATE TABLE IF NOT EXISTS transcode_settings (
|
||||
id INTEGER PRIMARY KEY CHECK (id = 1),
|
||||
cleanup_ttl_hours INTEGER NOT NULL DEFAULT 24
|
||||
);
|
||||
INSERT OR IGNORE INTO transcode_settings (id, cleanup_ttl_hours) VALUES (1, 24);
|
||||
2
migrations_sqlite/20260316000000_add_webhook_fields.sql
Normal file
2
migrations_sqlite/20260316000000_add_webhook_fields.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE channels ADD COLUMN webhook_url TEXT;
|
||||
ALTER TABLE channels ADD COLUMN webhook_poll_interval_secs INTEGER NOT NULL DEFAULT 5;
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE channels ADD COLUMN webhook_body_template TEXT;
|
||||
ALTER TABLE channels ADD COLUMN webhook_headers TEXT;
|
||||
9
migrations_sqlite/20260317000000_add_activity_log.sql
Normal file
9
migrations_sqlite/20260317000000_add_activity_log.sql
Normal file
@@ -0,0 +1,9 @@
|
||||
CREATE TABLE IF NOT EXISTS activity_log (
|
||||
id TEXT PRIMARY KEY NOT NULL,
|
||||
timestamp TEXT NOT NULL,
|
||||
event_type TEXT NOT NULL,
|
||||
detail TEXT NOT NULL,
|
||||
channel_id TEXT
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_activity_log_timestamp ON activity_log(timestamp DESC);
|
||||
@@ -0,0 +1,8 @@
|
||||
ALTER TABLE users ADD COLUMN is_admin INTEGER NOT NULL DEFAULT 0;
|
||||
|
||||
CREATE TABLE provider_configs (
|
||||
provider_type TEXT PRIMARY KEY,
|
||||
config_json TEXT NOT NULL,
|
||||
enabled INTEGER NOT NULL DEFAULT 1,
|
||||
updated_at TEXT NOT NULL
|
||||
);
|
||||
12
migrations_sqlite/20260319000000_add_config_snapshots.sql
Normal file
12
migrations_sqlite/20260319000000_add_config_snapshots.sql
Normal file
@@ -0,0 +1,12 @@
|
||||
CREATE TABLE channel_config_snapshots (
|
||||
id TEXT PRIMARY KEY NOT NULL,
|
||||
channel_id TEXT NOT NULL REFERENCES channels(id) ON DELETE CASCADE,
|
||||
config_json TEXT NOT NULL,
|
||||
version_num INTEGER NOT NULL,
|
||||
label TEXT,
|
||||
created_at TEXT NOT NULL,
|
||||
UNIQUE (channel_id, version_num)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_config_snapshots_channel
|
||||
ON channel_config_snapshots(channel_id, version_num DESC);
|
||||
@@ -0,0 +1,17 @@
|
||||
-- Recreate provider_configs with per-instance id as PK
|
||||
CREATE TABLE provider_configs_new (
|
||||
id TEXT PRIMARY KEY,
|
||||
provider_type TEXT NOT NULL,
|
||||
config_json TEXT NOT NULL,
|
||||
enabled INTEGER NOT NULL DEFAULT 1,
|
||||
updated_at TEXT NOT NULL
|
||||
);
|
||||
INSERT INTO provider_configs_new (id, provider_type, config_json, enabled, updated_at)
|
||||
SELECT provider_type, provider_type, config_json, enabled, updated_at
|
||||
FROM provider_configs;
|
||||
DROP TABLE provider_configs;
|
||||
ALTER TABLE provider_configs_new RENAME TO provider_configs;
|
||||
|
||||
-- Scope local_files_index entries by provider instance
|
||||
ALTER TABLE local_files_index ADD COLUMN provider_id TEXT NOT NULL DEFAULT 'local';
|
||||
CREATE INDEX IF NOT EXISTS idx_local_files_provider ON local_files_index(provider_id);
|
||||
37
migrations_sqlite/20260319000002_add_library_tables.sql
Normal file
37
migrations_sqlite/20260319000002_add_library_tables.sql
Normal file
@@ -0,0 +1,37 @@
|
||||
CREATE TABLE IF NOT EXISTS library_items (
|
||||
id TEXT PRIMARY KEY,
|
||||
provider_id TEXT NOT NULL,
|
||||
external_id TEXT NOT NULL,
|
||||
title TEXT NOT NULL,
|
||||
content_type TEXT NOT NULL,
|
||||
duration_secs INTEGER NOT NULL DEFAULT 0,
|
||||
series_name TEXT,
|
||||
season_number INTEGER,
|
||||
episode_number INTEGER,
|
||||
year INTEGER,
|
||||
genres TEXT NOT NULL DEFAULT '[]',
|
||||
tags TEXT NOT NULL DEFAULT '[]',
|
||||
collection_id TEXT,
|
||||
collection_name TEXT,
|
||||
collection_type TEXT,
|
||||
thumbnail_url TEXT,
|
||||
synced_at TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_library_items_provider ON library_items(provider_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_library_items_content_type ON library_items(content_type);
|
||||
CREATE INDEX IF NOT EXISTS idx_library_items_series ON library_items(series_name);
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_library_items_provider_external ON library_items(provider_id, external_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS library_sync_log (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
provider_id TEXT NOT NULL,
|
||||
started_at TEXT NOT NULL,
|
||||
finished_at TEXT,
|
||||
items_found INTEGER NOT NULL DEFAULT 0,
|
||||
status TEXT NOT NULL DEFAULT 'running',
|
||||
error_msg TEXT
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_library_sync_log_provider ON library_sync_log(provider_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_library_sync_log_provider_started ON library_sync_log(provider_id, started_at DESC);
|
||||
6
migrations_sqlite/20260319000003_add_app_settings.sql
Normal file
6
migrations_sqlite/20260319000003_add_app_settings.sql
Normal file
@@ -0,0 +1,6 @@
|
||||
CREATE TABLE IF NOT EXISTS app_settings (
|
||||
key TEXT PRIMARY KEY,
|
||||
value TEXT NOT NULL
|
||||
);
|
||||
|
||||
INSERT OR IGNORE INTO app_settings(key, value) VALUES ('library_sync_interval_hours', '6');
|
||||
Reference in New Issue
Block a user