blow-data
Version:
Data access layer for Blow.
116 lines (98 loc) • 3.38 kB
text/typescript
;
import {Observable} from 'rxjs';
import {isString} from 'util';
import {Connection} from './Connection';
import {ModelMetadata} from './ModelMetadata';
import {
IManager,
IBaseModel,
IBaseModelConstructor,
IPersistedModelConstructor,
IModelMetadataOptions,
IModelPropertyMetadataOptions,
IModelRelationMetadataOptions,
IModelMetadata,
IConnection,
IConnectionOptions
} from './interfaces';
export class Manager implements IManager {
protected _connections: Map<string, IConnection> = new Map();
protected _models: Map<string, IBaseModelConstructor> = new Map();
protected _applyMetadataToModels() {
for (const model of this._models.values()) {
if (!model.ready) {
model.metadata.apply(model);
model.ready = true;
}
}
}
protected _attachModelsToConnections() {
for (const model of this._models.values()) {
this.attachModelToConnection(model, model.metadata.connectionName);
}
}
attachModelToConnection(model: string | IBaseModelConstructor, connection: string | IConnection): void {
const model_ = isString(model) ? this.getModel(<string>model) : <IBaseModelConstructor>model;
const connection_: IConnection = isString(connection) ? this.getConnection(<string>connection) : <IConnection>connection;
if(connection_ && model_) {
connection_.attach(model_);
}
}
hasConnection(connectionName: string): boolean {
return this._connections.has(connectionName);
}
getConnection(connectionName: string): IConnection {
return this._connections.get(connectionName);
}
defineConnection(options: IConnectionOptions): IConnection {
const connection = Connection.create(options);
this._connections.set(connection.name, connection);
return connection;
}
hasModel(modelName: string): boolean {
return this._models.has(modelName);
}
getModel(modelName: string): IBaseModelConstructor {
return this._models.get(modelName);
}
defineModel(model: IBaseModelConstructor, options: IModelMetadataOptions, properties?: {[key: string]: IModelPropertyMetadataOptions}, relations?: {[key: string]: IModelRelationMetadataOptions}): void {
const metadata = new ModelMetadata(options, properties, relations);
Object.defineProperty(model, '_metadata', {
configurable: false,
writable: false,
enumerable: false,
value: metadata
});
this._models.set(options.name, model);
}
init(): Observable<Manager> {
return Observable.create(observer => {
if (this._connections.size) {
(<Observable<IConnection>>Observable.from(this._connections.values()))
.mergeMap(connection => {
if (connection.isConnected) {
return Observable.of(connection);
} else {
return connection.init();
}
})
.toArray()
.subscribe(
() => { },
error => {
throw new Error(error);
}, () => {
this._attachModelsToConnections();
this._applyMetadataToModels();
observer.next(this);
observer.complete();
}
);
} else {
observer.next(this);
observer.complete();
}
});
}
}
export const manager = new Manager();