UNPKG

generator-upendodnn

Version:

Scaffolds DNN extensions, including Modules (Webforms, SPA, and MVC), Persona Bar, Skin Object, Library, Scheduler, and Hotcakes Commerce projects (based on the generator built by Matt Rutledge).

674 lines (590 loc) 21.6 kB
'use strict'; const DnnGeneratorBase = require('../lib/DnnGeneratorBase'); const chalk = require('chalk'); const fs = require('fs'); const constants = require('../lib/Constants'); const { removeLeadingZeros } = require('../lib/versionUtil'); module.exports = class extends DnnGeneratorBase { prompting() { const prompts = [ { when: !this.options.spaType, type: 'list', name: 'spaType', message: 'What language do you want your SPA Module to use?', choices: [ { name: 'Angular', value: 'Angular' }, { name: 'ReactJS', value: 'ReactJS' }, { name: 'Vue 2', value: 'Vue 2' }, { name: 'Vue 3', value: 'Vue 3' } ] }, { when: function (response) { return response.spaType === 'ReactJS'; }, type: 'list', name: 'langType', message: 'What Script Language do you want to use?', choices: [ { name: 'ECMAScript (jsx)', value: 'jsx' }, { name: 'TypeScript (tsx)', value: 'tsx' } ] }, { when: !this.options.friendlyName, type: 'input', name: 'friendlyName', message: 'What is the name of your SPA Module?', default: this.appname, /*to-do: figure out if we want to populate and actually use this later */ validate: str => { return str.length > 0; } }, { when: !this.options.extensionDescription, type: 'input', name: 'extensionDescription', message: 'Describe your SPA module:', validate: str => { return str.length > 0; } }, { when: !this.options.companyName, type: 'input', name: 'companyName', message: 'Namespace root for your SPA module (Usually a company name)?', store: true, validate: str => { return str.length > 0; } } ]; var msBuildVersion = this._getMsBuildVersion(); if (msBuildVersion == "") { this.log(chalk.red("YIKES! A valid version of MSBuild was not found! This is a critical error... :(")); } return this.prompt(prompts).then(props => { // To access props later use this.props.someAnswer; props.currentDate = new Date(); if (this.options.companyName.endsWith(" -f")) { props.namespaceRoot = this.options.companyName.replace(" -f", ""); } else { props.namespaceRoot = this._pascalCaseName(this.options.companyName); } if (props.friendlyName.endsWith(" -f")) { props.friendlyName = props.friendlyName.replace(" -f", ""); } else { props.friendlyName = this._pascalCaseName(props.friendlyName); } props.extensionType = "Modules"; props.fullNamespace = props.namespaceRoot + "." + props.extensionType + "." + props.friendlyName; props.guid = this._generateGuid(); props.msBuildVersion = msBuildVersion; props.dnnBuildVersion = constants.DNN_BUILD_VERSION; props.dnnBuildVersionShort = removeLeadingZeros(constants.DNN_BUILD_VERSION); this.props = props; }); } writing() { this.log( chalk.white(`Creating ${this.props.spaType} ${this.props.langType ? this.props.langType : ""} SPA Module.`) ); // mod: this follows the Upendo development/solution pattern this.destinationRoot("Modules/"); let spaType = this.props.spaType; let spaPath = spaType === "ReactJS" ? `${this.props.spaType}/${this.props.langType}` : spaType === "Vue 2" ? "VueJS/" : spaType === "Vue 3" ? "Vue3JS/" : `${this.props.spaType}/`; let namespaceRoot = this.props.namespaceRoot; let friendlyName = this.props.friendlyName; let currentDate = this.props.currentDate; let fullNamespace = this.props.fullNamespace; let guid = this.props.guid; let template = { ownerName: this.options.ownerName, companyName: this.options.companyName, currentDate: this.props.currentDate, extensionType: this.props.extensionType, namespaceRoot: namespaceRoot, friendlyName: this.props.friendlyName, extensionDescription: this.props.extensionDescription, companyUrl: this.options.companyUrl, emailAddress: this.options.emailAddress, currentYear: currentDate.getFullYear(), version: '01.00.00', extensionType: this.props.extensionType, fullNamespace: this.props.fullNamespace, guid: this.props.guid, localhost: this.options.dnnHost, dnnRoot: this.options.dnnRoot, msBuildVersion: this.props.msBuildVersion, dnnBuildVersion: this.props.dnnBuildVersion, dnnBuildVersionShort: this.props.dnnBuildVersionShort }; if (spaType === "ReactJS") { this.fs.copyTpl( this.templatePath('../../common/build/*.*'), this.destinationPath(friendlyName + '/_BuildScripts'), template ); this.fs.copyTpl( this.templatePath('common/_BuildScripts/**'), this.destinationPath(friendlyName + '/_BuildScripts/'), template ); this.fs.copyTpl( this.templatePath(spaPath + '/_BuildScripts/**'), this.destinationPath(friendlyName + '/_BuildScripts/'), template ); this.fs.copyTpl( this.templatePath('../../common/csproj/Providers/**'), this.destinationPath(friendlyName + '/Providers'), template ); this.fs.copyTpl( this.templatePath('../../common/csproj/NuGet.config'), this.destinationPath(friendlyName + '/NuGet.config'), template ); this.fs.copyTpl( this.templatePath('common/App_LocalResources/**'), this.destinationPath(friendlyName + '/App_LocalResources/'), template ); this.fs.copyTpl( this.templatePath('common/Components/**'), this.destinationPath(friendlyName + '/Components/'), template ); this.fs.copyTpl( this.templatePath('common/Controllers/**'), this.destinationPath(friendlyName + '/Controllers/'), template ); this.fs.copyTpl( this.templatePath('common/Data/**'), this.destinationPath(friendlyName + '/Data/'), template ); this.fs.copyTpl( this.templatePath('common/ViewModels/**'), this.destinationPath(friendlyName + '/ViewModels/'), template ); this.fs.copyTpl( this.templatePath('common/Providers/**'), this.destinationPath(friendlyName + '/Providers/'), template ); // Do all templated copies this.fs.copyTpl( this.templatePath('../../common/src/**'), this.destinationPath(friendlyName + '/src/'), template ); this.fs.copyTpl( this.templatePath('common/src/**'), this.destinationPath(friendlyName + '/src/'), template ); this.fs.copyTpl( this.templatePath(spaPath + '/**/*.*'), this.destinationPath(friendlyName + '/.'), template ); this.fs.copyTpl( this.templatePath('common/RouteConfig.cs'), this.destinationPath(friendlyName + '/RouteConfig.cs'), template ); this.fs.copyTpl( this.templatePath('common/Constants.cs'), this.destinationPath(friendlyName + '/Constants.cs'), template ); this.fs.copyTpl( this.templatePath('common/manifest.dnn'), this.destinationPath(friendlyName + '/' + friendlyName + '.dnn'), template ); this.fs.copyTpl( this.templatePath('common/symbols.dnn'), this.destinationPath(friendlyName + '/' + friendlyName + '_Symbols.dnn'), template ); this.fs.copyTpl( this.templatePath('common/License.txt'), this.destinationPath(friendlyName + '/License.txt'), template ); this.fs.copyTpl( this.templatePath('common/ReleaseNotes.txt'), this.destinationPath(friendlyName + '/ReleaseNotes.txt'), template ); this.fs.copyTpl( this.templatePath(spaType + '/common/Module.csproj'), this.destinationPath(friendlyName + '/' + fullNamespace + '.csproj'), template ); this.fs.copyTpl( this.templatePath(spaType + '/common/Module.build'), this.destinationPath(friendlyName + '/Module.build'), template ); this.fs.copyTpl( this.templatePath('common/Data/ModuleContext.cs'), this.destinationPath(friendlyName + '/Data/' + friendlyName + 'Context.cs'), template ); this.fs.copyTpl( this.templatePath('common/package.json'), this.destinationPath(friendlyName + '/package.json'), template ); this.fs.copyTpl( this.templatePath('../../common/branding/Images/**'), this.destinationPath(friendlyName + '/Images'), template ); this._writeBabelRc(); const pkgJson = { devDependencies: { "@babel/plugin-proposal-object-rest-spread": "^7.20.7", "@babel/plugin-transform-object-assign": "^7.22.5", "@babel/core": "^7.22.5", "@babel/preset-env": "^7.22.5", "@babel/preset-react": "^7.22.5", // eslint-disable-next-line prettier/prettier 'archiver': '^3.0.0', "babel-loader": "^9.1.2", 'browser-sync': '^2.26.3', // eslint-disable-next-line prettier/prettier "babel-plugin-transform-react-remove-prop-types": "^0.4.24", 'chokidar': '^3.5.3', // eslint-disable-next-line prettier/prettier 'concurrently': '^8.2.0', "copy-webpack-plugin": "^11.0.0", "css-loader": "^6.8.1", "file-loader": "^6.2.0", // eslint-disable-next-line prettier/prettier 'dotenv': '^6.2.0', 'fs-extra': '^7.0.1', "html-webpack-plugin": "^5.5.1", // eslint-disable-next-line prettier/prettier 'marked': '^4.3.0', "sass": "^1.63.2", "sass-loader": "^13.3.1", "style-loader": "^3.3.3", // eslint-disable-next-line prettier/prettier "webpack": "^5.86.0", "webpack-cli": "^5.1.4", "webpack-dev-server": "^4.15.0", "@testing-library/dom": "^7.21.4" }, dependencies: { "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", "react": "^18.2.0", "react-dom": "^18.2.0", "web-vitals": "^2.1.4" } }; if (this.props.langType === 'jsx') { this._writeJsConfig(); this.fs.copyTpl( this.templatePath(spaPath + '/.eslintrc.js'), this.destinationPath(friendlyName + '/.eslintrc.js'), template ); pkgJson.devDependencies = { ...pkgJson.devDependencies, // eslint-disable-next-line prettier/prettier 'eslint': '^8.42.0', 'eslint-plugin-react': '^7.32.2', }; } else { this._writeTsConfig(); this.fs.copyTpl( this.templatePath(spaPath + '/tslint.json'), this.destinationPath(friendlyName + '/tslint.json'), template ); pkgJson.devDependencies = { ...pkgJson.devDependencies, "@types/react": "^18.2.9", "@types/react-dom": "^18.2.4", "ts-loader": "^9.4.3", "typescript": "^5.1.3", }; } // Extend package.json file in destination path this.fs.extendJSON(this.destinationPath(friendlyName + '/package.json'), pkgJson); let launchJsonConfig = { type: 'chrome', request: 'launch', name: 'Launch Chrome against ' + friendlyName, url: 'http://localhost:3000', // eslint-disable-next-line no-template-curly-in-string webRoot: '${workspaceRoot}/' + friendlyName, sourceMaps: true, trace: true }; // For some reason json extend is throwing a conflict. Use FS to do this outside of yeoman to avoid conflict message to user. let launchJsonPath = this.destinationPath('.vscode/launch.json'); if (fs.existsSync(launchJsonPath)) { // eslint-disable-next-line handle-callback-err fs.readFile(launchJsonPath, function (err, data) { let json = JSON.parse(data); json.configurations.push(launchJsonConfig); fs.writeFileSync(launchJsonPath, JSON.stringify(json, null, 2)); }); } else { let launchJson = { version: '0.2.0', configurations: [] }; launchJson.configurations.push(launchJsonConfig); this.fs.extendJSON(launchJsonPath, launchJson); } } else if (spaType === "Vue 2") { this.fs.copyTpl( this.templatePath(spaPath + 'Module.csproj'), this.destinationPath(friendlyName + '/' + fullNamespace + '.csproj'), template ); this.fs.copyTpl( this.templatePath(spaPath + 'Module.dnn'), this.destinationPath(friendlyName + '/' + friendlyName + '.dnn'), template ); this.fs.copyTpl( this.templatePath(spaPath + 'symbols.dnn'), this.destinationPath(friendlyName + '/' + friendlyName + '_Symbols.dnn'), template ); this.fs.copyTpl( this.templatePath(spaPath + 'Data/ModuleContext.cs'), this.destinationPath(friendlyName + '/Data/' + friendlyName + 'Context.cs'), template ); this.fs.copyTpl( this.templatePath(spaPath + 'common/**'), this.destinationPath(friendlyName + '/.'), template ); this.fs.copyTpl( this.templatePath('../../common/branding/Images/**'), this.destinationPath(friendlyName + '/Images'), template ); } else if (spaType === "Vue 3") { this.fs.copyTpl( this.templatePath(spaPath + 'Module.csproj'), this.destinationPath(friendlyName + '/' + fullNamespace + '.csproj'), template ); this.fs.copyTpl( this.templatePath(spaPath + 'Module.dnn'), this.destinationPath(friendlyName + '/' + friendlyName + '.dnn'), template ); this.fs.copyTpl( this.templatePath(spaPath + 'symbols.dnn'), this.destinationPath(friendlyName + '/' + friendlyName + '_Symbols.dnn'), template ); this.fs.copyTpl( this.templatePath(spaPath + 'common/**'), this.destinationPath(friendlyName + '/.'), template ); this.fs.copyTpl( this.templatePath('../../common/branding/Images/**'), this.destinationPath(friendlyName + '/Images'), template ); } else if (spaType === "Angular") { this.fs.copyTpl( this.templatePath('common/package.json'), this.destinationPath(friendlyName + '/package.json'), template ); this.fs.copyTpl( this.templatePath('../../common/branding/Images/**'), this.destinationPath(friendlyName + '/Images'), template ); this.fs.copyTpl( this.templatePath('common/Controllers/**'), this.destinationPath(friendlyName + '/Controllers'), template ); this.fs.copyTpl( this.templatePath('common/License.txt'), this.destinationPath(friendlyName + '/License.txt'), template ); this.fs.copyTpl( this.templatePath('common/ReleaseNotes.txt'), this.destinationPath(friendlyName + '/ReleaseNotes.txt'), template ); this.fs.copyTpl( this.templatePath('common/Components/**'), this.destinationPath(friendlyName + '/Components/.'), template ); this.fs.copyTpl( this.templatePath('common/ViewModels/**'), this.destinationPath(friendlyName + '/ViewModels/.'), template ); this.fs.copyTpl( this.templatePath('common/Constants.cs'), this.destinationPath(friendlyName + '/Constants.cs'), template ); this.fs.copyTpl( this.templatePath('common/Data/Item.cs'), this.destinationPath(friendlyName + '/Data/Item.cs'), template ); this.fs.copyTpl( this.templatePath('common/Data/ModuleContext.cs'), this.destinationPath(friendlyName + '/Data/' + friendlyName + 'Context.cs'), template ); this.fs.copyTpl( this.templatePath('common/_BuildScripts/**'), this.destinationPath(friendlyName + '/_BuildScripts'), template ); this.fs.copyTpl( this.templatePath('common/src/Resources/**'), this.destinationPath(friendlyName + '/src/Resources/.'), template ); this.fs.copyTpl( this.templatePath('common/src/Settings.html'), this.destinationPath(friendlyName + '/src/Settings.html'), template ); this.fs.copyTpl( this.templatePath('common/App_LocalResources/**'), this.destinationPath(friendlyName + '/App_LocalResources'), template ); this.fs.copyTpl( this.templatePath('common/Providers/**'), this.destinationPath(friendlyName + '/Providers'), template ); this.fs.copyTpl( this.templatePath('common/manifest.dnn'), this.destinationPath(friendlyName + '/' + friendlyName + '.dnn'), template ); this.fs.copyTpl( this.templatePath('common/symbols.dnn'), this.destinationPath(friendlyName + '/' + friendlyName + '_Symbols.dnn'), template ); this.fs.copyTpl( this.templatePath('common/RouteConfig.cs'), this.destinationPath(friendlyName + '/RouteConfig.cs'), template ); this.fs.copyTpl( this.templatePath(spaPath + '/webpack.config.js'), this.destinationPath(friendlyName + '/webpack.config.js'), template ); this.fs.copyTpl( this.templatePath(spaPath + '/Module.csproj'), this.destinationPath(friendlyName + '/' + fullNamespace + '.csproj'), template ); this.fs.copyTpl( this.templatePath(spaPath + '/src/**'), this.destinationPath(friendlyName + '/src/.'), template ); this.fs.copyTpl( this.templatePath(spaPath + '/Module.build'), this.destinationPath(friendlyName + '/' + 'Module.build'), template ); this.fs.copyTpl( this.templatePath(spaPath + '/angular.json'), this.destinationPath(friendlyName + '/' + 'angular.json'), template ); this.fs.copyTpl( this.templatePath(spaPath + '/tsconfig.app.json'), this.destinationPath(friendlyName + '/' + 'tsconfig.app.json'), template ); this.fs.copyTpl( this.templatePath(spaPath + '/tsconfig.json'), this.destinationPath(friendlyName + '/' + 'tsconfig.json'), template ); this.fs.copyTpl( this.templatePath(spaPath + '/tsconfig.spec.json'), this.destinationPath(friendlyName + '/' + 'tsconfig.spec.json'), template ); const pkgJson = { "scripts": { "ng": "ng", "angular-build": "ng build --output-hashing none", "start": "ng run " + friendlyName + ":builddev --watch", }, "dependencies": { "@angular/animations": "^14.0.0", "@angular/common": "^14.0.0", "@angular/compiler": "^14.0.0", "@angular/core": "^14.0.0", "@angular/forms": "^14.0.0", "@angular/platform-browser": "^14.0.0", "@angular/platform-browser-dynamic": "^14.0.0", "@angular/router": "^14.0.0", "rxjs": "~7.5.0", "tslib": "^2.3.0", "zone.js": "~0.11.4" }, "devDependencies": { "@angular-builders/custom-webpack": "^14.1.0", "@angular-devkit/build-angular": "^14.2.1", "copy-webpack-plugin": "^11.0.0", "html-webpack-plugin": "^5.5.0", "@angular/cli": "~14.2.1", "@angular/compiler-cli": "^14.0.0", "@types/jasmine": "~4.0.0", "jasmine-core": "~4.3.0", "karma": "~6.4.0", "karma-chrome-launcher": "~3.1.0", "karma-coverage": "~2.2.0", "karma-jasmine": "~5.1.0", "karma-jasmine-html-reporter": "~2.0.0", "typescript": "~4.7.2" } } this.fs.extendJSON(this.destinationPath(friendlyName + '/package.json'), pkgJson); } } install() { this._writeSolution(); this._restoreSolution(); this._addProjectToSolution(); this._installDependencies(); } end() { this.log(chalk.white('All Ready!')); } };