tachybase_todo/packages/database/src/relation-repository/relation-repository.ts
chenos bf2840b089
feat: context field type support (#131)
* feat: context field type support

* fix: missing options
2021-12-07 21:19:28 +08:00

82 lines
2.5 KiB
TypeScript

import { Association, BelongsTo, BelongsToMany, HasMany, HasOne, Model, ModelCtor, Transaction } from 'sequelize';
import { OptionsParser } from '../options-parser';
import { Collection } from '../collection';
import { CreateOptions, Filter, FindOptions } from '../repository';
import FilterParser from '../filter-parser';
import { UpdateGuard } from '../update-guard';
import { updateAssociations } from '../update-associations';
import lodash from 'lodash';
import { transactionWrapperBuilder } from '../transaction-decorator';
export const transaction = transactionWrapperBuilder(function () {
return this.source.model.sequelize.transaction();
});
export abstract class RelationRepository {
source: Collection;
association: Association;
target: ModelCtor<any>;
sourceId: string | number;
sourceModel: Model;
constructor(source: Collection, association: string, sourceId: string | number) {
this.source = source;
this.sourceId = sourceId;
this.association = this.source.model.associations[association];
this.target = this.association.target;
}
protected accessors() {
return (<BelongsTo | HasOne | HasMany | BelongsToMany>this.association).accessors;
}
async create(options?: CreateOptions): Promise<any> {
const createAccessor = this.accessors().create;
const guard = UpdateGuard.fromOptions(this.target, options);
const values = options.values;
const sourceModel = await this.getSourceModel();
const instance = await sourceModel[createAccessor](guard.sanitize(options.values), options);
await updateAssociations(instance, values, options);
return instance;
}
async getSourceModel(transaction?: any) {
if (!this.sourceModel) {
this.sourceModel = await this.source.model.findByPk(this.sourceId, {
transaction,
});
}
return this.sourceModel;
}
protected buildQueryOptions(options: FindOptions) {
const parser = new OptionsParser(this.target, this.source.context.database, options);
const params = parser.toSequelizeParams();
return { ...options, ...params };
}
protected parseFilter(filter: Filter) {
const parser = new FilterParser(this.target, this.source.context.database, filter);
return parser.toSequelizeParams();
}
protected async getTransaction(options: any, autoGen = false): Promise<Transaction | null> {
if (lodash.isPlainObject(options) && options.transaction) {
return options.transaction;
}
if (autoGen) {
return await this.source.model.sequelize.transaction();
}
return null;
}
}