added entity schemas sample draft

This commit is contained in:
Umed Khudoiberdiev 2016-05-11 12:42:18 +05:00
parent 0055a381d1
commit d4cc792b95
15 changed files with 340 additions and 18 deletions

View File

@ -0,0 +1,47 @@
import {createConnection, CreateConnectionOptions} from "../../src/typeorm";
import {Post} from "./entity/Post";
// NOTE: this example is not working yet, only concepts of how this feature must work described here
const options: CreateConnectionOptions = {
driver: "mysql",
connection: {
host: "192.168.99.100",
port: 3306,
username: "root",
password: "admin",
database: "test",
autoSchemaCreate: true
},
// entitySchemaDirectories: [__dirname + "/schemas"],
entitySchemas: [
require("./schemas/post.json"),
require("./schemas/post-details.json"),
require("./schemas/category.json"),
require("./schemas/image.json")
]
};
createConnection(options).then(connection => {
let postRepository = connection.getRepository<Post>("post");
let post: Post = {
title: "Hello post",
text: "I am virtual post!",
details: {
metadata: "#post,#virtual",
comment: "it all about a post"
},
images: [],
secondaryImages: [],
categories: []
};
postRepository
.persist(post)
.then(result => {
console.log(result);
})
.catch(error => console.log(error.stack ? error.stack : error));
}).catch(error => console.log(error.stack ? error.stack : error));

View File

@ -0,0 +1,9 @@
import {Post} from "./Post";
export interface Category {
id?: number;
description: string;
posts?: Post[];
}

View File

@ -0,0 +1,11 @@
import {Post} from "./Post";
export interface Image {
id?: number;
name: string;
url: string;
post?: Post;
secondaryPost?: Post;
}

View File

@ -0,0 +1,15 @@
import {Image} from "./Image";
import {Category} from "./Category";
import {PostDetails} from "./PostDetails";
export interface Post {
id?: number;
title: string;
text: string;
details?: PostDetails;
images?: Image[];
secondaryImages?: Image[];
categories?: Category[];
}

View File

@ -0,0 +1,10 @@
import {Post} from "./Post";
export interface PostDetails {
id?: number;
metadata: string;
comment: string;
post?: Post;
}

View File

@ -0,0 +1,39 @@
{
"name": "Image",
"table": {
"name": "sample24_image"
},
"columns": {
"id": {
"type": "int",
"primary": true,
"generated": true
},
"name": {
"type": "string",
"nullable": false
},
"url": {
"type": "string",
"nullable": false
}
},
"relations": {
"post": {
"target": "Post",
"type": "many-to-one",
"cascadeInsert": true,
"cascadeUpdate": true,
"cascadeRemove": true,
"inverseSide": "images"
},
"secondaryImages": {
"target": "Post",
"type": "many-to-one",
"cascadeInsert": true,
"cascadeUpdate": true,
"cascadeRemove": true,
"inverseSide": "secondaryImages"
}
}
}

View File

@ -0,0 +1,27 @@
{
"name": "Category",
"table": {
"name": "sample24_category"
},
"columns": {
"id": {
"type": "int",
"primary": true,
"generated": true
},
"description": {
"type": "string",
"nullable": false
}
},
"relations": {
"posts": {
"target": "Post",
"type": "many-to-many",
"cascadeInsert": true,
"cascadeUpdate": true,
"cascadeRemove": true,
"inverseSide": "categories"
}
}
}

View File

@ -0,0 +1,29 @@
{
"name": "PostDetails",
"table": {
"name": "sample24_post_details"
},
"columns": {
"id": {
"type": "int",
"primary": true,
"generated": true
},
"comment": {
"type": "string",
"nullable": false
},
"metadata": {
"type": "string",
"nullable": false
}
},
"relations": {
"post": {
"target": "Post",
"type": "one-to-one",
"owner": false,
"inverseSide": "postDetails"
}
}
}

View File

