first commit
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* A persistent, process-shared session backend built on `bun:sqlite` (sync, so
|
||||
* it satisfies `SessionBackend` without a load/save wrapper). Sessions survive
|
||||
* restarts and are shared by every worker pointed at the same file.
|
||||
*
|
||||
* import { setSessionBackend } from "@wrnexus/core";
|
||||
* import { sqliteSessionStore } from "@wrnexus/db/session";
|
||||
* setSessionBackend(sqliteSessionStore("./sessions.db"));
|
||||
*/
|
||||
|
||||
import { Database } from "bun:sqlite";
|
||||
import type { SessionBackend, SessionEntry } from "@wrnexus/core";
|
||||
|
||||
export function sqliteSessionStore(path = "sessions.db"): SessionBackend {
|
||||
const db = new Database(path);
|
||||
db.run("PRAGMA journal_mode = WAL");
|
||||
db.run(
|
||||
"CREATE TABLE IF NOT EXISTS sessions (id TEXT PRIMARY KEY, data TEXT NOT NULL, expiresAt INTEGER NOT NULL)",
|
||||
);
|
||||
const getStmt = db.query("SELECT data, expiresAt FROM sessions WHERE id = ?");
|
||||
const setStmt = db.query(
|
||||
"INSERT INTO sessions (id, data, expiresAt) VALUES (?, ?, ?) " +
|
||||
"ON CONFLICT(id) DO UPDATE SET data = excluded.data, expiresAt = excluded.expiresAt",
|
||||
);
|
||||
const delStmt = db.query("DELETE FROM sessions WHERE id = ?");
|
||||
const gcStmt = db.query("DELETE FROM sessions WHERE expiresAt <= ?");
|
||||
|
||||
return {
|
||||
get(id): SessionEntry | undefined {
|
||||
const row = getStmt.get(id) as { data: string; expiresAt: number } | null;
|
||||
if (!row) return undefined;
|
||||
try {
|
||||
return { data: JSON.parse(row.data) as Record<string, unknown>, expiresAt: row.expiresAt };
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
},
|
||||
set(id, entry) {
|
||||
setStmt.run(id, JSON.stringify(entry.data), entry.expiresAt);
|
||||
},
|
||||
delete(id) {
|
||||
delStmt.run(id);
|
||||
},
|
||||
gc(now) {
|
||||
gcStmt.run(now);
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user