You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
lib/src/orm/model/ModelSerializer.ts

69 lines
2.2 KiB

import {BaseSerializer, ObjectSerializer} from '../../support/bus'
import {Model} from './Model'
import {Awaitable, ErrorWithContext, JSONState, Maybe} from '../../util'
import {QueryRow} from '../types'
import {Inject, Injectable, isInstantiable} from '../../di'
import {Canon} from '../../service/Canon'
export interface ModelSerialPayload extends JSONState {
canonicalResolver: string,
primaryKey: any,
objectValues: QueryRow,
}
@ObjectSerializer()
@Injectable()
export class ModelSerializer extends BaseSerializer<Model<any>, ModelSerialPayload> {
@Inject()
protected readonly canon!: Canon
protected async decodeSerial(serial: ModelSerialPayload): Promise<Model<any>> {
const ModelClass = this.canon.getFromFullyQualified(serial.canonicalResolver) as typeof Model
if ( !ModelClass || !(ModelClass.prototype instanceof Model) || !isInstantiable<Model<any>>(ModelClass) ) {
throw new ErrorWithContext('Cannot decode serialized model as canonical resolver is invalid', {
serial,
})
}
let inst: Maybe<Model<any>> = this.make<Model<any>>(ModelClass)
if ( serial.primaryKey ) {
inst = await ModelClass.query()
.whereKey(serial.primaryKey)
.first()
}
if ( !inst ) {
throw new ErrorWithContext('Could not look up serialized model', {
serial,
})
}
await inst.assume(serial.objectValues)
return inst
}
protected encodeActual(actual: Model<any>): Awaitable<ModelSerialPayload> {
const ctor = actual.constructor as typeof Model
const canonicalResolver = ctor.getFullyQualifiedCanonicalResolver()
if ( !canonicalResolver ) {
throw new ErrorWithContext('Unable to serialize model: no Canonical resolver', {
actual,
})
}
return {
canonicalResolver,
primaryKey: actual.key(),
objectValues: actual.toObject(),
}
}
protected getName(): string {
return '@extollo/lib.ModelSerializer'
}
matchActual(some: Model<any>): boolean {
return some instanceof Model
}
}