Skip to content

Instantly share code, notes, and snippets.

@adamelliotfields
Last active February 3, 2019 17:15
Show Gist options
  • Save adamelliotfields/e2dd1b62d02d1a813d54e4d4b46faa42 to your computer and use it in GitHub Desktop.
Save adamelliotfields/e2dd1b62d02d1a813d54e4d4b46faa42 to your computer and use it in GitHub Desktop.
Express Session Memory Store
import { BaseMemoryStore, Store } from 'express-session';
export class MemoryStore extends Store implements BaseMemoryStore {
/**
* A key/value mapping of session IDs to serialized (stringified) sessions.
*/
private readonly sessions: Map<string, string>;
public constructor() {
super();
this.sessions = new Map();
}
/**
* Get all active sessions.
*/
public all: Store['all'] = (callback) => {
// NOTE: The docs indicate that this should be an array of sessions; however, the signature in
// the TypeScript definition indicates this should be an object.
const sessions: { [sid: string]: Express.SessionData } = {};
try {
this.sessions.forEach((value, key) => {
sessions[key] = JSON.parse(value);
});
callback && setImmediate(callback, null, sessions);
} catch (err) {
callback && setImmediate(callback, err)
}
}
/**
* Destroy the session associated with the given session ID.
*/
public destroy: Store['destroy'] = (id, callback) => {
this.sessions.delete(id);
callback && setImmediate(callback, null);
}
/**
* Clear all sessions.
*/
public clear: Store['clear'] = (callback) => {
this.sessions.clear();
callback && setImmediate(callback, null);
}
/**
* Get number of active sessions.
*/
public length: Store['length'] = (callback) => {
const { size } = this.sessions;
callback && setImmediate(callback, null, size);
}
/**
* Fetch session by the given session ID.
*/
public get: Store['get'] = (id, callback) => {
try {
const session = this.sessions.has(id)
? JSON.parse(this.sessions.get(id) as string)
: undefined;
if (typeof session !== 'undefined' && typeof session.cookie === 'object') {
const expires = typeof session.cookie.expires === 'string'
? new Date(session.cookie.expires)
: session.cookie.expires;
// Destroy expired session
// NOTE: if expires === true, then expires <= new Date() === true
if (expires && expires <= new Date()) {
this.sessions.delete(id);
callback && setImmediate(callback, null, undefined);
return;
}
}
callback && setImmediate(callback, null, session);
} catch (err) {
callback && setImmediate(callback, err);
}
}
/**
* Commit the given session associated with the given sessionId to the store.
*/
public set: Store['set'] = (id, session, callback) => {
try {
this.sessions.set(id, JSON.stringify(session));
callback && setImmediate(callback, null);
} catch (err) {
callback && setImmediate(callback, err);
}
}
/**
* Touch the given session object associated with the given session ID.
*/
public touch: Store['touch'] = (id, session, callback) => {
if (this.sessions.has(id)) {
try {
const oldSession: Express.SessionData = JSON.parse(this.sessions.get(id) as string);
const newSession: Express.SessionData = { ...oldSession, ...session };
this.sessions.set(id, JSON.stringify(newSession));
} catch (err) {
callback && setImmediate(callback, err);
return;
}
}
callback && setImmediate(callback, null);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment