All files / _book/src Relation.ts

93.62% Statements 44/47
89.74% Branches 35/39
100% Functions 17/17
100% Lines 42/42

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 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146    9x 9x 9x               9x                 20x 20x 20x 19x               21x 21x   21x 21x   21x 21x 21x   20x         20x 20x   20x 20x 20x       968x 968x 516x   452x         516x   13x                     3x       3x                         4x         80x         1x         3x           516x         452x   65x   2x       8x       1x       2x   4x     452x      
import neo4js, { Model, ModelInstance } from "./index";
import { relationProperty, lazyModel } from "./Decorators";
import { lazy } from "./utils";
import * as HasMany from "./HasManyRelation";
import * as HasOne from "./HasOneRelation";
 
export type RelationType = {
  many: boolean;
  out?: boolean;
  any?: boolean;
};
 
export class Relation {
  relationType: RelationType;
  src: Model<any, any>;
  dest: lazyModel<any, any>;
  propertyName: string;
  label: string;
  lazy: relationProperty;
 
  constructor(src: Model<any, any>, property: relationProperty) {
    this.src = src;
    this.lazy = property;
    if (lazy(property.relation)) {
      this.init();
    }
  }
 
  /**
   * Initialise all lazy stuff
   */
  init() {
    const property = lazy(this.lazy);
    Iif (!property) return;
 
    const relation = lazy(property.relation);
    Iif (!relation) return;
 
    const from = lazy(relation.from);
    const to = lazy(relation.to);
    if (!from || !to) return;
 
    this.relationType = {
      many: property.many,
      out: property.out !== null ? property.out : from === this.src,
      any: property.any,
    };
    this.dest = lazy(from === this.src ? relation.to : relation.from);
    Iif (!this.dest) return;
 
    this.propertyName = property.propertyName;
    this.label = relation.via;
    delete this.lazy;
  }
 
  addFunctionsToInstance<P, M extends ModelInstance<P>>(instance: M): M {
    if (this.lazy) this.init();
    if (this.relationType.many) {
      return this.addHasManyToInstance(instance);
    }
    return this.addHasOneToInstance(instance);
  }
 
  addHasManyToInstance<P, M extends ModelInstance<P>>(instance: M): any {
    // @ts-ignore
    instance[this.propertyName] = {
      get: (props: any, relationProps: any = {}) =>
        HasMany.get.bind(this, instance, this.label, this.relationType)(
          props,
          relationProps
        ),
      update: (
        options: any,
        whereProps: any,
        relationProps: any = {},
        whereRelationProps: any = {}
      ) => {
        const optionsInUse =
          options.props ||
          options.whereProps ||
          options.relationProps ||
          options.whereRelationProps;
        return HasMany.update.bind(
          this,
          instance,
          this.label,
          this.relationType
        )(
          optionsInUse ? options.props : options,
          options.whereProps || whereProps,
          options.relationProps || relationProps,
          options.whereRelationProps || whereRelationProps
        );
      },
      remove: (props: any, relationProps: any = {}) =>
        HasMany.remove.bind(this, instance, this.label, this.relationType)(
          props,
          relationProps
        ),
      create: (props: any, relationProps: any = {}) =>
        HasMany.create.bind(this, instance, this.label, this.relationType)(
          props,
          relationProps
        ),
      add: (instances: any, relationProps: any = {}) =>
        HasMany.add.bind(this, instance, this.label, this.relationType)(
          instances,
          relationProps
        ),
      count: (props: any, relationProps: any = {}) =>
        HasMany.count.bind(this, instance, this.label, this.relationType)(
          props,
          relationProps
        ),
    };
 
    return instance;
  }
 
  addHasOneToInstance<P, M extends ModelInstance<P>>(instance: M): any {
    // @ts-ignore
    instance[this.propertyName] = {
      get: () =>
        HasOne.get.bind(this, instance, this.label, this.relationType)(),
      update: (props: any, label?: string) =>
        HasOne.update.bind(this, instance, this.label, this.relationType)(
          props
        ),
      create: (props: any, label?: string) =>
        HasOne.create.bind(this, instance, this.label, this.relationType)(
          props
        ),
      add: (destInstance: ModelInstance<any>, label?: string) =>
        HasOne.add.bind(this, instance, this.label, this.relationType)(
          destInstance
        ),
      remove: (label?: string) =>
        HasOne.remove.bind(this, instance, this.label, this.relationType)(),
      hasOne: (label?: string) =>
        HasOne.hasOne.bind(this, instance, this.label, this.relationType)(),
    };
 
    return instance;
  }
}