UNPKG

@pecometer/peco-cli

Version:

Pecometer Command Line Interface Application

1 lines 14.7 kB
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.CreateApp=void 0;const base_command_1=require("../classes/base-command"),file_1=require("../classes/file"),path=require("path"),_=require("lodash"),npm=require("npm"),backend_app_config_1=require("../helpers/backend-app-config");class CreateApp extends base_command_1.CBaseCommand{constructor(){super(...arguments),this.description="Create a PecoTS and/or Angular app basic application",this._fileHelper=new file_1.CFileHelper,this._folderPath=process.cwd(),this._cwdPath=process.cwd(),this._backend=!1,this._frontend=!1,this._angularFrontend=!1,this._backendStructure=backend_app_config_1.BACKEND_STRUCTURE,this._backendFiles=backend_app_config_1.BACKEND_FILES,this._backendDependencies=backend_app_config_1.BACKEND_DEPENDENCIES,this._frontendStructure=[],this._frontendFiles=[],this._frontendDependencies={dev:{},main:{}},this._commonFiles=[{content:"gitignore.data",location:[""],name:".gitignore"},{content:"gitattributes.data",location:[""],name:".gitattributes"},{content:"license.data",location:[""],name:"license"},{content:"readme.data",location:[""],name:"README.md"},{content:"prettierrc.data",location:[""],name:".prettierrc"},{content:"prettierignore.data",location:[""],name:".prettierignore"}],this._commonFolders=[["public"]],this._npmRcFile=[{backend:!0,data:"//registry.npmjs.org/:_authToken={{npm_auth_token}}",name:"npm_auth_token",prompt:"NPM Auth Token"},{backend:!0,angular:!0,pecular:!0,data:"@pecometer:registry=https://npm.pecometer.co.uk\n//npm.pecometer.co.uk/:_authToken={{pecots_npm_token}}",name:"pecots_npm_token",prompt:"Auth Token For @pecometer NPM Server"},{data:"@fortawesome:registry=https://npm.fontawesome.com/\n//npm.fontawesome.com/:_authToken={{font_awesome_token}}",angular:!0,pecular:!0,name:"font_awesome_token",prompt:"Auth Token for FontAwesome"}],this._packageJson={author:"",dependencies:{},description:"",devDependencies:{},license:"SEE LICENSE IN licence",main:"index.js",name:"",scripts:{},version:"1.0.0"},this._commonDependencies={dev:{"@pecometer/eslint-config":"","@typescript-eslint/eslint-plugin":"","@typescript-eslint/parser":"",eslint:"","eslint-config-prettier":"","eslint-plugin-prettier":"",prettier:"",terser:"",typescript:""},main:{}},this._ifBothDependencies={dev:{concurrently:""},main:{}},this._frontEndPlaceholders=[{default:"127.0.0.1",name:"ip-address",prompt:"Development IP Address (127.0.0.1)"}]}async execute(name){if(name||(this.outputNewLine(),this.info("Please enter a name for your project/application: "),name=await this.waitForPrompt()),this._folderName=name,this._name=_.kebabCase(name),this.outputNewLine(),this.info("Would you like to install a PecoTS backend? Y/N (N): ",!1),this._backend=await this.waitForYesNo(),this.info("Would you like to install a Pecular frontend? Y/N (N): ",!1),this._frontend=await this.waitForYesNo(),this._frontend||(this.info("Would you like to install an Angular frontend? Y/N (N): ",!1),this._angularFrontend=await this.waitForYesNo()),!this._backend&&!this._frontend&&!this._angularFrontend)return this.error("Please select either a backend or frontend app, or both."),!1;if(await this._setupFrontendConfig(),this.notice("Creating folder structure."),!await this._createAppFolders(name))return!1;if(this._backend&&(this.notice("Creating basic backend application."),this.outputNewLine(),!await this._createBackendApp()))return!1;if(this._frontend||this._angularFrontend){this.notice("Creating basic frontend application."),this.outputNewLine();for(let i=0;i<this._frontEndPlaceholders.length;i++){const placeholder=this._frontEndPlaceholders[i];if(placeholder.prompt){this.info(`${placeholder.prompt}: `,!1);const value=await this.waitForPrompt();placeholder.value=()=>value||placeholder.default}}if(this.outputNewLine(),!await this._createFrontendApp())return!1}return this.notice("Adding common files."),!(!await this._addCommonFiles()||(this.notice("Preparing npmrc file."),this.outputNewLine(),!await this._prepareNpmRcFile()||(this.notice("Creating package.json."),this.outputNewLine(),!await this._writePackageJson()||(this.notice("Installing packages..."),this.outputNewLine(),!await this._installPackages()||(this.outputNewLine(),this.notice("Adding debug config files for Visual Code..."),!await this._addVsCodeDebug()||(this.outputNewLine(),this.notice("Adding eslint config..."),!await this._addEslintConfig()||(this.notice(`Application setup, enter the directory using \`cd ${this._folderName}\` and run the command \`npm run dev\` to begin development.`),0)))))))}async _setupFrontendConfig(){if(this._angularFrontend){const{FRONTEND_STRUCTURE,FRONTEND_FILES,FRONTEND_DEPENDENCIES}=await Promise.resolve().then((()=>require("../helpers/angular-frontend-app-config")));this._frontendStructure=FRONTEND_STRUCTURE,this._frontendDependencies=FRONTEND_DEPENDENCIES,this._frontendFiles=FRONTEND_FILES}else if(this._frontend){const{FRONTEND_STRUCTURE,FRONTEND_FILES,FRONTEND_DEPENDENCIES}=await Promise.resolve().then((()=>require("../helpers/pecular-frontend-app-config")));this._frontendStructure=FRONTEND_STRUCTURE,this._frontendDependencies=FRONTEND_DEPENDENCIES,this._frontendFiles=FRONTEND_FILES}}async _prepareNpmRcFile(){let npmrc="";for(let i=0,n=this._npmRcFile.length;i<n;i++)if(this._npmRcFile[i].both||this._backend&&this._npmRcFile[i].backend||this._angularFrontend&&this._npmRcFile[i].angular||this._frontend&&this._npmRcFile[i].pecular){this.info(`${this._npmRcFile[i].prompt}: `,!1);const result=await this.waitForPrompt(),regex=new RegExp(`{{${this._npmRcFile[i].name}}}`,"gi");npmrc+=this._npmRcFile[i].data.replace(regex,""!==result?result:""),npmrc+="\n"}return!!await this._fileHelper.writeFile(path.join(this._folderPath,".npmrc"),npmrc)}async _installPackages(){return new Promise(((resolve,reject)=>{this.outputNewLine(),process.chdir(this._folderPath),npm.load((async err=>{err&&(process.chdir(this._cwdPath),reject(!1)),await this._installDependencies(this._prepareModulesToInstall()),await this._installDependencies(this._prepareDevModulesToInstall(),!0),resolve(!0)}))}))}_installDependencies(modules,dev=!1){return new Promise(((resolve,reject)=>{dev?(npm.config.set("save-dev",!0),npm.config.set("save",!1)):(npm.config.set("save-dev",!1),npm.config.set("save",!0)),npm.commands.install(modules,(err=>{process.chdir(this._cwdPath),err?(this.error(err.message),reject(!1)):resolve(!0)}))}))}_prepareModulesToInstall(){const modules=[];return this._backend&&modules.push(..._.map(this._backendDependencies.main,((o,k)=>`${k}${o?"@"+o:""}`))),(this._frontend||this._angularFrontend)&&modules.push(..._.map(this._frontendDependencies.main,((o,k)=>`${k}${o?"@"+o:""}`))),this._backend&&(this._frontend||this._angularFrontend)&&modules.push(..._.map(this._ifBothDependencies.main,((o,k)=>`${k}${o?"@"+o:""}`))),modules.push(..._.map(this._commonDependencies.main,((o,k)=>`${k}${o?"@"+o:""}`))),modules}_prepareDevModulesToInstall(){const modules=[];return this._backend&&modules.push(..._.map(this._backendDependencies.dev,((o,k)=>`${k}${o?"@"+o:""}`))),(this._frontend||this._angularFrontend)&&modules.push(..._.map(this._frontendDependencies.dev,((o,k)=>`${k}${o?"@"+o:""}`))),this._backend&&(this._frontend||this._angularFrontend)&&modules.push(..._.map(this._ifBothDependencies.dev,((o,k)=>`${k}${o?"@"+o:""}`))),modules.push(..._.map(this._commonDependencies.dev,((o,k)=>`${k}${o?"@"+o:""}`))),modules}async _writePackageJson(){return!!await this._fileHelper.writeFile(path.join(this._folderPath,"package.json"),JSON.stringify(await this._preparePackageJson(),null,4))}async _preparePackageJson(){const packageJson=this._packageJson;return this.info("Package Author: ",!1),packageJson.author=await this.waitForPrompt(),packageJson.name=this._name,packageJson.description=this._name,(this._frontend||this._angularFrontend)&&this._backend?packageJson.scripts={build:"npm run build:backend && npm run build:frontend","build:backend":"gulp","build:frontend":"cd frontend && webpack --config config/webpack.prod.js --progress --profile --bail",cli:"cd backend && ts-node -r tsconfig-paths/register index.ts","dev:backend":"cd backend && ts-node-dev --ignore-watch node_modules --poll --inspect --pretty --respawn --watch .env -r tsconfig-paths/register server.ts","dev:frontend":"cd frontend && webpack serve",dev:'concurrently --kill-others "npm run dev:backend" "npm run dev:frontend"',tsc:"tsc"}:this._frontend||this._angularFrontend?packageJson.scripts={build:"webpack --config config/webpack.prod.js --progress --profile --bail",dev:"webpack serve"}:this._backend&&(packageJson.scripts={build:"gulp",cli:"ts-node -r tsconfig-paths/register index.ts",dev:"ts-node-dev --ignore-watch node_modules --pretty --inspect --respawn --watch .env -r tsconfig-paths/register server.ts"}),this.info("Package Version (1.0.0): ",!1),packageJson.version=await this.waitForPrompt()||packageJson.version,packageJson}async _addCommonFiles(){for(let i=0,n=this._commonFiles.length;i<n;i++)if(!await this._processFile(this._commonFiles[i],this._folderPath))return!1;return!0}async _createFrontendApp(){for(let i=0,n=this._frontendFiles.length;(this._frontend||this._angularFrontend)&&i<n;i++)if((this._backend&&!1!==this._frontendFiles[i].withBackend||!this._backend&&!0!==this._frontendFiles[i].withBackend)&&!await this._processFile(this._frontendFiles[i],this._frontendFolder,!0))return!1;return!0}async _createBackendApp(){for(let i=0,n=this._backendFiles.length;this._backend&&i<n;i++)if((this._frontend&&!1!==this._backendFiles[i].withFrontend||!this._frontend&&!0!==this._backendFiles[i].withFrontend)&&!await this._processFile(this._backendFiles[i],this._backendFolder))return!1;return!0}async _processFile(file,basePath,frontend=!1){let dataToWrite=await this._fileHelper.readFile(path.join(__dirname,"..","data",file.content));if(dataToWrite=dataToWrite.toString(),file.placeholders)for(let i=0,n=file.placeholders.length;i<n;i++){const placeholder=file.placeholders[i];let result=null;if(frontend){const completed=_.find(this._frontEndPlaceholders,["name",placeholder.name]);completed&&(result=completed.value(placeholder.name))}!result&&placeholder.prompt?(this.info(`${placeholder.prompt}: `,!1),result=await this.waitForPrompt()):!result&&placeholder.value&&(result=await placeholder.value(this._name));const regex=new RegExp(`{{${placeholder.name}}}`,"gi");dataToWrite=dataToWrite.replace(regex,""!==result?result:void 0!==placeholder.default?placeholder.default:"")}return!!await this._fileHelper.writeFile(path.join(basePath,...file.location,file.name),dataToWrite)||(this.error(`An error has occurred trying to create the file ${path.join(__dirname,this._folderPath,...file.location)}.`),!1)}async _createAppFolders(name){return this._folderPath=path.join(this._folderPath,name),!0===await this._fileHelper.exists(this._folderPath)?(this.error(`Folder ${name} already exists, please use another name.`),!1):!!await this._createBackendStructure()&&!!await this._createFrontendStructure()&&!!await this._createCommonFolders()}async _createBackendStructure(){this._backendFolder=this._frontend||this._angularFrontend?path.join(this._folderPath,"backend"):this._folderPath;for(let i=0,n=this._backendStructure.length;this._backend&&i<n;i++)if(!await this._fileHelper.createFolder(path.join(this._backendFolder,...this._backendStructure[i])))return this.error(`An error has occurred trying to create folder ${path.join(this._backendFolder,...this._backendStructure[i])}.`),!1;return!0}async _createFrontendStructure(){this._frontendFolder=this._backend?path.join(this._folderPath,"frontend"):this._folderPath;for(let i=0,n=this._frontendStructure.length;(this._frontend||this._angularFrontend)&&i<n;i++)if(!await this._fileHelper.createFolder(path.join(this._frontendFolder,...this._frontendStructure[i])))return this.error(`An error has occurred trying to create folder ${path.join(this._frontendFolder,...this._frontendStructure[i])}.`),!1;return!0}async _createCommonFolders(){for(let i=0,n=this._commonFolders.length;i<n;i++)if(!await this._fileHelper.createFolder(path.join(this._folderPath,...this._commonFolders[i])))return this.error(`An error has occurred trying to create folder ${path.join(this._folderPath,...this._commonFolders[i])}.`),!1;return!0}async _addVsCodeDebug(){if(!await this._fileHelper.createFolder(path.join(this._folderPath,".vscode")))return this.error(`An error has occurred trying to create folder ${path.join(this._folderPath,".vscode")}.`),!1;if(!await this._fileHelper.writeFile(path.join(this._folderPath,".vscode","settings.json"),JSON.stringify({"codemetrics.basics.CodeLensHiddenUnder":5,"codemetrics.basics.ComplexityLevelExtreme":40,"codemetrics.basics.ComplexityLevelHigh":30,"codemetrics.basics.ComplexityLevelLow":5,"codemetrics.basics.ComplexityLevelNormal":20},null,4)))return this.error(`An error has occurred trying to write ${path.join(this._folderPath,".vscode","settings.json")}.`),!1;const launch={configurations:[],version:"0.2.0"};if(this._backend&&launch.configurations.push({cwd:"${workspaceRoot}"+(this._frontend||this._angularFrontend?"/backend":""),name:"Attach to Server Debug",port:9229,protocol:"inspector",request:"attach",restart:!0,type:"node"}),this._frontend||this._angularFrontend){const ip=_.find(this._frontEndPlaceholders,["name","ip-address"]);launch.configurations.push({disableNetworkCache:!0,name:"Launch Chrome for Frontend",request:"launch",sourceMapPathOverrides:{"webpack:///./src/*":"${webRoot}/*"},sourceMaps:!0,trace:!0,type:"chrome",url:`http://${ip&&ip.value?ip.value("ip-address"):"127.0.0.1"}:5555`,webRoot:this._backend?"${workspaceRoot}/frontend/src":"${workspaceRoot}/src"})}return!!await this._fileHelper.writeFile(path.join(this._folderPath,".vscode","launch.json"),JSON.stringify(launch,null,4))||(this.error(`An error has occurred trying to write ${path.join(this._folderPath,".vscode","launch.json")}.`),!1)}async _addEslintConfig(){const config={extends:["@pecometer"],ignorePatterns:["spec/**/*","gulpfile.js","**/*.js"],parserOptions:{project:[]}};return this._backend&&this._frontend?config.parserOptions.project=["./backend/tsconfig.json","./frontend/src/tsconfig.json"]:this._backend&&this._angularFrontend?config.parserOptions.project=["./backend/tsconfig.json","./src/tsconfig.json"]:this._backend||this._frontend?config.parserOptions.project=["./tsconfig.json"]:this._angularFrontend&&(config.parserOptions.project=["./src/tsconfig.json"]),!!await this._fileHelper.writeFile(path.join(this._folderPath,".eslintrc.js"),`module.exports = ${JSON.stringify(config,null,4)}`)||(this.error(`An error has occurred trying to write ${path.join(this._folderPath,".vscode","launch.json")}.`),!1)}}exports.CreateApp=CreateApp;