tachybase_todo/packages/database-next/src/collection.ts

119 lines
2.8 KiB
TypeScript
Raw Normal View History

2021-09-27 15:28:32 +08:00
import { Sequelize, ModelCtor, Model, DataTypes, Utils } from 'sequelize';
import { EventEmitter } from 'events';
2021-09-18 00:23:21 +08:00
import { Database } from './database';
2021-09-27 15:28:32 +08:00
import { Field } from './fields';
2021-09-18 00:23:21 +08:00
import _ from 'lodash';
2021-09-25 23:56:26 +08:00
import { Repository } from './repository';
2021-09-18 00:23:21 +08:00
export interface CollectionOptions {
2021-09-27 15:28:32 +08:00
name: string;
tableName?: string;
fields?: any;
2021-09-18 00:23:21 +08:00
[key: string]: any;
}
export interface CollectionContext {
database: Database;
}
2021-09-27 15:28:32 +08:00
export class Collection extends EventEmitter {
2021-09-18 00:23:21 +08:00
options: CollectionOptions;
context: CollectionContext;
2021-09-27 15:28:32 +08:00
fields: Map<string, any>;
model: ModelCtor<Model>;
repository: Repository;
2021-09-18 00:23:21 +08:00
get name() {
return this.options.name;
}
2021-09-27 15:28:32 +08:00
constructor(options: CollectionOptions, context?: CollectionContext) {
super();
2021-09-18 00:23:21 +08:00
this.options = options;
this.context = context;
2021-09-27 15:28:32 +08:00
this.fields = new Map<string, any>();
2021-09-18 00:23:21 +08:00
this.model = class extends Model<any, any> {};
const attributes = {};
2021-09-27 15:28:32 +08:00
const { name, tableName } = options;
2021-09-23 00:16:04 +08:00
// TODO: 不能重复 model.init如果有涉及 InitOptions 参数修改,需要另外处理。
2021-09-18 00:23:21 +08:00
this.model.init(attributes, {
2021-09-27 15:28:32 +08:00
..._.omit(options, ['name', 'fields']),
2021-09-18 00:23:21 +08:00
sequelize: context.database.sequelize,
modelName: name,
tableName: tableName || name,
});
2021-09-27 15:28:32 +08:00
this.on('field.afterAdd', (field) => field.bind());
this.on('field.afterRemove', (field) => field.unbind());
this.setFields(options.fields);
2021-09-25 23:56:26 +08:00
this.repository = new Repository(this);
2021-09-18 00:23:21 +08:00
}
2021-09-27 15:28:32 +08:00
forEachField(callback: (field: Field) => void) {
return [...this.fields.values()].forEach(callback);
}
findField(callback: (field: Field) => boolean) {
return [...this.fields.values()].find(callback);
}
hasField(name: string) {
return this.fields.has(name);
}
getField(name: string) {
return this.fields.get(name);
}
addField(options) {
const { name, ...others } = options;
if (!name) {
return this;
}
const { database } = this.context;
const field = database.buildField({ name, ...others }, {
...this.context,
collection: this,
model: this.model,
2021-09-18 00:23:21 +08:00
});
2021-09-27 15:28:32 +08:00
this.fields.set(name, field);
this.emit('field.afterAdd', field);
}
setFields(fields: any, reset = true) {
if (!fields) {
return this;
}
if (reset) {
this.fields.clear();
}
if (Array.isArray(fields)) {
for (const field of fields) {
this.addField(field);
}
} else if (typeof fields === 'object') {
for (const [name, options] of Object.entries<any>(fields)) {
this.addField({...options, name});
}
}
}
removeField(name) {
const field = this.fields.get(name);
const bool = this.fields.delete(name);
if (bool) {
this.emit('field.afterRemove', field);
}
return bool;
}
// TODO
extend(options) {
const { fields } = options;
this.setFields(fields);
}
sync() {
2021-09-18 00:23:21 +08:00
}
}