Skip to content

Commit

Permalink
refactor(bootstrap): Fix issues with the registration of metadata not…
Browse files Browse the repository at this point in the history
… going to the correct static constructor, implement migration bootstrapping
  • Loading branch information
zakhenry committed Jun 29, 2016
1 parent 575bec9 commit 7645592
Show file tree
Hide file tree
Showing 13 changed files with 73 additions and 39 deletions.
10 changes: 3 additions & 7 deletions src/common/metadata/metadata.ts
@@ -1,7 +1,7 @@
import { TableOptions } from 'typeorm/decorator/options/TableOptions';
import { RelationType, Relation } from '../models/relations/index';
import { ModelConstructor } from '../models/model';
import { RegistryEntity } from '../registry/entityRegistry';
import { RegistryEntityConstructor } from '../registry/entityRegistry';

export interface ModelMetadata {
storageKey?: string;
Expand All @@ -11,12 +11,8 @@ export interface ModelMetadata {
identifierKey?:string;
}

export interface RegistryEntityConstructor extends Function {
constructor: RegistryEntity;
}

export function initializeMetadata(target: RegistryEntityConstructor) {
if (!target.constructor.__metadata) {
target.constructor.__metadata = {};
if (!target.__metadata) {
target.__metadata = {};
}
}
6 changes: 3 additions & 3 deletions src/common/models/model.ts
@@ -1,6 +1,6 @@
import { Collection } from './collection';

import { RegistryEntity } from '../registry/entityRegistry';
import { RegistryEntityConstructor } from '../registry/entityRegistry';
import { RelationType, Relation } from './relations/index';
import { ModelMetadata } from '../metadata/metadata';

Expand All @@ -23,7 +23,7 @@ export interface ModelConstructor<T extends BaseModel> extends Function {
constructor: ModelStatic<T>;
}

export interface ModelStatic<T extends BaseModel> extends RegistryEntity {
export interface ModelStatic<T extends BaseModel> extends RegistryEntityConstructor {
new(data?: any, exists?: boolean): T;
prototype: T;
}
Expand Down Expand Up @@ -60,7 +60,7 @@ export abstract class BaseModel {
* @returns {ModelMetadata}
*/
public static getMetadata(): ModelMetadata {
return (this.constructor as ModelStatic<any>).__metadata;
return this.__metadata;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/common/models/relations/index.ts
Expand Up @@ -9,7 +9,7 @@ export interface Relation {
}

export function initializeRelationMap(target: ModelConstructor<any>, type: RelationType) {
initializeMetadata(target);
initializeMetadata(target.constructor);

if (!target.constructor.__metadata.relations) {
target.constructor.__metadata.relations = new Map();
Expand Down
4 changes: 2 additions & 2 deletions src/common/models/types/primary.decorator.ts
@@ -1,7 +1,7 @@
// import { PrimaryColumn } from 'typeorm/columns';
// import {ColumnType} from 'typeorm/metadata/types/ColumnTypes'
// import {ColumnOptions} from 'typeorm/decorator/options/ColumnOptions';
import { ModelConstructor } from '../model';
import { ModelConstructor, ModelStatic } from '../model';
import { initializeMetadata } from '../../metadata/metadata';
export type ColumnType = any;
export type ColumnOptions = any;
Expand All @@ -13,7 +13,7 @@ export function Primary(typeOrOptions?: ColumnType|ColumnOptions, options?: Colu

return function primary(target: ModelConstructor<any>, propertyKey: string) {

initializeMetadata(target);
initializeMetadata(target.constructor);
target.constructor.__metadata.identifierKey = propertyKey;
};

Expand Down
8 changes: 4 additions & 4 deletions src/common/registry/decorators.ts
@@ -1,13 +1,13 @@
import { registry, EntityType, RegistryEntity, EntityMetadata } from './entityRegistry';
import { registry, EntityType, RegistryEntityConstructor, EntityMetadata } from './entityRegistry';
import { ModelMetadata } from '../metadata/metadata';

function entityRegistryFunction(type: EntityType, metadata?:EntityMetadata) {
function entityRegistryFunction(type: EntityType, metadata?: EntityMetadata): ClassDecorator {
return function <TFunction extends Function>(target: TFunction): void {
registry.register(type, (target as RegistryEntity), metadata);
registry.register(type, target.prototype.constructor, metadata);
}
}

export function Model(metadata?:ModelMetadata): ClassDecorator {
export function Model(metadata?: ModelMetadata): ClassDecorator {

return entityRegistryFunction('model', metadata);
}
Expand Down
18 changes: 9 additions & 9 deletions src/common/registry/entityRegistry.ts
Expand Up @@ -4,19 +4,19 @@ import { ModelMetadata, initializeMetadata } from '../metadata/metadata';
export type EntityType = 'model' | 'controller' | 'seeder' | 'middleware' | 'migration' | 'store';
export type EntityMetadata = ModelMetadata /* | <list other metadata types>*/;

export interface RegistryEntity extends Function {
export interface RegistryEntityConstructor extends Function {
__metadata?:EntityMetadata;
getMetadata?():EntityMetadata;
}

export class EntityRegistry {

protected registry: Map<EntityType, Map<string, RegistryEntity>> = new Map();
protected registry: Map<EntityType, Map<string, RegistryEntityConstructor>> = new Map();

constructor() {
}

public register<T extends RegistryEntity>(type: EntityType, entity: T, metadata?:any): this {
public register(type: EntityType, entity: RegistryEntityConstructor, metadata?:any): this {

if (!this.registry.get(type)) {
this.registry.set(type, new Map());
Expand All @@ -26,15 +26,15 @@ export class EntityRegistry {

if (metadata){
initializeMetadata(entity);
_.merge((entity.constructor as RegistryEntity).__metadata, metadata);
_.merge((entity).__metadata, metadata);
}

typeRegistry.set(entity.name, entity);

return this;
}

public getAllOfType(type: EntityType): Map<string, RegistryEntity> {
public getAllOfType(type: EntityType): Map<string, RegistryEntityConstructor> {
if (!this.registry.has(type)) {
return new Map();
}
Expand Down Expand Up @@ -62,15 +62,15 @@ export class EntityRegistry {
return !!this.findByType(type, name);
}

public findByType(type: EntityType, name: string): RegistryEntity {
public findByType(type: EntityType, name: string): RegistryEntityConstructor {
return this.getAllOfType(type)
.get(name);
}

public findAllWithName(name: string): Map<EntityType, RegistryEntity> | null {
public findAllWithName(name: string): Map<EntityType, RegistryEntityConstructor> | null {

let found: Map<EntityType, RegistryEntity> = new Map();
this.registry.forEach((entitySet: Map<string, RegistryEntity>, key: EntityType) => {
let found: Map<EntityType, RegistryEntityConstructor> = new Map();
this.registry.forEach((entitySet: Map<string, RegistryEntityConstructor>, key: EntityType) => {
let search = entitySet.get(name);
if (search) {
found.set(key, search);
Expand Down
4 changes: 2 additions & 2 deletions src/server/bootstrap/entity.bootstrapper.ts
Expand Up @@ -2,7 +2,7 @@ import 'core-js';
import 'reflect-metadata';
import { ReflectiveInjector, ResolvedReflectiveProvider } from '@angular/core';
import { Logger } from '../../common/services/logger.service';
import { registry, EntityType, RegistryEntity } from '../../common/registry/entityRegistry';
import { registry, EntityType, RegistryEntityConstructor } from '../../common/registry/entityRegistry';

export abstract class EntityBootstrapper {

Expand All @@ -20,7 +20,7 @@ export abstract class EntityBootstrapper {

protected abstract bootstrap(): void | Promise<void>;

protected getFromRegistry(type: EntityType): RegistryEntity[] {
protected getFromRegistry(type: EntityType): RegistryEntityConstructor[] {
return [
...registry.getAllOfType(type)
.values()
Expand Down
3 changes: 2 additions & 1 deletion src/server/bootstrap/index.ts
Expand Up @@ -10,6 +10,7 @@ import { ControllerBootstrapper } from './controllers.bootstrapper';
import { ModelBootstrapper } from './models.bootstrapper';
import { SeederBootstrapper } from './seeders.bootstrapper';
import { EntityBootstrapper } from './entity.bootstrapper';
import { MigrationBootstrapper } from './migration.bootstrapper';

export type ProviderType = Type | Provider | {
[k: string]: any;
Expand Down Expand Up @@ -75,14 +76,14 @@ export function bootstrap(loadClasses: ClassDictionary<any>[], providers: Provid
return (): Promise<BootstrapResponse> => {

deferredLog('info', 'Bootstrapping server');
console.log('awaiting deferred providers');

return Promise.all(providers)
.then((providers: ProviderType[]) => {

//initialize all bootstrappers (in order they need to be created)
const resolvedBootstrappers:EntityBootstrapper[] = [
new ModelBootstrapper,
new MigrationBootstrapper,
new SeederBootstrapper,
new ControllerBootstrapper,
];
Expand Down
25 changes: 25 additions & 0 deletions src/server/bootstrap/migration.bootstrapper.ts
@@ -0,0 +1,25 @@
import { ResolvedReflectiveProvider } from '@angular/core';
import { EntityBootstrapper } from './entity.bootstrapper';
import { BaseMigration } from '../migrations/index';

export class MigrationBootstrapper extends EntityBootstrapper {

public getResolvedEntities(): ResolvedReflectiveProvider[] {
return this.getResolvedFromRegistry('migration');
}

public bootstrap(): Promise<void> {

this.logger.debug(`Running [${this.resolvedEntityProviders.length}] migrations`);

const allMigrationPromises = this.resolvedEntityProviders.map((resolvedControllerProvider: ResolvedReflectiveProvider) => {

this.logger.info(`migrating ${resolvedControllerProvider.key.displayName}`);
return (this.injector.instantiateResolved(resolvedControllerProvider) as BaseMigration).migrate();

}, []);

return Promise.all(allMigrationPromises);
}

}
11 changes: 8 additions & 3 deletions src/server/bootstrap/models.bootstrapper.ts
Expand Up @@ -2,7 +2,7 @@ import { ResolvedReflectiveProvider } from '@angular/core';
import { EntityBootstrapper } from './entity.bootstrapper';
import { ModelStatic } from '../../common/models/model';
import {Table} from 'typeorm/tables';
import { PrimaryColumn } from 'typeorm/columns';
import { PrimaryColumn, Column } from 'typeorm/columns';
import { ModelMetadata } from '../../common/metadata/metadata';

export class ModelBootstrapper extends EntityBootstrapper {
Expand All @@ -16,8 +16,13 @@ export class ModelBootstrapper extends EntityBootstrapper {
const meta:ModelMetadata = model.getMetadata();

this.logger.info(`initializing ${model.name}`, meta);
// Table(meta.storageKey, meta.tableOptions)(model);
// PrimaryColumn()(model, meta.identifierKey);

Table(meta.storageKey, meta.tableOptions)(model);
PrimaryColumn()(model.prototype, meta.identifierKey);

for(const [property, type] of meta.storedProperties){
Column()(model.prototype, property)
}

//@todo assign table/columns etc

Expand Down
1 change: 1 addition & 0 deletions src/server/index.ts
Expand Up @@ -4,6 +4,7 @@ export * from './controllers';
export * from './servers';
export * from './services';
export * from './seeders';
export * from './migrations';
export * from './stores';
export * from './middleware';
export * from './exeptions';
13 changes: 13 additions & 0 deletions src/server/migrations/index.ts
@@ -0,0 +1,13 @@
import { Database } from '../services/database.service';
import { Logger } from '../../common/services/logger.service';
export abstract class BaseMigration {

protected logger:Logger;
constructor(loggerBase:Logger, protected database:Database){
this.logger = loggerBase.source(this.constructor.name);

}

public abstract migrate():Promise<void>;

}
7 changes: 0 additions & 7 deletions src/server/services/database.service.ts
Expand Up @@ -66,15 +66,8 @@ export class Database {
}
},
entities: [...registry.getAllOfType('model').values()],
// entityDirectories: [
// process.cwd() + '/lib/server/common/models' //@todo make configurable so bootstrap can
// define relative values
// ],

};

logFunction('info', 'reading directories', options.entityDirectories);

return createConnection(options);
}

Expand Down

0 comments on commit 7645592

Please sign in to comment.