Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 2x 2x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 38x 36x 38x 3x 24x 24x 18x 18x 6x 6x 24x 24x 3x 3x 3x 3x 3x | import { assign, Mutable, TypeOf } from '@sgrud/core'; import { Model } from '../model/model'; /** * Unique symbol used as property key by the {@link HasOne} decorator to * register decorated {@link Model} fields for further computation, e.g., * serialization, treemapping etc. * * @see {@link HasOne} */ export const hasOne = Symbol('@sgrud/data/model/has-one'); /** * {@link Model} field decorator factory. Using this decorator, {@link Model}s * can be enriched with one-to-one associations to other {@link Model}s. The * value for the `typeFactory` argument has to be another {@link Model}. By * applying this decorator, the decorated field will (depending on the * `transient` argument value) be taken into account when serializing or * treemapping the {@link Model} containing the decorated field. * * @param typeFactory - A forward reference to the field value constructor. * @param transient - Whether the decorated field is `transient`. * @typeParam T - The field value constructor type. * @returns A {@link Model} field decorator. * * @example * {@link Model} with a one-to-one association: * ```ts * import { HasOne, Model } from '@sgrud/data'; * import { OwnedModel } from './owned-model'; * * export class ExampleModel extends Model<ExampleModel> { * * @HasOne(() => OwnedModel) * public field?: OwnedModel; * * protected [Symbol.toStringTag]: string = 'ExampleModel'; * * } * ``` * * @see {@link Model} * @see {@link HasMany} * @see {@link Property} */ export function HasOne<T extends Model.Type<Model>>( typeFactory: () => T, transient: boolean = false ) { /** * @param model - The {@link Model} to be decorated. * @param field - The {@link Model} `field` to be decorated. */ return function<M extends Model>( model: M, field: Model.Field<M> ): void { const key = '#' + field as Model.Field<M>; if (!transient) { assign((model as Mutable<M>)[hasOne] ||= {}, { [field]: typeFactory }); } Object.defineProperties(model, { [key]: { writable: true }, [field]: { enumerable: true, get(this: M): InstanceType<T> | null | undefined { if (TypeOf.null(this[key])) return null; else return this[key]?.valueOf() as InstanceType<T>; }, set(this: M, value?: InstanceType<T>): void { if (TypeOf.null(value)) { (this[key] as unknown) = null; } else if (!TypeOf.undefined(value)) { (this[key] as unknown) = new (typeFactory())(value); } else return; this.changes.next(this); } } }); }; } |