@@ -43,7 +43,7 @@ export { UserStore } from './userStore'
4343export { GroupStore } from './groupStore'
4444export { ReportStore } from './reportStore'
4545
46- const SCHEMA_VERSION : number = 8
46+ const SCHEMA_VERSION : number = 9
4747const REQUIRED_TABLES = [
4848 'sessions' ,
4949 'machines' ,
@@ -192,6 +192,13 @@ export class Store {
192192 return
193193 }
194194
195+ if ( currentVersion === 8 && SCHEMA_VERSION >= 9 ) {
196+ this . migrateFromV8ToV9 ( )
197+ this . setUserVersion ( 9 )
198+ this . initSchema ( )
199+ return
200+ }
201+
195202 if ( currentVersion !== SCHEMA_VERSION ) {
196203 throw this . buildSchemaMismatchError ( currentVersion )
197204 }
@@ -794,6 +801,69 @@ export class Store {
794801 }
795802 }
796803
804+ private migrateFromV8ToV9 ( ) : void {
805+ try {
806+ this . db . exec ( 'BEGIN' )
807+ this . db . exec ( `
808+ CREATE TABLE IF NOT EXISTS reports (
809+ id TEXT PRIMARY KEY,
810+ namespace TEXT NOT NULL DEFAULT 'default',
811+ session_id TEXT,
812+ task_id TEXT,
813+ title TEXT NOT NULL,
814+ status TEXT NOT NULL DEFAULT 'unknown',
815+ markdown TEXT NOT NULL DEFAULT '',
816+ metadata TEXT,
817+ created_at INTEGER NOT NULL,
818+ updated_at INTEGER NOT NULL,
819+ FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE SET NULL
820+ );
821+ CREATE INDEX IF NOT EXISTS idx_reports_namespace_updated
822+ ON reports(namespace, updated_at DESC);
823+ CREATE INDEX IF NOT EXISTS idx_reports_session_namespace
824+ ON reports(session_id, namespace);
825+
826+ CREATE TABLE IF NOT EXISTS report_assets (
827+ id TEXT PRIMARY KEY,
828+ report_id TEXT NOT NULL,
829+ namespace TEXT NOT NULL DEFAULT 'default',
830+ file_name TEXT NOT NULL,
831+ storage_key TEXT NOT NULL,
832+ mime_type TEXT NOT NULL,
833+ size INTEGER NOT NULL,
834+ caption TEXT,
835+ created_at INTEGER NOT NULL,
836+ FOREIGN KEY (report_id) REFERENCES reports(id) ON DELETE CASCADE
837+ );
838+ CREATE INDEX IF NOT EXISTS idx_report_assets_report
839+ ON report_assets(report_id, created_at ASC);
840+ CREATE UNIQUE INDEX IF NOT EXISTS idx_report_assets_storage_key
841+ ON report_assets(report_id, storage_key);
842+
843+ CREATE TABLE IF NOT EXISTS report_shares (
844+ id TEXT PRIMARY KEY,
845+ report_id TEXT NOT NULL,
846+ namespace TEXT NOT NULL DEFAULT 'default',
847+ token TEXT NOT NULL UNIQUE,
848+ created_by TEXT,
849+ created_at INTEGER NOT NULL,
850+ expires_at INTEGER,
851+ revoked_at INTEGER,
852+ FOREIGN KEY (report_id) REFERENCES reports(id) ON DELETE CASCADE
853+ );
854+ CREATE INDEX IF NOT EXISTS idx_report_shares_report
855+ ON report_shares(report_id, created_at DESC);
856+ CREATE INDEX IF NOT EXISTS idx_report_shares_token
857+ ON report_shares(token);
858+ ` )
859+ this . db . exec ( 'COMMIT' )
860+ } catch ( error ) {
861+ this . db . exec ( 'ROLLBACK' )
862+ const message = error instanceof Error ? error . message : String ( error )
863+ throw new Error ( `SQLite schema migration v8->v9 failed: ${ message } ` )
864+ }
865+ }
866+
797867 private getMachineColumnNames ( ) : Set < string > {
798868 const rows = this . db . prepare ( 'PRAGMA table_info(machines)' ) . all ( ) as Array < { name : string } >
799869 return new Set ( rows . map ( ( row ) => row . name ) )
0 commit comments