Skip to content

Commit

Permalink
implemented entity listeners and refactored orm broadcaster
Browse files Browse the repository at this point in the history
  • Loading branch information
Umed Khudoiberdiev committed Mar 22, 2016
1 parent bc3cfe8 commit 2e99b1a
Show file tree
Hide file tree
Showing 28 changed files with 624 additions and 83 deletions.
4 changes: 4 additions & 0 deletions sample/sample4-many-to-many/entity/PostCategory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,9 @@ export class PostCategory {

@Column()
name: string;

constructor(name?: string) {
this.name = name;
}

}
2 changes: 1 addition & 1 deletion sample/sample5-subscribers/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ createMysqlConnection(options, [__dirname + "/entity"], [__dirname + "/subscribe
})
.then(loadedPost => {
console.log("---------------------------");
console.log("load removed.");
console.log("post removed.");
})
.catch(error => console.log("Cannot save. Error: ", error.stack ? error.stack : error));

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {OrmEventSubscriber} from "../../../src/decorator/OrmEventSubscriber";
import {OrmEventSubscriber} from "../../../src/decorator/listeners/OrmEventSubscriber";
import {OrmSubscriber} from "../../../src/subscriber/OrmSubscriber";
import {InsertEvent} from "../../../src/subscriber/event/InsertEvent";
import {RemoveEvent} from "../../../src/subscriber/event/RemoveEvent";
Expand Down
70 changes: 70 additions & 0 deletions sample/sample9-entity-listeners/app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import {createMysqlConnection} from "../../src/typeorm";
import {Post} from "./entity/Post";
import {PostCategory} from "./entity/PostCategory";
import {PostAuthor} from "./entity/PostAuthor";

// first create a connection
let options = {
host: "192.168.99.100",
port: 3306,
username: "root",
password: "admin",
database: "test",
autoSchemaCreate: true
};

createMysqlConnection(options, [__dirname + "/entity"], [__dirname + "/subscriber"]).then(connection => {

let category1 = new PostCategory();
category1.name = "post category #1";

let category2 = new PostCategory();
category2.name = "post category #2";

let author = new PostAuthor();
author.name = "Umed";

let post = new Post();
post.text = "Hello how are you?";
post.title = "hello";
post.categories.push(category1, category2);
post.author = author;

let postRepository = connection.getRepository(Post);

postRepository
.persist(post)
.then(post => {
console.log("Post has been saved");
console.log("---------------------------");
return postRepository.findById(post.id);
})
.then(loadedPost => {
console.log("post is loaded. Its uid is " + loadedPost.uid);
console.log("Lets now load it with relations.");
console.log("---------------------------");
return postRepository
.createQueryBuilder("p")
.leftJoinAndSelect("p.author", "author")
.leftJoinAndSelect("p.categories", "categories")
.where("p.id = :id", { id: loadedPost.id })
.getSingleResult();
})
.then(loadedPost => {
console.log("load finished. Now lets update entity");
console.log("---------------------------");
loadedPost.text = "post updated";
loadedPost.author.name = "Bakha";
return postRepository.persist(loadedPost);
})
.then(loadedPost => {
console.log("update finished. Now lets remove entity");
console.log("---------------------------");
return postRepository.remove(loadedPost);
})
.then(loadedPost => {
console.log("post removed.");
})
.catch(error => console.log("Cannot save. Error: ", error.stack ? error.stack : error));

}, error => console.log("Cannot connect: ", error.stack ? error.stack : error));
78 changes: 78 additions & 0 deletions sample/sample9-entity-listeners/entity/Post.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import {PrimaryColumn, Column} from "../../../src/decorator/Columns";
import {Table} from "../../../src/decorator/Tables";
import {ManyToMany} from "../../../src/decorator/Relations";
import {PostCategory} from "./PostCategory";
import {PostAuthor} from "./PostAuthor";
import {ManyToOne} from "../../../src/decorator/relations/ManyToOne";
import {AfterLoad} from "../../../src/decorator/listeners/AfterLoad";
import {AfterInsert} from "../../../src/decorator/listeners/AfterInsert";
import {BeforeInsert} from "../../../src/decorator/listeners/BeforeInsert";
import {BeforeUpdate} from "../../../src/decorator/listeners/BeforeUpdate";
import {AfterUpdate} from "../../../src/decorator/listeners/AfterUpdate";
import {BeforeRemove} from "../../../src/decorator/listeners/BeforeRemove";
import {AfterRemove} from "../../../src/decorator/listeners/AfterRemove";

