UNPKG

5.27 kBJavaScriptView Raw
1const Generator = require('yeoman-generator');
2const chalk = require('chalk');
3const config = require('../lib/config');
4const { validate, find } = require('../lib/schemas');
5
6module.exports = class EgGenerator extends Generator {
7 constructor (args, opts) {
8 super(args, opts);
9
10 this._configuration = null;
11 this.eg = this.env.eg;
12 this.argv = this.env.argv;
13 this.admin = require('../admin')({
14 baseUrl: this._getAdminClientBaseURL(),
15 verbose: this._getAdminClientVerboseFlag(),
16 headers: this.argv && this.argv.H ? this.processHeaders(this.argv.H) : null
17 });
18 }
19
20 configureCommand (configuration) {
21 const builder = configuration.builder;
22 configuration.builder = yargs => {
23 return this._wrapConfig(builder(yargs));
24 };
25
26 configuration.handler = argv => {
27 this.env.argv = argv;
28
29 const command = this.options.env.commandAliases[0][argv._[0]];
30 const subCommand = this.options.env.commandAliases[1][command][argv._[1]];
31
32 this.env.run(`express-gateway:${command}:${subCommand}`);
33 };
34
35 this._configuration = configuration;
36 }
37
38 stdout (...args) {
39 // eslint-disable-next-line no-console
40 console.log.apply(console, args);
41 }
42
43 createSubCommand (name) {
44 const generatorName = `${this.constructor.namespace}:${name}`;
45 return this.env.create(generatorName)._configuration;
46 }
47
48 // configuration defaults
49 _wrapConfig (yargs) {
50 return yargs
51 .boolean(['no-color', 'q', 'v'])
52 .string(['H'])
53 .describe('no-color', 'Disable color in prompts')
54 .alias('q', 'quiet')
55 .describe('q', 'Only show major pieces of output')
56 .describe('H', 'Header to send with each request to Express Gateway Admin API KEY:VALUE format')
57 .alias('v', 'verbose')
58 .describe('v', 'Verbose output, will show request to Admin API')
59 .group(['no-color', 'q'], 'Options:');
60 }
61
62 _getAdminClientBaseURL () {
63 const gatewayConfig = config.gatewayConfig;
64 const systemConfig = config.systemConfig;
65
66 let baseURL = 'http://localhost:9876'; // fallback default
67
68 if (process.env.EG_ADMIN_URL) {
69 baseURL = process.env.EG_ADMIN_URL;
70 } else if (systemConfig && systemConfig.cli && systemConfig.cli.url) {
71 baseURL = systemConfig.cli.url;
72 } else if (gatewayConfig && gatewayConfig.admin) {
73 const adminConfig = gatewayConfig.admin;
74 const host = adminConfig.host || adminConfig.hostname || 'localhost';
75 const port = adminConfig.port || 9876;
76
77 baseURL = `http://${host}:${port}`;
78 }
79
80 /*
81 This bad hack is required because of the weird way superagent is managing urls. Hopefully this is not
82 going to be here forever — we'll replace the client with Axios hopefully.
83 Ref: https://github.com/ExpressGateway/express-gateway/issues/672
84 */
85
86 if (baseURL.endsWith('/')) {
87 baseURL = baseURL.substr(0, baseURL.length - 1);
88 }
89
90 return baseURL;
91 }
92
93 _getAdminClientVerboseFlag () {
94 let verbose = false; // default
95
96 if (this.argv && this.argv.v) {
97 verbose = this.argv.v;
98 } else if (config.systemConfig && config.systemConfig.cli) {
99 verbose = !!config.systemConfig.cli.verbose;
100 }
101
102 return verbose;
103 }
104
105 processHeaders (headers) {
106 const ArrayHeaders = Array.isArray(headers) ? headers : [headers];
107
108 return ArrayHeaders.reduce((prev, header) => {
109 const [headerName, headerValue] = header.split(/:(.+)/);
110
111 if (headerValue) {
112 prev[headerName] = headerValue;
113 }
114
115 return prev;
116 }, {});
117 }
118
119 _promptAndValidate (object, schema, { skipPrompt = false } = {}) {
120 let questions = [];
121
122 if (!skipPrompt) {
123 let shouldPrompt = false;
124 const missingProperties = [];
125 const modelSchema = find(schema).schema;
126
127 Object.keys(modelSchema.properties).forEach(prop => {
128 const descriptor = modelSchema.properties[prop];
129 if (!object[prop]) {
130 if (!shouldPrompt && modelSchema.required && modelSchema.required.includes(prop)) {
131 shouldPrompt = true;
132 }
133
134 missingProperties.push({ name: prop, descriptor });
135 }
136 });
137
138 if (shouldPrompt) {
139 questions = missingProperties.map(p => {
140 const required = modelSchema.required.includes(p.name)
141 ? ' [required]'
142 : '';
143
144 return {
145 name: p.name,
146 message: `Enter ${chalk.yellow(p.name)}${chalk.green(required)}:`,
147 default: object[p.name] || p.descriptor.default,
148 validate: input => !modelSchema.required.includes(p.name) ||
149 (!!input && modelSchema.required.includes(p.name)),
150 filter: input => input === '' && !modelSchema.required.includes(p.name) ? undefined : input
151
152 };
153 });
154 }
155 }
156
157 const validateData = data => {
158 const { isValid, error } = validate(schema, data);
159 if (!isValid) {
160 this.log.error(error);
161 if (!skipPrompt) {
162 return this.prompt(questions).then(validateData);
163 }
164 throw new Error(error);
165 }
166 return data;
167 };
168
169 return this.prompt(questions).then((answers) => {
170 Object.assign(object, answers);
171 return validateData(object);
172 });
173 }
174};