Added a registry to hold all of the factories and adapters
This commit is contained in:
parent
627bd5a99a
commit
e6e764320b
|
@ -1,5 +1,8 @@
|
|||
import { Model } from '../models/model';
|
||||
|
||||
/**
|
||||
* An interface for implementing adapters to create models.
|
||||
*/
|
||||
export interface Adapter<T extends Model> {
|
||||
/**
|
||||
* Creates a model or array of models using a service..
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
import { AdapterTypes, FactoryRegistry } from './factory-registry';
|
||||
import { ModelFactory } from './model-factory';
|
||||
import { Product } from '../models/product';
|
||||
import { APIAdapter } from './api-adapter';
|
||||
|
||||
describe( 'FactoryRegistry', () => {
|
||||
let factoryRegistry: FactoryRegistry;
|
||||
|
||||
beforeEach( () => {
|
||||
factoryRegistry = new FactoryRegistry();
|
||||
} );
|
||||
|
||||
it( 'should register factories once', () => {
|
||||
const factory = ModelFactory.define<Product, any, ModelFactory<Product>>( ( { params } ) => {
|
||||
return new Product( params );
|
||||
} );
|
||||
|
||||
expect( factoryRegistry.getFactory( Product ) ).toBeNull();
|
||||
|
||||
factoryRegistry.registerFactory( Product, factory );
|
||||
|
||||
expect( () => factoryRegistry.registerFactory( Product, factory ) ).toThrowError( /already been registered/ );
|
||||
|
||||
const loaded = factoryRegistry.getFactory( Product );
|
||||
|
||||
expect( loaded ).toBe( factory );
|
||||
} );
|
||||
|
||||
it( 'should register adapters once', () => {
|
||||
const adapter = new APIAdapter<Product>( '', ( model ) => model );
|
||||
|
||||
expect( factoryRegistry.getAdapter( Product, AdapterTypes.API ) ).toBeNull();
|
||||
|
||||
factoryRegistry.registerAdapter( Product, AdapterTypes.API, adapter );
|
||||
|
||||
expect( () => factoryRegistry.registerAdapter( Product, AdapterTypes.API, adapter ) ).toThrowError( /already been registered/ );
|
||||
|
||||
const loaded = factoryRegistry.getAdapter( Product, AdapterTypes.API );
|
||||
|
||||
expect( loaded ).toBe( adapter );
|
||||
} );
|
||||
} );
|
|
@ -0,0 +1,87 @@
|
|||
import { Adapter } from './adapter';
|
||||
import { Model } from '../models/model';
|
||||
import { ModelFactory } from './model-factory';
|
||||
|
||||
type Registry<T> = { [key: string ]: T };
|
||||
|
||||
/**
|
||||
* The types of adapters that can be stored in the registry.
|
||||
*
|
||||
* @typedef AdapterTypes
|
||||
* @property {string} API "api"
|
||||
* @property {string} Database "database"
|
||||
* @property {string} Custom "custom"
|
||||
*/
|
||||
export enum AdapterTypes {
|
||||
API = 'api',
|
||||
Database = 'database',
|
||||
Custom = 'custom'
|
||||
}
|
||||
|
||||
/**
|
||||
* A registry that allows for us to easily manage all of our factories and related state.
|
||||
*/
|
||||
export class FactoryRegistry {
|
||||
private readonly registry: Registry<ModelFactory<any>> = {};
|
||||
private readonly adapters: { [key in AdapterTypes]: Registry<Adapter<any>> } = {
|
||||
api: {},
|
||||
database: {},
|
||||
custom: {},
|
||||
};
|
||||
|
||||
/**
|
||||
* Registers a factory for the class.
|
||||
*
|
||||
* @param {Function} modelClass The class of model we're registering the factory for.
|
||||
* @param {ModelFactory} factory The factory that we're registering.
|
||||
*/
|
||||
public registerFactory<T extends Model>( modelClass: new () => T, factory: ModelFactory<T> ): void {
|
||||
if ( this.registry.hasOwnProperty( modelClass.name ) ) {
|
||||
throw new Error( 'A factory of this type has already been registered for the model class.' );
|
||||
}
|
||||
|
||||
this.registry[ modelClass.name ] = factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a factory that was registered for the class.
|
||||
*
|
||||
* @param {Function} modelClass The class of model for the factory we're fetching.
|
||||
*/
|
||||
public getFactory<T extends Model>( modelClass: new () => T ): ModelFactory<T> | null {
|
||||
if ( this.registry.hasOwnProperty( modelClass.name ) ) {
|
||||
return this.registry[ modelClass.name ];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers an adapter for the class.
|
||||
*
|
||||
* @param {Function} modelClass The class of model that we're registering the adapter for.
|
||||
* @param {AdapterTypes} type The type of adapter that we're registering.
|
||||
* @param {Adapter} adapter The adapter that we're registering.
|
||||
*/
|
||||
public registerAdapter<T extends Model>( modelClass: new () => T, type: AdapterTypes, adapter: Adapter<T> ): void {
|
||||
if ( this.adapters[ type ].hasOwnProperty( modelClass.name ) ) {
|
||||
throw new Error( 'An adapter of this type has already been registered for the model class.' );
|
||||
}
|
||||
|
||||
this.adapters[ type ][ modelClass.name ] = adapter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches an adapter registered for the class.
|
||||
*
|
||||
* @param {Function} modelClass The class of the model for the adapter we're fetching.
|
||||
* @param {AdapterTypes} type The type of adapter we're fetching.
|
||||
*/
|
||||
public getAdapter<T extends Model>( modelClass: new () => T, type: AdapterTypes ): Adapter<T> | null {
|
||||
if ( this.adapters[ type ].hasOwnProperty( modelClass.name ) ) {
|
||||
return this.adapters[ type ][ modelClass.name ];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue