A SQLite-backed session store for express-session, built on top of better-sqlite3.
npm install @bleed-believer/connect-sqlite3 express-session better-sqlite3express-session and better-sqlite3 are peer dependencies of this store — install them alongside it.
import express from 'express';
import session from 'express-session';
import { SQLite3Store } from '@bleed-believer/connect-sqlite3';
const app = express();
app.use(session({
store: new SQLite3Store('./sessions.db'),
secret: 'change-me',
resave: false,
saveUninitialized: false
}));
app.get('/', (req, res) => {
req.session.visits ??= 0;
req.session.visits += 1;
res.send(`You've visited this page ${req.session.visits} time(s).`);
});
app.listen(3000);Every top-level property you set on req.session (other than cookie, which express-session manages) is persisted and restored automatically — there's no dedicated payload property to nest your data under. To get it typed, declaration-merge your own shape into SessionData:
declare module 'express-session' {
interface SessionData {
visits?: number;
}
}The underlying SQLite table (and database file) is created automatically via migrations as soon as SQLite3Store is constructed; there is no manual setup step.
new SQLite3Store(target, verbose?)| Parameter | Type | Description |
|---|---|---|
target |
string | Buffer |
Path to the SQLite database file (or an in-memory buffer), forwarded to better-sqlite3. |
verbose |
boolean (optional) |
When true, logs every SQL statement executed against the database. |
SQLite3Store extends express-session's Store, so it implements the full standard store interface (get, set, touch, destroy, all, length, clear) and can be passed directly to express-session's store option, as shown above. You generally won't call these methods yourself — express-session calls them for you as requests come in.
touch(sid, session, callback)only refreshes a session that already exists; it never creates one.- Every method (
get,set,touch,destroy,all,length) purges expired sessions before performing its own operation.cleardoesn't need this pass since it wipes the table itself. - Expiration is driven by the session cookie's
maxAge/expires; a session with no expiry never gets swept by the cleanup pass.
node --run test # run the test suite (node:test)
node --run build # transpile to dist/ and emit type declarations