master
parent
8a153e3807
commit
efb9726470
@ -0,0 +1,119 @@
|
||||
import {NoSessionKeyError, Session, SessionData, SessionNotLoadedError} from './Session'
|
||||
import {Inject, Injectable} from '../../di'
|
||||
import {Cache, Maybe} from '../../util'
|
||||
import {Config} from '../../service/Config'
|
||||
|
||||
/**
|
||||
* A Session implementation that uses the configured Cache driver for persistence.
|
||||
*/
|
||||
@Injectable()
|
||||
export class CacheSession extends Session {
|
||||
@Inject()
|
||||
protected readonly cache!: Cache
|
||||
|
||||
@Inject()
|
||||
protected readonly config!: Config
|
||||
|
||||
protected key?: string
|
||||
|
||||
protected data?: SessionData
|
||||
|
||||
protected dirty = false
|
||||
|
||||
forget(key: string): void {
|
||||
if ( !this.data ) {
|
||||
throw new SessionNotLoadedError()
|
||||
}
|
||||
|
||||
delete this.data[key]
|
||||
this.dirty = true
|
||||
}
|
||||
|
||||
get(key: string, fallback?: unknown): any {
|
||||
if ( !this.data ) {
|
||||
throw new SessionNotLoadedError()
|
||||
}
|
||||
|
||||
return this.data[key] ?? fallback
|
||||
}
|
||||
|
||||
getData(): SessionData {
|
||||
if ( !this.data ) {
|
||||
throw new SessionNotLoadedError()
|
||||
}
|
||||
|
||||
return {...this.data}
|
||||
}
|
||||
|
||||
getKey(): string {
|
||||
if ( !this.key ) {
|
||||
throw new NoSessionKeyError()
|
||||
}
|
||||
|
||||
return this.key
|
||||
}
|
||||
|
||||
async load(): Promise<void> {
|
||||
const json = await this.cache.fetch(this.formatKey())
|
||||
if ( json ) {
|
||||
this.data = JSON.parse(json)
|
||||
} else {
|
||||
this.data = {}
|
||||
}
|
||||
|
||||
this.dirty = false
|
||||
}
|
||||
|
||||
async persist(): Promise<void> {
|
||||
if ( !this.dirty ) {
|
||||
return
|
||||
}
|
||||
|
||||
const json = JSON.stringify(this.data)
|
||||
await this.cache.put(this.formatKey(), json, this.getExpiration())
|
||||
this.dirty = false
|
||||
}
|
||||
|
||||
private getExpiration(): Maybe<Date> {
|
||||
// Get the session expiration. By default, this is 4 hours.
|
||||
const durationMins = this.config.safe('server.session.durationMins')
|
||||
.or(4 * 60)
|
||||
.integer()
|
||||
|
||||
if ( durationMins !== 0 ) {
|
||||
const date = new Date()
|
||||
date.setMinutes(date.getMinutes() + durationMins)
|
||||
return date
|
||||
}
|
||||
}
|
||||
|
||||
private formatKey(): string {
|
||||
if ( !this.key ) {
|
||||
throw new NoSessionKeyError()
|
||||
}
|
||||
|
||||
const prefix = this.config.safe('app.name')
|
||||
.or('Extollo')
|
||||
.string()
|
||||
|
||||
return `${prefix}_session_${this.key}`
|
||||
}
|
||||
|
||||
set(key: string, value: unknown): void {
|
||||
if ( !this.data ) {
|
||||
throw new SessionNotLoadedError()
|
||||
}
|
||||
|
||||
this.data[key] = value
|
||||
this.dirty = true
|
||||
}
|
||||
|
||||
setData(data: SessionData): void {
|
||||
this.data = {...data}
|
||||
this.dirty = true
|
||||
}
|
||||
|
||||
setKey(key: string): void {
|
||||
this.key = key
|
||||
}
|
||||
}
|
Loading…
Reference in new issue