@digipolis/start-ui
Version:
234 lines (211 loc) • 8.27 kB
JavaScript
/**
* Main generator file for generating Angular projects.
*/
import * as fs from 'fs';
import * as path from 'path';
import options from './config/options.js';
import questions from './config/questions.js';
import { updateLog } from '../../utils/log.js';
import { execPromise } from '../../utils/exec.js';
import { mapRouting } from './helpers/routing.js';
import { deleteFolderSync } from '../../utils/delete.js';
import { updatePackageJson, getlatestverion } from '../../utils/package.js';
import { copyFolderRecursiveSync, copyFileSync } from '../../utils/copy.js';
import HandlebarsTemplateGenerator from '../../utils/template-generator.js';
function getQuestions() {
return questions;
}
function getOptions() {
return options;
}
class AngularAppGenerator {
/**
* @param configuration Configuration object
* @param execCallback Callback used for executing command on the child process spawn
* @param templateGenerator Instance of HandlebarsTemplateGenerator
*/
constructor(configuration, execCallback, templateGenerator) {
this.execPromise = execCallback;
this.configuration = configuration;
this.generator = templateGenerator;
}
async start() {
updateLog('Preparing...');
await this.prepareDirectory();
await this.installAngular(this.configuration);
await this.installAntwerpUI(this.configuration);
await this.createStarterTemplate(this.configuration);
updateLog('Done with frontend setup', 'cyan');
}
/**
* Deletes & recreates the frontend directory (if present)
* The method won't crash if no frontend directory is present.
*/
async prepareDirectory() {
deleteFolderSync(__frontenddir);
// eslint-disable-next-line
return new Promise((resolve, reject) => fs.mkdir(__frontenddir, (err) => (err ? reject(err) : resolve())));
}
/**
* Creates a new application by invoking the @angular/cli new command.
* Additionaly a git and routing config is added if necessary
* @param Configuration config
*/
async installAngular(config) {
updateLog('Installing Angular...');
await this.execPromise('npx', [
'-p',
'@angular/cli',
'ng',
'new',
'frontend',
`--skip-git=${!!config.backend}`,
'--style=scss',
`--routing=${!!config.routing.add}`,
'--strict=false',
]);
}
/**
* Installs necessary Antwerp UI libraries:
* - Antwerp UI
* - SASS
*/
async installAntwerpUI(config) {
updateLog('Installing Antwerp UI...');
await this.execPromise('npm', [
'install',
'--save',
'@acpaas-ui/ngx-layout',
'@acpaas-ui/ngx-logo',
...config.branding.npm,
...config.routing.npm,
], {
cwd: path.resolve(__frontenddir),
});
if (config.auth) {
await this.execPromise('npm', [
'install',
'--save',
'@acpaas-ui/ngx-user-menu',
], {
cwd: path.resolve(__frontenddir),
});
}
}
/**
* Compiles and renders template files and copies necessary files for a complete
* angular app setup. THis method does the actual method of generating the project.
*/
async createStarterTemplate(config) {
updateLog(`Creating starter template (v.${config.coreVersion})...`);
// src/proxy.conf.js
if (config.backend) {
copyFileSync(`${__basedir}/generators/angular/files/proxy.conf.js`, `${__frontenddir}`);
updatePackageJson(
{
scripts: {
start: 'ng serve --proxy-config proxy.conf.js',
},
},
`${__frontenddir}/package.json`,
);
}
// First copy all files necessary, we'll compile the templates later on
copyFolderRecursiveSync(`${__basedir}/generators/angular/files/src/app`, `${__frontenddir}/src`);
copyFileSync(`${__basedir}/generators/angular/files/src/index.html.template.hbs`, `${__frontenddir}/src`);
copyFileSync(`${__basedir}/generators/angular/files/src/styles.scss.template.hbs`, `${__frontenddir}/src`);
// src/index.html
await this.generator.generate({
fromTemplate: path.resolve(__frontenddir, 'src/index.html.template.hbs'),
to: path.resolve(__frontenddir, 'src/index.html'),
});
updateLog('CREATED: index.html');
// src/styles.scss
await this.generator.generate({
fromTemplate: path.resolve(__frontenddir, 'src/styles.scss.template.hbs'),
to: path.resolve(__frontenddir, 'src/styles.scss'),
});
updateLog('CREATED: styles.scss');
// app.module.ts
await this.generator.generate({
fromTemplate: path.resolve(__frontenddir, 'src/app/app.module.ts.template.hbs'),
to: path.resolve(__frontenddir, 'src/app/app.module.ts'),
});
updateLog('CREATED: app.module.ts');
// app.component.html
await this.generator.generate({
fromTemplate: path.resolve(__frontenddir, 'src/app/app.component.html.template.hbs'),
to: path.resolve(__frontenddir, 'src/app/app.component.html'),
});
updateLog('CREATED: app.component.html');
// app.component.ts
await this.generator.generate({
fromTemplate: path.resolve(__frontenddir, 'src/app/app.component.ts.template.hbs'),
to: path.resolve(__frontenddir, 'src/app/app.component.ts'),
});
updateLog('CREATED: app.component.ts');
// AUI module
await copyFolderRecursiveSync(
path.resolve(__basedir, 'generators/angular/files/src/app/aui'),
path.resolve(__frontenddir, 'src/app/'),
);
// aui-imports.ts
await this.generator.generate({
fromTemplate: path.resolve(__frontenddir, 'src/app/aui/aui.imports.ts.template.hbs'),
to: path.resolve(__frontenddir, 'src/app/aui/aui.imports.ts'),
});
updateLog('CREATED: aui.module.ts');
if (config.routing && config.routing.add) {
await copyFolderRecursiveSync(`${__basedir}/generators/angular/files/extra/src/app/pages/`, `${__frontenddir}/src/app`);
await copyFolderRecursiveSync(`${__basedir}/generators/angular/files/extra/src/app/services`, `${__frontenddir}/src/app`);
copyFileSync(`${__basedir}/generators/angular/files/extra/src/app/app-routing.module.ts.template.hbs`, `${__frontenddir}/src/app`);
if (!config.auth) {
deleteFolderSync(`${__frontenddir}/src/app/pages/login`);
} else {
// Auth is enabled
await copyFolderRecursiveSync(`${__basedir}/generators/angular/files/extra/src/app/pages/login/`, `${__frontenddir}/src/app/pages`);
await copyFolderRecursiveSync(`${__basedir}/generators/angular/files/extra/src/app/services`, `${__frontenddir}/src/app`);
}
// src/app/pages/index.ts
await this.generator.generate({
fromTemplate: path.resolve(__frontenddir, 'src/app/pages/index.ts.template.hbs'),
to: path.resolve(__frontenddir, 'src/app/pages/index.ts'),
});
updateLog('CREATED: pages/index.ts');
// src/app/app-routing.module.ts
await this.generator.generate({
fromTemplate: path.resolve(__frontenddir, 'src/app/app-routing.module.ts.template.hbs'),
to: path.resolve(__frontenddir, 'src/app/app-routing.module.ts'),
});
updateLog('CREATED: app-routing.module.ts');
} else {
await copyFolderRecursiveSync(
path.resolve(__basedir, 'generators/angular/files/extra/src/app/pages'),
path.resolve(__frontenddir, 'src/app/'),
);
deleteFolderSync(path.resolve(__frontenddir, 'src/app/pages/about'));
deleteFolderSync(path.resolve(__frontenddir, 'src/app/pages/login'));
deleteFolderSync(path.resolve(__frontenddir, 'src/app/pages/index.ts.template.hbs'));
}
}
}
/**
* Dependency injection is used here for testing purposes.
* However, to prevent to start reworking the whole application,
* we imply with the export default interface that is also present in other
* generator files.
*/
export default {
getOptions,
getQuestions,
start: async (config) => {
const configuration = {
...config,
routing: mapRouting(config),
coreVersion: await getlatestverion('@a-ui/core'),
};
const generator = new AngularAppGenerator(configuration, execPromise, new HandlebarsTemplateGenerator(configuration));
return generator.start();
},
AngularAppGenerator,
};