parent
878de025d8
commit
25a37cf1a2
@ -0,0 +1,20 @@
|
||||
import {Field} from '../../../orm/src/model/Field.ts'
|
||||
import {Type} from '../../../orm/src/db/types.ts'
|
||||
import {SessionModel} from '../../../lib/src/module.ts'
|
||||
|
||||
export default class Session extends SessionModel {
|
||||
protected static table = 'sessions'
|
||||
protected static key = 'session_id'
|
||||
|
||||
protected static readonly CREATED_AT = 'start_time'
|
||||
protected static readonly UPDATED_AT = null // No updated at
|
||||
|
||||
@Field(Type.int)
|
||||
protected session_id!: number
|
||||
|
||||
@Field(Type.int)
|
||||
protected user_id?: number
|
||||
|
||||
@Field(Type.timestamp)
|
||||
protected start_time!: Date
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
import Instantiable from './Instantiable.ts'
|
||||
import {StaticClass} from './StaticClass.ts'
|
||||
const DEPENDENCY_KEYS_METADATA_KEY = 'daton:di:dependencyKeys.ts'
|
||||
type DependencyKey = Instantiable<any> | StaticClass<any> | string
|
||||
type DependencyKey = Instantiable<any> | StaticClass<any, any> | string
|
||||
export { DependencyKey, DEPENDENCY_KEYS_METADATA_KEY }
|
||||
|
@ -1,5 +1,5 @@
|
||||
export type StaticClass<T> = Function & {prototype: T}
|
||||
export type StaticClass<T, T2> = Function & {prototype: T} & T2
|
||||
|
||||
export function isStaticClass<T>(something: any): something is StaticClass<T> {
|
||||
export function isStaticClass<T, T2>(something: any): something is StaticClass<T, T2> {
|
||||
return typeof something === 'function' && typeof something.prototype !== 'undefined'
|
||||
}
|
||||
|
@ -0,0 +1,9 @@
|
||||
import SessionFactory from './SessionFactory.ts'
|
||||
import MemorySession from './MemorySession.ts'
|
||||
import SessionInterface from './SessionInterface.ts'
|
||||
|
||||
export default class MemorySessionFactory extends SessionFactory {
|
||||
produce(dependencies: any[], parameters: any[]): SessionInterface {
|
||||
return new MemorySession()
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
import SessionManagerFactory from "./SessionManagerFactory.ts";
|
||||
import MemorySessionManager from "./MemorySessionManager.ts";
|
||||
|
||||
export default class MemorySessionManagerFactory extends SessionManagerFactory {
|
||||
produce(dependencies: any[], parameters: any[]): any {
|
||||
return new MemorySessionManager()
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
import SessionFactory from './SessionFactory.ts'
|
||||
import SessionInterface from './SessionInterface.ts'
|
||||
import {Model} from '../../../../orm/src/model/Model.ts'
|
||||
import {StaticClass} from '../../../../di/src/type/StaticClass.ts'
|
||||
import {isInstantiable} from '../../../../di/src/type/Instantiable.ts'
|
||||
|
||||
export default class ModelSessionFactory extends SessionFactory {
|
||||
constructor(
|
||||
protected readonly ModelClass: StaticClass<SessionInterface, typeof Model>,
|
||||
) {
|
||||
super()
|
||||
}
|
||||
|
||||
produce(dependencies: any[], parameters: any[]): SessionInterface {
|
||||
if ( isInstantiable<SessionInterface>(this.ModelClass) )
|
||||
return new this.ModelClass() as SessionInterface
|
||||
else
|
||||
throw new TypeError(`Session model class ${this.ModelClass} is not instantiable.`)
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
import SessionManager, {InvalidSessionKeyError} from './SessionManager.ts'
|
||||
import {Model} from '../../../../orm/src/model/Model.ts'
|
||||
import SessionInterface, {isSessionInterface} from './SessionInterface.ts'
|
||||
import {StaticClass} from '../../../../di/src/type/StaticClass.ts'
|
||||
|
||||
export default class ModelSessionManager extends SessionManager {
|
||||
constructor(
|
||||
protected readonly ModelClass: StaticClass<SessionInterface, typeof Model>,
|
||||
) {
|
||||
super()
|
||||
}
|
||||
|
||||
public async get_session(key?: string): Promise<SessionInterface> {
|
||||
const ModelClass: typeof Model = this.ModelClass as typeof Model
|
||||
|
||||
if ( !key ) {
|
||||
const session = this.make(ModelClass)
|
||||
await session.init_session()
|
||||
|
||||
if ( isSessionInterface(session) )
|
||||
return session as SessionInterface
|
||||
|
||||
throw new TypeError(`Session model improperly implements the required SessionInterface.`)
|
||||
}
|
||||
|
||||
const session = await ModelClass.find_by_key(key)
|
||||
if ( !session ) throw new InvalidSessionKeyError(key)
|
||||
if ( isSessionInterface(session) )
|
||||
return session as SessionInterface
|
||||
|
||||
throw new TypeError(`Session model improperly implements the required SessionInterface.`)
|
||||
}
|
||||
|
||||
public async has_session(key: string): Promise<boolean> {
|
||||
const ModelClass: typeof Model = this.ModelClass as typeof Model
|
||||
|
||||
return ModelClass.select(ModelClass.qualified_key_name())
|
||||
.where(ModelClass.qualified_key_name(), '=', key)
|
||||
.exists()
|
||||
}
|
||||
|
||||
public async purge(key?: string): Promise<void> {
|
||||
const ModelClass: typeof Model = this.ModelClass as typeof Model
|
||||
const mutable = ModelClass.delete()
|
||||
|
||||
if ( key ) {
|
||||
mutable.where(ModelClass.qualified_key_name(), '=', key)
|
||||
}
|
||||
|
||||
await mutable.execute()
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
import SessionManagerFactory from './SessionManagerFactory.ts'
|
||||
import ModelSessionManager from './ModelSessionManager.ts'
|
||||
import {Model} from '../../../../orm/src/model/Model.ts'
|
||||
import {StaticClass} from '../../../../di/src/type/StaticClass.ts'
|
||||
import SessionInterface from './SessionInterface.ts'
|
||||
|
||||
export default class MemorySessionManagerFactory extends SessionManagerFactory {
|
||||
constructor(
|
||||
protected readonly ModelClass: StaticClass<SessionInterface, typeof Model>,
|
||||
) {
|
||||
super()
|
||||
}
|
||||
|
||||
produce(dependencies: any[], parameters: any[]): any {
|
||||
return new ModelSessionManager(this.ModelClass)
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
import {logger} from "../../service/logging/global.ts";
|
||||
|
||||
export type SessionData = { [key: string]: any }
|
||||
|
||||
export default interface SessionInterface {
|
||||
get_key(): string
|
||||
set_key(key: string): void
|
||||
persist(): Promise<void>
|
||||
get_data(): SessionData
|
||||
set_data(data: SessionData): void
|
||||
get_attribute(key: string): any
|
||||
set_attribute(key: string, value: any): void
|
||||
init_session(): Promise<void>
|
||||
}
|
||||
|
||||
export function isSessionInterface(what: any): what is SessionInterface {
|
||||
const name_length_checks = [
|
||||
{ name: 'get_key', length: 0 },
|
||||
{ name: 'set_key', length: 1 },
|
||||
{ name: 'persist', length: 0 },
|
||||
{ name: 'get_data', length: 0 },
|
||||
{ name: 'set_data', length: 1 },
|
||||
{ name: 'get_attribute', length: 1 },
|
||||
{ name: 'set_attribute', length: 2 },
|
||||
{ name: 'init_session', length: 0 },
|
||||
]
|
||||
|
||||
for ( const check of name_length_checks ) {
|
||||
const { name, length } = check
|
||||
if ( !(typeof what[name] === 'function') ) {
|
||||
logger.debug(`Invalid session interface: typeof ${name} is not a function.`)
|
||||
return false
|
||||
}
|
||||
|
||||
if ( what[name].length !== length ) {
|
||||
logger.debug(`Invalid session interface: method ${name} should expect ${length} arguments, ${what[name].length} actual.`)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
import {Model} from '../../../../orm/src/model/Model.ts'
|
||||
import SessionInterface, {SessionData} from './SessionInterface.ts'
|
||||
import {Field} from '../../../../orm/src/model/Field.ts'
|
||||
import {Type} from '../../../../orm/src/db/types.ts'
|
||||
|
||||
export default class SessionModel extends Model<SessionModel> implements SessionInterface {
|
||||
|
||||
@Field(Type.json)
|
||||
protected data?: string
|
||||
|
||||
public get_key(): string {
|
||||
return String(this.key())
|
||||
}
|
||||
|
||||
public set_key(key: string) {
|
||||
// @ts-ignore
|
||||
this[this.key_name()] = parseInt(key)
|
||||
}
|
||||
|
||||
public async persist(): Promise<void> {
|
||||
await this.save()
|
||||
}
|
||||
|
||||
public get_data(): SessionData {
|
||||
return this.data ? JSON.parse(this.data) : undefined
|
||||
}
|
||||
|
||||
public set_data(data: SessionData) {
|
||||
this.data = JSON.stringify(data)
|
||||
}
|
||||
|
||||
public get_attribute(key: string): any {
|
||||
const data = this.get_data()
|
||||
if ( data ) return data[key]
|
||||
}
|
||||
|
||||
public set_attribute(key: string, value: any) {
|
||||
const data = this.get_data()
|
||||
data[key] = value
|
||||
this.set_data(data)
|
||||
}
|
||||
|
||||
public async init_session(): Promise<void> {
|
||||
this.data = JSON.stringify({})
|
||||
await this.save()
|
||||
}
|
||||
}
|
@ -1,2 +1,3 @@
|
||||
export { default as Scaffolding } from './unit/Scaffolding.ts'
|
||||
export { default as Application } from './lifecycle/Application.ts'
|
||||
export { default as SessionModel } from './http/session/SessionModel.ts'
|
@ -0,0 +1,13 @@
|
||||
import {Canonical, CanonicalDefinition} from './Canonical.ts'
|
||||
import {InvalidCanonicalExportError} from './InstantiableCanonical.ts'
|
||||
import {isStaticClass, StaticClass} from '../../../di/src/type/StaticClass.ts'
|
||||
|
||||
export class StaticCanonical<T, T2> extends Canonical<StaticClass<T, T2>> {
|
||||
public async init_canonical_item(def: CanonicalDefinition): Promise<StaticClass<T, T2>> {
|
||||
if ( isStaticClass(def.imported.default) ) {
|
||||
return def.imported.default
|
||||
}
|
||||
|
||||
throw new InvalidCanonicalExportError(def.original_name)
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
import {CanonicalDefinition} from '../../lib/src/unit/Canonical.ts'
|
||||
import {Model} from './model/Model.ts'
|
||||
import {Unit} from '../../lib/src/lifecycle/decorators.ts'
|
||||
import {StaticCanonical} from '../../lib/src/unit/StaticCanonical.ts'
|
||||
|
||||
@Unit()
|
||||
export default class ModelsUnit extends StaticCanonical<Model<any>, typeof Model> {
|
||||
protected base_path = './app/models'
|
||||
protected canonical_item = 'model'
|
||||
protected suffix = '.model.ts'
|
||||
|
||||
public async init_canonical_item(def: CanonicalDefinition) {
|
||||
const item = await super.init_canonical_item(def)
|
||||
if ( !(item.prototype instanceof Model) ) {
|
||||
throw new TypeError(`Invalid model definition: ${def.original_name}. Models must extend from Daton ORM's base Model class.`)
|
||||
}
|
||||
|
||||
return item
|
||||
}
|
||||
}
|
Loading…
Reference in new issue