diff --git a/packages/core/database/src/__tests__/collection-factory.test.ts b/packages/core/database/src/__tests__/collection-factory.test.ts index e5022b294..ffbef3297 100644 --- a/packages/core/database/src/__tests__/collection-factory.test.ts +++ b/packages/core/database/src/__tests__/collection-factory.test.ts @@ -20,8 +20,8 @@ describe('collection factory', function () { static type = 'child'; } - db.collectionFactory.registerCollectionType(ChildCollection, (options) => { - return options.child == true; + db.collectionFactory.registerCollectionType(ChildCollection, { + condition: (options) => options.child, }); const collection = db.collectionFactory.createCollection({ @@ -37,4 +37,27 @@ describe('collection factory', function () { expect(collection2).toBeInstanceOf(Collection); }); + + it('should register collection type with sync logic', async () => { + class ChildCollection extends Collection { + static type = 'child'; + } + + const fn = jest.fn(); + + db.collectionFactory.registerCollectionType(ChildCollection, { + condition: (options) => options.child, + onSync(model, options) { + fn(); + }, + }); + + const collection = db.collectionFactory.createCollection({ + name: 'child', + child: true, + }); + + await collection.sync(); + expect(fn).toHaveBeenCalledTimes(1); + }); }); diff --git a/packages/core/database/src/collection-factory.ts b/packages/core/database/src/collection-factory.ts index 56a31d942..5d3324e39 100644 --- a/packages/core/database/src/collection-factory.ts +++ b/packages/core/database/src/collection-factory.ts @@ -1,28 +1,38 @@ import { Collection, CollectionOptions } from './collection'; import Database from './database'; +import { Model } from './model'; + +type CollectionTypeOptions = { + condition: (options: CollectionOptions) => boolean; + onSync?: (model: typeof Model, options: any) => Promise; +}; export class CollectionFactory { - private collectionTypes: Array<{ - ctor: typeof Collection; - condition: (options: CollectionOptions) => boolean; - }> = []; + // Using a Map with the collection subclass as the key and options as the value + public collectionTypes: Map = new Map(); constructor(private database: Database) {} - registerCollectionType(collectionClass: typeof Collection, condition: (options: CollectionOptions) => boolean) { - this.collectionTypes.push({ ctor: collectionClass, condition }); + registerCollectionType( + collectionClass: typeof Collection, // Using the collection class as the key + options: CollectionTypeOptions, + ) { + // Storing the options associated with the collection class + this.collectionTypes.set(collectionClass, options); } - createCollection(options: CollectionOptions): T { - let klass = Collection; - for (const { ctor, condition } of this.collectionTypes) { - if (condition(options)) { + createCollection(collectionOptions: CollectionOptions): T { + let klass: typeof Collection = Collection; + + // Iterating over the map to find the right class based on the condition + for (const [ctor, options] of this.collectionTypes) { + if (options.condition(collectionOptions)) { klass = ctor; break; } } - return new klass(options, { + return new klass(collectionOptions, { database: this.database, }) as T; } diff --git a/packages/core/database/src/database.ts b/packages/core/database/src/database.ts index 613f5386a..9809254f9 100644 --- a/packages/core/database/src/database.ts +++ b/packages/core/database/src/database.ts @@ -313,16 +313,22 @@ export class Database extends EventEmitter implements AsyncEmitter { } registerCollectionType() { - this.collectionFactory.registerCollectionType(InheritedCollection, (options) => { - return options.inherits && lodash.castArray(options.inherits).length > 0; + this.collectionFactory.registerCollectionType(InheritedCollection, { + condition: (options) => { + return options.inherits && lodash.castArray(options.inherits).length > 0; + }, }); - this.collectionFactory.registerCollectionType(ViewCollection, (options) => { - return options.viewName || options.view; + this.collectionFactory.registerCollectionType(ViewCollection, { + condition: (options) => { + return options.viewName || options.view; + }, }); - this.collectionFactory.registerCollectionType(SqlCollection, (options) => { - return options.sql; + this.collectionFactory.registerCollectionType(SqlCollection, { + condition: (options) => { + return options.sql; + }, }); } diff --git a/packages/core/database/src/model.ts b/packages/core/database/src/model.ts index 4cec90e6b..ef1f4eee3 100644 --- a/packages/core/database/src/model.ts +++ b/packages/core/database/src/model.ts @@ -31,6 +31,69 @@ export class Model