lib/src/http/session/SessionFactory.ts

88 lines
3.0 KiB
TypeScript
Raw Normal View History

2021-03-07 19:26:14 +00:00
import {
AbstractFactory,
Container,
DependencyRequirement,
PropertyDependency,
isInstantiable,
2021-03-07 19:26:14 +00:00
DEPENDENCY_KEYS_METADATA_KEY,
2021-06-03 03:36:25 +00:00
DEPENDENCY_KEYS_PROPERTY_METADATA_KEY, Instantiable,
} from '../../di'
import {Collection, ErrorWithContext} from '../../util'
import {MemorySession} from './MemorySession'
import {Session} from './Session'
import {Logging} from '../../service/Logging'
import {Config} from '../../service/Config'
2021-03-07 19:26:14 +00:00
2021-03-25 13:50:13 +00:00
/**
* A dependency injection factory that matches the abstract Session class
* and produces an instance of the configured session driver implementation.
*/
2021-06-03 03:36:25 +00:00
export class SessionFactory extends AbstractFactory<Session> {
2021-03-07 19:26:14 +00:00
protected readonly logging: Logging
2021-06-03 03:36:25 +00:00
protected readonly config: Config
2021-03-07 19:26:14 +00:00
2021-03-25 13:50:13 +00:00
/** True if we have printed the memory session warning at least once. */
private static loggedMemorySessionWarningOnce = false
2021-03-07 19:26:14 +00:00
constructor() {
super({})
this.logging = Container.getContainer().make<Logging>(Logging)
this.config = Container.getContainer().make<Config>(Config)
2021-03-07 19:26:14 +00:00
}
2021-06-03 03:36:25 +00:00
produce(): Session {
return new (this.getSessionClass())()
2021-03-07 19:26:14 +00:00
}
2021-06-03 03:36:25 +00:00
match(something: unknown): boolean {
2021-03-07 19:26:14 +00:00
return something === Session
}
getDependencyKeys(): Collection<DependencyRequirement> {
const meta = Reflect.getMetadata(DEPENDENCY_KEYS_METADATA_KEY, this.getSessionClass())
2021-06-03 03:36:25 +00:00
if ( meta ) {
return meta
}
2021-03-07 19:26:14 +00:00
return new Collection<DependencyRequirement>()
}
getInjectedProperties(): Collection<PropertyDependency> {
const meta = new Collection<PropertyDependency>()
let currentToken = this.getSessionClass()
2021-03-07 19:26:14 +00:00
do {
const loadedMeta = Reflect.getMetadata(DEPENDENCY_KEYS_PROPERTY_METADATA_KEY, currentToken)
2021-06-03 03:36:25 +00:00
if ( loadedMeta ) {
meta.concat(loadedMeta)
}
2021-03-07 19:26:14 +00:00
currentToken = Object.getPrototypeOf(currentToken)
} while (Object.getPrototypeOf(currentToken) !== Function.prototype && Object.getPrototypeOf(currentToken) !== Object.prototype)
return meta
}
2021-03-25 13:50:13 +00:00
/**
* Return the instantiable class of the configured session backend.
* @protected
* @return Instantiable<Session>
*/
2021-06-03 03:36:25 +00:00
protected getSessionClass(): Instantiable<Session> {
const SessionClass = this.config.get('server.session.driver', MemorySession)
if ( SessionClass === MemorySession && !SessionFactory.loggedMemorySessionWarningOnce ) {
this.logging.warn(`You are using the default memory-based session driver. It is recommended you configure a persistent session driver instead.`)
SessionFactory.loggedMemorySessionWarningOnce = true
}
if ( !isInstantiable(SessionClass) || !(SessionClass.prototype instanceof Session) ) {
2021-06-03 03:36:25 +00:00
const e = new ErrorWithContext('Provided session class does not extend from @extollo/lib.Session')
e.context = {
2021-06-03 03:36:25 +00:00
configKey: 'server.session.driver',
class: SessionClass.toString(),
}
}
return SessionClass
}
2021-03-07 19:26:14 +00:00
}