diff --git a/package.json b/package.json index d7717ac..a5e8d90 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wetland", - "version": "0.6.2", + "version": "0.7.0", "description": "An enterprise grade ORM for Node.js.", "main": "./build/src/index.js", "typings": "./build/src/index.d.ts", diff --git a/src/Mapping.ts b/src/Mapping.ts index fd22741..4e85074 100644 --- a/src/Mapping.ts +++ b/src/Mapping.ts @@ -33,16 +33,6 @@ export class Mapping { */ public static CASCADE_PERSIST = 'persist'; - /** - * @type {string} - */ - public static CASCADE_UPDATE = 'update'; - - /** - * @type {string} - */ - public static CASCADE_DELETE = 'delete'; - /** * The mapping data. * @@ -234,7 +224,7 @@ export class Mapping { indexName = `idx_${(fields as Array).join('_').toLowerCase()}}`; } - let indexes = this.mapping.fetchOrPut(`indexes.${indexName}`, new ArrayCollection); + let indexes = this.mapping.fetchOrPut(`indexes.${indexName}`, new ArrayCollection); indexes.add(...(Array.isArray(fields) ? fields : [fields]) as Array); @@ -554,7 +544,14 @@ export class Mapping { * @returns {Mapping} */ public joinColumn(property: string, options: JoinColumn): this { - this.extendField(property, {joinColumn: options}); + this.extendField(property, { + joinColumn: Homefront.merge({ + name : `${property}_id`, + referencedColumnName: 'id', + unique : false, + nullable : true + }, options) + }); return this; } @@ -589,36 +586,33 @@ export class Mapping { * * @returns {JoinTable} */ - public getJoinTable(property: string, entityManager?: EntityManager| Scope): JoinTable { - let field = this.mapping.fetchOrPut(`fields.${property}`, {}); + public getJoinTable(property: string, entityManager: EntityManager| Scope): JoinTable { + let field = this.mapping.fetchOrPut(`fields.${property}`, {}); + field.joinTable = field.joinTable || {}; - if (!field.joinTable) { - if (!entityManager) { - return null; - } - - let relationMapping = Mapping.forEntity(entityManager.resolveEntityReference(field.relationship.targetEntity)); - let ownTableName = this.getTableName(); - let withTableName = relationMapping.getTableName(); - let ownPrimary = this.getPrimaryKeyField(); - let withPrimary = relationMapping.getPrimaryKeyField(); - - field.joinTable = { - name : `${ownTableName}_${withTableName}`, - joinColumns : [{ - referencedColumnName: ownPrimary, - name : `${ownTableName}_id`, - type : 'integer' - }], - inverseJoinColumns: [{ - referencedColumnName: withPrimary, - name : `${withTableName}_id`, - type : 'integer' - }] - }; + if (!entityManager) { + throw new Error('EntityManager is required as a second argument for getJoinTable.'); } - return field.joinTable; + let relationMapping = Mapping.forEntity(entityManager.resolveEntityReference(field.relationship.targetEntity)); + let ownTableName = this.getTableName(); + let withTableName = relationMapping.getTableName(); + let ownPrimary = this.getPrimaryKeyField(); + let withPrimary = relationMapping.getPrimaryKeyField(); + + return Homefront.merge({ + name : `${ownTableName}_${withTableName}`, + joinColumns : [{ + referencedColumnName: ownPrimary, + name : `${ownTableName}_id`, + type : 'integer' + }], + inverseJoinColumns: [{ + referencedColumnName: withPrimary, + name : `${withTableName}_id`, + type : 'integer' + }] + }, field.joinTable) as JoinTable; } /** @@ -870,11 +864,13 @@ export interface JoinTable { } export interface JoinColumn { - referencedColumnName: string, - name: string, + referencedColumnName?: string, + name?: string, type?: string, size?: number, indexName?: string, + onDelete?: string, + onUpdate?: string, unique?: boolean, nullable?: boolean } diff --git a/src/SchemaBuilder.ts b/src/SchemaBuilder.ts index 9d1583a..1d02bcc 100644 --- a/src/SchemaBuilder.ts +++ b/src/SchemaBuilder.ts @@ -1,4 +1,4 @@ -import {Mapping, FieldOptions, Raw} from './Mapping'; +import {Mapping, FieldOptions, Raw, JoinColumn} from './Mapping'; import {EntityInterface, EntityCtor} from './EntityInterface'; import * as Knex from 'knex'; import {Scope} from './Scope'; @@ -149,16 +149,22 @@ export class SchemaBuilder { this.composeFields(table, relations.joinColumns); relations.foreignKeys.forEach(foreignKey => { - let foreign = table.foreign(foreignKey.foreign).references(foreignKey.references).inTable(foreignKey.inTable); + let column = foreignKey.joinColumn; + let foreign = table.foreign(column.name).references(column.referencedColumnName).inTable(foreignKey.inTable); - this.applyCascades(mapping.getField(foreignKey.owning).cascades, foreign); + if (column.onDelete) { + foreign.onDelete(column.onDelete); + } + + if (column.onUpdate) { + foreign.onDelete(column.onUpdate); + } }); }); this.addBuilder(entity, tableName, table => { this.composeIndexes(table, mapping); }, true); - } /** @@ -226,12 +232,7 @@ export class SchemaBuilder { nullable: true }; - return foreignKeys.push({ - owning : property, - foreign : column.name, - references: column.referencedColumnName, - inTable : targetMapping.getTableName() - }); + return foreignKeys.push({joinColumn: column, owning: property, inTable: targetMapping.getTableName()}); } // Nothing to do for other side. @@ -301,30 +302,6 @@ export class SchemaBuilder { return {joinColumns, foreignKeys}; } - /** - * Apply cascades to provided table builder. - * - * @param {string[]} cascades - * @param {Knex.ColumnBuilder} foreign - */ - private applyCascades(cascades: Array, foreign: Knex.ColumnBuilder) { - if (!cascades) { - return; - } - - cascades.forEach(cascade => { - if (cascade === Mapping.CASCADE_PERSIST) { - return; - } - - if (cascade === Mapping.CASCADE_UPDATE) { - foreign.onUpdate('cascade'); - } else if (cascade === Mapping.CASCADE_DELETE) { - foreign.onDelete('cascade'); - } - }); - } - /** * Compose the indexes for mapping. * @@ -396,7 +373,7 @@ export class SchemaBuilder { column.primary(); } - if (field.defaultTo) { + if (typeof field.defaultTo !== 'undefined') { if (field.defaultTo instanceof Raw) { column.defaultTo(this.client.raw(field.defaultTo.getQuery())); } else { @@ -612,5 +589,5 @@ export class SchemaBuilder { export interface ProcessedRelations { joinColumns: {[key: string]: FieldOptions}, - foreignKeys: Array<{owning: string, foreign: string, references: string, inTable: string}> + foreignKeys: Array<{joinColumn: JoinColumn, owning: string, inTable: string}> } diff --git a/test/resource/entity/postal/Delivery.ts b/test/resource/entity/postal/Delivery.ts index 4cd227b..75f6772 100644 --- a/test/resource/entity/postal/Delivery.ts +++ b/test/resource/entity/postal/Delivery.ts @@ -10,6 +10,8 @@ export class Delivery { mapping.manyToOne('address', {targetEntity: Address, inversedBy: 'deliveries'}); - mapping.forProperty('order').oneToOne({targetEntity: Order}).cascade(['delete']); + mapping.forProperty('order') + .joinColumn({onDelete: 'cascade'}) + .oneToOne({targetEntity: Order}); } }