mirror of
https://gitee.com/nocobase/nocobase.git
synced 2025-05-05 13:39:24 +08:00
* FIX: database test with sqlite * more types * filter test * split filter parser * filter test * filter test: hasMany * define inverse association for belongsTo & hasMany * chore: console.log * repository count method * chore: Collection * repository filter & appends & fields & expect * repository: sort option * chore: test * add: test * find & findAndCount * chore: test * database-next: update guard * database-next: update guard associationKeysToBeUpdate * chore: comment * update-guard OneToOne Association * has one repository * support through table value * belongs to many repository * has many repository * has many repository find * fix: has many find and count * clean code * add count method * chore: multiple relation * chore: single relation * repository find * relation repository builder * repository count * repository count test * fix test * close db afterEach test * sort with associations * repository update * has many repository: destroy * belongs to many repository: destroy * add transaction decorator * belongs to many with transaction * has many with transaction * clean types * clean types * clean types * repository transaction * fix test * single relation repository with transaction * single relation repository with transaction * fix: test * fix: option parser fields append * fix: typo * fix: string type * fix: import * collection field methods * cleanup * collection sync * fix: import * fix: test * collection update field * collection update options * database hook * database test * database event test * update database event * add async emmit mixin * async model event * database import * fix: model hook type * fix: collection event * recall model.init on collection update * skip redefine collection test * skip collection model update * add model hook class * global model event support * chore * chore * change utils import * add field types * database import * more import test * test case * fix: through model init... * bugfix * fix * update database import * collection sync by foreachModel * fix collection model sync * update * add field types * custom operator * sqlite array field * postgresql array field * array query escape * mysql array operators * date operators * array field sqlite fix * association operator * date operator empty & notEmpty * fix: fields import * fix array field nested association * filter parse prepare * fix test * string field empty * add date operator test * field option types * fix typo * fix: operator name conflict * rename function Co-authored-by: Chareice <chareice@live.com>
82 lines
2.5 KiB
TypeScript
82 lines
2.5 KiB
TypeScript
import { omit } from 'lodash';
|
|
import { Sequelize, ModelCtor, Model, DataTypes, Utils } from 'sequelize';
|
|
import { BaseRelationFieldOptions, RelationField } from './relation-field';
|
|
import { HasInverseField } from './has-inverse-field';
|
|
import { BaseColumnFieldOptions, Field } from './field';
|
|
import { HasManyField } from './has-many-field';
|
|
import { BelongsToOptions as SequelizeBelongsToOptions } from 'sequelize/types/lib/associations/belongs-to';
|
|
|
|
export class BelongsToField extends RelationField {
|
|
static type = 'belongsTo';
|
|
|
|
get target() {
|
|
const { target, name } = this.options;
|
|
return target || Utils.pluralize(name);
|
|
}
|
|
|
|
bind() {
|
|
const { database, collection } = this.context;
|
|
const Target = this.TargetModel;
|
|
|
|
// if target model not exists, add it to pending field,
|
|
// it will bind later
|
|
if (!Target) {
|
|
database.addPendingField(this);
|
|
return false;
|
|
}
|
|
|
|
if (collection.model.associations[this.name]) {
|
|
delete collection.model.associations[this.name];
|
|
}
|
|
|
|
// define relation on sequelize model
|
|
const association = collection.model.belongsTo(Target, {
|
|
as: this.name,
|
|
...omit(this.options, ['name', 'type', 'target']),
|
|
});
|
|
|
|
// inverse relation
|
|
this.TargetModel.hasMany(collection.model);
|
|
|
|
// 建立关系之后从 pending 列表中删除
|
|
database.removePendingField(this);
|
|
|
|
if (!this.options.foreignKey) {
|
|
this.options.foreignKey = association.foreignKey;
|
|
}
|
|
|
|
if (!this.options.sourceKey) {
|
|
// @ts-ignore
|
|
this.options.sourceKey = association.sourceKey;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
unbind() {
|
|
const { database, collection } = this.context;
|
|
// 如果关系字段还没建立就删除了,也同步删除待建立关联的关系字段
|
|
database.removePendingField(this);
|
|
// 如果外键没有显式的创建,关系表也无反向关联字段,删除关系时,外键也删除掉
|
|
const tcoll = database.collections.get(this.target);
|
|
const foreignKey = this.options.foreignKey;
|
|
const field1 = collection.getField(foreignKey);
|
|
const field2 = tcoll.findField((field) => {
|
|
return field.type === 'hasMany' && field.foreignKey === foreignKey;
|
|
});
|
|
if (!field1 && !field2) {
|
|
collection.model.removeAttribute(foreignKey);
|
|
}
|
|
// 删掉 model 的关联字段
|
|
delete collection.model.associations[this.name];
|
|
// @ts-ignore
|
|
collection.model.refreshAttributes();
|
|
}
|
|
}
|
|
|
|
export interface BelongsToFieldOptions
|
|
extends BaseRelationFieldOptions,
|
|
SequelizeBelongsToOptions {
|
|
type: 'belongsTo';
|
|
}
|