diff --git a/packages/core/database/src/collection.ts b/packages/core/database/src/collection.ts index 08584de5d..0b3a3d3b7 100644 --- a/packages/core/database/src/collection.ts +++ b/packages/core/database/src/collection.ts @@ -79,6 +79,31 @@ export class Collection< model: ModelStatic; repository: Repository; + constructor(options: CollectionOptions, context: CollectionContext) { + super(); + this.context = context; + this.options = options; + + this.checkOptions(options); + + this.bindFieldEventListener(); + this.modelInit(); + + this.db.modelCollection.set(this.model, this); + + // set tableName to collection map + // the form of key is `${schema}.${tableName}` if schema exists + // otherwise is `${tableName}` + this.db.tableNameCollectionMap.set(this.getTableNameWithSchemaAsString(), this); + + if (!options.inherits) { + this.setFields(options.fields); + } + + this.setRepository(options.repository); + this.setSortable(options.sortable); + } + get filterTargetKey() { const targetKey = lodash.get(this.options, 'filterTargetKey', this.model.primaryKeyAttribute); if (!targetKey && this.model.rawAttributes['id']) { @@ -116,65 +141,12 @@ export class Collection< } } - constructor(options: CollectionOptions, context: CollectionContext) { - super(); - this.context = context; - this.options = options; - - this.checkOptions(options); - - this.bindFieldEventListener(); - this.modelInit(); - - this.db.modelCollection.set(this.model, this); - - // set tableName to collection map - // the form of key is `${schema}.${tableName}` if schema exists - // otherwise is `${tableName}` - this.db.tableNameCollectionMap.set(this.getTableNameWithSchemaAsString(), this); - - if (!options.inherits) { - this.setFields(options.fields); - } - - this.setRepository(options.repository); - this.setSortable(options.sortable); - } - - private checkOptions(options: CollectionOptions) { - checkIdentifier(options.name); - this.checkTableName(); - } - - private checkTableName() { - const tableName = this.tableName(); - for (const [k, collection] of this.db.collections) { - if ( - collection.name != this.options.name && - tableName === collection.tableName() && - collection.collectionSchema() === this.collectionSchema() - ) { - throw new Error(`collection ${collection.name} and ${this.name} have same tableName "${tableName}"`); - } - } - } - tableName() { const { name, tableName } = this.options; const tName = tableName || name; return this.options.underscored ? snakeCase(tName) : tName; } - protected sequelizeModelOptions() { - const { name } = this.options; - return { - ..._.omit(this.options, ['name', 'fields', 'model', 'targetKey']), - modelName: name, - sequelize: this.context.database.sequelize, - tableName: this.tableName(), - }; - } - /** * TODO */ @@ -232,17 +204,6 @@ export class Collection< this.repository = new repo(this); } - private bindFieldEventListener() { - this.on('field.afterAdd', (field: Field) => { - field.bind(); - }); - - this.on('field.afterRemove', (field: Field) => { - field.unbind(); - this.db.emit('field.afterRemove', field); - }); - } - forEachField(callback: (field: Field) => void) { return [...this.fields.values()].forEach(callback); } @@ -299,12 +260,20 @@ export class Collection< const [sourceCollectionName, sourceFieldName] = options.source.split('.'); const sourceCollection = this.db.collections.get(sourceCollectionName); if (!sourceCollection) { - throw new Error( + this.db.logger.warn( `source collection "${sourceCollectionName}" not found for field "${name}" at collection "${this.name}"`, ); } + const sourceField = sourceCollection.fields.get(sourceFieldName); - options = { ...sourceField.options, ...options }; + + if (!sourceField) { + this.db.logger.warn( + `source field "${sourceFieldName}" not found for field "${name}" at collection "${this.name}"`, + ); + } else { + options = { ...sourceField.options, ...options }; + } } this.emit('field.beforeAdd', name, options, { collection: this }); @@ -678,4 +647,43 @@ export class Collection< public isView() { return false; } + + protected sequelizeModelOptions() { + const { name } = this.options; + return { + ..._.omit(this.options, ['name', 'fields', 'model', 'targetKey']), + modelName: name, + sequelize: this.context.database.sequelize, + tableName: this.tableName(), + }; + } + + private checkOptions(options: CollectionOptions) { + checkIdentifier(options.name); + this.checkTableName(); + } + + private checkTableName() { + const tableName = this.tableName(); + for (const [k, collection] of this.db.collections) { + if ( + collection.name != this.options.name && + tableName === collection.tableName() && + collection.collectionSchema() === this.collectionSchema() + ) { + throw new Error(`collection ${collection.name} and ${this.name} have same tableName "${tableName}"`); + } + } + } + + private bindFieldEventListener() { + this.on('field.afterAdd', (field: Field) => { + field.bind(); + }); + + this.on('field.afterRemove', (field: Field) => { + field.unbind(); + this.db.emit('field.afterRemove', field); + }); + } }