@Table("sample9_post")
export class Post {

@PrimaryColumn("int", { autoIncrement: true })
id: number;

@Column()
title: string;

@Column()
text: string;

@ManyToOne(type => PostAuthor, post => post.posts, {
cascadeInsert: true,
cascadeUpdate: true
})
author: PostAuthor;

@ManyToMany(type => PostCategory, category => category.posts, {
cascadeInsert: true,
cascadeUpdate: true,
cascadeRemove: true
})
categories: PostCategory[] = [];

uid: number;

@AfterLoad()
generateRandomNumbers() {
console.log(`event: Post "${this.title}" entity has been loaded and callback executed`);
this.uid = Math.ceil(Math.random() * 1000);
}

@BeforeInsert()
doSomethingBeforeInsertion() {
console.log("event: Post entity will be inserted so soon...");
}

@AfterInsert()
doSomethingAfterInsertion() {
console.log("event: Post entity has been inserted and callback executed");
}

@BeforeUpdate()
doSomethingBeforeUpdate() {
console.log("event: Post entity will be updated so soon...");
}

@AfterUpdate()
doSomethingAfterUpdate() {
console.log("event: Post entity has been updated and callback executed");
}

@BeforeRemove()
doSomethingBeforeRemove() {
console.log("event: Post entity will be removed so soon...");
}

@AfterRemove()
doSomethingAfterRemove() {
console.log("event: Post entity has been removed and callback executed");
}

}
54 changes: 54 additions & 0 deletions sample/sample9-entity-listeners/entity/PostAuthor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import {PrimaryColumn, Column} from "../../../src/decorator/Columns";
import {Table} from "../../../src/decorator/Tables";
import {Post} from "./Post";
import {OneToMany} from "../../../src/decorator/relations/OneToMany";
import {AfterRemove} from "../../../src/decorator/listeners/AfterRemove";
import {BeforeRemove} from "../../../src/decorator/listeners/BeforeRemove";
import {AfterUpdate} from "../../../src/decorator/listeners/AfterUpdate";
import {BeforeUpdate} from "../../../src/decorator/listeners/BeforeUpdate";
import {AfterInsert} from "../../../src/decorator/listeners/AfterInsert";
import {BeforeInsert} from "../../../src/decorator/listeners/BeforeInsert";

@Table("sample9_post_author")
export class PostAuthor {

@PrimaryColumn("int", { autoIncrement: true })
id: number;

@Column()
name: string;

@OneToMany(type => Post, post => post.author)
posts: Post[];

@BeforeInsert()
doSomethingBeforeInsertion() {
console.log("event: PostAuthor entity will be inserted so soon...");
}

@AfterInsert()
doSomethingAfterInsertion() {
console.log("event: PostAuthor entity has been inserted and callback executed");
}

@BeforeUpdate()
doSomethingBeforeUpdate() {
console.log("event: PostAuthor entity will be updated so soon...");
}

@AfterUpdate()
doSomethingAfterUpdate() {
console.log("event: PostAuthor entity has been updated and callback executed");
}

@BeforeRemove()
doSomethingBeforeRemove() {
console.log("event: PostAuthor entity will be removed so soon...");
}

@AfterRemove()
doSomethingAfterRemove() {
console.log("event: PostAuthor entity has been removed and callback executed");
}

}
58 changes: 58 additions & 0 deletions sample/sample9-entity-listeners/entity/PostCategory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import {PrimaryColumn, Column} from "../../../src/decorator/Columns";
import {Table} from "../../../src/decorator/Tables";
import {Post} from "./Post";
import {ManyToManyInverse} from "../../../src/decorator/relations/ManyToManyInverse";
import {AfterRemove} from "../../../src/decorator/listeners/AfterRemove";
import {BeforeRemove} from "../../../src/decorator/listeners/BeforeRemove";
import {AfterUpdate} from "../../../src/decorator/listeners/AfterUpdate";
import {BeforeUpdate} from "../../../src/decorator/listeners/BeforeUpdate";
import {AfterInsert} from "../../../src/decorator/listeners/AfterInsert";
import {BeforeInsert} from "../../../src/decorator/listeners/BeforeInsert";

