mirror of
https://github.com/typeorm/typeorm.git
synced 2025-12-08 21:26:23 +00:00
added build from entity schemas - first step
This commit is contained in:
parent
fa252fa68b
commit
0c20445d83
@ -29,6 +29,12 @@ export class ConnectionManager {
|
||||
const driver = this.createDriver(options.driver);
|
||||
const connection = this.createConnection(options.connectionName || "default", driver, options.connection);
|
||||
|
||||
if (options.entitySchemaDirectories && options.entitySchemaDirectories.length > 0)
|
||||
connection.importEntitySchemaFromDirectories(options.entitySchemaDirectories);
|
||||
|
||||
if (options.entitySchemas)
|
||||
connection.importEntities(options.entitySchemas);
|
||||
|
||||
if (options.entityDirectories && options.entityDirectories.length > 0)
|
||||
connection.importEntitiesFromDirectories(options.entityDirectories);
|
||||
|
||||
|
||||
@ -28,6 +28,7 @@ import {RepositoryFactory} from "../repository/RepositoryFactory";
|
||||
import {SchemaCreatorFactory} from "../schema-creator/SchemaCreatorFactory";
|
||||
import {ReactiveRepositoryNotFoundError} from "./error/ReactiveRepositoryNotFoundError";
|
||||
import {RepositoryNotTreeError} from "./error/RepositoryNotTreeError";
|
||||
import {EntitySchema} from "../metadata/entity-schema/EntitySchema";
|
||||
|
||||
/**
|
||||
* A single connection instance to the database. Each connection has its own repositories, subscribers and metadatas.
|
||||
@ -106,6 +107,11 @@ export class Connection {
|
||||
*/
|
||||
private readonly entityClasses: Function[] = [];
|
||||
|
||||
/**
|
||||
* Registered entity schemas to be used for this connection.
|
||||
*/
|
||||
private readonly entitySchemas: EntitySchema[] = [];
|
||||
|
||||
/**
|
||||
* Registered subscriber classes to be used for this connection.
|
||||
*/
|
||||
@ -202,6 +208,14 @@ export class Connection {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Imports entity schemas from the given paths (directories) for the current connection.
|
||||
*/
|
||||
importEntitySchemaFromDirectories(paths: string[]): this {
|
||||
this.importSchemas(importClassesFromDirectories(paths) as any[]); // todo: check it.
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Imports subscribers from the given paths (directories) for the current connection.
|
||||
*/
|
||||
@ -229,6 +243,17 @@ export class Connection {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Imports schemas for the current connection.
|
||||
*/
|
||||
importSchemas(schemas: EntitySchema[]): this {
|
||||
if (this.isConnected)
|
||||
throw new CannotImportAlreadyConnectedError("schemas", this.name);
|
||||
|
||||
schemas.forEach(schema => this.entitySchemas.push(schema));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Imports entities for the given connection. If connection name is not given then default connection is used.
|
||||
*/
|
||||
@ -365,13 +390,26 @@ export class Connection {
|
||||
.filterByClasses(this.entityClasses)
|
||||
.forEach(metadata => this.entityListeners.push(new EntityListenerMetadata(metadata)));
|
||||
|
||||
// build entity metadatas for the current connection
|
||||
getFromContainer(EntityMetadataBuilder)
|
||||
.build(this.createNamingStrategy(), this.entityClasses)
|
||||
.forEach(layout => {
|
||||
this.entityMetadatas.push(layout);
|
||||
this.createRepository(layout);
|
||||
});
|
||||
// build entity metadatas from metadata args storage (collected from decorators)
|
||||
if (this.entityClasses) {
|
||||
getFromContainer(EntityMetadataBuilder)
|
||||
.buildFromMetadataArgsStorage(this.createNamingStrategy(), this.entityClasses)
|
||||
.forEach(metadata => {
|
||||
this.entityMetadatas.push(metadata);
|
||||
this.createRepository(metadata);
|
||||
});
|
||||
}
|
||||
|
||||
// build entity metadatas from given entity schemas
|
||||
if (this.entitySchemas) {
|
||||
getFromContainer(EntityMetadataBuilder)
|
||||
.buildFromSchemas(this.createNamingStrategy(), this.entitySchemas)
|
||||
.forEach(metadata => {
|
||||
this.entityMetadatas.push(metadata);
|
||||
this.createRepository(metadata);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -394,13 +432,13 @@ export class Connection {
|
||||
private createRepository(entityLayout: EntityMetadata) {
|
||||
const repositoryFactory = getFromContainer(RepositoryFactory);
|
||||
if (entityLayout.table.isClosure) {
|
||||
const repository = repositoryFactory.createRepository(this, this.entityMetadatas, entityLayout);
|
||||
const reactiveRepository = repositoryFactory.createReactiveRepository(repository);
|
||||
const repository = repositoryFactory.createTreeRepository(this, this.entityMetadatas, entityLayout);
|
||||
const reactiveRepository = repositoryFactory.createReactiveTreeRepository(repository);
|
||||
this.repositories.push(repository);
|
||||
this.reactiveRepositories.push(reactiveRepository);
|
||||
} else {
|
||||
const repository = repositoryFactory.createTreeRepository(this, this.entityMetadatas, entityLayout);
|
||||
const reactiveRepository = repositoryFactory.createReactiveTreeRepository(repository);
|
||||
const repository = repositoryFactory.createRepository(this, this.entityMetadatas, entityLayout);
|
||||
const reactiveRepository = repositoryFactory.createReactiveRepository(repository);
|
||||
this.repositories.push(repository);
|
||||
this.reactiveRepositories.push(reactiveRepository);
|
||||
}
|
||||
|
||||
@ -69,10 +69,5 @@ export interface ColumnOptions {
|
||||
* Column collation. Note that not all databases support it.
|
||||
*/
|
||||
readonly collation?: string; // todo: looks like this is not used
|
||||
|
||||
/**
|
||||
* Indicates if this column is order id column.
|
||||
*/
|
||||
readonly isOrderId?: boolean; // todo: looks like this is not implemented yet
|
||||
|
||||
}
|
||||
|
||||
@ -49,7 +49,7 @@ export class MysqlDriver extends BaseDriver implements Driver {
|
||||
}
|
||||
|
||||
/**
|
||||
* Access to the native implementation of the database.
|
||||
* Access to the native connection to the database.
|
||||
*/
|
||||
get nativeConnection(): any {
|
||||
return this.mysqlConnection;
|
||||
@ -80,8 +80,9 @@ export class MysqlDriver extends BaseDriver implements Driver {
|
||||
if (!mysql && require) {
|
||||
try {
|
||||
mysql = require("mysql");
|
||||
|
||||
} catch (e) {
|
||||
throw new Error("Mysql package was not found installed. Try to install it: npm install mysql --save");
|
||||
throw new Error("Mysql package has not been found installed. Try to install it: npm install mysql --save");
|
||||
}
|
||||
} else {
|
||||
throw new Error("Cannot load mysql driver dependencies. Try to install all required dependencies.");
|
||||
|
||||
@ -7,7 +7,7 @@ import {ReactiveRepository} from "../repository/ReactiveRepository";
|
||||
import {TreeRepository} from "../repository/TreeRepository";
|
||||
|
||||
/**
|
||||
* Entity manager supposed to work with any entity, automatically find its repository and call its method, whatever
|
||||
* Entity manager supposed to work with any entity, automatically find its repository and call its methods, whatever
|
||||
* entity type are you passing.
|
||||
*/
|
||||
export class EntityManager {
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import * as Rx from "rxjs/Rx";
|
||||
import {Connection} from "../connection/Connection";
|
||||
import {QueryBuilder} from "../query-builder/QueryBuilder";
|
||||
import {FindOptions} from "../repository/FindOptions";
|
||||
import {Repository} from "../repository/Repository";
|
||||
import {ConstructorFunction} from "../common/ConstructorFunction";
|
||||
import {ReactiveRepository} from "../repository/ReactiveRepository";
|
||||
import * as Rx from "rxjs/Rx";
|
||||
import {ReactiveTreeRepository} from "../repository/ReactiveTreeRepository";
|
||||
|
||||
/**
|
||||
@ -303,6 +303,7 @@ export class ReactiveEntityManager {
|
||||
|
||||
/**
|
||||
* Roots are entities that have no ancestors. Finds them all.
|
||||
* Used on the tree-type (e.g. closure table) entities.
|
||||
*/
|
||||
findRoots<Entity>(entityClass: ConstructorFunction<Entity>|Function): Rx.Observable<Entity[]> {
|
||||
return this.getReactiveTreeRepository(entityClass).findRoots();
|
||||
@ -310,6 +311,7 @@ export class ReactiveEntityManager {
|
||||
|
||||
/**
|
||||
* Creates a query builder used to get descendants of the entities in a tree.
|
||||
* Used on the tree-type (e.g. closure table) entities.
|
||||
*/
|
||||
createDescendantsQueryBuilder<Entity>(entityClass: ConstructorFunction<Entity>|Function, alias: string, closureTableAlias: string, entity: Entity): QueryBuilder<Entity> {
|
||||
return this.getReactiveTreeRepository(entityClass).createDescendantsQueryBuilder(alias, closureTableAlias, entity);
|
||||
@ -317,6 +319,7 @@ export class ReactiveEntityManager {
|
||||
|
||||
/**
|
||||
* Gets all children (descendants) of the given entity. Returns them all in a flat array.
|
||||
* Used on the tree-type (e.g. closure table) entities.
|
||||
*/
|
||||
findDescendants<Entity>(entityClass: ConstructorFunction<Entity>|Function, entity: Entity): Rx.Observable<Entity[]> {
|
||||
return this.getReactiveTreeRepository(entityClass).findDescendants(entity);
|
||||
@ -324,6 +327,7 @@ export class ReactiveEntityManager {
|
||||
|
||||
/**
|
||||
* Gets all children (descendants) of the given entity. Returns them in a tree - nested into each other.
|
||||
* Used on the tree-type (e.g. closure table) entities.
|
||||
*/
|
||||
findDescendantsTree<Entity>(entityClass: ConstructorFunction<Entity>|Function, entity: Entity): Rx.Observable<Entity> {
|
||||
return this.getReactiveTreeRepository(entityClass).findDescendantsTree(entity);
|
||||
@ -331,6 +335,7 @@ export class ReactiveEntityManager {
|
||||
|
||||
/**
|
||||
* Gets number of descendants of the entity.
|
||||
* Used on the tree-type (e.g. closure table) entities.
|
||||
*/
|
||||
countDescendants<Entity>(entityClass: ConstructorFunction<Entity>|Function, entity: Entity): Rx.Observable<number> {
|
||||
return this.getReactiveTreeRepository(entityClass).countDescendants(entity);
|
||||
@ -338,6 +343,7 @@ export class ReactiveEntityManager {
|
||||
|
||||
/**
|
||||
* Creates a query builder used to get ancestors of the entities in the tree.
|
||||
* Used on the tree-type (e.g. closure table) entities.
|
||||
*/
|
||||
createAncestorsQueryBuilder<Entity>(entityClass: ConstructorFunction<Entity>|Function, alias: string, closureTableAlias: string, entity: Entity): QueryBuilder<Entity> {
|
||||
return this.getReactiveTreeRepository(entityClass).createAncestorsQueryBuilder(alias, closureTableAlias, entity);
|
||||
@ -345,20 +351,23 @@ export class ReactiveEntityManager {
|
||||
|
||||
/**
|
||||
* Gets all parents (ancestors) of the given entity. Returns them all in a flat array.
|
||||
* Used on the tree-type (e.g. closure table) entities.
|
||||
*/
|
||||
findAncestors<Entity>(entityClass: ConstructorFunction<Entity>|Function, entity: Entity): Rx.Observable<Entity[]> {
|
||||
return this.getReactiveTreeRepository(entityClass).findAncestors(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all parents (ancestors) of the given entity. Returns them in a tree - nested into each other.
|
||||
* Gets all parents (ancestors) of the given entity. \Returns them in a tree - nested into each other.
|
||||
* Used on the tree-type (e.g. closure table) entities.
|
||||
*/
|
||||
findAncestorsTree<Entity>(entityClass: ConstructorFunction<Entity>|Function, entity: Entity): Rx.Observable<Entity> {
|
||||
return this.getReactiveTreeRepository(entityClass).findAncestorsTree(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets number of ancestors of the entity.
|
||||
* Gets number of ancestors of the entity.
|
||||
* Used on the tree-type (e.g. closure table) entities.
|
||||
*/
|
||||
countAncestors<Entity>(entityClass: ConstructorFunction<Entity>|Function, entity: Entity): Rx.Observable<number> {
|
||||
return this.getReactiveTreeRepository(entityClass).countAncestors(entity);
|
||||
|
||||
@ -11,6 +11,12 @@ export interface ColumnMetadataArgs {
|
||||
*/
|
||||
readonly target?: Function;
|
||||
|
||||
/**
|
||||
* In the case if this column is without a target, targetId must be specified.
|
||||
* This is used for entity schemas without classes.
|
||||
*/
|
||||
readonly targetId?: string;
|
||||
|
||||
/**
|
||||
* Class's property name to which column is applied.
|
||||
*/
|
||||
@ -18,11 +24,15 @@ export interface ColumnMetadataArgs {
|
||||
|
||||
/**
|
||||
* Class's property type (reflected) to which column is applied.
|
||||
*
|
||||
* todo: check when this is not set, because for the entity schemas we don't set it.
|
||||
*/
|
||||
readonly propertyType: string;
|
||||
readonly propertyType?: string;
|
||||
|
||||
/**
|
||||
* Column mode in which column will work.
|
||||
*
|
||||
* todo: find name better then "mode".
|
||||
*/
|
||||
readonly mode: ColumnMode;
|
||||
|
||||
|
||||
@ -10,7 +10,13 @@ export interface RelationMetadataArgs {
|
||||
/**
|
||||
* Class to which this relation is applied.
|
||||
*/
|
||||
readonly target: Function;
|
||||
readonly target?: Function;
|
||||
|
||||
/**
|
||||
* In the case if this relation is without a target, targetId must be specified.
|
||||
* This is used for entity schemas without classes.
|
||||
*/
|
||||
readonly targetId?: string;
|
||||
|
||||
/**
|
||||
* Class's property name to which this relation is applied.
|
||||
@ -19,8 +25,10 @@ export interface RelationMetadataArgs {
|
||||
|
||||
/**
|
||||
* Original (reflected) class's property type.
|
||||
*
|
||||
* todo: this can be empty for relations from entity schemas.
|
||||
*/
|
||||
readonly propertyType: any;
|
||||
readonly propertyType?: any;
|
||||
|
||||
/**
|
||||
* Type of relation. Can be one of the value of the RelationTypes class.
|
||||
|
||||
@ -10,6 +10,12 @@ export interface TableMetadataArgs {
|
||||
*/
|
||||
readonly target?: Function;
|
||||
|
||||
/**
|
||||
* In the case if this table is without a target, targetId must be specified.
|
||||
* This is used for entity schemas without classes.
|
||||
*/
|
||||
readonly targetId?: string;
|
||||
|
||||
/**
|
||||
* Table name.
|
||||
*/
|
||||
|
||||
@ -13,6 +13,11 @@ import {JoinTableMetadata} from "../metadata/JoinTableMetadata";
|
||||
import {JunctionEntityMetadataBuilder} from "./JunctionEntityMetadataBuilder";
|
||||
import {ClosureJunctionEntityMetadataBuilder} from "./ClosureJunctionEntityMetadataBuilder";
|
||||
import {EmbeddedMetadata} from "../metadata/EmbeddedMetadata";
|
||||
import {EntitySchema} from "../metadata/entity-schema/EntitySchema";
|
||||
import {MetadataArgsStorage} from "../metadata-args/MetadataArgsStorage";
|
||||
import {TableMetadataArgs} from "../metadata-args/TableMetadataArgs";
|
||||
import {ColumnMetadataArgs} from "../metadata-args/ColumnMetadataArgs";
|
||||
import {RelationMetadataArgs} from "../metadata-args/RelationMetadataArgs";
|
||||
|
||||
/**
|
||||
* Aggregates all metadata: table, column, relation into one collection grouped by tables for a given set of classes.
|
||||
@ -31,14 +36,93 @@ export class EntityMetadataBuilder {
|
||||
// -------------------------------------------------------------------------
|
||||
// Public Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
|
||||
buildFromSchemas(namingStrategy: NamingStrategyInterface, schemas: EntitySchema[]): EntityMetadata[] {
|
||||
const metadataArgsStorage = new MetadataArgsStorage();
|
||||
|
||||
schemas.forEach(schema => {
|
||||
|
||||
// add table metadata args from the schema
|
||||
const tableSchema = schema.table || {} as any;
|
||||
const table: TableMetadataArgs = {
|
||||
target: schema.target,
|
||||
name: tableSchema.name,
|
||||
type: tableSchema.type || "regular",
|
||||
targetId: schema.name,
|
||||
orderBy: tableSchema.orderBy,
|
||||
primaryKeys: tableSchema.primaryKeys
|
||||
};
|
||||
metadataArgsStorage.tables.add(table);
|
||||
|
||||
// add columns metadata args from the schema
|
||||
Object.keys(schema.columns).forEach(columnName => {
|
||||
const columnSchema = schema.columns[columnName];
|
||||
const column: ColumnMetadataArgs = {
|
||||
target: schema.target,
|
||||
targetId: schema.name,
|
||||
mode: columnSchema.mode,
|
||||
propertyName: columnName,
|
||||
// todo: what to do with it?: propertyType:
|
||||
options: {
|
||||
type: columnSchema.type,
|
||||
name: columnSchema.name,
|
||||
length: columnSchema.length,
|
||||
generated: columnSchema.generated,
|
||||
unique: columnSchema.unique,
|
||||
nullable: columnSchema.nullable,
|
||||
columnDefinition: columnSchema.columnDefinition,
|
||||
comment: columnSchema.comment,
|
||||
oldColumnName: columnSchema.oldColumnName,
|
||||
precision: columnSchema.precision,
|
||||
scale: columnSchema.scale,
|
||||
collation: columnSchema.collation
|
||||
}
|
||||
};
|
||||
|
||||
metadataArgsStorage.columns.add(column);
|
||||
});
|
||||
|
||||
// add relation metadata args from the schema
|
||||
Object.keys(schema.relations).forEach(relationName => {
|
||||
const relationSchema = schema.relations[relationName];
|
||||
const relation: RelationMetadataArgs = {
|
||||
target: schema.target,
|
||||
targetId: schema.name,
|
||||
propertyName: relationName,
|
||||
// todo: what to do with it?: propertyType:
|
||||
relationType: relationSchema.relationType,
|
||||
type: relationSchema.type,
|
||||
inverseSideProperty: relationSchema.inverseSide,
|
||||
isTreeParent: relationSchema.isTreeParent,
|
||||
isTreeChildren: relationSchema.isTreeChildren,
|
||||
options: {
|
||||
cascadeAll: relationSchema.cascadeAll,
|
||||
cascadeInsert: relationSchema.cascadeInsert,
|
||||
cascadeUpdate: relationSchema.cascadeUpdate,
|
||||
cascadeRemove: relationSchema.cascadeRemove,
|
||||
oldColumnName: relationSchema.oldColumnName,
|
||||
nullable: relationSchema.nullable,
|
||||
onDelete: relationSchema.onDelete
|
||||
}
|
||||
};
|
||||
|
||||
metadataArgsStorage.relations.add(relation);
|
||||
});
|
||||
});
|
||||
|
||||
return this.buildFromAnyMetadataArgsStorage(metadataArgsStorage, namingStrategy, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a complete metadata aggregations for the given entity classes.
|
||||
*/
|
||||
build(namingStrategy: NamingStrategyInterface, entityClasses: Function[]): EntityMetadata[] {
|
||||
|
||||
const embeddableMergedArgs = getMetadataArgsStorage().getMergedEmbeddableTableMetadatas(entityClasses);
|
||||
const entityMetadatas = getMetadataArgsStorage().getMergedTableMetadatas(entityClasses).map(mergedArgs => {
|
||||
buildFromMetadataArgsStorage(namingStrategy: NamingStrategyInterface, entityClasses: Function[]): EntityMetadata[] {
|
||||
return this.buildFromAnyMetadataArgsStorage(getMetadataArgsStorage(), namingStrategy, entityClasses);
|
||||
}
|
||||
|
||||
buildFromAnyMetadataArgsStorage(metadataArgsStorage: MetadataArgsStorage, namingStrategy: NamingStrategyInterface, entityClasses: Function[]): EntityMetadata[] {
|
||||
const embeddableMergedArgs = metadataArgsStorage.getMergedEmbeddableTableMetadatas(entityClasses);
|
||||
const entityMetadatas = metadataArgsStorage.getMergedTableMetadatas(entityClasses).map(mergedArgs => {
|
||||
|
||||
// find embeddable tables for embeddeds registered in this table and create EmbeddedMetadatas from them
|
||||
const embeddeds: EmbeddedMetadata[] = [];
|
||||
|
||||
@ -6,7 +6,9 @@ import {EmbeddedMetadata} from "./EmbeddedMetadata";
|
||||
|
||||
/**
|
||||
* Kinda type of the column. Not a type in the database, but locally used type to determine what kind of column
|
||||
* we are working with.
|
||||
* we are working with.
|
||||
* For example, "primary" means that it will be a primary column, or "createDate" means that it will create a create
|
||||
* date column.
|
||||
*/
|
||||
export type ColumnMode = "regular"|"virtual"|"primary"|"createDate"|"updateDate"|"version"|"treeChildrenCount"|"treeLevel";
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@ import {RelationMetadataArgs} from "../metadata-args/RelationMetadataArgs";
|
||||
/**
|
||||
* Function that returns a type of the field. Returned value must be a class used on the relation.
|
||||
*/
|
||||
export type RelationTypeInFunction = ((type?: any) => Function);
|
||||
export type RelationTypeInFunction = ((type?: any) => Function)|string; // todo: |string ?
|
||||
|
||||
|
||||
/**
|
||||
@ -198,8 +198,8 @@ export class RelationMetadata extends PropertyMetadata {
|
||||
/**
|
||||
* Gets the property's type to which this relation is applied.
|
||||
*/
|
||||
get type(): Function {
|
||||
return this._type();
|
||||
get type(): Function|string {
|
||||
return this._type instanceof Function ? this._type() : this._type;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
226
src/metadata/entity-schema/EntitySchema.ts
Normal file
226
src/metadata/entity-schema/EntitySchema.ts
Normal file
@ -0,0 +1,226 @@
|
||||
import {ColumnMode} from "../ColumnMetadata";
|
||||
import {ColumnType} from "../types/ColumnTypes";
|
||||
import {TableType} from "../TableMetadata";
|
||||
import {RelationType} from "../types/RelationTypes";
|
||||
import {OnDeleteType} from "../ForeignKeyMetadata";
|
||||
|
||||
export interface EntitySchema {
|
||||
|
||||
/**
|
||||
* Name of the schema it extends.
|
||||
*/
|
||||
extends?: string;
|
||||
|
||||
/**
|
||||
* Target bind to this entity schema. Optional.
|
||||
*/
|
||||
target?: Function;
|
||||
|
||||
/**
|
||||
* Entity name.
|
||||
*/
|
||||
name: string;
|
||||
|
||||
/**
|
||||
* Entity table's options.
|
||||
*/
|
||||
table: {
|
||||
|
||||
/**
|
||||
* Table name.
|
||||
*/
|
||||
name?: string;
|
||||
|
||||
/**
|
||||
* Table type.
|
||||
*/
|
||||
type: TableType;
|
||||
|
||||
/**
|
||||
* Specifies array of properties that will be used in a composite primary key of the table.
|
||||
*/
|
||||
primaryKeys?: string|((object: any) => string|any)[];
|
||||
|
||||
/**
|
||||
* Specifies a property name by which queries will perform ordering by default when fetching rows.
|
||||
*/
|
||||
orderBy?: string|((object: any) => string|any);
|
||||
};
|
||||
|
||||
/**
|
||||
* Entity column's options.
|
||||
*/
|
||||
columns: {
|
||||
[columnName: string]: {
|
||||
|
||||
/**
|
||||
* Column mode in which column will work.
|
||||
* For example, "primary" means that it will be a primary column, or "createDate" means that it will create a create
|
||||
* date column.
|
||||
*/
|
||||
mode: ColumnMode;
|
||||
|
||||
/**
|
||||
* Column type. Must be one of the value from the ColumnTypes class.
|
||||
*/
|
||||
type: ColumnType;
|
||||
|
||||
/**
|
||||
* Column name in the database.
|
||||
*/
|
||||
name?: string;
|
||||
|
||||
/**
|
||||
* Column type's length. For example type = "string" and length = 100 means that ORM will create a column with
|
||||
* type varchar(100).
|
||||
*/
|
||||
length?: string;
|
||||
|
||||
/**
|
||||
* Specifies if this column will use AUTO_INCREMENT or not (e.g. generated number).
|
||||
*/
|
||||
generated?: boolean;
|
||||
|
||||
/**
|
||||
* Specifies if column's value must be unique or not.
|
||||
*/
|
||||
unique?: boolean;
|
||||
|
||||
/**
|
||||
* Indicates if column's value can be set to NULL.
|
||||
*/
|
||||
nullable?: boolean;
|
||||
|
||||
/**
|
||||
* Extra column definition. Should be used only in emergency situations. Note that if you'll use this property
|
||||
* auto schema generation will not work properly anymore. Avoid using it.
|
||||
*/
|
||||
columnDefinition?: string;
|
||||
|
||||
/**
|
||||
* Column comment.
|
||||
*/
|
||||
comment?: string;
|
||||
|
||||
/**
|
||||
* Column name used previously for this column. Used to make safe schema updates. Experimental and most probably
|
||||
* will be removed in the future. Avoid using it.
|
||||
*/
|
||||
oldColumnName?: string;
|
||||
|
||||
/**
|
||||
* The precision for a decimal (exact numeric) column (applies only for decimal column), which is the maximum
|
||||
* number of digits that are stored for the values.
|
||||
*/
|
||||
precision?: number;
|
||||
|
||||
/**
|
||||
* The scale for a decimal (exact numeric) column (applies only for decimal column), which represents the number
|
||||
* of digits to the right of the decimal point and must not be greater than precision.
|
||||
*/
|
||||
scale?: number;
|
||||
|
||||
/**
|
||||
* Column collation. Note that not all databases support it.
|
||||
*/
|
||||
collation?: string; // todo: looks like this is not used
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Entity relation's options.
|
||||
*/
|
||||
relations: {
|
||||
[relationName: string]: {
|
||||
|
||||
/**
|
||||
* Type of relation. Can be one of the value of the RelationTypes class.
|
||||
*/
|
||||
relationType: RelationType;
|
||||
|
||||
/**
|
||||
* Type of the relation. This type is in function because of language specifics and problems with recursive
|
||||
* referenced classes.
|
||||
*/
|
||||
type: string;
|
||||
|
||||
/**
|
||||
* Inverse side of the relation.
|
||||
*/
|
||||
inverseSide?: string;
|
||||
|
||||
/**
|
||||
* Join table options of this column. If set to true then it simply means that it has a join table.
|
||||
*/
|
||||
joinTable?: boolean|{
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Join column options of this column. If set to true then it simply means that it has a join column.
|
||||
*/
|
||||
joinColumn?: boolean|{
|
||||
|
||||
/**
|
||||
* Name of the column.
|
||||
*/
|
||||
name?: string;
|
||||
|
||||
/**
|
||||
* Name of the column in the entity to which this column is referenced.
|
||||
*/
|
||||
referencedColumnName?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Indicates if this is a parent (can be only many-to-one relation) relation in the tree tables.
|
||||
*/
|
||||
isTreeParent?: boolean;
|
||||
|
||||
/**
|
||||
* Indicates if this is a children (can be only one-to-many relation) relation in the tree tables.
|
||||
*/
|
||||
isTreeChildren?: boolean;
|
||||
|
||||
/**
|
||||
* If set to true then it means that related object can be allowed to be inserted / updated / removed to the db.
|
||||
* This is option a shortcut if you would like to set cascadeInsert, cascadeUpdate and cascadeRemove to true.
|
||||
*/
|
||||
cascadeAll?: boolean;
|
||||
|
||||
/**
|
||||
* If set to true then it means that related object can be allowed to be inserted to the db.
|
||||
*/
|
||||
cascadeInsert?: boolean;
|
||||
|
||||
/**
|
||||
* If set to true then it means that related object can be allowed to be updated in the db.
|
||||
*/
|
||||
cascadeUpdate?: boolean;
|
||||
|
||||
/**
|
||||
* If set to true then it means that related object can be allowed to be remove from the db.
|
||||
*/
|
||||
cascadeRemove?: boolean;
|
||||
|
||||
/**
|
||||
* Column name used previously for this column. Used to make safe schema updates. Experimental and most probably
|
||||
* will be removed in the future. Avoid using it.
|
||||
*/
|
||||
oldColumnName?: string;
|
||||
|
||||
/**
|
||||
* Indicates if relation column value can be nullable or not.
|
||||
*/
|
||||
nullable?: boolean;
|
||||
|
||||
/**
|
||||
* Database cascade action on delete.
|
||||
*/
|
||||
onDelete?: OnDeleteType;
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
@ -8,6 +8,7 @@ import {Category} from "./entity/Category";
|
||||
import {CreateConnectionOptions} from "../../../../src/connection-manager/CreateConnectionOptions";
|
||||
import {createConnection} from "../../../../src/index";
|
||||
import {CategoryMetadata} from "./entity/CategoryMetadata";
|
||||
import {setupConnection} from "../../../utils/utils";
|
||||
|
||||
chai.should();
|
||||
chai.use(require("sinon-chai"));
|
||||
@ -19,35 +20,10 @@ describe("persistence > custom-column-names", function() {
|
||||
// Configuration
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
const parameters: CreateConnectionOptions = {
|
||||
driver: "mysql",
|
||||
connection: {
|
||||
host: "192.168.99.100",
|
||||
port: 3306,
|
||||
username: "root",
|
||||
password: "admin",
|
||||
database: "test",
|
||||
autoSchemaCreate: true,
|
||||
logging: {
|
||||
logFailedQueryError: true
|
||||
}
|
||||
},
|
||||
entities: [Post, Category, CategoryMetadata]
|
||||
};
|
||||
// connect to db
|
||||
let connection: Connection;
|
||||
before(function() {
|
||||
return createConnection(parameters)
|
||||
.then(con => connection = con)
|
||||
.catch(e => {
|
||||
console.log("Error during connection to db: " + e);
|
||||
throw e;
|
||||
});
|
||||
});
|
||||
|
||||
after(function() {
|
||||
connection.close();
|
||||
});
|
||||
before(setupConnection(con => connection = con, [Post, Category, CategoryMetadata]));
|
||||
after(() => connection.close());
|
||||
|
||||
// clean up database before each test
|
||||
function reloadDatabase() {
|
||||
|
||||
@ -2,7 +2,7 @@ import {CreateConnectionOptions} from "../../src/connection-manager/CreateConnec
|
||||
import {createConnection} from "../../src/index";
|
||||
import {Connection} from "../../src/connection/Connection";
|
||||
|
||||
export function setupConnection(entities: Function[], callback?: (connection: Connection) => any) {
|
||||
export function setupConnection(callback: (connection: Connection) => any, entities: Function[]) {
|
||||
|
||||
const parameters: CreateConnectionOptions = {
|
||||
driver: "mysql",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user