UNPKG

generator-luna

Version:

generate specific EHR application,it's built beyond the jhipster

527 lines (497 loc) 21.5 kB
/** * Copyright 2013-2019 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 * * http://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 chalk = require('chalk'); const _ = require('lodash'); const path = require('path'); const shelljs = require('shelljs'); const jhiCore = require('jhipster-core'); const fs = require('fs-extra'); const pretty = require('js-object-pretty-print').pretty; const pluralize = require('pluralize'); const { fork } = require('child_process'); const waitUntil = require('./wait-until'); const { CLI_NAME, GENERATOR_NAME, logger, toString, getOptionsFromArgs, done, getOptionAsArgs } = require('./utils'); const jhipsterUtils = require('../generators/utils'); const packagejs = require('../package.json'); const statistics = require('../generators/statistics'); const runYeomanProcess = require.resolve('./run-yeoman-process.js'); // holds the state of generation for interactive mode const generationCompletionState = { exportedEntities: {}, exportedApplications: {}, exportedDeployments: {} }; const getBaseName = application => application && application[GENERATOR_NAME] && application[GENERATOR_NAME].baseName; const getDeploymentType = deployment => deployment && deployment[GENERATOR_NAME] && deployment[GENERATOR_NAME].deploymentType; /** * update the initial state */ const updateDeploymentState = importState => Object.entries(importState).forEach(([key, val]) => { val.forEach(it => { generationCompletionState[key][getBaseName(it) || getDeploymentType(it) || it.name] = false; }); }); /** * Imports the Applications and Entities defined in JDL * The app .yo-rc.json files and entity json files are written to disk */ function importJDL() { logger.info('The JDL is being parsed.'); const jdlImporter = new jhiCore.JDLImporter(this.jdlFiles, { databaseType: this.prodDatabaseType, applicationType: this.applicationType, applicationName: this.baseName, generatorVersion: packagejs.version, forceNoFiltering: this.options.force }); let importState = { exportedEntities: [], exportedApplications: [], exportedDeployments: [] }; try { importState = jdlImporter.import(); logger.debug(`importState exportedEntities: ${importState.exportedEntities.length}`); logger.debug(`importState exportedApplications: ${importState.exportedApplications.length}`); logger.debug(`importState exportedDeployments: ${importState.exportedDeployments.length}`); updateDeploymentState(importState); if (importState.exportedEntities.length > 0) { const entityNames = _.uniq(importState.exportedEntities.map(exportedEntity => exportedEntity.name)).join(', '); logger.info(`Found entities: ${chalk.yellow(entityNames)}.`); } else { logger.info(chalk.yellow('No change in entity configurations, no entities were updated.')); } logger.info('The JDL has been successfully parsed'); } catch (error) { logger.debug('Error:', error); if (error) { const errorName = `${error.name}:` || ''; const errorMessage = error.message || ''; logger.log(chalk.red(`${errorName} ${errorMessage}`)); } logger.error(`Error while parsing applications and entities from the JDL ${error}`, error); } return importState; } /** * Check if application needs to be generated * @param {any} generator */ const shouldGenerateApplications = generator => !generator.options['ignore-application'] && generator.importState.exportedApplications.length !== 0; /** * Check if deployments needs to be generated * @param {any} generator */ const shouldGenerateDeployments = generator => !generator.options['ignore-deployments'] && generator.importState.exportedDeployments.length !== 0; /** * Generate deployment source code for JDL deployments defined. * @param {any} config * @param {function} forkProcess * @returns {obj} Nodejs ChildProcess: https://nodejs.org/api/child_process.html#child_process_child_process */ const generateDeploymentFiles = ({ generator, deployment, inFolder }, forkProcess) => { const deploymentType = getDeploymentType(deployment); logger.info(`Generating deployment ${deploymentType} in a new parallel process`); logger.debug(`Generating deployment: ${pretty(deployment[GENERATOR_NAME])}`); const cwd = inFolder ? path.join(generator.pwd, deploymentType) : generator.pwd; logger.debug(`Child process will be triggered for ${runYeomanProcess} with cwd: ${cwd}`); const command = `${CLI_NAME}:${deploymentType}`; const childProc = forkProcess( runYeomanProcess, [command, '--skip-prompts', ...getOptionAsArgs(generator.options, false, !generator.options.interactive)], { cwd } ); childProc.on('exit', code => { logger.info(`Deployment: child process exited with code ${code}`); generationCompletionState.exportedDeployments[deploymentType] = true; }); }; /** * Generate application source code for JDL apps defined. * @param {any} config * @param {function} forkProcess * @returns {obj} Nodejs ChildProcess: https://nodejs.org/api/child_process.html#child_process_child_process */ const generateApplicationFiles = ({ generator, application, withEntities, inFolder }, forkProcess) => { const baseName = getBaseName(application); logger.info(`Generating application ${baseName} in a new parallel process`); logger.debug(`Generating application: ${pretty(application[GENERATOR_NAME])}`); const cwd = inFolder ? path.join(generator.pwd, baseName) : generator.pwd; logger.debug(`Child process will be triggered for ${runYeomanProcess} with cwd: ${cwd}`); const command = `${CLI_NAME}:server`; const childProc = forkProcess( runYeomanProcess, [command, ...getOptionAsArgs(generator.options, withEntities, !generator.options.interactive)], { cwd } ); childProc.on('exit', code => { logger.info(`App: child process exited with code ${code}`); generationCompletionState.exportedApplications[baseName] = true; }); }; /** * Generate entities for the applications * @param {any} generator * @param {any} entity * @param {boolean} inFolder * @param {any} env * @param {boolean} shouldTriggerInstall * @param {function} forkProcess */ const generateEntityFiles = (generator, entity, inFolder, env, shouldTriggerInstall, forkProcess) => { const options = { ...generator.options, regenerate: true, 'from-cli': true, 'skip-install': true, 'skip-client': entity.skipClient, 'skip-server': entity.skipServer, 'no-fluent-methods': entity.noFluentMethod, 'skip-user-management': entity.skipUserManagement, 'skip-ui-grouping': generator.options['skip-ui-grouping'] }; const command = `${CLI_NAME}:entity-form ${entity.name}`; logger.info(command); logger.info(inFolder); if (inFolder) { /* Generating entities inside multiple apps */ let previousEntity; const callGenerator = baseName => { logger.info(`Generating entities for application ${baseName} in a new parallel process`); const cwd = path.join(generator.pwd, baseName); logger.debug(`Child process will be triggered for ${runYeomanProcess} with cwd: ${cwd}`); const childProc = forkProcess(runYeomanProcess, [command, ...getOptionAsArgs(options, false, !options.interactive)], { cwd }); childProc.on('exit', code => { logger.info(`Entity: child process exited with code ${code}`); generationCompletionState.exportedEntities[entity.name] = true; }); previousEntity = entity.name; }; const baseNames = entity.applications; baseNames.forEach(baseName => { if (generator.options.interactive) { waitUntil() .interval(500) .times(200) // approximate 2 minutes .condition(() => generationCompletionState.exportedEntities[previousEntity] || !previousEntity) .done(result => { logger.debug(`Result from waitUntil for application ${previousEntity} to finish: ${result}`); callGenerator(baseName); }); } else { callGenerator(baseName); } }); } else { /* Traditional entity only generation */ logger.info(JSON.stringify(options)); env.run( command, { ...options, force: !options.interactive, 'skip-install': !shouldTriggerInstall }, done ); } }; /** * Check if NPM/Yarn install needs to be triggered. This will be done for the last entity. * @param {any} generator * @param {number} index */ const shouldTriggerInstall = (generator, index) => index === generator.importState.exportedEntities.length - 1 && !generator.options['skip-install'] && !generator.skipClient && !generator.options['json-only'] && !shouldGenerateApplications(generator); const isAllCompleted = items => Object.values(items).every(it => it); class JDLProcessor { constructor(jdlFiles, options) { logger.debug(`JDLProcessor started with jdlFiles: ${jdlFiles} and options: ${toString(options)}`); this.jdlFiles = jdlFiles; this.options = options; this.pwd = process.cwd(); } validate() { if (this.jdlFiles) { this.jdlFiles.forEach(key => { if (!shelljs.test('-f', key)) { logger.error(chalk.red(`\nCould not find ${key}, make sure the path is correct.\n`)); } }); } } getConfig() { if (jhiCore.FileUtils.doesFileExist('.yo-rc.json')) { logger.info('Found .yo-rc.json on path. This is an existing app'); const configuration = jhipsterUtils.getAllJhipsterConfig(null, true); this.applicationType = configuration.applicationType; this.packageFolder = configuration.packageFolder; this.baseName = configuration.baseName; this.databaseType = configuration.databaseType || jhipsterUtils.getDBTypeFromDBValue(this.options.db); this.prodDatabaseType = configuration.prodDatabaseType || this.options.db; this.devDatabaseType = configuration.devDatabaseType || this.options.db; this.skipClient = configuration.skipClient; this.clientFramework = configuration.clientFramework; this.clientFramework = this.clientFramework || 'angularX'; this.clientPackageManager = configuration.clientPackageManager; if (!this.clientPackageManager) { if (this.useNpm) { this.clientPackageManager = 'npm'; } else { this.clientPackageManager = 'yarn'; } } } } importJDL() { this.importState = importJDL.call(this); } sendInsight() { statistics.sendSubGenEvent('generator', 'import-jdl'); } generateApplications(env,forkProcess) { logger.info('generator server'); if (!shouldGenerateApplications(this)) { logger.debug('Applications not generated'); return; } logger.info( `Generating ${this.importState.exportedApplications.length} ` + `${pluralize('application', this.importState.exportedApplications.length)}.` ); let previousApp; const callGenerator = application => { try { generateApplicationFiles( { generator: this, application, withEntities: this.importState.exportedEntities.length !== 0, inFolder: this.importState.exportedApplications.length > 1 }, forkProcess ); previousApp = getBaseName(application); } catch (error) { logger.error(`Error while generating applications from the parsed JDL\n${error}`, error); } }; this.importState.exportedApplications.forEach(application => { if (this.options.interactive) { waitUntil() .interval(500) .times(500) // approximate 5 minutes .condition(() => generationCompletionState.exportedApplications[previousApp] || !previousApp) .done(result => { logger.debug(`Result from waitUntil for application ${previousApp} to finish: ${result}`); callGenerator(application); }); } else { callGenerator(application); } }); } generateDeployments(forkProcess) { if (!shouldGenerateDeployments(this)) { logger.debug('Deployments not generated'); return; } logger.info( `Generating ${this.importState.exportedDeployments.length} ` + `${pluralize('deployment', this.importState.exportedDeployments.length)}.` ); const callDeploymentGenerator = () => { let previousDeployment; const callGenerator = deployment => { try { generateDeploymentFiles( { generator: this, deployment, inFolder: true }, forkProcess ); previousDeployment = getDeploymentType(deployment); } catch (error) { logger.error(`Error while generating deployments from the parsed JDL\n${error}`, error); } }; this.importState.exportedDeployments.forEach(deployment => { if (this.options.interactive) { waitUntil() .interval(500) .times(200) // approximate 2 minutes .condition(() => generationCompletionState.exportedDeployments[previousDeployment] || !previousDeployment) .done(result => { logger.debug(`Result from waitUntil for deployment ${previousDeployment} to finish: ${result}`); callGenerator(deployment); }); } else { callGenerator(deployment); } }); }; if (shouldGenerateApplications(this)) { waitUntil() .interval(500) .times(1000) // approximate 10 minutes .condition(() => isAllCompleted(generationCompletionState.exportedApplications)) .done(result => { logger.info('Done waiting for application generation'); logger.debug(`Result from waitUntil for all applications to finish: ${result}`); callDeploymentGenerator(); }); } else { callDeploymentGenerator(); } } generateEntities(env,forkProcess) { let packageFolder = ''; if (jhiCore.FileUtils.doesFileExist('.yo-rc.json')) { logger.info('Found .yo-rc.json on path. This is an existing app'); const configuration = jhipsterUtils.getAllJhipsterConfig(null, true); packageFolder = configuration.packageFolder; } logger.info('generateEntities'); if (this.importState.exportedEntities.length === 0 || shouldGenerateApplications(this)) { logger.info('Entities not generated'); } if (this.options['json-only']) { logger.info('Entity JSON files created. Entity generation skipped.'); return; } try { logger.info( `Generating ${this.importState.exportedEntities.length} ` + `${pluralize('entity', this.importState.exportedEntities.length)}.` ); jhiCore.FileUtils.createDirectory('form'); var value = 'public static final String ANONYMOUS = "ROLE_ANONYMOUS";\n\n'; var authnames = 'name\n'; authnames += 'ROLE_ADMIN\n'; authnames += 'ROLE_USER\n'; this.importState.exportedEntities.forEach((exportedEntity, i) => { logger.info("生成entiy配置信息"); let key = exportedEntity.name.toUpperCase(); authnames += 'ROLE_CREATE_'+key +'\n'; authnames += 'ROLE_EDIT_'+key +'\n'; authnames += 'ROLE_SELECT_'+key +'\n'; authnames += 'ROLE_DELETE_'+key +'\n'; authnames += 'ROLE_ALL_'+key +'\n'; value += ' public static final String CREATE_'+key +' = "ROLE_CREATE_'+key+'";\n\n'; value += ' public static final String EDIT_'+key +' = "ROLE_EDIT_'+key+'";\n\n'; value += ' public static final String SELECT_'+key +' = "ROLE_SELECT_'+key+'";\n\n'; value += ' public static final String DELETE_'+key +' = "ROLE_DELETE_'+key+'";\n\n'; value += ' public static final String ALL_'+key +' = "ROLE_ALL_'+key+'";\n\n'; var formconfig = {}; formconfig.formname= exportedEntity.name; formconfig.data = []; exportedEntity.fields.forEach((field,i)=>{ var tmpfield = {}; tmpfield.id= i; tmpfield.span= 8; var labelProps = {}; labelProps.name = field.fieldName; labelProps.label = field.javadoc; tmpfield.labelProps = labelProps; var inputProps = {}; inputProps.value = ''; inputProps.placeholder = '请输入'+field.javadoc; if(field.fieldType == 'String'){ inputProps.type = 'input'; }else if(field.fieldType == 'Integer'){ inputProps.type = 'inputNumber'; }else if(field.fieldType == 'LocalDate'){ inputProps.type = 'date'; } tmpfield.inputProps = inputProps; var rule = {}; rule.required = 'false'; tmpfield.rule = rule; formconfig.data.push(tmpfield); }); fs.writeJSON('form/'+formconfig.formname+".json", formconfig, null, 4); //logger.info( JSON.stringify(formconfig)); //logger.info(value); generateEntityFiles( this, exportedEntity, this.importState.exportedApplications.length > 1, env, shouldTriggerInstall(this, i), forkProcess ); }); let authfile = 'src/main/java/'+packageFolder+'/security/AuthoritiesConstants.java' fs.readFile(authfile,function(err,bdata){     if(err){         logger.error(authfile + "is not exist ,please create server first");     }else{ let data = bdata.toString();         data = data.replace('public static final String ANONYMOUS = "ROLE_ANONYMOUS";',value); fs.writeFile(authfile,data,'utf-8',null);    } }) let csvfile = 'src/main/resources/config/liquibase/authorities.csv' fs.writeFile(csvfile,authnames,'utf-8',null); } catch (error) { logger.error(`Error while generating entities from the parsed JDL\n${error}`, error); } } } /** * Import-JDL sub generator * @param {any} args arguments passed for import-jdl * @param {any} options options passed from CLI * @param {any} env the yeoman environment * @param {function} forkProcess the method to use for process forking */ module.exports = (args, options, env, forkProcess = fork) => { logger.info('cmd: genform from ./genform'); logger.debug(`args: ${toString(args)}`); const jdlFiles = getOptionsFromArgs(args); logger.info(chalk.yellow(`Executing genform ${jdlFiles.join(' ')}`)); logger.info(chalk.yellow(`Options: ${toString(options)}`)); try { const jdlImporter = new JDLProcessor(jdlFiles, options); jdlImporter.validate(); jdlImporter.getConfig(); jdlImporter.importJDL(); //jdlImporter.sendInsight(); jdlImporter.generateApplications(env,forkProcess); setTimeout(function(){ jdlImporter.generateEntities(env, forkProcess); },16000); //jdlImporter.generateDeployments(forkProcess); } catch (e) { logger.error(`Error during import-jdl: ${e.message}`, e); } };