@cuba-platform/front-generator
Version:
CUBA Platform front-end clients generator
218 lines • 9.59 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.refineAnswers = exports.readProjectModel = exports.BaseGenerator = void 0;
const Base = require("yeoman-generator");
const path = require("path");
const cli_options_1 = require("./cli-options");
const questions_1 = require("./questions");
const fs = require("fs");
const cuba_model_utils_1 = require("./model/cuba-model-utils");
const studio_integration_1 = require("./studio/studio-integration");
const AutocompletePrompt = require("inquirer-autocomplete-prompt");
const through2 = require("through2");
const prettier = require("prettier");
/**
* @alpha
*/
class BaseGenerator extends Base {
constructor(args, options) {
super(args, options);
this.options = {};
// store initial dir where generator invoked from, process.cwd() is changed after
// this.destinationRoot() called
const executionDir = process.cwd();
this._populateOptions(this._getAvailableOptions());
this.destinationRoot(this._getDestRoot());
this.modelFilePath = this._composeModelFilePath(this.options, executionDir);
// @ts-ignore this.env.adapter is missing in the typings
this.env.adapter
.promptModule.registerPrompt('autocomplete', AutocompletePrompt);
this.registerTransformStream(createEjsRenameTransform());
this.registerTransformStream(createFormatTransform());
}
_composeModelFilePath(options, executionDir) {
const { model } = options;
if (model == null)
return undefined;
return path.isAbsolute(model) ? model : path.join(executionDir, model);
}
_obtainCubaProjectModel() {
return __awaiter(this, void 0, void 0, function* () {
if (this.modelFilePath) {
this.log('Skipping project model prompts since model is provided');
this.conflicter.force = true;
this.cubaProjectModel = this._readProjectModel();
}
else {
const openedCubaProjects = yield (0, studio_integration_1.getOpenedCubaProjects)();
if (!openedCubaProjects || openedCubaProjects.length < 1) {
this.env.error(Error(studio_integration_1.ERR_STUDIO_NOT_CONNECTED));
return;
}
const projectModelAnswers = yield this.prompt([{
name: 'projectInfo',
type: 'list',
message: 'Please select CUBA project you want to use for generation',
choices: openedCubaProjects && openedCubaProjects.map(p => ({
name: `${p.name} [${p.path}]`,
value: p
}))
}]);
this.modelFilePath = path.join(process.cwd(), 'projectModel.json');
yield (0, studio_integration_1.exportProjectModel)(projectModelAnswers.projectInfo.locationHash, this.modelFilePath);
this.cubaProjectModel = this._readProjectModel();
}
});
}
// TODO Remove method, use readProjectModel() function directly
_readProjectModel() {
const { modelFilePath } = this;
return readProjectModel(modelFilePath);
}
_obtainAnswers() {
return __awaiter(this, void 0, void 0, function* () {
yield this._obtainCubaProjectModel();
let unrefinedAnswers;
if (this.options.answers) {
this.log('Skipping prompts since answers are provided');
this.conflicter.force = true;
const answersBuffer = Buffer.from(this.options.answers, 'base64').toString('utf8');
unrefinedAnswers = JSON.parse(answersBuffer);
}
else {
unrefinedAnswers = (yield this.prompt((0, questions_1.fromStudioProperties)(this._getParams(), this.cubaProjectModel)));
unrefinedAnswers = yield this._additionalPrompts(unrefinedAnswers);
this.options.verbose && this.log('Component config:\n' + JSON.stringify(unrefinedAnswers));
}
this.answers = refineAnswers(this.cubaProjectModel, this._getParams(), unrefinedAnswers);
});
}
_promptOrParse() {
return __awaiter(this, void 0, void 0, function* () {
if (this.modelFilePath) {
this.cubaProjectModel = this._readProjectModel();
}
if (this.options.model && this.options.answers) { // passed from studio
this.conflicter.force = true;
const encodedAnswers = Buffer.from(this.options.answers, 'base64').toString('utf8');
const parsedAnswers = JSON.parse(encodedAnswers);
this.answers = refineAnswers(this.cubaProjectModel, this._getParams(), parsedAnswers);
return Promise.resolve();
}
this.answers = (yield this.prompt((0, questions_1.fromStudioProperties)(this._getParams())));
});
}
_populateOptions(availableOption) {
Object.keys(availableOption).forEach(optionName => {
this.option(optionName, availableOption[optionName]);
});
}
_getDestRoot() {
if (!this.options.dest) {
return this.destinationRoot();
}
if (path.isAbsolute(this.options.dest)) {
return this.options.dest;
}
return path.join(this.destinationRoot(), this.options.dest);
}
_getAvailableOptions() {
return cli_options_1.commonGenerationOptionsConfig;
}
_getParams() {
return [];
}
/**
* Additional dynamic prompts where questions depend on answers to initial prompt
*
* @param answers
* @private
*/
_additionalPrompts(answers) {
return __awaiter(this, void 0, void 0, function* () {
return answers;
});
}
}
exports.BaseGenerator = BaseGenerator;
function readProjectModel(modelFilePath) {
if (!modelFilePath || !fs.existsSync(modelFilePath)) {
throw new Error('Specified model file does not exist ' + modelFilePath);
}
return JSON.parse(fs.readFileSync(modelFilePath, "utf8"));
}
exports.readProjectModel = readProjectModel;
// TODO fix answers type
function refineAnswers(projectModel, generatorParams, answers) {
const refinedAnswers = {};
if (answers == null)
return refinedAnswers;
Object.keys(answers).forEach((key) => {
const prop = generatorParams.find(p => p.code === key);
// leave answer as is if it is not exist in props
if (prop == null) {
refinedAnswers[key] = answers[key];
return;
}
switch (prop.propertyType) {
case "ENTITY" /* ENTITY */:
refinedAnswers[key] = (0, cuba_model_utils_1.findEntity)(projectModel, answers[key]);
return;
case "VIEW" /* VIEW */:
refinedAnswers[key] = (0, cuba_model_utils_1.findView)(projectModel, answers[key]);
return;
case "REST_QUERY" /* REST_QUERY */:
refinedAnswers[key] = (0, cuba_model_utils_1.findQuery)(projectModel, answers[key]);
return;
case "REST_SERVICE_METHOD" /* REST_SERVICE_METHOD */:
refinedAnswers[key] = (0, cuba_model_utils_1.findServiceMethod)(projectModel, answers[key]);
return;
case "INTEGER" /* INTEGER */:
const value = answers[key];
if (!Number.isInteger(value))
throw new Error(`Question with code '${key}' has INTEGER type and can't contain '${value}' as answer`);
refinedAnswers[key] = value;
return;
default:
refinedAnswers[key] = answers[key];
}
});
return refinedAnswers;
}
exports.refineAnswers = refineAnswers;
/**
* Transform stream for remove .ejs extension from files. We are using this extension to improve code
* highlight in editor
*/
function createEjsRenameTransform() {
return through2.obj(function (file, enc, callback) {
file.basename = file.basename
.replace(/.ts.ejs$/, '.ts')
.replace(/.tsx.ejs$/, '.tsx');
this.push(file);
callback();
});
}
/**
* Prettier formatting transform stream for .ts and .tsx files
*/
function createFormatTransform() {
return through2.obj(function (file, enc, callback) {
if (file.path.endsWith('.ts') || file.path.endsWith('.tsx')) {
const contents = Buffer.from(file.contents).toString('utf8');
file.contents = Buffer.from(prettier.format(contents, { parser: "typescript" }));
}
this.push(file);
callback();
});
}
//# sourceMappingURL=base-generator.js.map