mirror of
https://github.com/nocobase/nocobase
synced 2024-11-15 07:45:18 +00:00
feat: collection factory (#3047)
This commit is contained in:
parent
3aca9e05d9
commit
b497ef125e
@ -0,0 +1,40 @@
|
||||
import Database from '../database';
|
||||
import { mockDatabase } from './index';
|
||||
import { Collection } from '../collection';
|
||||
|
||||
describe('collection factory', function () {
|
||||
let db: Database;
|
||||
|
||||
beforeEach(async () => {
|
||||
db = mockDatabase();
|
||||
|
||||
await db.clean({ drop: true });
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await db.close();
|
||||
});
|
||||
|
||||
it('should register new collection type', async () => {
|
||||
class ChildCollection extends Collection {
|
||||
static type = 'child';
|
||||
}
|
||||
|
||||
db.collectionFactory.registerCollectionType(ChildCollection, (options) => {
|
||||
return options.child == true;
|
||||
});
|
||||
|
||||
const collection = db.collectionFactory.createCollection({
|
||||
name: 'child',
|
||||
child: true,
|
||||
});
|
||||
|
||||
expect(collection).toBeInstanceOf(ChildCollection);
|
||||
|
||||
const collection2 = db.collectionFactory.createCollection({
|
||||
name: 'collection',
|
||||
});
|
||||
|
||||
expect(collection2).toBeInstanceOf(Collection);
|
||||
});
|
||||
});
|
29
packages/core/database/src/collection-factory.ts
Normal file
29
packages/core/database/src/collection-factory.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import { Collection, CollectionOptions } from './collection';
|
||||
import Database from './database';
|
||||
|
||||
export class CollectionFactory {
|
||||
private collectionTypes: Array<{
|
||||
ctor: typeof Collection;
|
||||
condition: (options: CollectionOptions) => boolean;
|
||||
}> = [];
|
||||
|
||||
constructor(private database: Database) {}
|
||||
|
||||
registerCollectionType(collectionClass: typeof Collection, condition: (options: CollectionOptions) => boolean) {
|
||||
this.collectionTypes.push({ ctor: collectionClass, condition });
|
||||
}
|
||||
|
||||
createCollection<T extends Collection>(options: CollectionOptions): T {
|
||||
let klass = Collection;
|
||||
for (const { ctor, condition } of this.collectionTypes) {
|
||||
if (condition(options)) {
|
||||
klass = ctor;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return new klass(options, {
|
||||
database: this.database,
|
||||
}) as T;
|
||||
}
|
||||
}
|
@ -72,6 +72,7 @@ import {
|
||||
import { patchSequelizeQueryInterface, snakeCase } from './utils';
|
||||
import { BaseValueParser, registerFieldValueParsers } from './value-parsers';
|
||||
import { ViewCollection } from './view-collection';
|
||||
import { CollectionFactory } from './collection-factory';
|
||||
|
||||
export type MergeOptions = merge.Options;
|
||||
|
||||
@ -177,23 +178,17 @@ export class Database extends EventEmitter implements AsyncEmitter {
|
||||
tableNameCollectionMap = new Map<string, Collection>();
|
||||
context: any = {};
|
||||
queryInterface: QueryInterface;
|
||||
|
||||
_instanceId: string;
|
||||
|
||||
utils = new DatabaseUtils(this);
|
||||
referenceMap = new ReferencesMap();
|
||||
inheritanceMap = new InheritanceMap();
|
||||
|
||||
importedFrom = new Map<string, Array<string>>();
|
||||
|
||||
modelHook: ModelHook;
|
||||
version: DatabaseVersion;
|
||||
|
||||
delayCollectionExtend = new Map<string, { collectionOptions: CollectionOptions; mergeOptions?: any }[]>();
|
||||
|
||||
logger: Logger;
|
||||
|
||||
collectionGroupManager = new CollectionGroupManager(this);
|
||||
|
||||
collectionFactory: CollectionFactory = new CollectionFactory(this);
|
||||
declare emitAsync: (event: string | symbol, ...args: any[]) => Promise<boolean>;
|
||||
|
||||
constructor(options: DatabaseOptions) {
|
||||
@ -307,12 +302,30 @@ export class Database extends EventEmitter implements AsyncEmitter {
|
||||
|
||||
this.initListener();
|
||||
patchSequelizeQueryInterface(this);
|
||||
|
||||
this.registerCollectionType();
|
||||
}
|
||||
|
||||
_instanceId: string;
|
||||
|
||||
get instanceId() {
|
||||
return this._instanceId;
|
||||
}
|
||||
|
||||
registerCollectionType() {
|
||||
this.collectionFactory.registerCollectionType(InheritedCollection, (options) => {
|
||||
return options.inherits && lodash.castArray(options.inherits).length > 0;
|
||||
});
|
||||
|
||||
this.collectionFactory.registerCollectionType(ViewCollection, (options) => {
|
||||
return options.viewName || options.view;
|
||||
});
|
||||
|
||||
this.collectionFactory.registerCollectionType(SqlCollection, (options) => {
|
||||
return options.sql;
|
||||
});
|
||||
}
|
||||
|
||||
setContext(context: any) {
|
||||
this.context = context;
|
||||
}
|
||||
@ -447,10 +460,6 @@ export class Database extends EventEmitter implements AsyncEmitter {
|
||||
return dialect.includes(this.sequelize.getDialect());
|
||||
}
|
||||
|
||||
escapeId(identifier: string) {
|
||||
return this.inDialect('mysql') ? `\`${identifier}\`` : `"${identifier}"`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add collection to database
|
||||
* @param options
|
||||
@ -466,29 +475,7 @@ export class Database extends EventEmitter implements AsyncEmitter {
|
||||
|
||||
this.emit('beforeDefineCollection', options);
|
||||
|
||||
const hasValidInheritsOptions = (() => {
|
||||
return options.inherits && lodash.castArray(options.inherits).length > 0;
|
||||
})();
|
||||
|
||||
const hasViewOptions = options.viewName || options.view;
|
||||
|
||||
const collectionKlass = (() => {
|
||||
if (hasValidInheritsOptions) {
|
||||
return InheritedCollection;
|
||||
}
|
||||
|
||||
if (hasViewOptions) {
|
||||
return ViewCollection;
|
||||
}
|
||||
|
||||
if (options.sql) {
|
||||
return SqlCollection;
|
||||
}
|
||||
|
||||
return Collection;
|
||||
})();
|
||||
|
||||
const collection = new collectionKlass(options, { database: this });
|
||||
const collection = this.collectionFactory.createCollection(options);
|
||||
|
||||
this.collections.set(collection.name, collection);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user