@Table("sample9_post_category")
export class PostCategory {

@PrimaryColumn("int", { autoIncrement: true })
id: number;

@Column()
name: string;

@ManyToManyInverse(type => Post, post => post.categories, {
cascadeInsert: true,
cascadeUpdate: true,
cascadeRemove: true
})
posts: Post[] = [];

@BeforeInsert()
doSomethingBeforeInsertion() {
console.log(`event: PostCategory "${this.name}" will be inserted so soon...`);
}

@AfterInsert()
doSomethingAfterInsertion() {
console.log(`event: PostCategory "${this.name}" has been inserted and callback executed`);
}

@BeforeUpdate()
doSomethingBeforeUpdate() {
console.log(`event: PostCategory "${this.name}" will be updated so soon...`);
}

@AfterUpdate()
doSomethingAfterUpdate() {
console.log(`event: PostCategory "${this.name}" has been updated and callback executed`);
}

@BeforeRemove()
doSomethingBeforeRemove() {
console.log(`event: PostCategory "${this.name}" will be removed so soon...`);
}

@AfterRemove()
doSomethingAfterRemove() {
console.log(`event: PostCategory "${this.name}" has been removed and callback executed`);
}

}
37 changes: 26 additions & 11 deletions src/connection/Connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import {ConnectionOptions} from "./ConnectionOptions";
import {Repository} from "../repository/Repository";
import {OrmSubscriber} from "../subscriber/OrmSubscriber";
import {RepositoryNotFoundError} from "./error/RepositoryNotFoundError";
import {BroadcasterNotFoundError} from "./error/BroadcasterNotFoundError";
import {EntityMetadata} from "../metadata-builder/metadata/EntityMetadata";
import {SchemaCreator} from "../schema-creator/SchemaCreator";
import {MetadataNotFoundError} from "./error/MetadataNotFoundError";
import {ConstructorFunction} from "../common/ConstructorFunction";
import {EntityListenerMetadata} from "../metadata-builder/metadata/EntityListenerMetadata";

interface RepositoryAndMetadata {
repository: Repository<any>;
Expand All @@ -25,7 +25,8 @@ export class Connection {

private _name: string;
private _driver: Driver;
private _metadatas: EntityMetadata[] = [];
private _entityMetadatas: EntityMetadata[] = [];
private _entityListenerMetadatas: EntityListenerMetadata[] = [];
private _subscribers: OrmSubscriber<any>[] = [];
private repositoryAndMetadatas: RepositoryAndMetadata[] = [];
private _options: ConnectionOptions;
Expand Down Expand Up @@ -66,10 +67,17 @@ export class Connection {
}

/**
* All metadatas that are registered for this connection.
* All entity metadatas that are registered for this connection.
*/
get metadatas(): EntityMetadata[] {
return this._metadatas;
get entityMetadatas(): EntityMetadata[] {
return this._entityMetadatas;
}

/**
* All entity listener metadatas that are registered for this connection.
*/
get entityListeners(): EntityListenerMetadata[] {
return this._entityListenerMetadatas;
}

/**
Expand Down Expand Up @@ -114,9 +122,16 @@ export class Connection {
/**
* Registers entity metadatas for the current connection.
*/
addMetadatas(metadatas: EntityMetadata[]) {
this._metadatas = this._metadatas.concat(metadatas);
this.repositoryAndMetadatas = this.repositoryAndMetadatas.concat(metadatas.map(metadata => this.createRepoMeta(metadata)));
addEntityMetadatas(metadatas: EntityMetadata[]) {
this._entityMetadatas = this._entityMetadatas.concat(metadatas);
this.repositoryAndMetadatas = this.repositoryAndMetadatas.concat(metadatas.map(metadata => this.createRepoMeta(metadata)));
}

/**
* Registers entity listener metadatas for the current connection.
*/
addEntityListenerMetadatas(metadatas: EntityListenerMetadata[]) {
this._entityListenerMetadatas = this._entityListenerMetadatas.concat(metadatas);
}

/**
Expand All @@ -130,7 +145,7 @@ export class Connection {
* Gets repository for the given entity class.
*/
getRepository<Entity>(entityClass: ConstructorFunction<Entity>|Function): Repository<Entity> {
const metadata = this.getMetadata(entityClass);
const metadata = this.getEntityMetadata(entityClass);
const repoMeta = this.repositoryAndMetadatas.find(repoMeta => repoMeta.metadata === metadata);
if (!repoMeta)
throw new RepositoryNotFoundError(entityClass);
Expand All @@ -141,8 +156,8 @@ export class Connection {
/**
* Gets the entity metadata for the given entity class.
*/
getMetadata(entityClass: Function): EntityMetadata {
const metadata = this.metadatas.find(metadata => metadata.target === entityClass);
getEntityMetadata(entityClass: Function): EntityMetadata {
const metadata = this.entityMetadatas.find(metadata => metadata.target === entityClass);
if (!metadata)
throw new MetadataNotFoundError(entityClass);

Expand Down
7 changes: 5 additions & 2 deletions src/connection/ConnectionManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,11 @@ export class ConnectionManager {
entities = <Function[]> connectionNameOrEntities;
}

const metadatas = this.entityMetadataBuilder.build(entities);
this.getConnection(connectionName).addMetadatas(metadatas);
const entityMetadatas = this.entityMetadataBuilder.build(entities);
const entityListenerMetadatas = defaultMetadataStorage.findEntityListenersForClasses(entities);

this.getConnection(connectionName).addEntityMetadatas(entityMetadatas);
this.getConnection(connectionName).addEntityListenerMetadatas(entityListenerMetadatas);
}

// -------------------------------------------------------------------------
Expand Down
Loading

0 comments on commit 2e99b1a

Please sign in to comment.