@ -0,0 +1,54 @@
{
"name": "Post",
"table": {
"name": "sample24_post"
},
"columns": {
"id": {
"type": "int",
"primary": true,
"generated": true
},
"title": {
"type": "string",
"nullable": false
},
"text": {
"type": "string",
"nullable": false
}
},
"relations": {
"details": {
"target": "PostDetails",
"type": "one-to-one",
"owner": true,
"inverseSide": "post",
"cascadeInsert": true,
"cascadeUpdate": true,
"cascadeRemove": true
},
"images": {
"target": "Image",
"type": "one-to-many",
"inverseSide": "post",
"cascadeInsert": true,
"cascadeUpdate": true,
"cascadeRemove": true
},
"secondaryImages": {
"target": "Image",
"type": "one-to-many",
"inverseSide": "secondaryPost"
},
"categories": {
"target": "Category",
"type": "many-to-many",
"owner": true,
"cascadeInsert": true,
"cascadeUpdate": true,
"cascadeRemove": true,
"inverseSide": "posts"
}
}
}

View File

@ -35,6 +35,11 @@ export interface CreateConnectionOptions {
*/
namingStrategies?: Function[];
/**
* Entity schemas to be loaded for the new connection.
*/
entitySchemas?: any[];
/**
* List of directories from where entities will be loaded.
*/
@ -49,4 +54,9 @@ export interface CreateConnectionOptions {
* List of directories from where naming strategies will be loaded.
*/
namingStrategyDirectories?: string[];
/**
* List of directories from where entity schemas will be loaded.
*/
entitySchemaDirectories?: string[];
}

View File

@ -243,30 +243,63 @@ export class Connection {
/**
* Gets repository for the given entity class.
*/
getRepository<Entity>(entityClass: ConstructorFunction<Entity>|Function): Repository<Entity> {
getRepository<Entity>(entityClass: ConstructorFunction<Entity>|Function): Repository<Entity>;
// getRepository<Entity>(entityClass: Function): Repository<Entity>;
/**
* Gets repository for the given entity name.
*/
getRepository<Entity>(entityClass: string): Repository<Entity>;
/**
* Gets repository for the given entity class or name.
*/
getRepository<Entity>(entityClassOrName: ConstructorFunction<Entity>|Function|string): Repository<Entity> {
if (!this.isConnected)
throw new NoConnectionForRepositoryError(this.name);
const metadata = this.entityMetadatas.findByTarget(entityClass);
let metadata: EntityMetadata;
if (typeof entityClassOrName === "string") {
metadata = this.entityMetadatas.findByName(entityClassOrName);
} else {
metadata = this.entityMetadatas.findByTarget(entityClassOrName);
}
const repoMeta = this.repositoryAndMetadatas.find(repoMeta => repoMeta.metadata === metadata);
if (!repoMeta)
throw new RepositoryNotFoundError(this.name, entityClass);
throw new RepositoryNotFoundError(this.name, entityClassOrName);
return repoMeta.repository;
}
/**
* Gets tree repository for the given entity class.
* Gets repository for the given entity class.
*/
getTreeRepository<Entity>(entityClass: ConstructorFunction<Entity>|Function): TreeRepository<Entity> {
const repository = this.getRepository(entityClass);
getTreeRepository<Entity>(entityClass: ConstructorFunction<Entity>|Function): TreeRepository<Entity>;
// getTreeRepository<Entity>(entityClass: Function): TreeRepository<Entity>;
/**
* Gets repository for the given entity name.
*/
getTreeRepository<Entity>(entityClass: string): TreeRepository<Entity>;
/**
* Gets repository for the given entity class or name.
*/
getTreeRepository<Entity>(entityClassOrName: ConstructorFunction<Entity>|Function|string): TreeRepository<Entity> {
if (!this.isConnected)
throw new NoConnectionForRepositoryError(this.name);
const metadata = this.entityMetadatas.findByTarget(entityClass);
let metadata: EntityMetadata;
if (typeof entityClassOrName === "string") {
metadata = this.entityMetadatas.findByName(entityClassOrName);
} else {
metadata = this.entityMetadatas.findByTarget(entityClassOrName);
}
const repoMeta = this.repositoryAndMetadatas.find(repoMeta => repoMeta.metadata === metadata);
if (!repoMeta)
throw new RepositoryNotFoundError(this.name, entityClass);
throw new RepositoryNotFoundError(this.name, entityClassOrName);
if (!repoMeta.metadata.table.isClosure)
throw new Error(`Cannot get a tree repository. ${repoMeta.metadata.name} is not a tree table. Try to use @ClosureTable decorator instead of @Table.`);

View File

@ -4,9 +4,9 @@
export class RepositoryNotFoundError extends Error {
name = "RepositoryNotFoundError";
constructor(connectionName: string, entityClass: Function) {
constructor(connectionName: string, entityClass: Function|string) {
super();
const targetName = (<any> entityClass).name ? (<any> entityClass).name : entityClass;
const targetName = typeof entityClass === "function" && (<any> entityClass).name ? (<any> entityClass).name : entityClass;
this.message = `No repository for "${targetName}" was found. Looks like this entity is not registered in ` +
`current "${connectionName}" connection?`;
}

View File

@ -24,17 +24,47 @@ export class EntityManager {
// -------------------------------------------------------------------------
/**
* Gets repository of the given entity.
* Gets repository for the given entity class.
*/
getRepository<Entity>(entityClass: ConstructorFunction<Entity>|Function): Repository<Entity> {
return this.connection.getRepository(entityClass);
getRepository<Entity>(entityClass: ConstructorFunction<Entity>|Function): Repository<Entity>;
// getRepository<Entity>(entityClass: Function): Repository<Entity>;
/**
* Gets repository for the given entity name.
*/
getRepository<Entity>(entityClass: string): Repository<Entity>;
/**
* Gets repository for the given entity class or name.
*/
getRepository<Entity>(entityClassOrName: ConstructorFunction<Entity>|Function|string): Repository<Entity> {
if (typeof entityClassOrName === "string") {
return this.connection.getRepository<Entity>(entityClassOrName);
} else {
return this.connection.getRepository(<ConstructorFunction<Entity>|Function> entityClassOrName);
}
}
/**
* Gets a tree repository of the given entity.
* Gets repository for the given entity class.
*/
getTreeRepository<Entity>(entityClass: ConstructorFunction<Entity>|Function): TreeRepository<Entity> {
return this.connection.getTreeRepository(entityClass);
getTreeRepository<Entity>(entityClass: ConstructorFunction<Entity>|Function): TreeRepository<Entity>;
// getTreeRepository<Entity>(entityClass: Function): TreeRepository<Entity>;
/**
* Gets repository for the given entity name.
*/
getTreeRepository<Entity>(entityClass: string): TreeRepository<Entity>;
/**
* Gets repository for the given entity class or name.
*/
getTreeRepository<Entity>(entityClassOrName: ConstructorFunction<Entity>|Function|string): TreeRepository<Entity> {
if (typeof entityClassOrName === "string") {
return this.connection.getTreeRepository<Entity>(entityClassOrName);
} else {
return this.connection.getTreeRepository(<ConstructorFunction<Entity>|Function> entityClassOrName);
}
}
/**

View File

@ -21,5 +21,13 @@ export class EntityMetadataCollection extends Array<EntityMetadata> {
return metadata;
}
findByName(name: string) {
const metadata = this.find(metadata => metadata.name === name);
if (!metadata)
throw new EntityMetadataNotFound(name);
return metadata;
}
}

View File

@ -4,9 +4,9 @@
export class EntityMetadataNotFound extends Error {
name = "EntityMetadataNotFound";
constructor(target: Function) {
constructor(target: Function|string) {
super();
const targetName = (<any> target).name ? (<any> target).name : target;
const targetName = typeof target === "function" && (<any> target).name ? (<any> target).name : target;
this.message = `No metadata for "${targetName}" was found.`;
}