diff --git a/packages/cli/generators/relation/base-relation.generator.js b/packages/cli/generators/relation/base-relation.generator.js index 3a9ba0a0bf36..12dbacb27431 100644 --- a/packages/cli/generators/relation/base-relation.generator.js +++ b/packages/cli/generators/relation/base-relation.generator.js @@ -99,6 +99,8 @@ module.exports = class BaseRelationGenerator extends ArtifactGenerator { type: this._getRepositoryRelationPropertyType(), }; + if (classDeclaration.getProperty(property.name)) return; + // already checked the existence of property before relationUtils.addProperty(classDeclaration, property); } diff --git a/packages/cli/generators/relation/belongs-to-relation.generator.js b/packages/cli/generators/relation/belongs-to-relation.generator.js index f5a1d46e180d..befb393bb719 100644 --- a/packages/cli/generators/relation/belongs-to-relation.generator.js +++ b/packages/cli/generators/relation/belongs-to-relation.generator.js @@ -95,7 +95,9 @@ module.exports = class BelongsToRelationGenerator extends ( ); const sourceClass = relationUtils.getClassObj(sourceFile, sourceModel); // this checks if the foreign key already exists, so the 2nd param should be foreignKeyName - relationUtils.doesRelationExist(sourceClass, foreignKeyName); + relationUtils.doesRelationExist(sourceClass, foreignKeyName, { + force: this.options.force, + }); const modelProperty = this.getBelongsTo( targetModel, diff --git a/packages/cli/generators/relation/has-many-relation.generator.js b/packages/cli/generators/relation/has-many-relation.generator.js index 4d56c005f0c2..8e71f1111277 100644 --- a/packages/cli/generators/relation/has-many-relation.generator.js +++ b/packages/cli/generators/relation/has-many-relation.generator.js @@ -99,7 +99,9 @@ module.exports = class HasManyRelationGenerator extends BaseRelationGenerator { sourceModel, ); const sourceClass = relationUtils.getClassObj(sourceFile, sourceModel); - relationUtils.doesRelationExist(sourceClass, relationName); + relationUtils.doesRelationExist(sourceClass, relationName, { + force: this.options.force, + }); modelProperty = this.getHasMany( targetModel, @@ -121,6 +123,20 @@ module.exports = class HasManyRelationGenerator extends BaseRelationGenerator { ); const targetClass = relationUtils.getClassObj(targetFile, targetModel); + if (isForeignKeyExist) { + const existingFK = targetClass.getProperty(foreignKeyName); + if ( + existingFK && + !relationUtils.isValidPropertyType(targetClass, foreignKeyName, fktype) + ) { + existingFK.remove(); + const newFK = relationUtils.addForeignKey(foreignKeyName, fktype); + relationUtils.addProperty(targetClass, newFK); + targetClass.formatText(); + await targetFile.save(); + } + } + if (isForeignKeyExist) { if ( !relationUtils.isValidPropertyType(targetClass, foreignKeyName, fktype) diff --git a/packages/cli/generators/relation/has-many-through-relation.generator.js b/packages/cli/generators/relation/has-many-through-relation.generator.js index a7cb949595cd..c7d8d40c56e9 100644 --- a/packages/cli/generators/relation/has-many-through-relation.generator.js +++ b/packages/cli/generators/relation/has-many-through-relation.generator.js @@ -133,7 +133,9 @@ module.exports = class HasManyThroughRelationGenerator extends ( sourceModel, ); const sourceClass = relationUtils.getClassObj(sourceFile, sourceModel); - relationUtils.doesRelationExist(sourceClass, relationName); + relationUtils.doesRelationExist(sourceClass, relationName, { + force: this.options.force, + }); // add the relation to the source model const isDefaultSourceKey = sourceKey === dftSourceKey; const isDefaultTargetKey = targetKey === dftTargetKey; diff --git a/packages/cli/generators/relation/has-one-relation.generator.js b/packages/cli/generators/relation/has-one-relation.generator.js index 2c4585ced1c0..8fd8b0cbc1fc 100644 --- a/packages/cli/generators/relation/has-one-relation.generator.js +++ b/packages/cli/generators/relation/has-one-relation.generator.js @@ -96,7 +96,9 @@ module.exports = class HasOneRelationGenerator extends BaseRelationGenerator { sourceModel, ); const sourceClass = relationUtils.getClassObj(sourceFile, sourceModel); - relationUtils.doesRelationExist(sourceClass, relationName); + relationUtils.doesRelationExist(sourceClass, relationName, { + force: this.options.force, + }); modelProperty = this.getHasOne( targetModel, @@ -122,6 +124,20 @@ module.exports = class HasOneRelationGenerator extends BaseRelationGenerator { ); const targetClass = relationUtils.getClassObj(targetFile, targetModel); + if (isForeignKeyExist) { + const existingFK = targetClass.getProperty(foreignKeyName); + if ( + existingFK && + !relationUtils.isValidPropertyType(targetClass, foreignKeyName, fktype) + ) { + existingFK.remove(); + const newFK = relationUtils.addForeignKey(foreignKeyName, fktype); + relationUtils.addProperty(targetClass, newFK); + targetClass.formatText(); + await targetFile.save(); + } + } + if (isForeignKeyExist) { if ( !relationUtils.isValidPropertyType(targetClass, foreignKeyName, fktype) diff --git a/packages/cli/generators/relation/index.js b/packages/cli/generators/relation/index.js index 0c7cb5703e50..c37c1b72efa1 100644 --- a/packages/cli/generators/relation/index.js +++ b/packages/cli/generators/relation/index.js @@ -603,7 +603,11 @@ module.exports = class RelationGenerator extends ArtifactGenerator { this.artifactInfo.relationType === 'referencesMany') ) { try { - relationUtils.doesRelationExist(cl, this.artifactInfo.foreignKeyName); + relationUtils.doesRelationExist( + cl, + this.artifactInfo.foreignKeyName, + {force: this.options.force}, + ); } catch (err) { /* istanbul ignore next */ this.exit(err); @@ -682,6 +686,19 @@ module.exports = class RelationGenerator extends ArtifactGenerator { ? PROMPT_MESSAGE_RELATION_NAME : PROMPT_MESSAGE_PROPERTY_NAME; + if (!this.options.relationName) + this.artifactInfo.relationName = this.artifactInfo.defaultRelationName; + if ( + (this.artifactInfo.relationType === 'hasMany' || + this.artifactInfo.relationType === 'hasManyThrough') && + this.options.relationName && + !this.options.relationName.endsWith('s') + ) { + this.artifactInfo.relationName = utils.pluralize( + this.artifactInfo.relationName, + ); + } + return this.prompt([ { type: 'string', diff --git a/packages/cli/generators/relation/references-many-relation.generator.js b/packages/cli/generators/relation/references-many-relation.generator.js index dc55fe69abef..8a91ca37084b 100644 --- a/packages/cli/generators/relation/references-many-relation.generator.js +++ b/packages/cli/generators/relation/references-many-relation.generator.js @@ -41,7 +41,9 @@ module.exports = class ReferencesManyRelationGenerator extends ( ); const sourceClass = relationUtils.getClassObj(sourceFile, sourceModel); // this checks if the foreign key already exists, so the 2nd param should be foreignKeyName - relationUtils.doesRelationExist(sourceClass, foreignKeyName); + relationUtils.doesRelationExist(sourceClass, foreignKeyName, { + force: this.options.force, + }); const modelProperty = this.getReferencesMany( targetModel, diff --git a/packages/cli/generators/relation/utils.generator.js b/packages/cli/generators/relation/utils.generator.js index 7fc6cc6efde9..bc35282e487b 100644 --- a/packages/cli/generators/relation/utils.generator.js +++ b/packages/cli/generators/relation/utils.generator.js @@ -114,22 +114,26 @@ exports.doesPropertyExist = function (classObj, propertyName) { .includes(propertyName); }; -exports.doesRelationExist = function (classObj, propertyName) { +exports.doesRelationExist = function (classObj, propertyName, options = {}) { + const force = options.force; if (this.doesPropertyExist(classObj, propertyName)) { // If the property is decorated by `@property()`, // turn it to be a relational property decorated by `@belongsTo()` const decorators = classObj.getProperty(propertyName).getDecorators(); const hasPropertyDecorator = decorators.length > 0 && decorators[0].getName() === 'property'; - // If it's already decorated by a relational decorator, - // throw error - if (!hasPropertyDecorator) { - throw new Error( - 'relational property ' + - propertyName + - ' already exist in the model ' + - classObj.getName(), - ); + if (!force) { + // If it's already decorated by a relational decorator, + // throw error + if (!hasPropertyDecorator) { + throw new Error( + 'relational property ' + + propertyName + + ' already exist in the model ' + + classObj.getName() + + ' Use --force to overwrite it', + ); + } } this.deleteProperty(classObj.getProperty(propertyName));