From 01edb2a3ca046f6f8001e53355a2a493d2089078 Mon Sep 17 00:00:00 2001 From: Marcelo Shima Date: Sun, 9 Apr 2023 22:04:49 -0300 Subject: [PATCH] replace skipUserManagement logic with 'with builtInEntity' definition --- generators/info/generator.mts | 5 +- .../incremental-liquibase.spec.mts | 2 +- jdl/__snapshots__/jdl-importer.spec.ts.snap | 2 + jdl/__test-files__/big_sample.jdl | 2 +- jdl/__test-files__/complex_jdl.jdl | 2 +- .../jhipster_app/.jhipster/Country.json | 1 + jdl/__test-files__/multiple_jdl_comments.jdl | 2 +- jdl/__test-files__/realistic_sample.jdl | 2 +- .../user_entity_to_relationship.jdl | 4 +- .../jdl-to-json-basic-entity-converter.ts | 12 - ...basic-entity-information-converter.spec.ts | 16 +- ...jdl-to-json-relationship-converter.spec.ts | 10 +- .../jdl-to-json-relationship-converter.ts | 8 +- ...ith-applications-to-json-converter.spec.ts | 4 +- ...hout-application-to-json-converter.spec.ts | 6 +- jdl/converters/json-to-jdl-converter.ts | 3 +- .../json-to-jdl-entity-converter.spec.ts | 40 +-- .../json-to-jdl-entity-converter.ts | 169 +++++------ .../parsed-jdl-to-jdl-object-converter.ts | 29 +- .../relationship-converter.ts | 9 +- jdl/converters/types.ts | 4 +- jdl/jdl-importer.spec.ts | 14 + jdl/jdl-importer.ts | 8 - jdl/jhipster/relationship-options.ts | 1 + jdl/jhipster/relationship-types.spec.ts | 5 +- jdl/jhipster/relationship-types.ts | 7 +- jdl/models/jdl-object.ts | 3 +- jdl/models/jdl-options.ts | 4 +- jdl/models/jdl-relationship.ts | 91 +++--- jdl/models/jdl-relationships.ts | 14 +- .../generated/generated-serialized-grammar.js | 7 + jdl/parsing/jdl-ast-builder-visitor.ts | 6 +- jdl/parsing/jdl-parser.ts | 2 +- jdl/parsing/lexer/lexer.ts | 4 + jdl/parsing/lexer/relationship-type-tokens.ts | 14 +- jdl/readers/json-reader.ts | 3 +- .../jdl-with-application-validator.spec.ts | 271 ++++++------------ .../jdl-with-application-validator.ts | 34 ++- .../jdl-without-application-validator.spec.ts | 215 +++++--------- .../jdl-without-application-validator.ts | 28 +- jdl/validators/relationship-validator.spec.ts | 48 +--- jdl/validators/relationship-validator.ts | 80 +----- .../liquibase-jdl-rename-field-post/app.jdl | 4 +- .../liquibase-jdl-rename-field/app.jdl | 4 +- .../blog-store.jdl | 2 +- .../blog-store.jdl | 2 +- .../blog-store.jdl | 2 +- .../blog-store.jdl | 4 +- .../blog-store.jdl | 2 +- .../blog-store.jdl | 2 +- .../blog-store.jdl | 2 +- test-integration/samples/jdl-default/app.jdl | 4 +- .../samples/jdl-entities/custom-domain.jdl | 2 +- .../user-relationships/entities.jdl | 2 + .../import-jdl/common/jdl-ambiguous.jdl | 2 +- test/templates/import-jdl/common/jdl.jdl | 2 +- 56 files changed, 456 insertions(+), 771 deletions(-) diff --git a/generators/info/generator.mts b/generators/info/generator.mts index 76a41a2abe0a..2519d4af1d8f 100644 --- a/generators/info/generator.mts +++ b/generators/info/generator.mts @@ -118,12 +118,11 @@ export default class InfoGenerator extends BaseApplicationGenerator { }); jdlObject = JSONToJDLEntityConverter.convertEntitiesToJDL({ entities, - skippedUserManagement: this.jhipsterConfig.skipUserManagement, }); JSONToJDLOptionConverter.convertServerOptionsToJDL({ 'generator-jhipster': this.config.getAll() }, jdlObject); } catch (error) { - this.logger.warn((error as any).message || error); - throw new Error('\nError while parsing entities to JDL\n'); + this.logger.error('Error while parsing entities to JDL', error); + throw new Error('\nError while parsing entities to JDL\n', { cause: error }); } return jdlObject; } diff --git a/generators/liquibase-changelogs/incremental-liquibase.spec.mts b/generators/liquibase-changelogs/incremental-liquibase.spec.mts index 02dbdfe5b79f..369f63d9fee8 100644 --- a/generators/liquibase-changelogs/incremental-liquibase.spec.mts +++ b/generators/liquibase-changelogs/incremental-liquibase.spec.mts @@ -39,7 +39,7 @@ entity Another { const jdlApplicationWithRelationshipToUser = ` ${jdlApplicationWithEntities} relationship ManyToOne { - One{user(login)} to User + One{user(login)} to User with builtInEntity } `; diff --git a/jdl/__snapshots__/jdl-importer.spec.ts.snap b/jdl/__snapshots__/jdl-importer.spec.ts.snap index 013975a78aa6..df87ab7181a0 100644 --- a/jdl/__snapshots__/jdl-importer.spec.ts.snap +++ b/jdl/__snapshots__/jdl-importer.spec.ts.snap @@ -152,6 +152,7 @@ exports[`jdl - JDLImporter import when not parsing applications should export en "otherEntityName": "user", "relationshipName": "user", "relationshipType": "many-to-one", + "relationshipWithBuiltInEntity": true, }, { "otherEntityField": "lastName", @@ -567,6 +568,7 @@ exports[`jdl - JDLImporter import when not parsing applications should return th "otherEntityName": "user", "relationshipName": "user", "relationshipType": "many-to-one", + "relationshipWithBuiltInEntity": true, }, { "otherEntityField": "lastName", diff --git a/jdl/__test-files__/big_sample.jdl b/jdl/__test-files__/big_sample.jdl index 8b8385840c81..a09736c52bb9 100644 --- a/jdl/__test-files__/big_sample.jdl +++ b/jdl/__test-files__/big_sample.jdl @@ -86,7 +86,7 @@ relationship OneToMany { } relationship ManyToOne { - Employee{user(login)} to User, + Employee{user(login)} to User with builtInEntity, Employee{manager(lastName)} to Employee } diff --git a/jdl/__test-files__/complex_jdl.jdl b/jdl/__test-files__/complex_jdl.jdl index e86a1fa1c2d3..4f9c88428c78 100644 --- a/jdl/__test-files__/complex_jdl.jdl +++ b/jdl/__test-files__/complex_jdl.jdl @@ -84,7 +84,7 @@ relationship ManyToMany { } relationship ManyToOne { - Employee{user(login)} to User + Employee{user(login)} to User with builtInEntity } relationship OneToOne { diff --git a/jdl/__test-files__/jhipster_app/.jhipster/Country.json b/jdl/__test-files__/jhipster_app/.jhipster/Country.json index 79f53f6f7590..b6332ebbdd39 100644 --- a/jdl/__test-files__/jhipster_app/.jhipster/Country.json +++ b/jdl/__test-files__/jhipster_app/.jhipster/Country.json @@ -13,6 +13,7 @@ "relationshipType": "one-to-one", "relationshipName": "user", "otherEntityName": "user", + "relationshipWithBuiltInEntity": true, "ownerSide": true, "otherEntityRelationshipName": "country" } diff --git a/jdl/__test-files__/multiple_jdl_comments.jdl b/jdl/__test-files__/multiple_jdl_comments.jdl index c19a119bae08..25f66de0c33c 100644 --- a/jdl/__test-files__/multiple_jdl_comments.jdl +++ b/jdl/__test-files__/multiple_jdl_comments.jdl @@ -9,5 +9,5 @@ entity A { // Another line } // thing relationship OneToOne { - A to User + A to User with builtInEntity } diff --git a/jdl/__test-files__/realistic_sample.jdl b/jdl/__test-files__/realistic_sample.jdl index e7c85dcc32f6..4ce455ff7a45 100644 --- a/jdl/__test-files__/realistic_sample.jdl +++ b/jdl/__test-files__/realistic_sample.jdl @@ -79,7 +79,7 @@ enum Gender { } relationship OneToOne { - Customer{user(login) required} to User + Customer{user(login) required} to User with builtInEntity } service Customer with serviceClass diff --git a/jdl/__test-files__/user_entity_to_relationship.jdl b/jdl/__test-files__/user_entity_to_relationship.jdl index ffd814e91caa..f659f6e4b9f0 100644 --- a/jdl/__test-files__/user_entity_to_relationship.jdl +++ b/jdl/__test-files__/user_entity_to_relationship.jdl @@ -2,9 +2,9 @@ entity A entity B relationship ManyToOne { - A{user} to User + A{user} to User with builtInEntity } relationship OneToOne { - B{user} to User + B{user} to User with builtInEntity } diff --git a/jdl/converters/jdl-to-json/jdl-to-json-basic-entity-converter.ts b/jdl/converters/jdl-to-json/jdl-to-json-basic-entity-converter.ts index 83380d19643f..2a31259f85a9 100644 --- a/jdl/converters/jdl-to-json/jdl-to-json-basic-entity-converter.ts +++ b/jdl/converters/jdl-to-json/jdl-to-json-basic-entity-converter.ts @@ -48,18 +48,6 @@ function createJSONEntities(jdlEntities: JDLEntity[]): Map { jdlEntities.forEach(jdlEntity => { const entityName = jdlEntity.name; - /* - * If the user adds a 'User' entity we consider it as the already - * created JHipster User entity and none of its fields and owner-side - * relationships will be considered. - */ - if (builtInEntities.has(entityName.toLowerCase())) { - logger.warn( - `An Entity name '${entityName}' was used: '${entityName}' is an entity created by default by JHipster.` + - ' All relationships toward it will be kept but any attributes and relationships from it will be disregarded.' - ); - return; - } convertedEntities.set( entityName, new JSONEntity({ diff --git a/jdl/converters/jdl-to-json/jdl-to-json-basic-entity-information-converter.spec.ts b/jdl/converters/jdl-to-json/jdl-to-json-basic-entity-information-converter.spec.ts index f8e79e6e8920..c220893d07be 100644 --- a/jdl/converters/jdl-to-json/jdl-to-json-basic-entity-information-converter.spec.ts +++ b/jdl/converters/jdl-to-json/jdl-to-json-basic-entity-information-converter.spec.ts @@ -46,10 +46,8 @@ describe('jdl - JDLToJSONBasicEntityConverter', () => { context('with some of them being built-in entities', () => { let builtInEntitiesAreConverted; let customEntitiesAreConverted; - let loggerSpy; before(() => { - loggerSpy = sinon.spy(logger, 'warn'); const entityA = new JDLEntity({ name: 'A', tableName: 'entity_a', @@ -66,18 +64,8 @@ describe('jdl - JDLToJSONBasicEntityConverter', () => { builtInEntitiesAreConverted = returnedMap.has('User') || returnedMap.has('Authority'); }); - after(() => { - loggerSpy.restore(); - }); - - it('should warn about them', () => { - expect(loggerSpy.getCall(0).args[0]).to.equal( - "An Entity name 'User' was used: 'User' is an entity created by default by JHipster. All relationships " + - 'toward it will be kept but any attributes and relationships from it will be disregarded.' - ); - }); - it('should not convert built-in entities', () => { - expect(builtInEntitiesAreConverted).to.be.false; + it('should convert built-in entities', () => { + expect(builtInEntitiesAreConverted).to.be.true; }); it('should convert custom entities', () => { expect(customEntitiesAreConverted).to.be.true; diff --git a/jdl/converters/jdl-to-json/jdl-to-json-relationship-converter.spec.ts b/jdl/converters/jdl-to-json/jdl-to-json-relationship-converter.spec.ts index 451659a78595..2043518bd06b 100644 --- a/jdl/converters/jdl-to-json/jdl-to-json-relationship-converter.spec.ts +++ b/jdl/converters/jdl-to-json/jdl-to-json-relationship-converter.spec.ts @@ -25,7 +25,7 @@ import { convert } from './jdl-to-json-relationship-converter.js'; import { relationshipTypes, relationshipOptions } from '../../jhipster/index.mjs'; const { ONE_TO_ONE, MANY_TO_MANY, MANY_TO_ONE, ONE_TO_MANY } = relationshipTypes; -const { JPA_DERIVED_IDENTIFIER } = relationshipOptions; +const { BUILT_IN_ENTITY } = relationshipOptions; describe('jdl - JDLToJSONRelationshipConverter', () => { describe('convert', () => { @@ -158,6 +158,8 @@ describe('jdl - JDLToJSONRelationshipConverter', () => { injectedFieldInTo: 'a', injectedFieldInFrom: 'b', options: { + source: {}, + destination: {}, global: { custom: 42, }, @@ -193,8 +195,10 @@ describe('jdl - JDLToJSONRelationshipConverter', () => { injectedFieldInTo: 'a', injectedFieldInFrom: 'b', options: { + source: {}, + destination: {}, global: { - [JPA_DERIVED_IDENTIFIER]: true, + [BUILT_IN_ENTITY]: true, }, }, }); @@ -210,7 +214,7 @@ describe('jdl - JDLToJSONRelationshipConverter', () => { "ownerSide": true, "relationshipName": "b", "relationshipType": "one-to-one", - "useJPADerivedIdentifier": true, + "relationshipWithBuiltInEntity": true, } `); }); diff --git a/jdl/converters/jdl-to-json/jdl-to-json-relationship-converter.ts b/jdl/converters/jdl-to-json/jdl-to-json-relationship-converter.ts index 3306bbe2f74f..56c8383e1e1c 100644 --- a/jdl/converters/jdl-to-json/jdl-to-json-relationship-converter.ts +++ b/jdl/converters/jdl-to-json/jdl-to-json-relationship-converter.ts @@ -25,13 +25,9 @@ import JDLRelationship from '../../models/jdl-relationship.js'; const { Validations: { REQUIRED }, } = validations; -const { JPA_DERIVED_IDENTIFIER } = relationshipOptions; +const { JPA_DERIVED_IDENTIFIER, BUILT_IN_ENTITY } = relationshipOptions; const { MANY_TO_MANY, MANY_TO_ONE, ONE_TO_MANY, ONE_TO_ONE } = relationshipTypes; -const USER = 'user'; -const AUTHORITY = 'authority'; -const builtInEntities = new Set([USER, AUTHORITY]); - let convertedRelationships; export default { convert }; @@ -156,6 +152,8 @@ function setOptionsForRelationshipSourceSide(relationshipToConvert, convertedRel if (convertedRelationship.ownerSide) { convertedRelationship.useJPADerivedIdentifier = optionValue; } + } else if (optionName === BUILT_IN_ENTITY) { + convertedRelationship.relationshipWithBuiltInEntity = optionValue; } else { convertedRelationship.options[optionName] = optionValue; } diff --git a/jdl/converters/jdl-to-json/jdl-with-applications-to-json-converter.spec.ts b/jdl/converters/jdl-to-json/jdl-with-applications-to-json-converter.spec.ts index 033b8c270919..1d07cfe998fb 100644 --- a/jdl/converters/jdl-to-json/jdl-with-applications-to-json-converter.spec.ts +++ b/jdl/converters/jdl-to-json/jdl-with-applications-to-json-converter.spec.ts @@ -142,12 +142,12 @@ describe('jdl - JDLWithApplicationsToJSONConverter', () => { const returnedMap: any = convert({ jdlObject, }); - customEntitiesAreConverted = returnedMap.get('toto').every(entity => entity.name === 'A'); + customEntitiesAreConverted = returnedMap.get('toto').some(entity => entity.name === 'A'); builtInEntitiesAreConverted = returnedMap.get('toto').some(entity => entity.name === 'User' || entity.name === 'Authority'); }); it('should not convert built-in entities', () => { - expect(builtInEntitiesAreConverted).to.be.false; + expect(builtInEntitiesAreConverted).to.be.true; }); it('should convert custom entities', () => { expect(customEntitiesAreConverted).to.be.true; diff --git a/jdl/converters/jdl-to-json/jdl-without-application-to-json-converter.spec.ts b/jdl/converters/jdl-to-json/jdl-without-application-to-json-converter.spec.ts index c8106394f5c9..8ed603c19f78 100644 --- a/jdl/converters/jdl-to-json/jdl-without-application-to-json-converter.spec.ts +++ b/jdl/converters/jdl-to-json/jdl-without-application-to-json-converter.spec.ts @@ -127,12 +127,12 @@ describe('jdl - JDLWithoutApplicationToJSONConverter', () => { applicationType: MONOLITH, databaseType: SQL, }); - customEntitiesAreConverted = returnedMap.get('toto').every(entity => entity.name === 'A'); + customEntitiesAreConverted = returnedMap.get('toto').some(entity => entity.name === 'A'); builtInEntitiesAreConverted = returnedMap.get('toto').some(entity => entity.name === 'User' || entity.name === 'Authority'); }); - it('should not convert built-in entities', () => { - expect(builtInEntitiesAreConverted).to.be.false; + it('should convert built-in entities', () => { + expect(builtInEntitiesAreConverted).to.be.true; }); it('should convert custom entities', () => { expect(customEntitiesAreConverted).to.be.true; diff --git a/jdl/converters/json-to-jdl-converter.ts b/jdl/converters/json-to-jdl-converter.ts index 2f46fae5cf7d..fa146a723a59 100644 --- a/jdl/converters/json-to-jdl-converter.ts +++ b/jdl/converters/json-to-jdl-converter.ts @@ -97,8 +97,7 @@ function getJDLObjectFromSingleApplication( existingJDLObject.addApplication(jdlApplication); return existingJDLObject; } - const skippedUserManagement = jdlApplication.getConfigurationOptionValue(OptionNames.SKIP_USER_MANAGEMENT); - const jdlObject = convertEntitiesToJDL({ entities, skippedUserManagement }); + const jdlObject = convertEntitiesToJDL({ entities }); entities.forEach((entity, entityName) => jdlApplication.addEntityName(entityName)); jdlObject.addApplication(jdlApplication); return mergeJDLObjects(existingJDLObject, jdlObject); diff --git a/jdl/converters/json-to-jdl-entity-converter.spec.ts b/jdl/converters/json-to-jdl-entity-converter.spec.ts index a43592ffc315..1cd1ac4a4c1e 100644 --- a/jdl/converters/json-to-jdl-entity-converter.spec.ts +++ b/jdl/converters/json-to-jdl-entity-converter.spec.ts @@ -30,7 +30,7 @@ import { unaryOptions, relationshipOptions, binaryOptions } from '../jhipster/in const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); -const { JPA_DERIVED_IDENTIFIER } = relationshipOptions; +const { JPA_DERIVED_IDENTIFIER, BUILT_IN_ENTITY } = relationshipOptions; const { Options: { DTO, SEARCH, PAGINATION, MICROSERVICE, ANGULAR_SUFFIX, SERVICE }, @@ -202,44 +202,6 @@ describe('jdl - JSONToJDLEntityConverter', () => { expect(jdlObject.relationships.getOneToOne('OneToOne_Country{user}_User')).not.to.be.undefined; }); }); - context('when there is a User.json entity', () => { - let entities; - - before(() => { - entities = new Map([ - ['Country', readJsonEntity('Country')], - ['User', readJsonEntity('Region')], - ]); - }); - - it('should fail', () => { - expect(() => { - convertEntitiesToJDL({ - entities, - }); - }).to.throw('User entity name is reserved if skipUserManagement is not set.'); - }); - }); - }); - context('when skipUserManagement flag is set', () => { - let jdlObject; - - before(() => { - const regionEntity = readJsonEntity('Region'); - regionEntity.relationships[0].otherEntityRelationshipName = 'user'; - const entities = new Map([ - ['Country', readJsonEntity('Country')], - ['User', regionEntity], - ]); - jdlObject = convertEntitiesToJDL({ entities, skippedUserManagement: true }); - }); - - it('should parse the User entity', () => { - expect(jdlObject.entities.Country).not.to.be.undefined; - expect(jdlObject.entities.User).not.to.be.undefined; - expect(jdlObject.entities.User.fields.regionId).not.to.be.undefined; - expect(jdlObject.relationships.getOneToOne('OneToOne_Country{user}_User{country}')).not.to.be.undefined; - }); }); context('without relationship', () => { let jdlObject; diff --git a/jdl/converters/json-to-jdl-entity-converter.ts b/jdl/converters/json-to-jdl-entity-converter.ts index 3b054a8753eb..b97e929c5d2a 100644 --- a/jdl/converters/json-to-jdl-entity-converter.ts +++ b/jdl/converters/json-to-jdl-entity-converter.ts @@ -21,19 +21,18 @@ import JDLObject from '../models/jdl-object.js'; import { JDLEntity, JDLEnum } from '../models/index.mjs'; import JDLField from '../models/jdl-field.js'; import JDLValidation from '../models/jdl-validation.js'; -import JDLRelationship from '../models/jdl-relationship.js'; +import JDLRelationship, { JDLRelationshipModel, JDLRelationshipOptions, JDL_RELATIONSHIP_ONE_TO_MANY } from '../models/jdl-relationship.js'; import JDLUnaryOption from '../models/jdl-unary-option.js'; import JDLBinaryOption from '../models/jdl-binary-option.js'; import { lowerFirst, upperFirst } from '../utils/string-utils.js'; -import { applicationOptions, fieldTypes, unaryOptions, binaryOptions, relationshipTypes, relationshipOptions } from '../jhipster/index.mjs'; +import { fieldTypes, unaryOptions, binaryOptions, relationshipOptions } from '../jhipster/index.mjs'; import { Entity, Field, Relationship } from './types.js'; +import { asJdlRelationshipType } from './parsed-jdl-to-jdl-object/relationship-converter.js'; const { BlobTypes, CommonDBTypes, RelationalOnlyDBTypes } = fieldTypes; -const { OptionNames } = applicationOptions; -const { ONE_TO_ONE, ONE_TO_MANY, MANY_TO_ONE, MANY_TO_MANY } = relationshipTypes; -const { JPA_DERIVED_IDENTIFIER } = relationshipOptions; +const { JPA_DERIVED_IDENTIFIER, BUILT_IN_ENTITY } = relationshipOptions; const { FILTER, NO_FLUENT_METHOD, READ_ONLY, EMBEDDED } = unaryOptions; const { ANGULAR_SUFFIX, CLIENT_ROOT_FOLDER, DTO, MICROSERVICE, PAGINATION, SEARCH, SERVICE } = binaryOptions.Options; @@ -44,21 +43,16 @@ export default { convertEntitiesToJDL, }; -const USER_ENTITY_NAME = 'User'; -const USER_ENTITY = new JDLEntity({ name: USER_ENTITY_NAME }); - let entities: Map; let jdlObject: JDLObject; -let skippedUserManagement: boolean; /** * Convert the passed entities (parsed from JSON files) to a JDL object. * @param params - an object containing the entities and relevant options. * @param params.entities - a Map having for keys the entity names and values the JSON entity files. - * @param params.skippedUserManagement - whether management of the User entity by JHipster is skipped. * @return the parsed entities in the JDL form. */ -export function convertEntitiesToJDL(params: { entities: Map; skippedUserManagement: boolean }): JDLObject { +export function convertEntitiesToJDL(params: { entities: Map }): JDLObject { if (!params.entities) { throw new Error('Entities have to be passed to be converted.'); } @@ -71,7 +65,6 @@ export function convertEntitiesToJDL(params: { entities: Map; sk function init(params) { entities = params.entities; jdlObject = new JDLObject(); - skippedUserManagement = params.skippedUserManagement; } function addEntities() { @@ -81,9 +74,6 @@ function addEntities() { } function addEntity(entity: Entity, entityName: string) { - if (entityName === USER_ENTITY_NAME && !skippedUserManagement) { - throw new Error(`User entity name is reserved if ${OptionNames.SKIP_USER_MANAGEMENT} is not set.`); - } jdlObject.addEntity(convertJSONToJDLEntity(entity, entityName)); addEnumsToJDL(entity); addEntityOptionsToJDL(entity, entityName); @@ -193,71 +183,76 @@ function dealWithRelationships(relationships: Relationship[] | undefined, entity } function getRelationship(relationship: Relationship, entityName: string) { - let relationshipConfiguration: any = { - sourceEntity: null, - destinationEntity: null, - type: null, - injectedFieldInSourceEntity: null, - injectedFieldInDestinationEntity: null, - injectedFieldInDestinationIsRequired: false, - injectedFieldInSourceIsRequired: false, - commentForSourceEntity: null, - commentForDestinationEntity: null, - destinationEntityAsJDLEntity: null, - options: {}, - }; + const type = asJdlRelationshipType(relationship.relationshipType); + const options = getRelationshipOptions(relationship); const sourceEntitySideAttributes = getSourceEntitySideAttributes(entityName, relationship); + const destinationEntityName = upperFirst(relationship.otherEntityName); + const destinationJDLEntity = jdlObject.getEntity(destinationEntityName); + const destinationEntity = entities.get(destinationEntityName); + + let relationshipConfiguration: JDLRelationshipModel = { + from: entityName, + to: destinationJDLEntity?.name ?? destinationEntityName, + type, + options, + injectedFieldInFrom: sourceEntitySideAttributes.injectedFieldInSourceEntity, + isInjectedFieldInFromRequired: sourceEntitySideAttributes.injectedFieldInSourceIsRequired, + commentInFrom: sourceEntitySideAttributes.commentForSourceEntity, + isInjectedFieldInToRequired: false, + injectedFieldInTo: null, + commentInTo: null, + }; + relationshipConfiguration = { ...relationshipConfiguration, ...sourceEntitySideAttributes, }; - relationshipConfiguration.options = getRelationshipOptions(relationship); - - if (shouldHandleUserEntity(relationship)) { - relationshipConfiguration.destinationEntityAsJDLEntity = USER_ENTITY; - } else { - const destinationEntity = upperFirst(relationship.otherEntityName); - relationshipConfiguration.destinationEntity = entities.get(destinationEntity); - relationshipConfiguration.destinationEntityAsJDLEntity = jdlObject.getEntity(destinationEntity); - if (!relationshipConfiguration.destinationEntity) { - return undefined; + if (!destinationJDLEntity || !destinationEntity) { + if (relationshipConfiguration.options.global[BUILT_IN_ENTITY]) { + return new JDLRelationship(relationshipConfiguration); } - const isEntityTheDestinationSideEntity = (otherEntityName, otherEntityRelationshipName) => - otherEntityName === entityName && otherEntityRelationshipName === relationship.relationshipName; - const destinationSideAttributes = getDestinationEntitySideAttributes( - isEntityTheDestinationSideEntity, - relationshipConfiguration.destinationEntity.relationships - ); - relationshipConfiguration = { - ...relationshipConfiguration, - ...destinationSideAttributes, - }; + return undefined; } + const isEntityTheDestinationSideEntity = (otherEntityName, otherEntityRelationshipName) => + otherEntityName === entityName && otherEntityRelationshipName === relationship.relationshipName; + const destinationSideAttributes = getDestinationEntitySideAttributes(isEntityTheDestinationSideEntity, destinationEntity.relationships); + relationshipConfiguration = { + ...relationshipConfiguration, + injectedFieldInTo: destinationSideAttributes.injectedFieldInDestinationEntity, + isInjectedFieldInToRequired: destinationSideAttributes.injectedFieldInDestinationIsRequired ?? false, + commentInTo: destinationSideAttributes.commentForDestinationEntity, + }; if (relationship.relationshipType === 'many-to-one') { - if (relationshipConfiguration.injectedFieldInDestinationEntity) { + if (destinationSideAttributes.injectedFieldInDestinationEntity) { // This is a bidirectional relationship so consider it as a OneToMany - return getBidirectionalOneToManyRelationship(relationshipConfiguration); + return new JDLRelationship({ + type: JDL_RELATIONSHIP_ONE_TO_MANY, + from: relationshipConfiguration.to, + to: relationshipConfiguration.from, + commentInFrom: relationshipConfiguration.commentInTo, + commentInTo: relationshipConfiguration.commentInFrom, + injectedFieldInFrom: relationshipConfiguration.injectedFieldInTo, + injectedFieldInTo: relationshipConfiguration.injectedFieldInFrom, + isInjectedFieldInFromRequired: relationshipConfiguration.isInjectedFieldInToRequired, + isInjectedFieldInToRequired: relationshipConfiguration.isInjectedFieldInFromRequired, + options: { + global: relationshipConfiguration.options.global, + destination: relationshipConfiguration.options.source, + source: relationshipConfiguration.options.destination, + }, + }); } - // Unidirectional ManyToOne - relationshipConfiguration.type = MANY_TO_ONE; - } else if (relationship.relationshipType === 'one-to-one' && relationship.ownerSide === true) { - relationshipConfiguration.type = ONE_TO_ONE; - } else if (relationship.relationshipType === 'many-to-many' && relationship.ownerSide === true) { - relationshipConfiguration.type = MANY_TO_MANY; } - if (relationshipConfiguration.type) { - return getDefaultRelationship(relationshipConfiguration); + // Only one side of the relationship with every information is added to the jdl + if (!relationship.ownerSide && relationship.relationshipType !== 'many-to-one') { + return undefined; } - return undefined; + return new JDLRelationship(relationshipConfiguration); } -function shouldHandleUserEntity(relationship: Relationship) { - return relationship.otherEntityName.toLowerCase() === USER_ENTITY_NAME.toLowerCase() && !skippedUserManagement; -} - -function getSourceEntitySideAttributes(entityName, relationship) { +function getSourceEntitySideAttributes(entityName: string, relationship: Relationship) { return { sourceEntity: entityName, injectedFieldInSourceEntity: getInjectedFieldInSourceEntity(relationship), @@ -266,8 +261,8 @@ function getSourceEntitySideAttributes(entityName, relationship) { }; } -function getDestinationEntitySideAttributes(isEntityTheDestinationSideEntity, destinationEntityRelationships) { - const foundDestinationSideEntity = destinationEntityRelationships.find(destinationEntityFromRelationship => { +function getDestinationEntitySideAttributes(isEntityTheDestinationSideEntity, destinationEntityRelationships?) { + const foundDestinationSideEntity = destinationEntityRelationships?.find(destinationEntityFromRelationship => { return isEntityTheDestinationSideEntity( upperFirst(destinationEntityFromRelationship.otherEntityName), destinationEntityFromRelationship.otherEntityRelationshipName @@ -290,50 +285,22 @@ function getDestinationEntitySideAttributes(isEntityTheDestinationSideEntity, de }; } -function getRelationshipOptions(relationship: Relationship) { - const options = relationship.options || { +function getRelationshipOptions(relationship: Relationship): JDLRelationshipOptions { + const options = { global: {}, - source: {}, + source: relationship.options ?? {}, destination: {}, }; if (relationship.useJPADerivedIdentifier) { options[JPA_DERIVED_IDENTIFIER] = true; } + if (relationship.relationshipWithBuiltInEntity) { + options.global[BUILT_IN_ENTITY] = true; + } return options; } -function getDefaultRelationship(relationshipConfiguration) { - return new JDLRelationship({ - from: relationshipConfiguration.sourceEntity, - to: relationshipConfiguration.destinationEntityAsJDLEntity.name, - type: relationshipConfiguration.type, - injectedFieldInFrom: relationshipConfiguration.injectedFieldInSourceEntity, - injectedFieldInTo: relationshipConfiguration.injectedFieldInDestinationEntity, - isInjectedFieldInFromRequired: relationshipConfiguration.injectedFieldInSourceIsRequired, - isInjectedFieldInToRequired: relationshipConfiguration.injectedFieldInDestinationIsRequired, - commentInFrom: relationshipConfiguration.commentForSourceEntity, - commentInTo: relationshipConfiguration.commentForDestinationEntity, - options: relationshipConfiguration.options, - }); -} - -// Based on a ManyToOne relationship, we determine the OneToMany relationship. -function getBidirectionalOneToManyRelationship(relationshipConfiguration) { - return new JDLRelationship({ - from: relationshipConfiguration.destinationEntityAsJDLEntity.name, - to: relationshipConfiguration.sourceEntity, - type: ONE_TO_MANY, - injectedFieldInFrom: relationshipConfiguration.injectedFieldInDestinationEntity, - injectedFieldInTo: relationshipConfiguration.injectedFieldInSourceEntity, - isInjectedFieldInFromRequired: relationshipConfiguration.injectedFieldInDestinationIsRequired, - isInjectedFieldInToRequired: relationshipConfiguration.injectedFieldInSourceIsRequired, - commentInFrom: relationshipConfiguration.commentForDestinationEntity, - commentInTo: relationshipConfiguration.commentForSourceEntity, - options: relationshipConfiguration.options, - }); -} - -function getInjectedFieldInSourceEntity(relationship) { +function getInjectedFieldInSourceEntity(relationship: Relationship) { return ( relationship.relationshipName + (relationship.otherEntityField && relationship.otherEntityField !== 'id' ? `(${relationship.otherEntityField})` : '') diff --git a/jdl/converters/parsed-jdl-to-jdl-object/parsed-jdl-to-jdl-object-converter.ts b/jdl/converters/parsed-jdl-to-jdl-object/parsed-jdl-to-jdl-object-converter.ts index 704d3b9bf46d..d03481c95740 100644 --- a/jdl/converters/parsed-jdl-to-jdl-object/parsed-jdl-to-jdl-object-converter.ts +++ b/jdl/converters/parsed-jdl-to-jdl-object/parsed-jdl-to-jdl-object-converter.ts @@ -18,7 +18,6 @@ */ import _ from 'lodash'; import JDLObject from '../../models/jdl-object.js'; -import { JDLEntity } from '../../models/index.mjs'; import JDLUnaryOption from '../../models/jdl-unary-option.js'; import JDLBinaryOption from '../../models/jdl-binary-option.js'; import { applicationTypes, binaryOptions, databaseTypes } from '../../jhipster/index.mjs'; @@ -32,8 +31,6 @@ import { convertOptions } from './option-converter.js'; import { convertRelationships } from './relationship-converter.js'; import { convertDeployments } from './deployment-converter.js'; -const USER = 'User'; - let parsedContent; let configuration; let jdlObject: JDLObject; @@ -48,7 +45,6 @@ let applicationsPerEntityName; * @param {String} configurationObject.applicationType - The application's type * @param {String} configurationObject.applicationName - The application's name * @param {String} configurationObject.databaseType - The application's database type - * @param {Boolean} configurationObject.skippedUserManagement - Whether user management is skipped * @return the built JDL object. */ export function parseFromConfigurationObject(configurationObject): JDLObject { @@ -110,7 +106,6 @@ function fillClassesAndFields() { jdlEntities.forEach(jdlEntity => { jdlObject.addEntity(jdlEntity); }); - addUserEntityIfNeedBe(); addOptionsFromEntityAnnotations(); } @@ -155,27 +150,6 @@ function addOptionsFromEntityAnnotations() { }); } -function addUserEntityIfNeedBe() { - const relationshipsToTheUserEntity = getRelationshipsToTheUserEntity(); - if (relationshipsToTheUserEntity && relationshipsToTheUserEntity.length && !jdlObject.getEntity(USER)) { - addUserEntity(); - } -} - -function getRelationshipsToTheUserEntity() { - return parsedContent.relationships.filter(relationship => relationship.to.name.toLowerCase() === USER.toLowerCase()); -} - -function addUserEntity() { - jdlObject.addEntity( - new JDLEntity({ - name: USER, - tableName: 'jhi_user', - fields: {}, - }) - ); -} - function getValidations(field) { return convertValidations(field.validations, getConstantValueFromConstantName).reduce((jdlValidations, jdlValidation) => { jdlValidations[jdlValidation.name] = jdlValidation; @@ -192,8 +166,7 @@ function fillAssociations() { jdlRelationships.forEach(jdlRelationship => { // TODO: addRelationship only expects one argument. // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - jdlObject.addRelationship(jdlRelationship, configuration.skippedUserManagement); + jdlObject.addRelationship(jdlRelationship); }); } diff --git a/jdl/converters/parsed-jdl-to-jdl-object/relationship-converter.ts b/jdl/converters/parsed-jdl-to-jdl-object/relationship-converter.ts index 28c2d9a0c04d..e258d1d45ef6 100644 --- a/jdl/converters/parsed-jdl-to-jdl-object/relationship-converter.ts +++ b/jdl/converters/parsed-jdl-to-jdl-object/relationship-converter.ts @@ -18,12 +18,17 @@ */ import _ from 'lodash'; -import JDLRelationship from '../../models/jdl-relationship.js'; +import JDLRelationship, { JDLRelationshipType } from '../../models/jdl-relationship.js'; import { lowerFirst, upperFirst } from '../../utils/string-utils.js'; import { formatComment } from '../../utils/format-utils.js'; +import { RelationshipType } from '../types.js'; + +const { camelCase } = _; export default { convertRelationships }; +export const asJdlRelationshipType = (type: RelationshipType): JDLRelationshipType => upperFirst(camelCase(type)) as JDLRelationshipType; + /** * Converts parsed relationships to JDLRelationship objects. * @param {Array} parsedRelationships - the parsed relationships. @@ -38,7 +43,7 @@ export function convertRelationships(parsedRelationships, annotationToOptionConv const relationshipConfiguration = { from: parsedRelationship.from.name, to: parsedRelationship.to.name, - type: upperFirst(_.camelCase(parsedRelationship.cardinality)), + type: asJdlRelationshipType(parsedRelationship.cardinality), injectedFieldInFrom: parsedRelationship.from.injectedField, injectedFieldInTo: parsedRelationship.to.injectedField, isInjectedFieldInFromRequired: parsedRelationship.from.required, diff --git a/jdl/converters/types.ts b/jdl/converters/types.ts index 36daddce4a8b..d2d6dc4d3064 100644 --- a/jdl/converters/types.ts +++ b/jdl/converters/types.ts @@ -1,3 +1,5 @@ +export type RelationshipType = 'one-to-one' | 'many-to-one' | 'one-to-many' | 'many-to-many'; + export type Field = { fieldName: string; fieldType: string; @@ -6,7 +8,7 @@ export type Field = { export type Relationship = { relationshipName: string; - relationshipType: string; + relationshipType: RelationshipType; otherEntityName: string; options?: Record; } & Record; diff --git a/jdl/jdl-importer.spec.ts b/jdl/jdl-importer.spec.ts index e56fe29537e3..39d360946c63 100644 --- a/jdl/jdl-importer.spec.ts +++ b/jdl/jdl-importer.spec.ts @@ -52,6 +52,20 @@ describe('jdl - JDLImporter', () => { }); }); describe('import', () => { + context('parsing a relationship with builtInEntity', () => { + it('import and add relationshipWithBuiltInEntity to the relationship', () => { + const importState = createImporterFromContent( + ` +entity A +relationship OneToMany { + A{user} to User with builtInEntity +} +`, + { applicationName: 'MyApp', databaseType: databaseTypes.SQL, skipFileGeneration: true } + ).import(); + jestExpect(importState.exportedEntities[0].relationships[0].relationshipWithBuiltInEntity).toBe(true); + }); + }); context('when not parsing applications', () => { const ENTITY_NAMES = ['Country', 'Department', 'Employee', 'Job', 'JobHistory', 'Location', 'Region', 'Task']; let filesExist: any = true; diff --git a/jdl/jdl-importer.ts b/jdl/jdl-importer.ts index 983a40429899..64dcbd209b9c 100644 --- a/jdl/jdl-importer.ts +++ b/jdl/jdl-importer.ts @@ -137,12 +137,10 @@ function getJDLObject(parsedJDLContent, configuration) { let baseName = configuration.applicationName; let applicationType = configuration.applicationType; let databaseType = configuration.databaseType; - let skippedUserManagement = false; if (configuration.application) { baseName = configuration.application['generator-jhipster'].baseName; applicationType = configuration.application['generator-jhipster'].applicationType; - skippedUserManagement = configuration.application['generator-jhipster'].skipUserManagement; databaseType = configuration.application['generator-jhipster'].databaseType; } @@ -150,7 +148,6 @@ function getJDLObject(parsedJDLContent, configuration) { parsedContent: parsedJDLContent, applicationType, applicationName: baseName, - skippedUserManagement, databaseType, }); } @@ -164,7 +161,6 @@ function checkForErrors(jdlObject, configuration, logger = console) { } let applicationType = configuration.applicationType; let databaseType = configuration.databaseType; - let skippedUserManagement = configuration.skipUserManagement; let blueprints = configuration.blueprints; if (application && application['generator-jhipster']) { if (applicationType === undefined) { @@ -173,9 +169,6 @@ function checkForErrors(jdlObject, configuration, logger = console) { if (databaseType === undefined) { databaseType = application['generator-jhipster'].databaseType; } - if (skippedUserManagement === undefined) { - skippedUserManagement = application['generator-jhipster'].skipUserManagement; - } if (blueprints === undefined) { blueprints = application['generator-jhipster'].blueprints; } @@ -185,7 +178,6 @@ function checkForErrors(jdlObject, configuration, logger = console) { { applicationType, databaseType, - skippedUserManagement, blueprints, }, logger diff --git a/jdl/jhipster/relationship-options.ts b/jdl/jhipster/relationship-options.ts index 045e8c7fc246..04974dc39f62 100644 --- a/jdl/jhipster/relationship-options.ts +++ b/jdl/jhipster/relationship-options.ts @@ -19,6 +19,7 @@ const Options = { JPA_DERIVED_IDENTIFIER: 'jpaDerivedIdentifier', + BUILT_IN_ENTITY: 'builtInEntity', }; function exists(option) { diff --git a/jdl/jhipster/relationship-types.spec.ts b/jdl/jhipster/relationship-types.spec.ts index 7121981ea42c..e36dc94d048d 100644 --- a/jdl/jhipster/relationship-types.spec.ts +++ b/jdl/jhipster/relationship-types.spec.ts @@ -20,17 +20,18 @@ /* eslint-disable no-new, no-unused-expressions */ import { expect } from 'chai'; import { relationshipTypes } from '../jhipster/index.mjs'; +import { relationshipTypeExists } from './relationship-types.js'; describe('jdl - RelationshipTypes', () => { describe('exists', () => { context('when checking for a valid unary relationship type', () => { it('should return true', () => { - expect(relationshipTypes.exists(relationshipTypes.MANY_TO_ONE)).to.be.true; + expect(relationshipTypeExists(relationshipTypes.MANY_TO_ONE)).to.be.true; }); }); context('when checking for an invalid relationship type', () => { it('should return false', () => { - expect(relationshipTypes.exists('NOTHING')).to.be.false; + expect(relationshipTypeExists('NOTHING')).to.be.false; }); }); }); diff --git a/jdl/jhipster/relationship-types.ts b/jdl/jhipster/relationship-types.ts index be2d88442902..2b4f54684485 100644 --- a/jdl/jhipster/relationship-types.ts +++ b/jdl/jhipster/relationship-types.ts @@ -19,13 +19,16 @@ import _ from 'lodash'; -const relationshipTypes: any = { +import { asJdlRelationshipType } from '../converters/parsed-jdl-to-jdl-object/relationship-converter.js'; +import { JDLRelationshipType } from '../models/jdl-relationship.js'; + +const relationshipTypes: Record<'ONE_TO_ONE' | 'ONE_TO_MANY' | 'MANY_TO_ONE' | 'MANY_TO_MANY', JDLRelationshipType> = { ONE_TO_ONE: 'OneToOne', ONE_TO_MANY: 'OneToMany', MANY_TO_ONE: 'ManyToOne', MANY_TO_MANY: 'ManyToMany', }; -relationshipTypes.exists = relationship => Object.values(relationshipTypes).includes(_.upperFirst(_.camelCase(relationship))); +export const relationshipTypeExists = relationship => Object.values(relationshipTypes).includes(asJdlRelationshipType(relationship)); export default relationshipTypes; diff --git a/jdl/models/jdl-object.ts b/jdl/models/jdl-object.ts index 346ea2fc7433..07bde019c332 100644 --- a/jdl/models/jdl-object.ts +++ b/jdl/models/jdl-object.ts @@ -22,6 +22,7 @@ import JDLRelationships from './jdl-relationships.js'; import JDLOptions from './jdl-options.js'; import { binaryOptions } from '../jhipster/index.mjs'; import JDLEntity from './jdl-entity.js'; +import JDLRelationship from './jdl-relationship.js'; /** * The JDL object class, containing applications, entities etc. @@ -202,7 +203,7 @@ export default class JDLObject { return count; } - forEachRelationship(passedFunction) { + forEachRelationship(passedFunction?: (relationship: JDLRelationship) => void) { if (!passedFunction) { return; } diff --git a/jdl/models/jdl-options.ts b/jdl/models/jdl-options.ts index e5df6fc90688..fa081bff86a2 100644 --- a/jdl/models/jdl-options.ts +++ b/jdl/models/jdl-options.ts @@ -50,14 +50,14 @@ export default class JDLOptions { return options; } - getOptionsForName(optionName) { + getOptionsForName(optionName: string) { if (!optionName) { return []; } return this.getOptions().filter(option => option.name === optionName); } - has(optionName) { + has(optionName: string) { if (!optionName) { return false; } diff --git a/jdl/models/jdl-relationship.ts b/jdl/models/jdl-relationship.ts index 35653ca12045..56a21ccf4927 100644 --- a/jdl/models/jdl-relationship.ts +++ b/jdl/models/jdl-relationship.ts @@ -16,33 +16,56 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import logger from '../utils/objects/logger.js'; -import { relationshipTypes, validations } from '../jhipster/index.mjs'; -import { lowerFirst } from '../utils/string-utils.js'; +import { validations } from '../jhipster/index.mjs'; +import { relationshipTypeExists } from '../jhipster/relationship-types.js'; const { Validations: { REQUIRED }, } = validations; -export default class JDLRelationship { - from: any; - to: any; - type: any; - options: any; - injectedFieldInFrom: any; - injectedFieldInTo: any; - isInjectedFieldInFromRequired: any; - isInjectedFieldInToRequired: any; - commentInFrom: any; - commentInTo: any; +export const JDL_RELATIONSHIP_ONE_TO_ONE = 'OneToOne'; +export const JDL_RELATIONSHIP_ONE_TO_MANY = 'OneToMany'; +export const JDL_RELATIONSHIP_MANY_TO_ONE = 'ManyToOne'; +export const JDL_RELATIONSHIP_MANY_TO_MANY = 'ManyToMany'; - constructor(args) { +export type JDLRelationshipType = + | typeof JDL_RELATIONSHIP_ONE_TO_ONE + | typeof JDL_RELATIONSHIP_ONE_TO_MANY + | typeof JDL_RELATIONSHIP_MANY_TO_ONE + | typeof JDL_RELATIONSHIP_MANY_TO_MANY; +export type JDLRelationshipOptions = Record<'global' | 'source' | 'destination', Record>; + +export type JDLRelationshipModel = { + from: string; + to: string; + type: JDLRelationshipType; + options: JDLRelationshipOptions; + injectedFieldInFrom: null | string; + injectedFieldInTo: null | string; + isInjectedFieldInFromRequired: boolean; + isInjectedFieldInToRequired: boolean; + commentInFrom: null | string; + commentInTo: null | string; +}; + +export default class JDLRelationship implements JDLRelationshipModel { + from: string; + to: string; + type: JDLRelationshipType; + options: { global: Record; source: Record; destination: Record }; + injectedFieldInFrom: null | string; + injectedFieldInTo: null | string; + isInjectedFieldInFromRequired: boolean; + isInjectedFieldInToRequired: boolean; + commentInFrom: null | string; + commentInTo: null | string; + + constructor(args: Partial & Pick) { const merged = mergeDefaultsWithOverrides(args); if (!merged.from || !merged.to) { throw new Error('Source and destination entities must be passed to create a relationship.'); } - checkFromAndToTypesAreString(merged); - if (!relationshipTypes.exists(merged.type) || !(merged.injectedFieldInFrom || merged.injectedFieldInTo)) { + if (!relationshipTypeExists(merged.type) || !(merged.injectedFieldInFrom || merged.injectedFieldInTo)) { throw new Error('A valid type and at least one injected field must be passed to create a relationship.'); } this.from = merged.from; @@ -68,23 +91,23 @@ export default class JDLRelationship { ); } - hasGlobalOption(option) { + hasGlobalOption(option: string) { return option in this.options.global; } - forEachGlobalOption(passedFunction) { + forEachGlobalOption(passedFunction: (optionName: string, value: any) => void) { Object.entries(this.options.global).forEach(([key, value]) => { passedFunction(key, value); }); } - forEachSourceOption(passedFunction) { + forEachSourceOption(passedFunction: (optionName: string, value: any) => void) { Object.entries(this.options.source).forEach(([key, value]) => { passedFunction(key, value); }); } - forEachDestinationOption(passedFunction) { + forEachDestinationOption(passedFunction: (optionName: string, value: any) => void) { Object.entries(this.options.destination).forEach(([key, value]) => { passedFunction(key, value); }); @@ -146,11 +169,10 @@ export default class JDLRelationship { } } -function mergeDefaultsWithOverrides(overrides) { +function mergeDefaultsWithOverrides( + overrides: Partial & Pick +): JDLRelationshipModel { const defaultOptions = defaults(); - if (!overrides || Object.keys(overrides).length === 0) { - return defaultOptions; - } const mergedOptions = { ...defaultOptions, ...overrides, @@ -161,9 +183,8 @@ function mergeDefaultsWithOverrides(overrides) { return mergedOptions; } -function defaults() { +function defaults(): Omit { return { - type: relationshipTypes.ONE_TO_ONE, injectedFieldInFrom: null, injectedFieldInTo: null, isInjectedFieldInFromRequired: false, @@ -177,19 +198,3 @@ function defaults() { commentInTo: '', }; } - -function checkFromAndToTypesAreString(merged) { - if (typeof merged.from === 'string' && typeof merged.to === 'string') { - return; - } - logger.warn( - "The 'from' and 'to' keys will only be accepted as strings in the next major version instead of " + - `JDLEntities, for relationship from '${merged.from.name}' to '${merged.to.name}'.` - ); - if (typeof merged.from !== 'string') { - merged.from = merged.from.name; - } - if (typeof merged.to !== 'string') { - merged.to = merged.to.name; - } -} diff --git a/jdl/models/jdl-relationships.ts b/jdl/models/jdl-relationships.ts index 6550f2f49fe8..b0b903bb2ecc 100644 --- a/jdl/models/jdl-relationships.ts +++ b/jdl/models/jdl-relationships.ts @@ -18,9 +18,11 @@ */ import { relationshipTypes } from '../jhipster/index.mjs'; +import { relationshipTypeExists } from '../jhipster/relationship-types.js'; +import JDLRelationship, { JDLRelationshipType } from './jdl-relationship.js'; export default class JDLRelationships { - relationships: { OneToOne: Map; OneToMany: Map; ManyToOne: Map; ManyToMany: Map }; + relationships: Record>; constructor() { this.relationships = { @@ -31,7 +33,7 @@ export default class JDLRelationships { }; } - add(relationship) { + add(relationship: JDLRelationship) { if (!relationship) { throw new Error('A relationship must be passed so as to be added.'); } @@ -54,8 +56,8 @@ export default class JDLRelationships { return this.get(relationshipTypes.MANY_TO_MANY, relationshipId); } - get(type, relationshipId) { - if (!relationshipTypes.exists(type)) { + get(type, relationshipId): JDLRelationship { + if (!relationshipTypeExists(type)) { throw new Error(`A valid relationship type must be passed so as to retrieve the relationship, got '${type}'.`); } if (!relationshipId) { @@ -84,7 +86,7 @@ export default class JDLRelationships { return this.oneToOneQuantity() + this.oneToManyQuantity() + this.manyToOneQuantity() + this.manyToManyQuantity(); } - forEach(passedFunction) { + forEach(passedFunction: (relationship: JDLRelationship) => void) { if (!passedFunction) { return; } @@ -93,7 +95,7 @@ export default class JDLRelationships { }); } - toArray() { + toArray(): JDLRelationship[] { const relationships: any[] = []; Object.keys(this.relationships).forEach(type => { this.relationships[type].forEach(relationship => { diff --git a/jdl/parsing/generated/generated-serialized-grammar.js b/jdl/parsing/generated/generated-serialized-grammar.js index 9dcb5ef7e08b..db890fc240ac 100644 --- a/jdl/parsing/generated/generated-serialized-grammar.js +++ b/jdl/parsing/generated/generated-serialized-grammar.js @@ -901,6 +901,13 @@ const serializedGrammar = [ idx: 0, pattern: 'jpaDerivedIdentifier', }, + { + type: 'Terminal', + name: 'BUILT_IN_ENTITY', + label: "'builtInEntity'", + idx: 0, + pattern: 'builtInEntity', + }, ], }, ], diff --git a/jdl/parsing/jdl-ast-builder-visitor.ts b/jdl/parsing/jdl-ast-builder-visitor.ts index 200dbcc3ae84..c1a7f8b1115f 100644 --- a/jdl/parsing/jdl-ast-builder-visitor.ts +++ b/jdl/parsing/jdl-ast-builder-visitor.ts @@ -19,8 +19,9 @@ import JDLParser from './jdl-parser.js'; import deduplicate from '../utils/array-utils.js'; -import { applicationOptions, entityOptions, validations } from '../jhipster/index.mjs'; +import { applicationOptions, entityOptions, validations, relationshipOptions } from '../jhipster/index.mjs'; +const { BUILT_IN_ENTITY } = relationshipOptions; const { OptionNames } = applicationOptions; const { PaginationTypes } = entityOptions; const { @@ -336,6 +337,9 @@ export default class JDLAstBuilderVisitor extends BaseJDLCSTVisitor { if (context.JPA_DERIVED_IDENTIFIER) { return { optionName: 'jpaDerivedIdentifier', type: 'UNARY' }; } + if (context.BUILT_IN_ENTITY) { + return { optionName: BUILT_IN_ENTITY, type: 'UNARY' }; + } /* istanbul ignore next */ throw new Error("No valid relationship option found, expected 'jpaDerivedIdentifier'."); diff --git a/jdl/parsing/jdl-parser.ts b/jdl/parsing/jdl-parser.ts index 716c19c36ac5..49112cd8e21c 100644 --- a/jdl/parsing/jdl-parser.ts +++ b/jdl/parsing/jdl-parser.ts @@ -322,7 +322,7 @@ export default class JDLParser extends CstParser { relationshipOption(): any { this.RULE('relationshipOption', () => { - this.OR([{ ALT: () => this.CONSUME(LexerTokens.JPA_DERIVED_IDENTIFIER) }]); + this.OR([{ ALT: () => this.CONSUME(LexerTokens.JPA_DERIVED_IDENTIFIER) }, { ALT: () => this.CONSUME(LexerTokens.BUILT_IN_ENTITY) }]); }); } diff --git a/jdl/parsing/lexer/lexer.ts b/jdl/parsing/lexer/lexer.ts index f04f9384317c..2132e23f2c8f 100644 --- a/jdl/parsing/lexer/lexer.ts +++ b/jdl/parsing/lexer/lexer.ts @@ -20,6 +20,7 @@ import { Lexer } from 'chevrotain'; import { NAME, UNARY_OPTION, BINARY_OPTION } from './shared-tokens.js'; +import { relationshipOptions } from '../../jhipster/index.mjs'; import ValidationTokens from './validation-tokens.js'; import ApplicationTokens from './application-tokens.js'; @@ -31,6 +32,8 @@ import createTokenFromConfigCreator from './token-creator.js'; export const tokens: any = {}; +const { BUILT_IN_ENTITY } = relationshipOptions; + function createTokenFromConfig(config) { const newToken = createTokenFromConfigCreator(config); tokens[config.name] = newToken; @@ -103,6 +106,7 @@ createTokenFromConfig({ name: 'ENUM', pattern: 'enum' }); // Relationship-related createTokenFromConfig({ name: 'RELATIONSHIP', pattern: 'relationship' }); createTokenFromConfig({ name: 'JPA_DERIVED_IDENTIFIER', pattern: 'jpaDerivedIdentifier' }); +createTokenFromConfig({ name: 'BUILT_IN_ENTITY', pattern: BUILT_IN_ENTITY }); // Category For the relationship type key names RelationshipTypeTokens.tokens.forEach(token => { diff --git a/jdl/parsing/lexer/relationship-type-tokens.ts b/jdl/parsing/lexer/relationship-type-tokens.ts index 95754e506c17..e8cc64a3b70d 100644 --- a/jdl/parsing/lexer/relationship-type-tokens.ts +++ b/jdl/parsing/lexer/relationship-type-tokens.ts @@ -18,15 +18,21 @@ */ import { Lexer } from 'chevrotain'; +import { + JDL_RELATIONSHIP_MANY_TO_MANY, + JDL_RELATIONSHIP_MANY_TO_ONE, + JDL_RELATIONSHIP_ONE_TO_MANY, + JDL_RELATIONSHIP_ONE_TO_ONE, +} from '../../models/jdl-relationship.js'; import createTokenFromConfig from './token-creator.js'; const relationshipTypeCategoryToken = createTokenFromConfig({ name: 'RELATIONSHIP_TYPE', pattern: Lexer.NA }); const relationshipTypeTokens = [ - { name: 'ONE_TO_ONE', pattern: 'OneToOne' }, - { name: 'ONE_TO_MANY', pattern: 'OneToMany' }, - { name: 'MANY_TO_ONE', pattern: 'ManyToOne' }, - { name: 'MANY_TO_MANY', pattern: 'ManyToMany' }, + { name: 'ONE_TO_ONE', pattern: JDL_RELATIONSHIP_ONE_TO_ONE }, + { name: 'ONE_TO_MANY', pattern: JDL_RELATIONSHIP_ONE_TO_MANY }, + { name: 'MANY_TO_ONE', pattern: JDL_RELATIONSHIP_MANY_TO_ONE }, + { name: 'MANY_TO_MANY', pattern: JDL_RELATIONSHIP_MANY_TO_MANY }, ].map(tokenConfig => { (tokenConfig as any).categories = [relationshipTypeCategoryToken]; return createTokenFromConfig(tokenConfig); diff --git a/jdl/readers/json-reader.ts b/jdl/readers/json-reader.ts index de0e9adc6906..b7883bd20aab 100644 --- a/jdl/readers/json-reader.ts +++ b/jdl/readers/json-reader.ts @@ -56,7 +56,6 @@ export default function parseFromDir(dir: string): JDLObject { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-expect-error const jdlObject = convertServerOptionsToJDL(applicationOptions); - const skippedUserManagement = !!applicationOptions[OptionNames.SKIP_USER_MANAGEMENT]; - const convertedJDLObject = convertEntitiesToJDL({ entities, skippedUserManagement }); + const convertedJDLObject = convertEntitiesToJDL({ entities }); return mergeJDLObjects(jdlObject, convertedJDLObject); } diff --git a/jdl/validators/jdl-with-application-validator.spec.ts b/jdl/validators/jdl-with-application-validator.spec.ts index 0b8f2f6a7462..763a688dd8ec 100644 --- a/jdl/validators/jdl-with-application-validator.spec.ts +++ b/jdl/validators/jdl-with-application-validator.spec.ts @@ -259,73 +259,48 @@ describe('jdl - JDLWithApplicationValidator', () => { it('should fail', () => { expect(() => { validator.checkForErrors(); - }).to.throw('In the relationship between Source and Valid, Source is not declared.'); + }).to.throw( + "In the relationship between Source and Valid, Source is not declared. If 'Valid' is a built-in entity declare like 'Source to Valid with builtInEntity'." + ); }); }); context('when the destination entity of a relationship is missing', () => { - context('if it is the User entity', () => { - context('when the skipUserManagement flag is not set', () => { - let validator; - - before(() => { - const sourceEntity = new JDLEntity({ - name: 'Source', - }); - const relationship = new JDLRelationship({ - from: sourceEntity.name, - to: 'User', - type: relationshipTypes.ONE_TO_ONE, - injectedFieldInFrom: 'other', - }); - const jdlObject = new JDLObject(); - const application = createJDLApplication({ - applicationType: MONOLITH, - databaseType: databaseTypes.SQL, - }); - jdlObject.addEntity(sourceEntity); - jdlObject.addRelationship(relationship); - application.addEntityName(sourceEntity.name); - jdlObject.addApplication(application); - validator = createValidator(jdlObject); - }); + context('if it has builtInEntity annotation', () => { + let validator; - it('should not fail', () => { - expect(() => { - validator.checkForErrors(); - }).not.to.throw(); + before(() => { + const sourceEntity = new JDLEntity({ + name: 'Source', }); - }); - context('when skipUserManagement flag is set', () => { - let checker; - - before(() => { - const sourceEntity = new JDLEntity({ - name: 'Source', - }); - const relationship = new JDLRelationship({ - from: sourceEntity.name, - to: 'User', - type: relationshipTypes.ONE_TO_ONE, - injectedFieldInFrom: 'other', - }); - const jdlObject = new JDLObject(); - const application = createJDLApplication({ - applicationType: MONOLITH, - databaseType: databaseTypes.SQL, - skipUserManagement: true, - }); - jdlObject.addEntity(sourceEntity); - jdlObject.addRelationship(relationship); - application.addEntityName(sourceEntity); - jdlObject.addApplication(application); - checker = createValidator(jdlObject); + const relationship = new JDLRelationship({ + from: sourceEntity.name, + to: 'User', + type: relationshipTypes.ONE_TO_ONE, + injectedFieldInFrom: 'other', + options: { + global: { + builtInEntity: true, + }, + source: {}, + destination: {}, + }, }); - - it('should fail', () => { - expect(() => { - checker.checkForErrors(); - }).to.throw('In the relationship between Source and User, User is not declared.'); + const jdlObject = new JDLObject(); + const application = createJDLApplication({ + applicationType: MONOLITH, + databaseType: databaseTypes.SQL, }); + jdlObject.addEntity(sourceEntity); + jdlObject.addRelationship(relationship); + application.addEntityName(sourceEntity.name); + jdlObject.addApplication(application); + validator = createValidator(jdlObject); + }); + + it('should not fail', () => { + expect(() => { + validator.checkForErrors(); + }).not.to.throw(); }); }); context('if it is not the User entity', () => { @@ -356,7 +331,9 @@ describe('jdl - JDLWithApplicationValidator', () => { it('should fail', () => { expect(() => { checker.checkForErrors(); - }).to.throw('In the relationship between Source and Other, Other is not declared.'); + }).to.throw( + "In the relationship between Source and Other, Other is not declared. If 'Other' is a built-in entity declare like 'Source to Other with builtInEntity'." + ); }); }); }); @@ -542,139 +519,71 @@ describe('jdl - JDLWithApplicationValidator', () => { }); }); context('when having a relationship with the User entity as source', () => { - context('with skipUserManagement', () => { - let validator; + let validator; - before(() => { - const sourceEntity = new JDLEntity({ - name: 'User', - }); - const destinationEntity = new JDLEntity({ - name: 'Destination', - }); - const relationship = new JDLRelationship({ - from: sourceEntity.name, - to: destinationEntity.name, - type: relationshipTypes.ONE_TO_ONE, - injectedFieldInFrom: 'other', - }); - const jdlObject = new JDLObject(); - const application = createJDLApplication({ - applicationType: MONOLITH, - databaseType: databaseTypes.SQL, - skipUserManagement: true, - }); - jdlObject.addEntity(sourceEntity); - jdlObject.addEntity(destinationEntity); - jdlObject.addRelationship(relationship); - application.addEntityName(sourceEntity); - application.addEntityName(destinationEntity); - jdlObject.addApplication(application); - validator = createValidator(jdlObject); + before(() => { + const sourceEntity = new JDLEntity({ + name: 'User', }); - - it('should not fail', () => { - expect(() => validator.checkForErrors()).not.to.throw(); + const destinationEntity = new JDLEntity({ + name: 'Destination', }); - }); - context('without skipUserManagement', () => { - let validator; - - before(() => { - const destinationEntity = new JDLEntity({ - name: 'Destination', - }); - const relationship = new JDLRelationship({ - from: 'User', - to: destinationEntity.name, - type: relationshipTypes.ONE_TO_ONE, - injectedFieldInFrom: 'other', - }); - const jdlObject = new JDLObject(); - const application = createJDLApplication({ - applicationType: MONOLITH, - databaseType: databaseTypes.SQL, - skipUserManagement: false, - }); - jdlObject.addEntity(destinationEntity); - jdlObject.addRelationship(relationship); - application.addEntityName(destinationEntity); - jdlObject.addApplication(application); - validator = createValidator(jdlObject); + const relationship = new JDLRelationship({ + from: sourceEntity.name, + to: destinationEntity.name, + type: relationshipTypes.ONE_TO_ONE, + injectedFieldInFrom: 'other', }); - - it('should fail', () => { - expect(() => validator.checkForErrors()).to.throw( - /^Relationships from the User entity is not supported in the declaration between 'User' and 'Destination'. You can have this by using the 'skipUserManagement' option.$/ - ); + const jdlObject = new JDLObject(); + const application = createJDLApplication({ + applicationType: MONOLITH, + databaseType: databaseTypes.SQL, }); + jdlObject.addEntity(sourceEntity); + jdlObject.addEntity(destinationEntity); + jdlObject.addRelationship(relationship); + application.addEntityName(sourceEntity); + application.addEntityName(destinationEntity); + jdlObject.addApplication(application); + validator = createValidator(jdlObject); + }); + + it('should not fail', () => { + expect(() => validator.checkForErrors()).not.to.throw(); }); }); context('when having a relationship with the User entity as destination', () => { - context('with skipUserManagement', () => { - let validator; + let validator; - before(() => { - const sourceEntity = new JDLEntity({ - name: 'Source', - }); - const destinationEntity = new JDLEntity({ - name: 'User', - }); - const relationship = new JDLRelationship({ - from: sourceEntity.name, - to: destinationEntity.name, - type: relationshipTypes.ONE_TO_ONE, - injectedFieldInFrom: 'other', - }); - const jdlObject = new JDLObject(); - const application = createJDLApplication({ - applicationType: MONOLITH, - databaseType: databaseTypes.SQL, - skipUserManagement: true, - }); - jdlObject.addEntity(sourceEntity); - jdlObject.addEntity(destinationEntity); - jdlObject.addRelationship(relationship); - application.addEntityName(sourceEntity); - application.addEntityName(destinationEntity); - jdlObject.addApplication(application); - validator = createValidator(jdlObject); + before(() => { + const sourceEntity = new JDLEntity({ + name: 'Source', }); - - it('should not fail', () => { - expect(() => validator.checkForErrors()).not.to.throw(); + const destinationEntity = new JDLEntity({ + name: 'User', }); - }); - context('without skipUserManagement', () => { - let validator; - - before(() => { - const sourceEntity = new JDLEntity({ - name: 'Source', - }); - const relationship = new JDLRelationship({ - from: sourceEntity.name, - to: 'User', - type: relationshipTypes.ONE_TO_ONE, - injectedFieldInFrom: 'other', - }); - const jdlObject = new JDLObject(); - const application = createJDLApplication({ - applicationType: MONOLITH, - databaseType: databaseTypes.SQL, - skipUserManagement: false, - }); - jdlObject.addEntity(sourceEntity); - jdlObject.addRelationship(relationship); - application.addEntityName(sourceEntity); - jdlObject.addApplication(application); - validator = createValidator(jdlObject); + const relationship = new JDLRelationship({ + from: sourceEntity.name, + to: destinationEntity.name, + type: relationshipTypes.ONE_TO_ONE, + injectedFieldInFrom: 'other', }); - - it('should not fail', () => { - expect(() => validator.checkForErrors()).not.to.throw(); + const jdlObject = new JDLObject(); + const application = createJDLApplication({ + applicationType: MONOLITH, + databaseType: databaseTypes.SQL, }); + jdlObject.addEntity(sourceEntity); + jdlObject.addEntity(destinationEntity); + jdlObject.addRelationship(relationship); + application.addEntityName(sourceEntity); + application.addEntityName(destinationEntity); + jdlObject.addApplication(application); + validator = createValidator(jdlObject); + }); + + it('should not fail', () => { + expect(() => validator.checkForErrors()).not.to.throw(); }); }); context('when blueprints is used', () => { diff --git a/jdl/validators/jdl-with-application-validator.ts b/jdl/validators/jdl-with-application-validator.ts index 3ca294c3b3a4..eaba226a6653 100644 --- a/jdl/validators/jdl-with-application-validator.ts +++ b/jdl/validators/jdl-with-application-validator.ts @@ -19,7 +19,15 @@ import EntityValidator from './entity-validator.js'; import FieldValidator from './field-validator.js'; -import { fieldTypes, applicationTypes, databaseTypes, binaryOptions, reservedKeywords, applicationOptions } from '../jhipster/index.mjs'; +import { + fieldTypes, + applicationTypes, + databaseTypes, + binaryOptions, + reservedKeywords, + applicationOptions, + relationshipOptions, +} from '../jhipster/index.mjs'; import ValidationValidator from './validation-validator.js'; import RelationshipValidator from './relationship-validator.js'; import EnumValidator from './enum-validator.js'; @@ -28,10 +36,12 @@ import UnaryOptionValidator from './unary-option-validator.js'; import BinaryOptionValidator from './binary-option-validator.js'; import ApplicationValidator from './application-validator.js'; import JDLObject from '../models/jdl-object.js'; +import JDLRelationship from '../models/jdl-relationship.js'; const { OptionNames } = applicationOptions; const { SQL } = databaseTypes; +const { BUILT_IN_ENTITY } = relationshipOptions; const { APPLICATION_TYPE, BLUEPRINTS, DATABASE_TYPE, BASE_NAME, REACTIVE, JHI_PREFIX, SKIP_USER_MANAGEMENT } = OptionNames; const { isReservedFieldName, isReservedTableName, isReservedPaginationWords } = reservedKeywords; /** @@ -138,14 +148,12 @@ export default function createValidator(jdlObject: JDLObject, logger: any = cons if (jdlObject.getRelationshipQuantity() === 0) { return; } - const skippedUserManagement = jdlApplication.getConfigurationOptionValue(SKIP_USER_MANAGEMENT); const validator = new RelationshipValidator(); jdlObject.forEachRelationship(jdlRelationship => { - validator.validate(jdlRelationship, { skippedUserManagement }); + validator.validate(jdlRelationship); checkForAbsentEntities({ jdlRelationship, doesEntityExist: entityName => !!jdlObject.getEntity(entityName), - skippedUserManagementOption: skippedUserManagement, }); }); } @@ -206,26 +214,30 @@ function checkForPaginationInAppWithCassandra(jdlOption, jdlApplication) { } } -function checkForAbsentEntities({ jdlRelationship, doesEntityExist, skippedUserManagementOption }) { +function checkForAbsentEntities({ + jdlRelationship, + doesEntityExist, +}: { + jdlRelationship: JDLRelationship; + doesEntityExist: (string) => boolean; +}) { const absentEntities: any[] = []; if (!doesEntityExist(jdlRelationship.from)) { absentEntities.push(jdlRelationship.from); } - if (!doesEntityExist(jdlRelationship.to) && (!isUserManagementEntity(jdlRelationship.to) || skippedUserManagementOption)) { + if (!doesEntityExist(jdlRelationship.to) && !jdlRelationship.options.global[BUILT_IN_ENTITY]) { absentEntities.push(jdlRelationship.to); } if (absentEntities.length !== 0) { throw new Error( `In the relationship between ${jdlRelationship.from} and ${jdlRelationship.to}, ` + - `${absentEntities.join(' and ')} ${absentEntities.length === 1 ? 'is' : 'are'} not declared.` + `${absentEntities.join(' and ')} ${absentEntities.length === 1 ? 'is' : 'are'} not declared. If '${ + jdlRelationship.to + }' is a built-in entity declare like '${jdlRelationship.from} to ${jdlRelationship.to} with builtInEntity'.` ); } } -function isUserManagementEntity(entityName) { - return entityName.toLowerCase() === 'user' || entityName.toLowerCase() === 'authority'; -} - function isTableNameReserved(tableName, jdlApplication: any = []) { return isReservedTableName(tableName, jdlApplication.getConfigurationOptionValue(DATABASE_TYPE)); } diff --git a/jdl/validators/jdl-without-application-validator.spec.ts b/jdl/validators/jdl-without-application-validator.spec.ts index 21e16d8f6ccf..209dac0c37e7 100644 --- a/jdl/validators/jdl-without-application-validator.spec.ts +++ b/jdl/validators/jdl-without-application-validator.spec.ts @@ -237,66 +237,45 @@ describe('jdl - JDLWithoutApplicationValidator', () => { it('should fail', () => { expect(() => { validator.checkForErrors(); - }).to.throw('In the relationship between Source and Valid, Source is not declared.'); + }).to.throw( + "In the relationship between Source and Valid, Source is not declared. If 'Valid' is a built-in entity declare like 'Source to Valid with builtInEntity'." + ); }); }); context('when the destination entity of a relationship is missing', () => { - context('if it is the User entity', () => { - context('when the skipUserManagement flag is not set', () => { - let validator; - - before(() => { - const sourceEntity = new JDLEntity({ - name: 'Source', - }); - const relationship = new JDLRelationship({ - from: sourceEntity.name, - to: 'User', - type: relationshipTypes.ONE_TO_ONE, - injectedFieldInFrom: 'other', - }); - const jdlObject = new JDLObject(); - jdlObject.addEntity(sourceEntity); - jdlObject.addRelationship(relationship); - validator = createValidator(jdlObject, { - databaseType: databaseTypes.SQL, - }); - }); + context('if it has builtInEntity annotation', () => { + let validator; - it('should not fail', () => { - expect(() => { - validator.checkForErrors(); - }).not.to.throw(); + before(() => { + const sourceEntity = new JDLEntity({ + name: 'Source', }); - }); - context('when skipUserManagement flag is set', () => { - let checker; - - before(() => { - const sourceEntity = new JDLEntity({ - name: 'Source', - }); - const relationship = new JDLRelationship({ - from: sourceEntity.name, - to: 'User', - type: relationshipTypes.ONE_TO_ONE, - injectedFieldInFrom: 'other', - }); - const jdlObject = new JDLObject(); - jdlObject.addEntity(sourceEntity); - jdlObject.addRelationship(relationship); - checker = createValidator(jdlObject, { - databaseType: databaseTypes.SQL, - skippedUserManagement: true, - }); + const relationship = new JDLRelationship({ + from: sourceEntity.name, + to: 'User', + type: relationshipTypes.ONE_TO_ONE, + injectedFieldInFrom: 'other', + options: { + global: { + builtInEntity: true, + }, + source: {}, + destination: {}, + }, }); - - it('should fail', () => { - expect(() => { - checker.checkForErrors(); - }).to.throw('In the relationship between Source and User, User is not declared.'); + const jdlObject = new JDLObject(); + jdlObject.addEntity(sourceEntity); + jdlObject.addRelationship(relationship); + validator = createValidator(jdlObject, { + databaseType: databaseTypes.SQL, }); }); + + it('should not fail', () => { + expect(() => { + validator.checkForErrors(); + }).not.to.throw(); + }); }); context('if it is not the User entity', () => { let checker; @@ -322,7 +301,9 @@ describe('jdl - JDLWithoutApplicationValidator', () => { it('should fail', () => { expect(() => { checker.checkForErrors(); - }).to.throw('In the relationship between Source and Other, Other is not declared.'); + }).to.throw( + "In the relationship between Source and Other, Other is not declared. If 'Other' is a built-in entity declare like 'Source to Other with builtInEntity'." + ); }); }); }); @@ -417,109 +398,57 @@ describe('jdl - JDLWithoutApplicationValidator', () => { }); }); context('when having a relationship with the User entity as source', () => { - context('with skipUserManagement', () => { - let validator; + let validator; - before(() => { - const sourceEntity = new JDLEntity({ - name: 'User', - }); - const destinationEntity = new JDLEntity({ - name: 'Destination', - }); - const relationship = new JDLRelationship({ - from: sourceEntity.name, - to: destinationEntity.name, - type: relationshipTypes.ONE_TO_ONE, - injectedFieldInFrom: 'other', - }); - const jdlObject = new JDLObject(); - jdlObject.addEntity(sourceEntity); - jdlObject.addEntity(destinationEntity); - jdlObject.addRelationship(relationship); - validator = createValidator(jdlObject, { databaseType: databaseTypes.SQL, skippedUserManagement: true }); + before(() => { + const sourceEntity = new JDLEntity({ + name: 'User', }); - - it('should not fail', () => { - expect(() => validator.checkForErrors()).not.to.throw(); + const destinationEntity = new JDLEntity({ + name: 'Destination', }); - }); - context('without skipUserManagement', () => { - let validator; - - before(() => { - const destinationEntity = new JDLEntity({ - name: 'Destination', - }); - const relationship = new JDLRelationship({ - from: 'User', - to: destinationEntity.name, - type: relationshipTypes.ONE_TO_ONE, - injectedFieldInFrom: 'other', - }); - const jdlObject = new JDLObject(); - jdlObject.addEntity(destinationEntity); - jdlObject.addRelationship(relationship); - validator = createValidator(jdlObject, { databaseType: databaseTypes.SQL, skippedUserManagement: false }); + const relationship = new JDLRelationship({ + from: sourceEntity.name, + to: destinationEntity.name, + type: relationshipTypes.ONE_TO_ONE, + injectedFieldInFrom: 'other', }); + const jdlObject = new JDLObject(); + jdlObject.addEntity(sourceEntity); + jdlObject.addEntity(destinationEntity); + jdlObject.addRelationship(relationship); + validator = createValidator(jdlObject, { databaseType: databaseTypes.SQL }); + }); - it('should fail', () => { - expect(() => validator.checkForErrors()).to.throw( - /^Relationships from the User entity is not supported in the declaration between 'User' and 'Destination'. You can have this by using the 'skipUserManagement' option.$/ - ); - }); + it('should not fail', () => { + expect(() => validator.checkForErrors()).not.to.throw(); }); }); context('when having a relationship with the User entity as destination', () => { - context('with skipUserManagement', () => { - let validator; + let validator; - before(() => { - const sourceEntity = new JDLEntity({ - name: 'Source', - }); - const destinationEntity = new JDLEntity({ - name: 'User', - }); - const relationship = new JDLRelationship({ - from: sourceEntity.name, - to: destinationEntity.name, - type: relationshipTypes.ONE_TO_ONE, - injectedFieldInFrom: 'other', - }); - const jdlObject = new JDLObject(); - jdlObject.addEntity(sourceEntity); - jdlObject.addEntity(destinationEntity); - jdlObject.addRelationship(relationship); - validator = createValidator(jdlObject, { databaseType: databaseTypes.SQL, skippedUserManagement: true }); + before(() => { + const sourceEntity = new JDLEntity({ + name: 'Source', }); - - it('should not fail', () => { - expect(() => validator.checkForErrors()).not.to.throw(); + const destinationEntity = new JDLEntity({ + name: 'User', }); - }); - context('without skipUserManagement', () => { - let validator; - - before(() => { - const sourceEntity = new JDLEntity({ - name: 'Source', - }); - const relationship = new JDLRelationship({ - from: sourceEntity.name, - to: 'User', - type: relationshipTypes.ONE_TO_ONE, - injectedFieldInFrom: 'other', - }); - const jdlObject = new JDLObject(); - jdlObject.addEntity(sourceEntity); - jdlObject.addRelationship(relationship); - validator = createValidator(jdlObject, { databaseType: databaseTypes.SQL, skippedUserManagement: false }); + const relationship = new JDLRelationship({ + from: sourceEntity.name, + to: destinationEntity.name, + type: relationshipTypes.ONE_TO_ONE, + injectedFieldInFrom: 'other', }); + const jdlObject = new JDLObject(); + jdlObject.addEntity(sourceEntity); + jdlObject.addEntity(destinationEntity); + jdlObject.addRelationship(relationship); + validator = createValidator(jdlObject, { databaseType: databaseTypes.SQL }); + }); - it('should not fail', () => { - expect(() => validator.checkForErrors()).not.to.throw(); - }); + it('should not fail', () => { + expect(() => validator.checkForErrors()).not.to.throw(); }); }); context('when blueprints is used', () => { diff --git a/jdl/validators/jdl-without-application-validator.ts b/jdl/validators/jdl-without-application-validator.ts index b7bfd5ed2c34..c7f4fafafc3c 100644 --- a/jdl/validators/jdl-without-application-validator.ts +++ b/jdl/validators/jdl-without-application-validator.ts @@ -19,7 +19,7 @@ import EntityValidator from './entity-validator.js'; import FieldValidator from './field-validator.js'; -import { fieldTypes, applicationTypes, databaseTypes, binaryOptions, applicationOptions, reservedKeywords } from '../jhipster/index.mjs'; +import { fieldTypes, applicationTypes, databaseTypes, binaryOptions, reservedKeywords, relationshipOptions } from '../jhipster/index.mjs'; import ValidationValidator from './validation-validator.js'; import RelationshipValidator from './relationship-validator.js'; import EnumValidator from './enum-validator.js'; @@ -28,9 +28,10 @@ import UnaryOptionValidator from './unary-option-validator.js'; import BinaryOptionValidator from './binary-option-validator.js'; import JDLObject from '../models/jdl-object.js'; +import JDLRelationship from '../models/jdl-relationship.js'; +const { BUILT_IN_ENTITY } = relationshipOptions; const { isReservedFieldName, isReservedTableName, isReservedPaginationWords } = reservedKeywords; -const { OptionNames } = applicationOptions; const { SQL } = databaseTypes; /** @@ -40,7 +41,6 @@ const { SQL } = databaseTypes; * @param {String} applicationSettings.baseName - the application's name. * @param {String} applicationSettings.applicationType - the application type. * @param {String} applicationSettings.databaseType - the DB type. - * @param {Boolean} applicationSettings.skippedUserManagement - whether user management is skipped. * @param {Array} applicationSettings.blueprints - the blueprints used. * @param {Object} [logger] - the logger to use, default to the console. * @param {Object} [options] @@ -123,15 +123,12 @@ export default function createValidator(jdlObject: JDLObject, applicationSetting if (jdlObject.getRelationshipQuantity() === 0) { return; } - const skippedUserManagement = - applicationSettings.skippedUserManagement || jdlObject.getOptionsForName(OptionNames.SKIP_USER_MANAGEMENT)[0]; const validator = new RelationshipValidator(); jdlObject.forEachRelationship(jdlRelationship => { - validator.validate(jdlRelationship, { skippedUserManagement }); + validator.validate(jdlRelationship); checkForAbsentEntities({ jdlRelationship, doesEntityExist: entityName => !!jdlObject.getEntity(entityName), - skippedUserManagementOption: skippedUserManagement, }); }); } @@ -180,24 +177,29 @@ function getTypeCheckingFunction(entityName, applicationSettings) { return fieldTypes.getIsType(applicationSettings.databaseType); } -function checkForAbsentEntities({ jdlRelationship, doesEntityExist, skippedUserManagementOption }) { +function checkForAbsentEntities({ + jdlRelationship, + doesEntityExist, +}: { + jdlRelationship: JDLRelationship; + doesEntityExist: (string) => boolean; +}) { const absentEntities: any[] = []; if (!doesEntityExist(jdlRelationship.from)) { absentEntities.push(jdlRelationship.from); } - if (!doesEntityExist(jdlRelationship.to) && (!isUserManagementEntity(jdlRelationship.to) || skippedUserManagementOption)) { + if (!doesEntityExist(jdlRelationship.to) && !jdlRelationship.options.global[BUILT_IN_ENTITY]) { absentEntities.push(jdlRelationship.to); } if (absentEntities.length !== 0) { throw new Error( `In the relationship between ${jdlRelationship.from} and ${jdlRelationship.to}, ` + - `${absentEntities.join(' and ')} ${absentEntities.length === 1 ? 'is' : 'are'} not declared.` + `${absentEntities.join(' and ')} ${absentEntities.length === 1 ? 'is' : 'are'} not declared. If '${ + jdlRelationship.to + }' is a built-in entity declare like '${jdlRelationship.from} to ${jdlRelationship.to} with builtInEntity'.` ); } } -function isUserManagementEntity(entityName) { - return entityName.toLowerCase() === 'user' || entityName.toLowerCase() === 'authority'; -} function checkForPaginationInAppWithCassandra(jdlOption, applicationSettings) { if (applicationSettings.databaseType === databaseTypes.CASSANDRA && jdlOption.name === binaryOptions.Options.PAGINATION) { throw new Error("Pagination isn't allowed when the application uses Cassandra."); diff --git a/jdl/validators/relationship-validator.spec.ts b/jdl/validators/relationship-validator.spec.ts index a1a619552acd..741506bcff9d 100644 --- a/jdl/validators/relationship-validator.spec.ts +++ b/jdl/validators/relationship-validator.spec.ts @@ -231,24 +231,6 @@ describe('jdl - RelationshipValidator', () => { expect(() => validator.validate(relationship)).not.to.throw(); }); }); - context('having the source entity as user', () => { - let relationship; - - before(() => { - relationship = { - from: 'User', - to: 'A', - type: ONE_TO_ONE, - injectedFieldInFrom: 'a', - }; - }); - - it('should fail', () => { - expect(() => validator.validate(relationship)).to.throw( - /^Relationships from the User entity is not supported in the declaration between 'User' and 'A'\. You can have this by using the 'skipUserManagement' option\.$/ - ); - }); - }); }); context(`when having a ${MANY_TO_ONE} relationship`, () => { context('without the User having the injected field', () => { @@ -268,22 +250,6 @@ describe('jdl - RelationshipValidator', () => { }); }); context('with the User having the injected field', () => { - context('with the skipUserManagement option', () => { - let relationship; - - before(() => { - relationship = new JDLRelationship({ - from: 'User', - to: 'A', - type: MANY_TO_ONE, - injectedFieldInFrom: 'a', - }); - }); - - it('should not fail', () => { - expect(() => validator.validate(relationship, true)).not.to.throw(); - }); - }); context('as the source', () => { let relationship; @@ -296,10 +262,8 @@ describe('jdl - RelationshipValidator', () => { }); }); - it('should fail', () => { - expect(() => validator.validate(relationship)).to.throw( - /^Relationships from the User entity is not supported in the declaration between 'User' and 'A'\. You can have this by using the 'skipUserManagement' option\.$/ - ); + it('should not fail', () => { + expect(() => validator.validate(relationship)).not.to.throw(); }); }); context('as the destination', () => { @@ -315,9 +279,7 @@ describe('jdl - RelationshipValidator', () => { }); it('should fail', () => { - expect(() => validator.validate(relationship)).to.throw( - /^In the Many-to-One relationship from A to User, the User entity has the injected field without its management being skipped\. To have such a relation, you should use the 'skipUserManagement' option\.$/ - ); + expect(() => validator.validate(relationship)).not.to.throw(); }); }); }); @@ -352,9 +314,7 @@ describe('jdl - RelationshipValidator', () => { }); it('should fail', () => { - expect(() => validator.validate(relationship)).to.throw( - /^Relationships from the User entity is not supported in the declaration between 'User' and 'A'. You can have this by using the 'skipUserManagement' option\.$/ - ); + expect(() => validator.validate(relationship)).not.to.throw(); }); }); }); diff --git a/jdl/validators/relationship-validator.ts b/jdl/validators/relationship-validator.ts index 3c86f5deb34b..19c5483dbba5 100644 --- a/jdl/validators/relationship-validator.ts +++ b/jdl/validators/relationship-validator.ts @@ -19,8 +19,10 @@ import Validator from './validator.js'; import { relationshipTypes, relationshipOptions } from '../jhipster/index.mjs'; +import JDLRelationship from '../models/jdl-relationship.js'; +import { relationshipTypeExists } from '../jhipster/relationship-types.js'; -const { exists, ONE_TO_ONE, MANY_TO_MANY, MANY_TO_ONE, ONE_TO_MANY } = relationshipTypes; +const { ONE_TO_ONE, MANY_TO_MANY, MANY_TO_ONE, ONE_TO_MANY } = relationshipTypes; const { JPA_DERIVED_IDENTIFIER } = relationshipOptions; export default class RelationshipValidator extends Validator { @@ -28,40 +30,35 @@ export default class RelationshipValidator extends Validator { super('relationship', ['from', 'to', 'type']); } - validate(jdlRelationship, options: any = {}) { - if (typeof options === 'boolean') { - options = { skippedUserManagement: options }; - } - const { skippedUserManagement } = options; + validate(jdlRelationship: JDLRelationship) { super.validate(jdlRelationship); checkType(jdlRelationship); checkInjectedFields(jdlRelationship); checkForValidUseOfJPaDerivedIdentifier(jdlRelationship); checkForRequiredReflexiveRelationship(jdlRelationship); - checkForInvalidUseOfTheUserEntity(jdlRelationship, skippedUserManagement); - checkRelationshipType(jdlRelationship, { skippedUserManagement }); + checkRelationshipType(jdlRelationship); } } -function checkType(jdlRelationship) { - if (!exists(jdlRelationship.type)) { +function checkType(jdlRelationship: JDLRelationship) { + if (!relationshipTypeExists(jdlRelationship.type)) { throw new Error(`The relationship type '${jdlRelationship.type}' doesn't exist.`); } } -function checkInjectedFields(jdlRelationship) { +function checkInjectedFields(jdlRelationship: JDLRelationship) { if (!(jdlRelationship.injectedFieldInFrom || jdlRelationship.injectedFieldInTo)) { throw new Error('At least one injected field is required.'); } } -function checkForValidUseOfJPaDerivedIdentifier(jdlRelationship) { +function checkForValidUseOfJPaDerivedIdentifier(jdlRelationship: JDLRelationship) { if (jdlRelationship.type !== ONE_TO_ONE && jdlRelationship.hasGlobalOption(JPA_DERIVED_IDENTIFIER)) { throw new Error(`Only a ${ONE_TO_ONE} relationship can have the '${JPA_DERIVED_IDENTIFIER}' option.`); } } -function checkForRequiredReflexiveRelationship(jdlRelationship) { +function checkForRequiredReflexiveRelationship(jdlRelationship: JDLRelationship) { if ( jdlRelationship.from.toLowerCase() === jdlRelationship.to.toLowerCase() && (jdlRelationship.isInjectedFieldInFromRequired || jdlRelationship.isInjectedFieldInToRequired) @@ -70,39 +67,13 @@ function checkForRequiredReflexiveRelationship(jdlRelationship) { } } -function checkForInvalidUseOfTheUserEntity(jdlRelationship, skippedUserManagementOption) { - const userIsTheSourceAndTheDestination = isUserManagementEntity(jdlRelationship.from) && isUserManagementEntity(jdlRelationship.to); - if (userIsTheSourceAndTheDestination && !skippedUserManagementOption) { - throw new Error( - 'Having the source and the destination entities being user management entities (User, Authority) is forbidden unless the ' + - "entity is not managed by JHipster (use the 'skipUserManagement' option)." - ); - } - checkForForbiddenUseOfUserAsSource(jdlRelationship, skippedUserManagementOption); -} - -function checkForForbiddenUseOfUserAsSource(jdlRelationship, skippedUserManagementOption) { - const theSourceIsUserManagement = isUserManagementEntity(jdlRelationship.from); - if (theSourceIsUserManagement && !skippedUserManagementOption) { - throw new Error( - `Relationships from the ${jdlRelationship.from} entity is not supported in the declaration between '${jdlRelationship.from}' and ` + - `'${jdlRelationship.to}'. You can have this by using the 'skipUserManagement' option.` - ); - } -} - -function checkRelationshipType(jdlRelationship, options) { - const { skippedUserManagement } = options; +function checkRelationshipType(jdlRelationship: JDLRelationship) { switch (jdlRelationship.type) { case ONE_TO_ONE: checkOneToOneRelationship(jdlRelationship); break; case MANY_TO_ONE: - checkManyToOneRelationship(jdlRelationship, skippedUserManagement); - break; case MANY_TO_MANY: - checkManyToManyRelationship(jdlRelationship); - break; case ONE_TO_MANY: return; default: @@ -111,7 +82,7 @@ function checkRelationshipType(jdlRelationship, options) { } } -function checkOneToOneRelationship(jdlRelationship) { +function checkOneToOneRelationship(jdlRelationship: JDLRelationship) { if (!jdlRelationship.injectedFieldInFrom) { throw new Error( `In the One-to-One relationship from ${jdlRelationship.from} to ${jdlRelationship.to}, ` + @@ -119,30 +90,3 @@ function checkOneToOneRelationship(jdlRelationship) { ); } } - -function checkManyToOneRelationship(jdlRelationship, skippedUserManagementOption) { - const unidirectionalRelationship = !jdlRelationship.injectedFieldInFrom || !jdlRelationship.injectedFieldInTo; - const userIsTheSourceEntity = isUserManagementEntity(jdlRelationship.from); - const userIsTheDestinationEntity = isUserManagementEntity(jdlRelationship.to); - const userHasTheInjectedField = - (userIsTheSourceEntity && jdlRelationship.injectedFieldInFrom) || (userIsTheDestinationEntity && jdlRelationship.injectedFieldInTo); - if (unidirectionalRelationship && userHasTheInjectedField && !skippedUserManagementOption) { - throw new Error( - `In the Many-to-One relationship from ${jdlRelationship.from} to ${jdlRelationship.to}, ` + - 'the User entity has the injected field without its management being skipped. ' + - "To have such a relation, you should use the 'skipUserManagement' option." - ); - } -} - -function checkManyToManyRelationship(jdlRelationship) { - const destinationEntityIsTheUser = isUserManagementEntity(jdlRelationship.to); - if (jdlRelationship.injectedFieldInFrom && !jdlRelationship.injectedFieldInTo && destinationEntityIsTheUser) { - // This is a valid case: even though bidirectionality is required for MtM relationships, having the destination - // entity being the User is possible. - } -} - -function isUserManagementEntity(entityName) { - return entityName.toLowerCase() === 'user' || entityName.toLowerCase() === 'authority'; -} diff --git a/test-integration/incremental-changelog-samples/liquibase-jdl-rename-field-post/app.jdl b/test-integration/incremental-changelog-samples/liquibase-jdl-rename-field-post/app.jdl index 26ddd3baf7ec..5b7c434b5564 100644 --- a/test-integration/incremental-changelog-samples/liquibase-jdl-rename-field-post/app.jdl +++ b/test-integration/incremental-changelog-samples/liquibase-jdl-rename-field-post/app.jdl @@ -129,14 +129,14 @@ entity Region { relationship OneToOne { Department{location} to Location, - Employee{user(login)} to User with jpaDerivedIdentifier + Employee{user(login)} to @Id User with builtInEntity } relationship OneToMany { BankAccount{operation} to Operation{bankAccount(name)} } relationship ManyToOne { - BankAccount{user(login)} to User + BankAccount{user(login)} to User with builtInEntity } relationship ManyToMany { Operation{theLabel(labelName)} to TheLabel{operation(renamed)} diff --git a/test-integration/incremental-changelog-samples/liquibase-jdl-rename-field/app.jdl b/test-integration/incremental-changelog-samples/liquibase-jdl-rename-field/app.jdl index f50a0c7a0086..3b4de9903822 100644 --- a/test-integration/incremental-changelog-samples/liquibase-jdl-rename-field/app.jdl +++ b/test-integration/incremental-changelog-samples/liquibase-jdl-rename-field/app.jdl @@ -129,14 +129,14 @@ entity Region { relationship OneToOne { Department{location} to Location, - Employee{user(login)} to User with jpaDerivedIdentifier + Employee{user(login)} to @Id User with builtInEntity } relationship OneToMany { BankAccount{operation} to Operation{bankAccount(name)} } relationship ManyToOne { - BankAccount{user(login)} to User + BankAccount{user(login)} to User with builtInEntity } relationship ManyToMany { Operation{theLabel(labelName)} to TheLabel{operation} diff --git a/test-integration/jdl-samples/mf-ng-eureka-jwt-psql-ehcache/blog-store.jdl b/test-integration/jdl-samples/mf-ng-eureka-jwt-psql-ehcache/blog-store.jdl index aa78499d93aa..4c58b3599e89 100644 --- a/test-integration/jdl-samples/mf-ng-eureka-jwt-psql-ehcache/blog-store.jdl +++ b/test-integration/jdl-samples/mf-ng-eureka-jwt-psql-ehcache/blog-store.jdl @@ -134,7 +134,7 @@ entity Product { /* relationship OneToOne { - @Id UserData{user(login)} to User + @Id UserData{user(login)} to User with builtInEntity } */ diff --git a/test-integration/jdl-samples/ms-mf-ng-consul-oauth2-neo4j/blog-store.jdl b/test-integration/jdl-samples/ms-mf-ng-consul-oauth2-neo4j/blog-store.jdl index c39ce57f0e9e..12136641d819 100644 --- a/test-integration/jdl-samples/ms-mf-ng-consul-oauth2-neo4j/blog-store.jdl +++ b/test-integration/jdl-samples/ms-mf-ng-consul-oauth2-neo4j/blog-store.jdl @@ -128,7 +128,7 @@ entity Product { /* TODO relationships at Neo4J cascades, changing the user entity. relationship OneToOne { - @Id UserData{user(login)} to User + @Id UserData{user(login)} to User with builtInEntity } */ diff --git a/test-integration/jdl-samples/ms-mf-react-eureka-oauth2-mariadb-infinispan/blog-store.jdl b/test-integration/jdl-samples/ms-mf-react-eureka-oauth2-mariadb-infinispan/blog-store.jdl index ba3d790defa5..07eda396afea 100644 --- a/test-integration/jdl-samples/ms-mf-react-eureka-oauth2-mariadb-infinispan/blog-store.jdl +++ b/test-integration/jdl-samples/ms-mf-react-eureka-oauth2-mariadb-infinispan/blog-store.jdl @@ -128,7 +128,7 @@ entity Product { /* relationship OneToOne { - @Id UserData{user(login)} to User + @Id UserData{user(login)} to User with builtInEntity } */ diff --git a/test-integration/jdl-samples/ms-mf-vue-consul-oauth2-mysql-memcached/blog-store.jdl b/test-integration/jdl-samples/ms-mf-vue-consul-oauth2-mysql-memcached/blog-store.jdl index 52e2a3181da9..129361971b06 100644 --- a/test-integration/jdl-samples/ms-mf-vue-consul-oauth2-mysql-memcached/blog-store.jdl +++ b/test-integration/jdl-samples/ms-mf-vue-consul-oauth2-mysql-memcached/blog-store.jdl @@ -128,7 +128,7 @@ entity Product { /* relationship OneToOne { - @Id UserData{user(login)} to User + @Id UserData{user(login)} to User with builtInEntity } */ @@ -138,7 +138,7 @@ entity Notification { } relationship ManyToOne { - Blog{user(login)} to User + Blog{user(login)} to User with builtInEntity Post{blog(name)} to Blog } diff --git a/test-integration/jdl-samples/ms-ng-consul-oauth2-mongodb-caffeine/blog-store.jdl b/test-integration/jdl-samples/ms-ng-consul-oauth2-mongodb-caffeine/blog-store.jdl index cbf100deeb72..819349b9f51e 100644 --- a/test-integration/jdl-samples/ms-ng-consul-oauth2-mongodb-caffeine/blog-store.jdl +++ b/test-integration/jdl-samples/ms-ng-consul-oauth2-mongodb-caffeine/blog-store.jdl @@ -134,7 +134,7 @@ entity Notification { } relationship OneToOne { - @Id UserData{user(login)} to User + @Id UserData{user(login)} to User with builtInEntity } relationship ManyToOne { diff --git a/test-integration/jdl-samples/ms-react-consul-jwt-cassandra-redis/blog-store.jdl b/test-integration/jdl-samples/ms-react-consul-jwt-cassandra-redis/blog-store.jdl index b20bb9615f7a..5e4a4cd797c2 100644 --- a/test-integration/jdl-samples/ms-react-consul-jwt-cassandra-redis/blog-store.jdl +++ b/test-integration/jdl-samples/ms-react-consul-jwt-cassandra-redis/blog-store.jdl @@ -134,7 +134,7 @@ entity Notification { /* Relationships are broken or unsupported at cassandra db relationship OneToOne { - @Id UserData{user(login)} to User + @Id UserData{user(login)} to User with builtInEntity } relationship ManyToOne { diff --git a/test-integration/jdl-samples/ms-vue-eureka-jwt-couchbase-hazelcast/blog-store.jdl b/test-integration/jdl-samples/ms-vue-eureka-jwt-couchbase-hazelcast/blog-store.jdl index fa6ac683994b..27f99166b843 100644 --- a/test-integration/jdl-samples/ms-vue-eureka-jwt-couchbase-hazelcast/blog-store.jdl +++ b/test-integration/jdl-samples/ms-vue-eureka-jwt-couchbase-hazelcast/blog-store.jdl @@ -129,7 +129,7 @@ entity Notification { } relationship OneToOne { - @Id UserData{user(login)} to User + @Id UserData{user(login)} to User with builtInEntity } relationship ManyToOne { diff --git a/test-integration/samples/jdl-default/app.jdl b/test-integration/samples/jdl-default/app.jdl index b934a042deeb..3b1df7d3b063 100644 --- a/test-integration/samples/jdl-default/app.jdl +++ b/test-integration/samples/jdl-default/app.jdl @@ -130,14 +130,14 @@ entity Region { relationship OneToOne { Department{location} to Location, - Employee{user(login)} to User with jpaDerivedIdentifier + Employee{user(login)} to @Id User with builtInEntity } relationship OneToMany { BankAccount{operation} to Operation{bankAccount(name)} } relationship ManyToOne { - BankAccount{user(login)} to User + BankAccount{user(login)} to User with builtInEntity } relationship ManyToMany { Operation{theLabel(labelName)} to TheLabel{operation} diff --git a/test-integration/samples/jdl-entities/custom-domain.jdl b/test-integration/samples/jdl-entities/custom-domain.jdl index 4c4ee0937a40..ef6f48dec3be 100644 --- a/test-integration/samples/jdl-entities/custom-domain.jdl +++ b/test-integration/samples/jdl-entities/custom-domain.jdl @@ -15,7 +15,7 @@ relationship OneToMany { } relationship ManyToOne { - CustomPackageChild to User + CustomPackageChild to User with builtInEntity } dto CustomPackageParent, CustomPackageChild with mapstruct diff --git a/test-integration/samples/jdl-entities/user-relationships/entities.jdl b/test-integration/samples/jdl-entities/user-relationships/entities.jdl index a79557f95f88..6a196a2034d7 100644 --- a/test-integration/samples/jdl-entities/user-relationships/entities.jdl +++ b/test-integration/samples/jdl-entities/user-relationships/entities.jdl @@ -1,3 +1,5 @@ +entity User {} + @ChangelogDate(20200804040000) entity UserMapsId { } diff --git a/test/templates/import-jdl/common/jdl-ambiguous.jdl b/test/templates/import-jdl/common/jdl-ambiguous.jdl index 1d71232da898..2f58d6a944da 100644 --- a/test/templates/import-jdl/common/jdl-ambiguous.jdl +++ b/test/templates/import-jdl/common/jdl-ambiguous.jdl @@ -28,7 +28,7 @@ relationship OneToOne { Profile { user } - to User + to User with builtInEntity } relationship ManyToOne { diff --git a/test/templates/import-jdl/common/jdl.jdl b/test/templates/import-jdl/common/jdl.jdl index d8795712b423..c9077d229049 100644 --- a/test/templates/import-jdl/common/jdl.jdl +++ b/test/templates/import-jdl/common/jdl.jdl @@ -92,7 +92,7 @@ relationship OneToMany { relationship ManyToOne { Employee{manager} to Employee, - Employee{user} to User + Employee{user} to User with builtInEntity } // defining multiple oneToOne relationships