UNPKG

generator-pyhipster

Version:

Python (Flask) + Angular/React/Vue in one handy generator

274 lines (254 loc) 11.3 kB
/** * Copyright 2013-2022 the original author or authors from the JHipster project. * * This file is part of the JHipster project, see https://www.jhipster.tech/ * for more information. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ const EntityValidator = require('./entity-validator'); const FieldValidator = require('./field-validator'); const FieldTypes = require('../jhipster/field-types'); const ApplicationTypes = require('../jhipster/application-types'); const ValidationValidator = require('./validation-validator'); const RelationshipValidator = require('./relationship-validator'); const EnumValidator = require('./enum-validator'); const DeploymentValidator = require('./deployment-validator'); const UnaryOptionValidator = require('./unary-option-validator'); const BinaryOptionValidator = require('./binary-option-validator'); const DatabaseTypes = require('../jhipster/database-types'); const BinaryOptions = require('../jhipster/binary-options'); const ApplicationValidator = require('./application-validator'); const { isReservedFieldName } = require('../jhipster/reserved-keywords'); const { isReservedTableName } = require('../jhipster/reserved-keywords'); const { isReservedPaginationWords } = require('../jhipster/reserved-keywords'); module.exports = { createValidator, }; /** * Constructor taking the jdl object to check against application settings. * @param {JDLObject} jdlObject - the jdl object to check. * @param {Object} logger - the logger to use, default to the console. */ function createValidator(jdlObject, logger = console, options = {}) { if (!jdlObject) { throw new Error('A JDL object must be passed to check for business errors.'); } const { unidirectionalRelationships } = options; return { checkForErrors: () => { checkForApplicationErrors(); jdlObject.forEachApplication(jdlApplication => { const blueprints = jdlApplication.getConfigurationOptionValue('blueprints'); if (blueprints && blueprints.length > 0) { logger.warn('Blueprints are being used, the JDL validation phase is skipped.'); return; } checkForEntityErrors(jdlApplication); checkForRelationshipErrors(jdlApplication, { unidirectionalRelationships }); checkForEnumErrors(); checkDeploymentsErrors(); checkForOptionErrors(jdlApplication); }); checkForRelationshipsBetweenApplications(); }, }; function checkForApplicationErrors() { if (jdlObject.getApplicationQuantity() === 0) { return; } const validator = new ApplicationValidator(); jdlObject.forEachApplication(jdlApplication => { validator.validate(jdlApplication); }); } function checkForEntityErrors(jdlApplication) { if (jdlObject.getEntityQuantity() === 0) { return; } const validator = new EntityValidator(); jdlObject.forEachEntity(jdlEntity => { if (!jdlApplication.hasEntityName(jdlEntity.name)) { return; } validator.validate(jdlEntity); if ( jdlApplication.getConfigurationOptionValue('databaseType') && isReservedTableName(jdlEntity.tableName, jdlApplication.getConfigurationOptionValue('databaseType')) ) { logger.warn(`The table name '${jdlEntity.tableName}' is a reserved keyword, so it will be prefixed with the value of 'jhiPrefix'.`); } else if (!jdlApplication.getConfigurationOptionValue('databaseType') && isTableNameReserved(jdlEntity.tableName, jdlApplication)) { logger.warn( `The table name '${jdlEntity.tableName}' is a reserved keyword for application: ` + `${jdlApplication.getConfigurationOptionValue('baseName')}` + "so it will be prefixed with the value of 'jhiPrefix'." ); } checkForFieldErrors(jdlEntity.name, jdlEntity.fields, jdlApplication); }); } function checkForFieldErrors(entityName, jdlFields, jdlApplication) { const validator = new FieldValidator(); const filtering = jdlApplication.getConfigurationOptionValue('databaseType') === 'sql' && jdlApplication.getConfigurationOptionValue('reactive') === false; Object.keys(jdlFields).forEach(fieldName => { const jdlField = jdlFields[fieldName]; validator.validate(jdlField); if (isReservedFieldName(jdlField.name)) { logger.warn(`The name '${jdlField.name}' is a reserved keyword, so it will be prefixed with the value of 'jhiPrefix'.`); } if (filtering && isReservedPaginationWords(jdlField.name)) { throw new Error( `Field name '${fieldName}' found in ${entityName} is a reserved keyword, as it is used by Spring for pagination in the URL.` ); } const typeCheckingFunction = getTypeCheckingFunction(entityName, jdlApplication); if (!jdlObject.hasEnum(jdlField.type) && !typeCheckingFunction(jdlField.type)) { throw new Error(`The type '${jdlField.type}' is an unknown field type for field '${fieldName}' of entity '${entityName}'.`); } const isAnEnum = jdlObject.hasEnum(jdlField.type); checkForValidationErrors(jdlField, isAnEnum); }); } function checkForValidationErrors(jdlField, isAnEnum) { const validator = new ValidationValidator(); Object.keys(jdlField.validations).forEach(validationName => { const jdlValidation = jdlField.validations[validationName]; validator.validate(jdlValidation); if (!FieldTypes.hasValidation(jdlField.type, jdlValidation.name, isAnEnum)) { throw new Error(`The validation '${jdlValidation.name}' isn't supported for the type '${jdlField.type}'.`); } }); } function checkForRelationshipErrors(jdlApplication, options = {}) { if (jdlObject.getRelationshipQuantity() === 0) { return; } const { unidirectionalRelationships } = options; const skippedUserManagement = jdlApplication.getConfigurationOptionValue('skipUserManagement'); const validator = new RelationshipValidator(); jdlObject.forEachRelationship(jdlRelationship => { validator.validate(jdlRelationship, { skippedUserManagement, unidirectionalRelationships }); checkForAbsentEntities({ jdlRelationship, doesEntityExist: entityName => !!jdlObject.getEntity(entityName), skippedUserManagementOption: skippedUserManagement, }); }); } function checkForEnumErrors() { if (jdlObject.getEnumQuantity() === 0) { return; } const validator = new EnumValidator(); jdlObject.forEachEnum(jdlEnum => { validator.validate(jdlEnum); }); } function checkDeploymentsErrors() { if (jdlObject.getDeploymentQuantity() === 0) { return; } const validator = new DeploymentValidator(); jdlObject.forEachDeployment(deployment => { validator.validate(deployment); }); } function checkForOptionErrors(jdlApplication) { if (jdlObject.getOptionQuantity() === 0) { return; } const unaryOptionValidator = new UnaryOptionValidator(); const binaryOptionValidator = new BinaryOptionValidator(); jdlObject.getOptions().forEach(option => { if (option.getType() === 'UNARY') { unaryOptionValidator.validate(option); } else { binaryOptionValidator.validate(option); } checkForPaginationInAppWithCassandra(option, jdlApplication); }); } function checkForRelationshipsBetweenApplications() { const applicationsPerEntityNames = getApplicationsPerEntityNames(jdlObject); jdlObject.forEachRelationship(jdlRelationship => { checkIfRelationshipIsBetweenApplications({ jdlRelationship, applicationsPerEntityName: applicationsPerEntityNames, }); }); } } function checkForPaginationInAppWithCassandra(jdlOption, jdlApplication) { if ( jdlApplication.getConfigurationOptionValue('databaseType') === DatabaseTypes.CASSANDRA && jdlOption.name === BinaryOptions.Options.PAGINATION ) { throw new Error("Pagination isn't allowed when the application uses Cassandra."); } } function checkForAbsentEntities({ jdlRelationship, doesEntityExist, skippedUserManagementOption }) { const absentEntities = []; if (!doesEntityExist(jdlRelationship.from)) { absentEntities.push(jdlRelationship.from); } if (!doesEntityExist(jdlRelationship.to) && (!isUserManagementEntity(jdlRelationship.to) || skippedUserManagementOption)) { 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.` ); } } function isUserManagementEntity(entityName) { return entityName.toLowerCase() === 'user' || entityName.toLowerCase() === 'authority'; } function isTableNameReserved(tableName, jdlApplication = []) { return isReservedTableName(tableName, jdlApplication.getConfigurationOptionValue('databaseType')); } function getTypeCheckingFunction(entityName, jdlApplication) { if (jdlApplication.getConfigurationOptionValue('applicationType') === ApplicationTypes.GATEWAY) { return () => true; } return FieldTypes.getIsType(jdlApplication.getConfigurationOptionValue('databaseType')); } function checkIfRelationshipIsBetweenApplications({ jdlRelationship, applicationsPerEntityName }) { let applicationsForSourceEntity = applicationsPerEntityName[jdlRelationship.from]; let applicationsForDestinationEntity = applicationsPerEntityName[jdlRelationship.to]; if (!applicationsForDestinationEntity || !applicationsForSourceEntity) { return; } applicationsForSourceEntity = applicationsForSourceEntity.map(jdlApplication => jdlApplication.getConfigurationOptionValue('baseName')); applicationsForDestinationEntity = applicationsForDestinationEntity.map(jdlApplication => jdlApplication.getConfigurationOptionValue('baseName') ); const difference = applicationsForSourceEntity.filter(application => !applicationsForDestinationEntity.includes(application)); if (difference.length !== 0) { throw new Error( `Entities for the ${jdlRelationship.type} relationship from '${jdlRelationship.from}' to '${jdlRelationship.to}' do not belong to the same application.` ); } } function getApplicationsPerEntityNames(jdlObject) { const applicationsPerEntityName = {}; jdlObject.forEachApplication(jdlApplication => { jdlApplication.forEachEntityName(entityName => { applicationsPerEntityName[entityName] = applicationsPerEntityName[entityName] || []; applicationsPerEntityName[entityName].push(jdlApplication); }); }); return applicationsPerEntityName; }