mirror of
https://github.com/typeorm/typeorm.git
synced 2025-12-08 21:26:23 +00:00
upgraded typescript version and fixed all strictNullChecks flag errors
This commit is contained in:
parent
bcb684dced
commit
bd36765c54
@ -791,6 +791,8 @@ Feel free to contribute ;)
|
||||
* send entity changeset in update event
|
||||
* create a gulp task for schema update
|
||||
* fixtures and migrations
|
||||
* lazy loading of properties throw promises? Property can have a Promise\<Entity\> type.
|
||||
* cover everything with tests
|
||||
|
||||
|
||||
[1]: https://en.wikipedia.org/wiki/Object-relational_mapping
|
||||
|
||||
@ -46,7 +46,7 @@ createConnection(options).then(connection => {
|
||||
.persist(entity)
|
||||
.then(entity => {
|
||||
console.log("EverythingEntity has been saved. Lets insert a new one to update it later");
|
||||
entity.id = null;
|
||||
delete entity.id;
|
||||
return postRepository.persist(entity);
|
||||
})
|
||||
.then(entity => {
|
||||
@ -76,7 +76,7 @@ createConnection(options).then(connection => {
|
||||
.then(entity => {
|
||||
console.log("Entity has been updated. Persist once again to make find and remove then");
|
||||
|
||||
entity.id = null;
|
||||
delete entity.id;
|
||||
return postRepository.persist(entity);
|
||||
})
|
||||
.then(entity => {
|
||||
|
||||
@ -47,7 +47,7 @@ export class Post {
|
||||
@OneToOne(type => PostMetadata, metadata => metadata.post, {
|
||||
cascadeRemove: true
|
||||
})
|
||||
metadata: PostMetadata;
|
||||
metadata: PostMetadata|undefined;
|
||||
|
||||
// post has relation with details. full cascades here
|
||||
@OneToOne(type => PostInformation, information => information.post, {
|
||||
|
||||
@ -47,7 +47,7 @@ export class Post {
|
||||
@ManyToOne(type => PostMetadata, metadata => metadata.posts, {
|
||||
cascadeRemove: true
|
||||
})
|
||||
metadata: PostMetadata;
|
||||
metadata: PostMetadata|undefined;
|
||||
|
||||
// post has relation with details. full cascades here
|
||||
@ManyToOne(type => PostInformation, information => information.posts, {
|
||||
|
||||
@ -9,9 +9,5 @@ export class PostCategory {
|
||||
|
||||
@Column()
|
||||
name: string;
|
||||
|
||||
constructor(name?: string) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
}
|
||||
@ -107,6 +107,8 @@ export class Connection {
|
||||
return this._driver.connect().then(() => {
|
||||
if (this._options.autoSchemaCreate === true)
|
||||
return schemaCreator.create();
|
||||
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -57,15 +57,13 @@ export class ConnectionManager {
|
||||
* Creates and adds a new connection with given driver.
|
||||
*/
|
||||
createConnection(driver: Driver, options: ConnectionOptions): Connection;
|
||||
createConnection(name: string, driver: Driver, options: ConnectionOptions): Connection;
|
||||
createConnection(nameOrDriver: string|Driver, driver?: Driver|ConnectionOptions, options?: ConnectionOptions): Connection {
|
||||
if (typeof nameOrDriver === "object") {
|
||||
options = <ConnectionOptions> driver;
|
||||
driver = <Driver> nameOrDriver;
|
||||
}
|
||||
const name = typeof nameOrDriver === "string" ? <string> nameOrDriver : "default";
|
||||
createConnection(name: string|undefined, driver: Driver, options: ConnectionOptions): Connection;
|
||||
createConnection(nameOrDriver: string|undefined|Driver, driverOrOptions?: Driver|ConnectionOptions, maybeOptions?: ConnectionOptions): Connection {
|
||||
const name = typeof nameOrDriver === "string" ? nameOrDriver : "default";
|
||||
const driver = typeof nameOrDriver === "object" ? <Driver> nameOrDriver : <Driver> driverOrOptions;
|
||||
const options = typeof nameOrDriver === "object" ? <ConnectionOptions> driverOrOptions : <ConnectionOptions> maybeOptions;
|
||||
|
||||
return this.connections.createAndPush(name, <Driver> driver, options);
|
||||
return this.connections.createAndPush(name, driver, options);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -86,14 +84,10 @@ export class ConnectionManager {
|
||||
* then default connection is used.
|
||||
*/
|
||||
importEntitiesFromDirectories(paths: string[]): void;
|
||||
importEntitiesFromDirectories(connectionName: string, paths: string[]): void;
|
||||
importEntitiesFromDirectories(connectionNameOrPaths: string|string[], paths?: string[]): void {
|
||||
let connectionName = "default";
|
||||
if (paths) {
|
||||
connectionName = <string> connectionNameOrPaths;
|
||||
} else {
|
||||
paths = <string[]> connectionNameOrPaths;
|
||||
}
|
||||
importEntitiesFromDirectories(connectionName: string|undefined, paths: string[]): void;
|
||||
importEntitiesFromDirectories(connectionNameOrPaths: string|string[]|undefined, maybePaths?: string[]): void {
|
||||
const connectionName = typeof connectionNameOrPaths === "string" ? connectionNameOrPaths : "default";
|
||||
const paths = maybePaths ? <string[]> maybePaths : <string[]> connectionNameOrPaths;
|
||||
|
||||
this.importEntities(connectionName, importClassesFromDirectories(paths));
|
||||
}
|
||||
@ -103,14 +97,10 @@ export class ConnectionManager {
|
||||
* then default connection is used.
|
||||
*/
|
||||
importSubscribersFromDirectories(paths: string[]): void;
|
||||
importSubscribersFromDirectories(connectionName: string, paths: string[]): void;
|
||||
importSubscribersFromDirectories(connectionNameOrPaths: string|string[], paths?: string[]): void {
|
||||
let connectionName = "default";
|
||||
if (paths) {
|
||||
connectionName = <string> connectionNameOrPaths;
|
||||
} else {
|
||||
paths = <string[]> connectionNameOrPaths;
|
||||
}
|
||||
importSubscribersFromDirectories(connectionName: string|undefined, paths: string[]): void;
|
||||
importSubscribersFromDirectories(connectionNameOrPaths: string|string[]|undefined, maybePaths?: string[]): void {
|
||||
const connectionName = typeof connectionNameOrPaths === "string" ? connectionNameOrPaths : "default";
|
||||
const paths = maybePaths ? <string[]> maybePaths : <string[]> connectionNameOrPaths;
|
||||
|
||||
this.importSubscribers(connectionName, importClassesFromDirectories(paths));
|
||||
}
|
||||
@ -119,14 +109,13 @@ export class ConnectionManager {
|
||||
* Imports entities for the given connection. If connection name is not given then default connection is used.
|
||||
*/
|
||||
importEntities(entities: Function[]): void;
|
||||
importEntities(connectionName: string, entities: Function[]): void;
|
||||
importEntities(connectionNameOrEntities: string|Function[], entities?: Function[]): void {
|
||||
let connectionName = "default";
|
||||
if (entities) {
|
||||
connectionName = <string> connectionNameOrEntities;
|
||||
} else {
|
||||
entities = <Function[]> connectionNameOrEntities;
|
||||
}
|
||||
importEntities(connectionName: string|undefined, entities: Function[]): void;
|
||||
importEntities(connectionNameOrEntities: string|undefined|Function[], maybeEntities?: Function[]): void {
|
||||
const connectionName = typeof connectionNameOrEntities === "string" ? connectionNameOrEntities : "default";
|
||||
const entities = maybeEntities ? <Function[]> maybeEntities : <Function[]> connectionNameOrEntities;
|
||||
|
||||
// console.log("entities", entities);
|
||||
|
||||
const entityMetadatas = this.entityMetadataBuilder.build(entities);
|
||||
const entityListenerMetadatas = defaultMetadataStorage.findEntityListenersForClasses(entities);
|
||||
|
||||
@ -139,14 +128,10 @@ export class ConnectionManager {
|
||||
* Imports entities for the given connection. If connection name is not given then default connection is used.
|
||||
*/
|
||||
importSubscribers(subscriberClasses: Function[]): void;
|
||||
importSubscribers(connectionName: string, subscriberClasses: Function[]): void;
|
||||
importSubscribers(connectionNameOrSubscriberClasses: string|Function[], subscriberClasses?: Function[]): void {
|
||||
let connectionName = "default";
|
||||
if (subscriberClasses) {
|
||||
connectionName = <string> connectionNameOrSubscriberClasses;
|
||||
} else {
|
||||
subscriberClasses = <Function[]> connectionNameOrSubscriberClasses;
|
||||
}
|
||||
importSubscribers(connectionName: string|undefined, subscriberClasses: Function[]): void;
|
||||
importSubscribers(connectionNameOrSubscriberClasses: string|undefined|Function[], maybeSubscriberClasses?: Function[]): void {
|
||||
const connectionName = typeof connectionNameOrSubscriberClasses === "string" ? connectionNameOrSubscriberClasses : "default";
|
||||
const subscriberClasses = maybeSubscriberClasses ? <Function[]> maybeSubscriberClasses : <Function[]> connectionNameOrSubscriberClasses;
|
||||
|
||||
const subscribers = defaultMetadataStorage
|
||||
.findEventSubscribersForClasses(subscriberClasses)
|
||||
|
||||
@ -38,19 +38,18 @@ export function Column(typeOrOptions?: ColumnType|ColumnOptions, options?: Colum
|
||||
type = ColumnTypes.determineTypeFromFunction(Reflect.getMetadata("design:type", object, propertyName));
|
||||
|
||||
// if column options are not given then create a new empty options
|
||||
if (!options)
|
||||
options = {};
|
||||
const columnOptions = options ? options : {} as ColumnOptions;
|
||||
|
||||
// check if there is no type in column options then set type from first function argument, or guessed one
|
||||
if (!options.type)
|
||||
options.type = type;
|
||||
if (!columnOptions.type)
|
||||
columnOptions.type = type;
|
||||
|
||||
// if we still don't have a type then we need to give error to user that type is required
|
||||
if (!options.type)
|
||||
if (!columnOptions.type)
|
||||
throw new ColumnTypeUndefinedError(object, propertyName);
|
||||
|
||||
// check if auto increment is not set for simple column
|
||||
if (options.autoIncrement)
|
||||
if (columnOptions.autoIncrement)
|
||||
throw new AutoIncrementOnlyForPrimaryError(object, propertyName);
|
||||
|
||||
// create and register a new column metadata
|
||||
@ -58,7 +57,7 @@ export function Column(typeOrOptions?: ColumnType|ColumnOptions, options?: Colum
|
||||
target: object.constructor,
|
||||
propertyName: propertyName,
|
||||
propertyType: reflectedType,
|
||||
options: options
|
||||
options: columnOptions
|
||||
}));
|
||||
};
|
||||
}
|
||||
|
||||
@ -14,11 +14,10 @@ export function CreateDateColumn(options?: ColumnOptions): Function {
|
||||
const reflectedType = ColumnTypes.typeToString(Reflect.getMetadata("design:type", object, propertyName));
|
||||
|
||||
// if column options are not given then create a new empty options
|
||||
if (!options)
|
||||
options = {};
|
||||
const columnOptions = options ? options : {} as ColumnOptions;
|
||||
|
||||
// implicitly set a type, because this column's type cannot be anything else except date
|
||||
options.type = <ColumnType> ColumnTypes.DATETIME;
|
||||
columnOptions.type = ColumnTypes.DATETIME;
|
||||
|
||||
// create and register a new column metadata
|
||||
defaultMetadataStorage.addColumnMetadata(new ColumnMetadata({
|
||||
@ -26,7 +25,7 @@ export function CreateDateColumn(options?: ColumnOptions): Function {
|
||||
propertyName: propertyName,
|
||||
propertyType: reflectedType,
|
||||
isCreateDate: true,
|
||||
options: options
|
||||
options: columnOptions
|
||||
}));
|
||||
};
|
||||
}
|
||||
|
||||
@ -41,19 +41,18 @@ export function PrimaryColumn(typeOrOptions?: ColumnType|ColumnOptions, options?
|
||||
type = ColumnTypes.determineTypeFromFunction(Reflect.getMetadata("design:type", object, propertyName));
|
||||
|
||||
// if column options are not given then create a new empty options
|
||||
if (!options)
|
||||
options = {};
|
||||
const columnOptions = options ? options : {} as ColumnOptions;
|
||||
|
||||
// check if there is no type in column options then set type from first function argument, or guessed one
|
||||
if (!options.type)
|
||||
options.type = type;
|
||||
if (!columnOptions.type)
|
||||
columnOptions.type = type;
|
||||
|
||||
// if we still don't have a type then we need to give error to user that type is required
|
||||
if (!options.type)
|
||||
if (!columnOptions.type)
|
||||
throw new ColumnTypeUndefinedError(object, propertyName);
|
||||
|
||||
// check if column is not nullable, because we cannot allow a primary key to be nullable
|
||||
if (options.nullable)
|
||||
if (columnOptions.nullable)
|
||||
throw new PrimaryColumnCannotBeNullableError(object, propertyName);
|
||||
|
||||
// create and register a new column metadata
|
||||
@ -62,7 +61,7 @@ export function PrimaryColumn(typeOrOptions?: ColumnType|ColumnOptions, options?
|
||||
propertyName: propertyName,
|
||||
propertyType: reflectedType,
|
||||
isPrimaryKey: true,
|
||||
options: options
|
||||
options: columnOptions
|
||||
}));
|
||||
};
|
||||
}
|
||||
|
||||
@ -14,11 +14,10 @@ export function UpdateDateColumn(options?: ColumnOptions): Function {
|
||||
const reflectedType = ColumnTypes.typeToString(Reflect.getMetadata("design:type", object, propertyName));
|
||||
|
||||
// if column options are not given then create a new empty options
|
||||
if (!options)
|
||||
options = {};
|
||||
const columnOptions = options ? options : {} as ColumnOptions;
|
||||
|
||||
// implicitly set a type, because this column's type cannot be anything else except date
|
||||
options.type = <ColumnType> ColumnTypes.DATETIME;
|
||||
columnOptions.type = ColumnTypes.DATETIME;
|
||||
|
||||
// create and register a new column metadata
|
||||
defaultMetadataStorage.addColumnMetadata(new ColumnMetadata({
|
||||
@ -26,7 +25,7 @@ export function UpdateDateColumn(options?: ColumnOptions): Function {
|
||||
propertyName: propertyName,
|
||||
propertyType: reflectedType,
|
||||
isUpdateDate: true,
|
||||
options: options
|
||||
options: columnOptions
|
||||
}));
|
||||
};
|
||||
}
|
||||
|
||||
@ -37,8 +37,7 @@ export function ManyToMany<T>(typeFunction: (type?: any) => ConstructorFunction<
|
||||
|
||||
return function (object: Object, propertyName: string) {
|
||||
|
||||
if (!options)
|
||||
options = {};
|
||||
const relationOptions = options ? options : {} as RelationOptions;
|
||||
|
||||
defaultMetadataStorage.addRelationMetadata(new RelationMetadata({
|
||||
target: object.constructor,
|
||||
@ -47,7 +46,7 @@ export function ManyToMany<T>(typeFunction: (type?: any) => ConstructorFunction<
|
||||
type: typeFunction,
|
||||
inverseSideProperty: inverseSideProperty,
|
||||
isOwning: true,
|
||||
options: options
|
||||
options: relationOptions
|
||||
}));
|
||||
};
|
||||
}
|
||||
|
||||
@ -37,8 +37,7 @@ export function ManyToManyInverse<T>(typeFunction: (type?: any) => ConstructorFu
|
||||
|
||||
return function (object: Object, propertyName: string) {
|
||||
|
||||
if (!options)
|
||||
options = {};
|
||||
const relationOptions = options ? options : {} as RelationOptions;
|
||||
|
||||
defaultMetadataStorage.addRelationMetadata(new RelationMetadata({
|
||||
target: object.constructor,
|
||||
@ -47,7 +46,7 @@ export function ManyToManyInverse<T>(typeFunction: (type?: any) => ConstructorFu
|
||||
type: typeFunction,
|
||||
inverseSideProperty: inverseSideProperty,
|
||||
isOwning: false,
|
||||
options: options
|
||||
options: relationOptions
|
||||
}));
|
||||
};
|
||||
}
|
||||
|
||||
@ -37,8 +37,7 @@ export function ManyToOne<T>(typeFunction: (type?: any) => ConstructorFunction<T
|
||||
|
||||
return function (object: Object, propertyName: string) {
|
||||
|
||||
if (!options)
|
||||
options = {};
|
||||
const relationOptions = options ? options : {} as RelationOptions;
|
||||
|
||||
defaultMetadataStorage.addRelationMetadata(new RelationMetadata({
|
||||
target: object.constructor,
|
||||
@ -47,7 +46,7 @@ export function ManyToOne<T>(typeFunction: (type?: any) => ConstructorFunction<T
|
||||
type: typeFunction,
|
||||
inverseSideProperty: inverseSideProperty,
|
||||
isOwning: true,
|
||||
options: options
|
||||
options: relationOptions
|
||||
}));
|
||||
};
|
||||
}
|
||||
|
||||
@ -34,8 +34,7 @@ export function OneToMany<T>(typeFunction: (type?: any) => ConstructorFunction<T
|
||||
|
||||
return function (object: Object, propertyName: string) {
|
||||
|
||||
if (!options)
|
||||
options = {};
|
||||
const relationOptions = options ? options : {} as RelationOptions;
|
||||
|
||||
defaultMetadataStorage.addRelationMetadata(new RelationMetadata({
|
||||
target: object.constructor,
|
||||
@ -44,7 +43,7 @@ export function OneToMany<T>(typeFunction: (type?: any) => ConstructorFunction<T
|
||||
type: typeFunction,
|
||||
inverseSideProperty: inverseSideProperty,
|
||||
isOwning: false,
|
||||
options: options
|
||||
options: relationOptions
|
||||
}));
|
||||
};
|
||||
}
|
||||
|
||||
@ -34,8 +34,7 @@ export function OneToOne<T>(typeFunction: (type?: any) => ConstructorFunction<T>
|
||||
|
||||
return function (object: Object, propertyName: string) {
|
||||
|
||||
if (!options)
|
||||
options = {};
|
||||
const relationOptions = options ? options : {} as RelationOptions;
|
||||
|
||||
defaultMetadataStorage.addRelationMetadata(new RelationMetadata({
|
||||
target: object.constructor,
|
||||
@ -44,7 +43,7 @@ export function OneToOne<T>(typeFunction: (type?: any) => ConstructorFunction<T>
|
||||
type: typeFunction,
|
||||
inverseSideProperty: inverseSideProperty,
|
||||
isOwning: true,
|
||||
options: options
|
||||
options: relationOptions
|
||||
}));
|
||||
};
|
||||
}
|
||||
@ -37,8 +37,7 @@ export function OneToOneInverse<T>(typeFunction: (type?: any) => ConstructorFunc
|
||||
|
||||
return function (object: Object, propertyName: string) {
|
||||
|
||||
if (!options)
|
||||
options = {};
|
||||
const relationOptions = options ? options : {} as RelationOptions;
|
||||
|
||||
defaultMetadataStorage.addRelationMetadata(new RelationMetadata({
|
||||
target: object.constructor,
|
||||
@ -47,7 +46,7 @@ export function OneToOneInverse<T>(typeFunction: (type?: any) => ConstructorFunc
|
||||
type: typeFunction,
|
||||
inverseSideProperty: inverseSideProperty,
|
||||
isOwning: false,
|
||||
options: options
|
||||
options: relationOptions
|
||||
}));
|
||||
};
|
||||
}
|
||||
@ -6,6 +6,6 @@ import {defaultMetadataStorage} from "../../metadata-builder/MetadataStorage";
|
||||
*/
|
||||
export function AbstractTable() {
|
||||
return function (cls: Function) {
|
||||
defaultMetadataStorage.addTableMetadata(new TableMetadata(cls, undefined, true));
|
||||
defaultMetadataStorage.addTableMetadata(new TableMetadata(cls, true));
|
||||
};
|
||||
}
|
||||
@ -7,6 +7,6 @@ import {TableMetadata} from "../../metadata-builder/metadata/TableMetadata";
|
||||
*/
|
||||
export function Table(name?: string) {
|
||||
return function (cls: Function) {
|
||||
defaultMetadataStorage.addTableMetadata(new TableMetadata(cls, name, false));
|
||||
defaultMetadataStorage.addTableMetadata(new TableMetadata(cls, name));
|
||||
};
|
||||
}
|
||||
|
||||
@ -35,7 +35,7 @@ export abstract class BaseDriver {
|
||||
|
||||
protected log(message: any, level: "log"|"debug"|"info"|"error") {
|
||||
if (!this.connection.options.logging) return;
|
||||
if ( this.connection.options.logging.logger) {
|
||||
if (this.connection.options && this.connection.options.logging && this.connection.options.logging.logger) {
|
||||
this.connection.options.logging.logger(message, level);
|
||||
} else {
|
||||
switch (level) {
|
||||
|
||||
@ -59,7 +59,14 @@ export class MysqlDriver extends BaseDriver implements Driver {
|
||||
* Database name to which this connection is made.
|
||||
*/
|
||||
get db(): string {
|
||||
return this.connection.options.database;
|
||||
if (this.mysqlConnection && this.mysqlConnection.config.database)
|
||||
return this.mysqlConnection.config.database;
|
||||
|
||||
if (this.connection.options.database)
|
||||
return this.connection.options.database;
|
||||
|
||||
throw new Error("Cannot get the database name. Since database name is not explicitly given in configuration " +
|
||||
"(maybe connection url is used?), database name cannot be retrieved until connection is made.");
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@ -6,6 +6,7 @@ import {NamingStrategy} from "../naming-strategy/NamingStrategy";
|
||||
import {ColumnMetadata} from "./metadata/ColumnMetadata";
|
||||
import {ColumnOptions} from "./options/ColumnOptions";
|
||||
import {ForeignKeyMetadata} from "./metadata/ForeignKeyMetadata";
|
||||
import {JunctionTableMetadata} from "./metadata/JunctionTableMetadata";
|
||||
|
||||
/**
|
||||
* Aggregates all metadata: table, column, relation into one collection grouped by tables for a given set of classes.
|
||||
@ -130,7 +131,7 @@ export class EntityMetadataBuilder {
|
||||
const tableName = metadata.table.name + "_" + relation.name + "_" +
|
||||
inverseSideMetadata.table.name + "_" + inverseSideMetadata.primaryColumn.name;
|
||||
|
||||
const tableMetadata = new TableMetadata(null, tableName, false);
|
||||
const tableMetadata = new JunctionTableMetadata(tableName);
|
||||
const column1options: ColumnOptions = {
|
||||
length: metadata.primaryColumn.length,
|
||||
type: metadata.primaryColumn.type,
|
||||
@ -143,14 +144,10 @@ export class EntityMetadataBuilder {
|
||||
};
|
||||
const columns = [
|
||||
new ColumnMetadata({
|
||||
target: null,
|
||||
propertyName: null,
|
||||
propertyType: inverseSideMetadata.primaryColumn.type,
|
||||
options: column1options
|
||||
}),
|
||||
new ColumnMetadata({
|
||||
target: null,
|
||||
propertyName: null,
|
||||
propertyType: inverseSideMetadata.primaryColumn.type,
|
||||
options: column2options
|
||||
})
|
||||
@ -180,9 +177,7 @@ export class EntityMetadataBuilder {
|
||||
|
||||
private filterObjectPropertyMetadatasIfNotExist<T extends PropertyMetadata>(newMetadatas: T[], existsMetadatas: T[]): T[] {
|
||||
return newMetadatas.filter(fieldFromMapped => {
|
||||
return existsMetadatas.reduce((found, fieldFromDocument) => {
|
||||
return fieldFromDocument.propertyName === fieldFromMapped.propertyName ? fieldFromDocument : found;
|
||||
}, null) === null;
|
||||
return !!existsMetadatas.find(fieldFromDocument => fieldFromDocument.propertyName === fieldFromMapped.propertyName);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -11,12 +11,12 @@ export interface ColumnMetadataArgs {
|
||||
/**
|
||||
* Class to which this column is applied.
|
||||
*/
|
||||
target: Function;
|
||||
target?: Function;
|
||||
|
||||
/**
|
||||
* Class's property name to which this column is applied.
|
||||
*/
|
||||
propertyName: string;
|
||||
propertyName?: string;
|
||||
|
||||
/**
|
||||
* Class's property type (reflected) to which this column is applied.
|
||||
|
||||
@ -50,7 +50,8 @@ export class ForeignKeyMetadata {
|
||||
this._columns = columns;
|
||||
this._referencedTable = referencedTable;
|
||||
this._referencedColumns = referencedColumns;
|
||||
this._onDelete = onDelete;
|
||||
if (onDelete)
|
||||
this._onDelete = onDelete;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@ -8,7 +8,7 @@ export class IndexMetadata extends PropertyMetadata {
|
||||
/**
|
||||
* The name of the index.
|
||||
*/
|
||||
name: string;
|
||||
name: string|undefined;
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Constructor
|
||||
|
||||
16
src/metadata-builder/metadata/JunctionTableMetadata.ts
Normal file
16
src/metadata-builder/metadata/JunctionTableMetadata.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import {TableMetadata} from "./TableMetadata";
|
||||
|
||||
/**
|
||||
* This metadata interface contains all information about junction table.
|
||||
*/
|
||||
export class JunctionTableMetadata extends TableMetadata {
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Constructor
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
constructor(name: string) {
|
||||
super(undefined, name);
|
||||
}
|
||||
|
||||
}
|
||||
@ -21,9 +21,12 @@ export abstract class PropertyMetadata {
|
||||
// Constructor
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
constructor(target: Function, propertyName: string) {
|
||||
this._target = target;
|
||||
this._propertyName = propertyName;
|
||||
constructor(target?: Function, propertyName?: string) {
|
||||
if (target)
|
||||
this._target = target;
|
||||
|
||||
if (propertyName)
|
||||
this._propertyName = propertyName;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
@ -265,7 +265,8 @@ export class RelationMetadata extends PropertyMetadata {
|
||||
if (typeof inverseSide === "string")
|
||||
return <string> inverseSide;
|
||||
|
||||
return null;
|
||||
// throw new Error("Cannot compute inverse side of the relation");
|
||||
return "";
|
||||
}
|
||||
|
||||
}
|
||||
@ -31,16 +31,23 @@ export class TableMetadata {
|
||||
/**
|
||||
* Indicates if this table is abstract or not. Regular tables can inherit columns from abstract tables.
|
||||
*/
|
||||
private _isAbstract: boolean;
|
||||
private _isAbstract = false;
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Constructor
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
constructor(target: Function, name: string, isAbstract: boolean) {
|
||||
this._target = target;
|
||||
this._name = name;
|
||||
this._isAbstract = isAbstract;
|
||||
constructor(target?: Function, name?: string);
|
||||
constructor(target: Function, isAbstract: boolean);
|
||||
constructor(target: Function, nameOrIsAbstract?: string|boolean, maybeIsAbstract?: boolean) {
|
||||
if (target)
|
||||
this._target = target;
|
||||
if (typeof nameOrIsAbstract === "string")
|
||||
this._name = nameOrIsAbstract;
|
||||
if (typeof nameOrIsAbstract === "boolean")
|
||||
this._isAbstract = nameOrIsAbstract;
|
||||
if (typeof maybeIsAbstract === "boolean")
|
||||
this._isAbstract = maybeIsAbstract;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
@ -148,7 +148,8 @@ export class ColumnTypes {
|
||||
return ColumnTypes.JSON;
|
||||
|
||||
}
|
||||
return undefined;
|
||||
throw new Error(`Column type of ${type} cannot be determined.`);
|
||||
// return undefined;
|
||||
}
|
||||
|
||||
static typeToString(type: Function) {
|
||||
|
||||
@ -68,16 +68,16 @@ export class EntityPersistOperationBuilder {
|
||||
persistOperation.persistedEntity = persistedEntity;
|
||||
persistOperation.allDbEntities = dbEntities;
|
||||
persistOperation.allPersistedEntities = allPersistedEntities;
|
||||
persistOperation.inserts = this.findCascadeInsertedEntities(persistedEntity, dbEntities, null);
|
||||
persistOperation.updates = this.findCascadeUpdateEntities(metadata, dbEntity, persistedEntity, null);
|
||||
persistOperation.inserts = this.findCascadeInsertedEntities(persistedEntity, dbEntities);
|
||||
persistOperation.updates = this.findCascadeUpdateEntities(metadata, dbEntity, persistedEntity);
|
||||
persistOperation.junctionInserts = this.findJunctionInsertOperations(metadata, persistedEntity, dbEntities);
|
||||
persistOperation.updatesByRelations = this.updateRelations(persistOperation.inserts, persistedEntity);
|
||||
persistOperation.removes = this.findCascadeRemovedEntities(metadata, dbEntity, allPersistedEntities, null, null, null);
|
||||
persistOperation.removes = this.findCascadeRemovedEntities(metadata, dbEntity, allPersistedEntities, undefined, undefined, undefined);
|
||||
persistOperation.junctionRemoves = this.findJunctionRemoveOperations(metadata, dbEntity, allPersistedEntities);
|
||||
|
||||
return persistOperation;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Finds columns and relations from entity2 which does not exist or does not match in entity1.
|
||||
*/
|
||||
@ -88,31 +88,31 @@ export class EntityPersistOperationBuilder {
|
||||
allPersistedEntities: EntityWithId[]): PersistOperation {
|
||||
// const dbEntities = this.extractObjectsById(dbEntity, metadata);
|
||||
// const allEntities = this.extractObjectsById(newEntity, metadata);
|
||||
|
||||
|
||||
const persistOperation = new PersistOperation();
|
||||
persistOperation.dbEntity = dbEntity;
|
||||
persistOperation.persistedEntity = persistedEntity;
|
||||
persistOperation.allDbEntities = dbEntities;
|
||||
persistOperation.allPersistedEntities = allPersistedEntities;
|
||||
persistOperation.removes = this.findCascadeRemovedEntities(metadata, dbEntity, allPersistedEntities, null, null, null);
|
||||
persistOperation.removes = this.findCascadeRemovedEntities(metadata, dbEntity, allPersistedEntities, undefined, undefined, undefined);
|
||||
persistOperation.junctionRemoves = this.findJunctionRemoveOperations(metadata, dbEntity, allPersistedEntities);
|
||||
|
||||
return persistOperation;
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Private Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
private findCascadeInsertedEntities(newEntity: any,
|
||||
dbEntities: EntityWithId[],
|
||||
fromRelation: RelationMetadata,
|
||||
|
||||
private findCascadeInsertedEntities(newEntity: any,
|
||||
dbEntities: EntityWithId[],
|
||||
fromRelation?: RelationMetadata,
|
||||
operations: InsertOperation[] = []): InsertOperation[] {
|
||||
const metadata = this.connection.getEntityMetadata(newEntity.constructor);
|
||||
const isObjectNew = !this.findEntityWithId(dbEntities, metadata.target, newEntity[metadata.primaryColumn.name]);
|
||||
|
||||
|
||||
// if object is new and should be inserted, we check if cascades are allowed before add it to operations list
|
||||
if (isObjectNew && !this.checkCascadesAllowed("insert", metadata, fromRelation)) {
|
||||
if (isObjectNew && fromRelation && !this.checkCascadesAllowed("insert", metadata, fromRelation)) {
|
||||
return operations; // looks like object is new here, but cascades are not allowed - then we should stop iteration
|
||||
|
||||
} else if (isObjectNew && !operations.find(o => o.entity === newEntity)) { // object is new and cascades are allow here
|
||||
@ -131,22 +131,22 @@ export class EntityPersistOperationBuilder {
|
||||
this.findCascadeInsertedEntities(value, dbEntities, relation, operations);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return operations;
|
||||
}
|
||||
|
||||
private findCascadeUpdateEntities(metadata: EntityMetadata,
|
||||
dbEntity: any,
|
||||
newEntity: any,
|
||||
fromRelation: RelationMetadata): UpdateOperation[] {
|
||||
fromRelation?: RelationMetadata): UpdateOperation[] {
|
||||
let operations: UpdateOperation[] = [];
|
||||
if (!dbEntity)
|
||||
return operations;
|
||||
|
||||
const diff = this.diffColumns(metadata, newEntity, dbEntity);
|
||||
if (diff.length && !this.checkCascadesAllowed("update", metadata, fromRelation)) {
|
||||
if (diff.length && fromRelation && !this.checkCascadesAllowed("update", metadata, fromRelation)) {
|
||||
return operations;
|
||||
|
||||
|
||||
} else if (diff.length) {
|
||||
const entityId = newEntity[metadata.primaryColumn.name];
|
||||
operations.push(new UpdateOperation(newEntity, entityId, diff));
|
||||
@ -159,7 +159,7 @@ export class EntityPersistOperationBuilder {
|
||||
const relationIdColumnName = relMetadata.primaryColumn.name;
|
||||
const value = newEntity[relation.propertyName];
|
||||
const dbValue = dbEntity[relation.propertyName];
|
||||
|
||||
|
||||
if (value instanceof Array) {
|
||||
value.forEach((subEntity: any) => {
|
||||
const subDbEntity = dbValue.find((subDbEntity: any) => {
|
||||
@ -173,15 +173,15 @@ export class EntityPersistOperationBuilder {
|
||||
operations = operations.concat(relationOperations);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return operations;
|
||||
}
|
||||
|
||||
private findCascadeRemovedEntities(metadata: EntityMetadata,
|
||||
dbEntity: any,
|
||||
allPersistedEntities: EntityWithId[],
|
||||
fromRelation: RelationMetadata,
|
||||
fromMetadata: EntityMetadata,
|
||||
fromRelation: RelationMetadata|undefined,
|
||||
fromMetadata: EntityMetadata|undefined,
|
||||
fromEntityId: any,
|
||||
parentAlreadyRemoved: boolean = false): RemoveOperation[] {
|
||||
let operations: RemoveOperation[] = [];
|
||||
@ -192,11 +192,11 @@ export class EntityPersistOperationBuilder {
|
||||
const isObjectRemoved = parentAlreadyRemoved || !this.findEntityWithId(allPersistedEntities, metadata.target, entityId);
|
||||
|
||||
// if object is removed and should be removed, we check if cascades are allowed before add it to operations list
|
||||
if (isObjectRemoved && !this.checkCascadesAllowed("remove", metadata, fromRelation)) {
|
||||
if (isObjectRemoved && fromRelation && !this.checkCascadesAllowed("remove", metadata, fromRelation)) {
|
||||
return operations; // looks like object is removed here, but cascades are not allowed - then we should stop iteration
|
||||
|
||||
} else if (isObjectRemoved) { // object is remove and cascades are allow here
|
||||
operations.push(new RemoveOperation(dbEntity, entityId, fromMetadata, fromRelation, fromEntityId));
|
||||
operations.push(new RemoveOperation(dbEntity, entityId, <EntityMetadata> fromMetadata, fromRelation, fromEntityId));
|
||||
}
|
||||
|
||||
metadata.relations
|
||||
@ -257,7 +257,7 @@ export class EntityPersistOperationBuilder {
|
||||
return operations;
|
||||
}, <UpdateByRelationOperation[]> []);
|
||||
}
|
||||
|
||||
|
||||
private findJunctionInsertOperations(metadata: EntityMetadata, newEntity: any, dbEntities: EntityWithId[]): JunctionInsertOperation[] {
|
||||
const dbEntity = dbEntities.find(dbEntity => {
|
||||
return dbEntity.id === newEntity[metadata.primaryColumn.name] && dbEntity.entity.constructor === metadata.target;
|
||||
@ -288,11 +288,11 @@ export class EntityPersistOperationBuilder {
|
||||
return operations;
|
||||
}, <JunctionInsertOperation[]> []);
|
||||
}
|
||||
|
||||
|
||||
private findJunctionRemoveOperations(metadata: EntityMetadata, dbEntity: any, newEntities: EntityWithId[]): JunctionInsertOperation[] {
|
||||
if (!dbEntity) // if new entity is persisted then it does not have anything to be deleted
|
||||
return [];
|
||||
|
||||
|
||||
const newEntity = newEntities.find(newEntity => {
|
||||
return newEntity.id === dbEntity[metadata.primaryColumn.name] && newEntity.entity.constructor === metadata.target;
|
||||
});
|
||||
@ -334,9 +334,6 @@ export class EntityPersistOperationBuilder {
|
||||
}
|
||||
|
||||
private checkCascadesAllowed(type: "insert"|"update"|"remove", metadata: EntityMetadata, relation: RelationMetadata) {
|
||||
if (!relation)
|
||||
return true;
|
||||
|
||||
let isAllowed = false;
|
||||
switch (type) {
|
||||
case "insert":
|
||||
|
||||
@ -150,7 +150,9 @@ export class PersistOperationExecutor {
|
||||
*/
|
||||
private executeRemoveRelationOperations(persistOperation: PersistOperation) {
|
||||
return Promise.all(persistOperation.removes
|
||||
.filter(operation => operation.relation && !operation.relation.isManyToMany && !operation.relation.isOneToMany)
|
||||
.filter(operation => {
|
||||
return !!(operation.relation && !operation.relation.isManyToMany && !operation.relation.isOneToMany);
|
||||
})
|
||||
.map(operation => {
|
||||
return this.updateDeletedRelations(operation);
|
||||
})
|
||||
@ -228,11 +230,15 @@ export class PersistOperationExecutor {
|
||||
}
|
||||
|
||||
private updateDeletedRelations(removeOperation: RemoveOperation) { // todo: check if both many-to-one deletions work too
|
||||
return this.connection.driver.update(
|
||||
removeOperation.fromMetadata.table.name,
|
||||
{ [removeOperation.relation.name]: null },
|
||||
{ [removeOperation.fromMetadata.primaryColumn.name]: removeOperation.fromEntityId }
|
||||
);
|
||||
if (removeOperation.relation) {
|
||||
return this.connection.driver.update(
|
||||
removeOperation.fromMetadata.table.name,
|
||||
{ [removeOperation.relation.name]: null },
|
||||
{ [removeOperation.fromMetadata.primaryColumn.name]: removeOperation.fromEntityId }
|
||||
);
|
||||
}
|
||||
|
||||
throw new Error("Remove operation relation is not set"); // todo: find out how its possible
|
||||
}
|
||||
|
||||
private delete(entity: any) {
|
||||
|
||||
@ -5,7 +5,7 @@ export class RemoveOperation {
|
||||
constructor(public entity: any,
|
||||
public entityId: any,
|
||||
public fromMetadata: EntityMetadata, // todo: use relation.metadata instead?
|
||||
public relation: RelationMetadata,
|
||||
public relation: RelationMetadata|undefined,
|
||||
public fromEntityId: any) {
|
||||
}
|
||||
}
|
||||
@ -77,7 +77,9 @@ export class QueryBuilder<Entity> {
|
||||
update(updateSet: Object): this;
|
||||
update(entity: Function, updateSet: Object): this;
|
||||
update(tableName: string, updateSet: Object): this;
|
||||
update(tableNameOrEntityOrUpdateSet?: string|Function, updateSet?: Object): this {
|
||||
update(tableNameOrEntityOrUpdateSet?: string|Function|Object, maybeUpdateSet?: Object): this {
|
||||
const updateSet = maybeUpdateSet ? maybeUpdateSet : <Object> tableNameOrEntityOrUpdateSet;
|
||||
|
||||
if (tableNameOrEntityOrUpdateSet instanceof Function) {
|
||||
const aliasName = (<any> tableNameOrEntityOrUpdateSet).name;
|
||||
const aliasObj = new Alias(aliasName);
|
||||
@ -85,9 +87,6 @@ export class QueryBuilder<Entity> {
|
||||
this._aliasMap.addMainAlias(aliasObj);
|
||||
this.fromEntity = { alias: aliasObj };
|
||||
|
||||
} else if (typeof tableNameOrEntityOrUpdateSet === "object") {
|
||||
updateSet = <Object> tableNameOrEntityOrUpdateSet;
|
||||
|
||||
} else if (typeof tableNameOrEntityOrUpdateSet === "string") {
|
||||
this.fromTableName = <string> tableNameOrEntityOrUpdateSet;
|
||||
}
|
||||
@ -141,34 +140,34 @@ export class QueryBuilder<Entity> {
|
||||
|
||||
innerJoinAndSelect(property: string, alias: string, conditionType?: "on"|"with", condition?: string): this;
|
||||
innerJoinAndSelect(entity: Function, alias: string, conditionType?: "on"|"with", condition?: string): this;
|
||||
innerJoinAndSelect(entityOrProperty: Function|string, alias: string, conditionType?: "on"|"with", condition?: string): this {
|
||||
innerJoinAndSelect(entityOrProperty: Function|string, alias: string, conditionType: "on"|"with" = "on", condition: string = ""): this {
|
||||
this.addSelect(alias);
|
||||
return this.join("inner", entityOrProperty, alias, conditionType, condition);
|
||||
}
|
||||
|
||||
innerJoin(property: string, alias: string, conditionType?: "on"|"with", condition?: string): this;
|
||||
innerJoin(entity: Function, alias: string, conditionType?: "on"|"with", condition?: string): this;
|
||||
innerJoin(entityOrProperty: Function|string, alias: string, conditionType?: "on"|"with", condition?: string): this {
|
||||
innerJoin(entityOrProperty: Function|string, alias: string, conditionType: "on"|"with" = "on", condition: string = ""): this {
|
||||
return this.join("inner", entityOrProperty, alias, conditionType, condition);
|
||||
}
|
||||
|
||||
leftJoinAndSelect(property: string, alias: string, conditionType?: "on"|"with", condition?: string): this;
|
||||
leftJoinAndSelect(entity: Function, alias: string, conditionType?: "on"|"with", condition?: string): this;
|
||||
leftJoinAndSelect(entityOrProperty: Function|string, alias: string, conditionType: "on"|"with" = "on", condition?: string): this {
|
||||
leftJoinAndSelect(entityOrProperty: Function|string, alias: string, conditionType: "on"|"with" = "on", condition: string = ""): this {
|
||||
this.addSelect(alias);
|
||||
return this.join("left", entityOrProperty, alias, conditionType, condition);
|
||||
}
|
||||
|
||||
leftJoin(property: string, alias: string, conditionType?: "on"|"with", condition?: string): this;
|
||||
leftJoin(entity: Function, alias: string, conditionType?: "on"|"with", condition?: string): this;
|
||||
leftJoin(entityOrProperty: Function|string, alias: string, conditionType: "on"|"with" = "on", condition?: string): this {
|
||||
leftJoin(entityOrProperty: Function|string, alias: string, conditionType: "on"|"with" = "on", condition: string = ""): this {
|
||||
return this.join("left", entityOrProperty, alias, conditionType, condition);
|
||||
}
|
||||
|
||||
join(joinType: "inner"|"left", property: string, alias: string, conditionType?: "on"|"with", condition?: string): this;
|
||||
join(joinType: "inner"|"left", entity: Function, alias: string, conditionType?: "on"|"with", condition?: string): this;
|
||||
join(joinType: "inner"|"left", entityOrProperty: Function|string, alias: string, conditionType: "on"|"with", condition: string): this;
|
||||
join(joinType: "inner"|"left", entityOrProperty: Function|string, alias: string, conditionType: "on"|"with" = "on", condition?: string): this {
|
||||
join(joinType: "inner"|"left", entityOrProperty: Function|string, alias: string, conditionType: "on"|"with" = "on", condition: string = ""): this {
|
||||
|
||||
const aliasObj = new Alias(alias);
|
||||
this._aliasMap.addAlias(aliasObj);
|
||||
|
||||
@ -20,7 +20,7 @@ export class PlainObjectToDatabaseEntityTransformer<Entity> {
|
||||
|
||||
// if object does not have id then nothing to load really
|
||||
if (!metadata.hasPrimaryKey || !object[metadata.primaryColumn.name])
|
||||
return null;
|
||||
return Promise.reject<Entity>("Given object does not have a primary column, cannot transform it to database entity.");
|
||||
|
||||
const alias = queryBuilder.aliasMap.mainAlias.name;
|
||||
const needToLoad = this.buildLoadMap(object, metadata, true);
|
||||
|
||||
@ -112,7 +112,15 @@ export class EntityManager {
|
||||
* Finds entities that match given conditions.
|
||||
*/
|
||||
find<Entity>(entityClass: ConstructorFunction<Entity>|Function, conditionsOrFindOptions?: Object|FindOptions, options?: FindOptions): Promise<Entity[]> {
|
||||
return this.getRepository(entityClass).find(conditionsOrFindOptions, options);
|
||||
if (conditionsOrFindOptions && options) {
|
||||
return this.getRepository(entityClass).find(conditionsOrFindOptions, options);
|
||||
|
||||
} else if (conditionsOrFindOptions) {
|
||||
return this.getRepository(entityClass).find(conditionsOrFindOptions);
|
||||
|
||||
} else {
|
||||
return this.getRepository(entityClass).find();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -139,7 +147,15 @@ export class EntityManager {
|
||||
* Finds entities that match given conditions.
|
||||
*/
|
||||
findAndCount<Entity>(entityClass: ConstructorFunction<Entity>|Function, conditionsOrFindOptions?: Object|FindOptions, options?: FindOptions): Promise<[Entity[], number]> {
|
||||
return this.getRepository(entityClass).findAndCount(conditionsOrFindOptions, options);
|
||||
if (conditionsOrFindOptions && options) {
|
||||
return this.getRepository(entityClass).findAndCount(conditionsOrFindOptions, options);
|
||||
|
||||
} else if (conditionsOrFindOptions) {
|
||||
return this.getRepository(entityClass).findAndCount(conditionsOrFindOptions);
|
||||
|
||||
} else {
|
||||
return this.getRepository(entityClass).findAndCount();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -166,7 +182,15 @@ export class EntityManager {
|
||||
* Finds first entity that matches given conditions.
|
||||
*/
|
||||
findOne<Entity>(entityClass: ConstructorFunction<Entity>|Function, conditionsOrFindOptions?: Object|FindOptions, options?: FindOptions): Promise<Entity> {
|
||||
return this.getRepository(entityClass).findOne(conditionsOrFindOptions, options);
|
||||
if (conditionsOrFindOptions && options) {
|
||||
return this.getRepository(entityClass).findOne(conditionsOrFindOptions, options);
|
||||
|
||||
} else if (conditionsOrFindOptions) {
|
||||
return this.getRepository(entityClass).findOne(conditionsOrFindOptions);
|
||||
|
||||
} else {
|
||||
return this.getRepository(entityClass).findOne();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import {QueryBuilder} from "../query-builder/QueryBuilder";
|
||||
import {ConnectionOptions} from "../connection/ConnectionOptions";
|
||||
|
||||
/**
|
||||
* Options to be passed to find methods.
|
||||
@ -207,16 +208,28 @@ export class FindOptionsUtils {
|
||||
options.groupBy.forEach(groupBy => qb.addGroupBy(groupBy));
|
||||
|
||||
if (options.leftJoin)
|
||||
Object.keys(options.leftJoin).forEach(key => qb.leftJoin(options.leftJoin[key], key));
|
||||
Object.keys(options.leftJoin).forEach(key => {
|
||||
if (options.leftJoin) // this check because of tsc bug
|
||||
qb.leftJoin(options.leftJoin[key], key);
|
||||
});
|
||||
|
||||
if (options.innerJoin)
|
||||
Object.keys(options.innerJoin).forEach(key => qb.innerJoin(options.innerJoin[key], key));
|
||||
Object.keys(options.innerJoin).forEach(key => {
|
||||
if (options.innerJoin) // this check because of tsc bug
|
||||
qb.innerJoin(options.innerJoin[key], key);
|
||||
});
|
||||
|
||||
if (options.leftJoinAndSelect)
|
||||
Object.keys(options.leftJoinAndSelect).forEach(key => qb.leftJoinAndSelect(options.leftJoinAndSelect[key], key));
|
||||
Object.keys(options.leftJoinAndSelect).forEach(key => {
|
||||
if (options.leftJoinAndSelect) // this check because of tsc bug
|
||||
qb.leftJoinAndSelect(options.leftJoinAndSelect[key], key);
|
||||
});
|
||||
|
||||
if (options.innerJoinAndSelect)
|
||||
Object.keys(options.innerJoinAndSelect).forEach(key => qb.innerJoinAndSelect(options.innerJoinAndSelect[key], key));
|
||||
Object.keys(options.innerJoinAndSelect).forEach(key => {
|
||||
if (options.innerJoinAndSelect) // this check because of tsc bug
|
||||
qb.innerJoinAndSelect(options.innerJoinAndSelect[key], key);
|
||||
});
|
||||
|
||||
if (options.parameters)
|
||||
qb.addParameters(options.parameters);
|
||||
|
||||
@ -92,11 +92,12 @@ export class Repository<Entity> {
|
||||
const persister = new PersistOperationExecutor(this.connection);
|
||||
const builder = new EntityPersistOperationBuilder(this.connection);
|
||||
const allPersistedEntities = this.extractObjectsById(entity, this.metadata);
|
||||
const promise = !this.hasId(entity) ? Promise.resolve(null) : this.initialize(entity);
|
||||
const promise: Promise<Entity> = !this.hasId(entity) ? Promise.resolve<Entity|null>(null) : this.initialize(entity);
|
||||
return promise
|
||||
.then(dbEntity => {
|
||||
loadedDbEntity = dbEntity;
|
||||
return this.findNotLoadedIds(this.extractObjectsById(dbEntity, this.metadata), allPersistedEntities);
|
||||
const entityWithIds = dbEntity ? this.extractObjectsById(dbEntity, this.metadata) : [];
|
||||
return this.findNotLoadedIds(entityWithIds, allPersistedEntities);
|
||||
}) // need to find db entities that were not loaded by initialize method
|
||||
.then(allDbEntities => {
|
||||
const persistOperation = builder.buildFullPersistment(this.metadata, loadedDbEntity, entity, allDbEntities, allPersistedEntities);
|
||||
@ -238,15 +239,10 @@ export class Repository<Entity> {
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
private createFindQueryBuilder(conditionsOrFindOptions?: Object|FindOptions, options?: FindOptions) {
|
||||
let findOptions: FindOptions, conditions: Object;
|
||||
if (FindOptionsUtils.isFindOptions(conditionsOrFindOptions)) {
|
||||
findOptions = conditionsOrFindOptions;
|
||||
} else {
|
||||
findOptions = options;
|
||||
conditions = conditionsOrFindOptions;
|
||||
}
|
||||
const findOptions = FindOptionsUtils.isFindOptions(conditionsOrFindOptions) ? conditionsOrFindOptions : <FindOptions> options;
|
||||
const conditions = FindOptionsUtils.isFindOptions(conditionsOrFindOptions) ? undefined : conditionsOrFindOptions;
|
||||
|
||||
const alias = findOptions ? options.alias : this.metadata.table.name;
|
||||
const alias = findOptions ? findOptions.alias : this.metadata.table.name;
|
||||
const qb = this.createQueryBuilder(alias);
|
||||
if (findOptions) {
|
||||
FindOptionsUtils.applyOptionsToQueryBuilder(qb, findOptions);
|
||||
@ -294,9 +290,6 @@ export class Repository<Entity> {
|
||||
* Extracts unique objects from given entity and all its downside relations.
|
||||
*/
|
||||
private extractObjectsById(entity: any, metadata: EntityMetadata, entityWithIds: EntityWithId[] = []): EntityWithId[] {
|
||||
if (!entity)
|
||||
return entityWithIds;
|
||||
|
||||
metadata.relations
|
||||
.filter(relation => !!entity[relation.propertyName])
|
||||
.forEach(relation => {
|
||||
|
||||
@ -111,6 +111,8 @@ export class SchemaCreator {
|
||||
return this.schemaBuilder.checkIfTableExist(table.name).then(exist => {
|
||||
if (!exist)
|
||||
return this.schemaBuilder.createTableQuery(table, columns);
|
||||
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
|
||||
@ -213,6 +215,8 @@ export class SchemaCreator {
|
||||
return this.schemaBuilder.getPrimaryConstraintName(table.name).then(constraintName => {
|
||||
if (constraintName)
|
||||
return this.schemaBuilder.dropIndex(table.name, constraintName);
|
||||
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -1,3 +1,7 @@
|
||||
/*!
|
||||
|
||||
*/
|
||||
|
||||
import {ConnectionOptions} from "./connection/ConnectionOptions";
|
||||
import {ConnectionManager} from "./connection/ConnectionManager";
|
||||
import {Connection} from "./connection/Connection";
|
||||
|
||||
@ -77,7 +77,7 @@ describe("insertion", function() {
|
||||
});
|
||||
|
||||
it("should have inserted post in the database", function() {
|
||||
postRepository.findById(savedPost.id).then(p => console.log(p));
|
||||
// postRepository.findById(savedPost.id).then(p => console.log(p));
|
||||
return postRepository.findById(savedPost.id).should.eventually.eql({
|
||||
id: savedPost.id,
|
||||
text: "Hello post",
|
||||
|
||||
@ -327,7 +327,7 @@ describe("one-to-one", function() {
|
||||
});
|
||||
|
||||
it("should ignore updates in the model and do not update the db when entity is updated", function () {
|
||||
newPost.details = null;
|
||||
delete newPost.details;
|
||||
return postRepository.persist(newPost).then(updatedPost => {
|
||||
return postRepository
|
||||
.createQueryBuilder("post")
|
||||
@ -421,7 +421,7 @@ describe("one-to-one", function() {
|
||||
.getSingleResult();
|
||||
|
||||
}).then(loadedPost => {
|
||||
loadedPost.metadata = null;
|
||||
loadedPost.metadata = undefined;
|
||||
return postRepository.persist(loadedPost);
|
||||
|
||||
}).then(() => {
|
||||
@ -433,7 +433,7 @@ describe("one-to-one", function() {
|
||||
.getSingleResult();
|
||||
|
||||
}).then(reloadedPost => {
|
||||
expect(reloadedPost.metadata).to.be.empty;
|
||||
expect(reloadedPost.metadata).to.not.exist;
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@ -326,7 +326,7 @@ describe("many-to-one", function() {
|
||||
});
|
||||
|
||||
it("should ignore updates in the model and do not update the db when entity is updated", function () {
|
||||
newPost.details = null;
|
||||
delete newPost.details;
|
||||
return postRepository.persist(newPost).then(updatedPost => {
|
||||
return postRepository
|
||||
.createQueryBuilder("post")
|
||||
@ -420,7 +420,7 @@ describe("many-to-one", function() {
|
||||
.getSingleResult();
|
||||
|
||||
}).then(loadedPost => {
|
||||
loadedPost.metadata = null;
|
||||
loadedPost.metadata = undefined;
|
||||
return postRepository.persist(loadedPost);
|
||||
|
||||
}).then(() => {
|
||||
|
||||
@ -346,7 +346,7 @@ describe("many-to-many", function() {
|
||||
});
|
||||
|
||||
it("should remove relation however should not remove details itself", function () {
|
||||
newPost.details = null;
|
||||
newPost.details = [];
|
||||
return postRepository.persist(newPost).then(updatedPost => {
|
||||
return postRepository
|
||||
.createQueryBuilder("post")
|
||||
@ -450,7 +450,7 @@ describe("many-to-many", function() {
|
||||
.getSingleResult();
|
||||
|
||||
}).then(loadedPost => {
|
||||
loadedPost.metadatas = null;
|
||||
loadedPost.metadatas = [];
|
||||
return postRepository.persist(loadedPost);
|
||||
|
||||
}).then(() => {
|
||||
|
||||
@ -9,12 +9,16 @@
|
||||
"experimentalDecorators": true,
|
||||
"sourceMap": true,
|
||||
"noImplicitAny": true,
|
||||
"declaration": true
|
||||
"declaration": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noImplicitReturns": true,
|
||||
"stripInternal": true,
|
||||
"pretty": true,
|
||||
"strictNullChecks": true
|
||||
},
|
||||
"exclude": [
|
||||
"build",
|
||||
"node_modules",
|
||||
"odmhelpers",
|
||||
"typings/browser.d.ts",
|
||||
"typings/browser"
|
||||
]
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user