chore: set default association reference on delete action to no action (#3722)
* chore: tmp commit * chore: build association reference * fix: test
This commit is contained in:
		
							parent
							
								
									fbed0201aa
								
							
						
					
					
						commit
						5ee278557d
					
				@ -0,0 +1,52 @@
 | 
				
			|||||||
 | 
					import { Database } from '../../database';
 | 
				
			||||||
 | 
					import { mockDatabase } from '../index';
 | 
				
			||||||
 | 
					describe('association references', () => {
 | 
				
			||||||
 | 
					  let db: Database;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  beforeEach(async () => {
 | 
				
			||||||
 | 
					    db = mockDatabase();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await db.clean({ drop: true });
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  afterEach(async () => {
 | 
				
			||||||
 | 
					    await db.close();
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should add reference with default priority', async () => {
 | 
				
			||||||
 | 
					    const User = db.collection({
 | 
				
			||||||
 | 
					      name: 'users',
 | 
				
			||||||
 | 
					      fields: [{ type: 'hasOne', name: 'profile' }],
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const Profile = db.collection({
 | 
				
			||||||
 | 
					      name: 'profiles',
 | 
				
			||||||
 | 
					      fields: [{ type: 'belongsTo', name: 'user' }],
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await db.sync();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const references = db.referenceMap.getReferences('users');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    expect(references[0].priority).toBe('default');
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should add reference with user defined priority', async () => {
 | 
				
			||||||
 | 
					    const User = db.collection({
 | 
				
			||||||
 | 
					      name: 'users',
 | 
				
			||||||
 | 
					      fields: [{ type: 'hasOne', name: 'profile', onDelete: 'CASCADE' }],
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const Profile = db.collection({
 | 
				
			||||||
 | 
					      name: 'profiles',
 | 
				
			||||||
 | 
					      fields: [{ type: 'belongsTo', name: 'user' }],
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await db.sync();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const references = db.referenceMap.getReferences('users');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    expect(references.length).toBe(1);
 | 
				
			||||||
 | 
					    expect(references[0].priority).toBe('user');
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
@ -14,6 +14,36 @@ describe('belongs to field', () => {
 | 
				
			|||||||
    await db.close();
 | 
					    await db.close();
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should load with no action', async () => {
 | 
				
			||||||
 | 
					    const User = db.collection({
 | 
				
			||||||
 | 
					      name: 'users',
 | 
				
			||||||
 | 
					      fields: [{ type: 'string', name: 'name', unique: true }],
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const Post = db.collection({
 | 
				
			||||||
 | 
					      name: 'posts',
 | 
				
			||||||
 | 
					      fields: [
 | 
				
			||||||
 | 
					        { type: 'string', name: 'title' },
 | 
				
			||||||
 | 
					        { type: 'belongsTo', name: 'user', onDelete: 'NO ACTION' },
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await db.sync();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const u1 = await User.repository.create({ values: { name: 'u1' } });
 | 
				
			||||||
 | 
					    const p1 = await Post.repository.create({ values: { title: 'p1', user: u1.id } });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // delete u1
 | 
				
			||||||
 | 
					    await User.repository.destroy({ filterByTk: u1.id });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // list posts with user
 | 
				
			||||||
 | 
					    const post = await Post.repository.findOne({
 | 
				
			||||||
 | 
					      appends: ['user'],
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    expect(post.user).toBeNull();
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  it('should throw error when associated with item that null with target key', async () => {
 | 
					  it('should throw error when associated with item that null with target key', async () => {
 | 
				
			||||||
    const User = db.collection({
 | 
					    const User = db.collection({
 | 
				
			||||||
      name: 'users',
 | 
					      name: 'users',
 | 
				
			||||||
 | 
				
			|||||||
@ -27,7 +27,7 @@ import { CollectionFactory } from './collection-factory';
 | 
				
			|||||||
import { CollectionGroupManager } from './collection-group-manager';
 | 
					import { CollectionGroupManager } from './collection-group-manager';
 | 
				
			||||||
import { ImporterReader, ImportFileExtension } from './collection-importer';
 | 
					import { ImporterReader, ImportFileExtension } from './collection-importer';
 | 
				
			||||||
import DatabaseUtils from './database-utils';
 | 
					import DatabaseUtils from './database-utils';
 | 
				
			||||||
import ReferencesMap from './features/ReferencesMap';
 | 
					import ReferencesMap from './features/references-map';
 | 
				
			||||||
import { referentialIntegrityCheck } from './features/referential-integrity-check';
 | 
					import { referentialIntegrityCheck } from './features/referential-integrity-check';
 | 
				
			||||||
import { ArrayFieldRepository } from './field-repository/array-field-repository';
 | 
					import { ArrayFieldRepository } from './field-repository/array-field-repository';
 | 
				
			||||||
import * as FieldTypes from './fields';
 | 
					import * as FieldTypes from './fields';
 | 
				
			||||||
 | 
				
			|||||||
@ -1,30 +1,57 @@
 | 
				
			|||||||
 | 
					export type ReferencePriority = 'default' | 'user';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface Reference {
 | 
					export interface Reference {
 | 
				
			||||||
  sourceCollectionName: string;
 | 
					  sourceCollectionName: string;
 | 
				
			||||||
  sourceField: string;
 | 
					  sourceField: string;
 | 
				
			||||||
  targetField: string;
 | 
					  targetField: string;
 | 
				
			||||||
  targetCollectionName: string;
 | 
					  targetCollectionName: string;
 | 
				
			||||||
  onDelete: string;
 | 
					  onDelete: string;
 | 
				
			||||||
 | 
					  priority: ReferencePriority;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const DEFAULT_ON_DELETE = 'NO ACTION';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function buildReference(options: Partial<Reference>): Reference {
 | 
				
			||||||
 | 
					  const { sourceCollectionName, sourceField, targetField, targetCollectionName, onDelete, priority } = options;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return {
 | 
				
			||||||
 | 
					    sourceCollectionName,
 | 
				
			||||||
 | 
					    sourceField,
 | 
				
			||||||
 | 
					    targetField,
 | 
				
			||||||
 | 
					    targetCollectionName,
 | 
				
			||||||
 | 
					    onDelete: (onDelete || DEFAULT_ON_DELETE).toUpperCase(),
 | 
				
			||||||
 | 
					    priority: assignPriority(priority, onDelete),
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function assignPriority(priority: string | undefined, onDelete: string | undefined): ReferencePriority {
 | 
				
			||||||
 | 
					  if (priority) {
 | 
				
			||||||
 | 
					    return priority as ReferencePriority;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return onDelete ? 'user' : 'default';
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const PRIORITY_MAP = {
 | 
				
			||||||
 | 
					  default: 1,
 | 
				
			||||||
 | 
					  user: 2,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ReferencesMap {
 | 
					class ReferencesMap {
 | 
				
			||||||
  protected map: Map<string, Reference[]> = new Map();
 | 
					  protected map: Map<string, Reference[]> = new Map();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  addReference(reference: Reference) {
 | 
					  addReference(reference: Reference) {
 | 
				
			||||||
    if (!reference.onDelete) {
 | 
					 | 
				
			||||||
      reference.onDelete = 'SET NULL';
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    reference.onDelete = reference.onDelete.toUpperCase();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const existReference = this.existReference(reference);
 | 
					    const existReference = this.existReference(reference);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (existReference && existReference.onDelete !== reference.onDelete) {
 | 
					    if (existReference && existReference.onDelete !== reference.onDelete) {
 | 
				
			||||||
      if (reference.onDelete === 'SET NULL') {
 | 
					      // check two references onDelete priority, using the higher priority, if both are the same, throw error
 | 
				
			||||||
        // using existing reference
 | 
					      const existPriority = PRIORITY_MAP[existReference.priority];
 | 
				
			||||||
        return;
 | 
					      const newPriority = PRIORITY_MAP[reference.priority];
 | 
				
			||||||
      } else if (existReference.onDelete === 'SET NULL') {
 | 
					
 | 
				
			||||||
 | 
					      if (newPriority > existPriority) {
 | 
				
			||||||
        existReference.onDelete = reference.onDelete;
 | 
					        existReference.onDelete = reference.onDelete;
 | 
				
			||||||
      } else {
 | 
					        existReference.priority = reference.priority;
 | 
				
			||||||
 | 
					      } else if (newPriority === existPriority && newPriority === PRIORITY_MAP['user']) {
 | 
				
			||||||
        throw new Error(
 | 
					        throw new Error(
 | 
				
			||||||
          `On Delete Conflict, exist reference ${JSON.stringify(existReference)}, new reference ${JSON.stringify(
 | 
					          `On Delete Conflict, exist reference ${JSON.stringify(existReference)}, new reference ${JSON.stringify(
 | 
				
			||||||
            reference,
 | 
					            reference,
 | 
				
			||||||
@ -52,7 +79,7 @@ class ReferencesMap {
 | 
				
			|||||||
      return null;
 | 
					      return null;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const keys = Object.keys(reference).filter((k) => k !== 'onDelete');
 | 
					    const keys = Object.keys(reference).filter((k) => k !== 'onDelete' && k !== 'priority');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return references.find((ref) => keys.every((key) => ref[key] === reference[key]));
 | 
					    return references.find((ref) => keys.every((key) => ref[key] === reference[key]));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -21,6 +21,11 @@ export async function referentialIntegrityCheck(options: ReferentialIntegrityChe
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  for (const reference of references) {
 | 
					  for (const reference of references) {
 | 
				
			||||||
    const { sourceCollectionName, sourceField, targetField, onDelete } = reference;
 | 
					    const { sourceCollectionName, sourceField, targetField, onDelete } = reference;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (onDelete === 'NO ACTION') {
 | 
				
			||||||
 | 
					      continue;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const sourceCollection = db.collections.get(sourceCollectionName);
 | 
					    const sourceCollection = db.collections.get(sourceCollectionName);
 | 
				
			||||||
    const sourceRepository = sourceCollection.repository;
 | 
					    const sourceRepository = sourceCollection.repository;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
import lodash, { omit } from 'lodash';
 | 
					import lodash, { omit } from 'lodash';
 | 
				
			||||||
import { BelongsToOptions as SequelizeBelongsToOptions, Utils } from 'sequelize';
 | 
					import { BelongsToOptions as SequelizeBelongsToOptions, Utils } from 'sequelize';
 | 
				
			||||||
import { Reference } from '../features/ReferencesMap';
 | 
					import { buildReference, Reference, ReferencePriority } from '../features/references-map';
 | 
				
			||||||
import { checkIdentifier } from '../utils';
 | 
					import { checkIdentifier } from '../utils';
 | 
				
			||||||
import { BaseRelationFieldOptions, RelationField } from './relation-field';
 | 
					import { BaseRelationFieldOptions, RelationField } from './relation-field';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -16,20 +16,26 @@ export class BelongsToField extends RelationField {
 | 
				
			|||||||
    return target || Utils.pluralize(name);
 | 
					    return target || Utils.pluralize(name);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  static toReference(db, association, onDelete) {
 | 
					  static toReference(db, association, onDelete, priority: ReferencePriority = 'default'): Reference {
 | 
				
			||||||
    const targetKey = association.targetKey;
 | 
					    const targetKey = association.targetKey;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return {
 | 
					    return buildReference({
 | 
				
			||||||
      sourceCollectionName: db.modelCollection.get(association.source).name,
 | 
					      sourceCollectionName: db.modelCollection.get(association.source).name,
 | 
				
			||||||
      sourceField: association.foreignKey,
 | 
					      sourceField: association.foreignKey,
 | 
				
			||||||
      targetField: targetKey,
 | 
					      targetField: targetKey,
 | 
				
			||||||
      targetCollectionName: db.modelCollection.get(association.target).name,
 | 
					      targetCollectionName: db.modelCollection.get(association.target).name,
 | 
				
			||||||
      onDelete: onDelete,
 | 
					      onDelete: onDelete,
 | 
				
			||||||
    };
 | 
					      priority: priority,
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  reference(association): Reference {
 | 
					  reference(association): Reference {
 | 
				
			||||||
    return BelongsToField.toReference(this.database, association, this.options.onDelete);
 | 
					    return BelongsToField.toReference(
 | 
				
			||||||
 | 
					      this.database,
 | 
				
			||||||
 | 
					      association,
 | 
				
			||||||
 | 
					      this.options.onDelete,
 | 
				
			||||||
 | 
					      this.options.onDelete ? 'user' : 'default',
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  checkAssociationKeys() {
 | 
					  checkAssociationKeys() {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
import { omit } from 'lodash';
 | 
					import { omit } from 'lodash';
 | 
				
			||||||
import { AssociationScope, BelongsToManyOptions as SequelizeBelongsToManyOptions, Utils } from 'sequelize';
 | 
					import { AssociationScope, BelongsToManyOptions as SequelizeBelongsToManyOptions, Utils } from 'sequelize';
 | 
				
			||||||
import { Collection } from '../collection';
 | 
					import { Collection } from '../collection';
 | 
				
			||||||
import { Reference } from '../features/ReferencesMap';
 | 
					import { Reference } from '../features/references-map';
 | 
				
			||||||
import { checkIdentifier } from '../utils';
 | 
					import { checkIdentifier } from '../utils';
 | 
				
			||||||
import { BelongsToField } from './belongs-to-field';
 | 
					import { BelongsToField } from './belongs-to-field';
 | 
				
			||||||
import { MultipleRelationFieldOptions, RelationField } from './relation-field';
 | 
					import { MultipleRelationFieldOptions, RelationField } from './relation-field';
 | 
				
			||||||
@ -32,6 +32,8 @@ export class BelongsToManyField extends RelationField {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    const onDelete = this.options.onDelete || 'CASCADE';
 | 
					    const onDelete = this.options.onDelete || 'CASCADE';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const priority = this.options.onDelete ? 'user' : 'default';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const targetAssociation = association.toTarget;
 | 
					    const targetAssociation = association.toTarget;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (association.targetKey) {
 | 
					    if (association.targetKey) {
 | 
				
			||||||
@ -45,8 +47,8 @@ export class BelongsToManyField extends RelationField {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return [
 | 
					    return [
 | 
				
			||||||
      BelongsToField.toReference(db, targetAssociation, onDelete),
 | 
					      BelongsToField.toReference(db, targetAssociation, onDelete, priority),
 | 
				
			||||||
      BelongsToField.toReference(db, sourceAssociation, onDelete),
 | 
					      BelongsToField.toReference(db, sourceAssociation, onDelete, priority),
 | 
				
			||||||
    ];
 | 
					    ];
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -149,10 +151,6 @@ export class BelongsToManyField extends RelationField {
 | 
				
			|||||||
      Object.defineProperty(Through.model, 'isThrough', { value: true });
 | 
					      Object.defineProperty(Through.model, 'isThrough', { value: true });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!this.options.onDelete) {
 | 
					 | 
				
			||||||
      this.options.onDelete = 'CASCADE';
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const belongsToManyOptions = {
 | 
					    const belongsToManyOptions = {
 | 
				
			||||||
      constraints: false,
 | 
					      constraints: false,
 | 
				
			||||||
      ...omit(this.options, ['name', 'type', 'target']),
 | 
					      ...omit(this.options, ['name', 'type', 'target']),
 | 
				
			||||||
 | 
				
			|||||||
@ -8,7 +8,7 @@ import {
 | 
				
			|||||||
  Utils,
 | 
					  Utils,
 | 
				
			||||||
} from 'sequelize';
 | 
					} from 'sequelize';
 | 
				
			||||||
import { Collection } from '../collection';
 | 
					import { Collection } from '../collection';
 | 
				
			||||||
import { Reference } from '../features/ReferencesMap';
 | 
					import { buildReference, Reference } from '../features/references-map';
 | 
				
			||||||
import { checkIdentifier } from '../utils';
 | 
					import { checkIdentifier } from '../utils';
 | 
				
			||||||
import { MultipleRelationFieldOptions, RelationField } from './relation-field';
 | 
					import { MultipleRelationFieldOptions, RelationField } from './relation-field';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -89,13 +89,13 @@ export class HasManyField extends RelationField {
 | 
				
			|||||||
  reference(association): Reference {
 | 
					  reference(association): Reference {
 | 
				
			||||||
    const sourceKey = association.sourceKey;
 | 
					    const sourceKey = association.sourceKey;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return {
 | 
					    return buildReference({
 | 
				
			||||||
      sourceCollectionName: this.database.modelCollection.get(association.target).name,
 | 
					      sourceCollectionName: this.database.modelCollection.get(association.target).name,
 | 
				
			||||||
      sourceField: association.foreignKey,
 | 
					      sourceField: association.foreignKey,
 | 
				
			||||||
      targetField: sourceKey,
 | 
					      targetField: sourceKey,
 | 
				
			||||||
      targetCollectionName: this.database.modelCollection.get(association.source).name,
 | 
					      targetCollectionName: this.database.modelCollection.get(association.source).name,
 | 
				
			||||||
      onDelete: this.options.onDelete,
 | 
					      onDelete: this.options.onDelete,
 | 
				
			||||||
    };
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  checkAssociationKeys() {
 | 
					  checkAssociationKeys() {
 | 
				
			||||||
 | 
				
			|||||||
@ -8,7 +8,7 @@ import {
 | 
				
			|||||||
  Utils,
 | 
					  Utils,
 | 
				
			||||||
} from 'sequelize';
 | 
					} from 'sequelize';
 | 
				
			||||||
import { Collection } from '../collection';
 | 
					import { Collection } from '../collection';
 | 
				
			||||||
import { Reference } from '../features/ReferencesMap';
 | 
					import { buildReference, Reference } from '../features/references-map';
 | 
				
			||||||
import { checkIdentifier } from '../utils';
 | 
					import { checkIdentifier } from '../utils';
 | 
				
			||||||
import { BaseRelationFieldOptions, RelationField } from './relation-field';
 | 
					import { BaseRelationFieldOptions, RelationField } from './relation-field';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -98,13 +98,13 @@ export class HasOneField extends RelationField {
 | 
				
			|||||||
  reference(association): Reference {
 | 
					  reference(association): Reference {
 | 
				
			||||||
    const sourceKey = association.sourceKey;
 | 
					    const sourceKey = association.sourceKey;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return {
 | 
					    return buildReference({
 | 
				
			||||||
      sourceCollectionName: this.database.modelCollection.get(association.target).name,
 | 
					      sourceCollectionName: this.database.modelCollection.get(association.target).name,
 | 
				
			||||||
      sourceField: association.foreignKey,
 | 
					      sourceField: association.foreignKey,
 | 
				
			||||||
      targetField: sourceKey,
 | 
					      targetField: sourceKey,
 | 
				
			||||||
      targetCollectionName: this.database.modelCollection.get(association.source).name,
 | 
					      targetCollectionName: this.database.modelCollection.get(association.source).name,
 | 
				
			||||||
      onDelete: this.options.onDelete,
 | 
					      onDelete: this.options.onDelete,
 | 
				
			||||||
    };
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  checkAssociationKeys() {
 | 
					  checkAssociationKeys() {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user