Skip to content

Commit ca27e09

Browse files
author
Fuss Florian (uid10804)
committed
feat(cli): add userfriendly output for create-stack or update-stack
1 parent bcd2eaf commit ca27e09

File tree

3 files changed

+173
-2
lines changed

3 files changed

+173
-2
lines changed

packages/cli/src/actions/helpers.ts

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import * as path from 'path';
33
const util = require('util');
44
const exec = util.promisify(require('child_process').exec);
55
import figlet from 'figlet';
6+
import chalk from 'chalk';
7+
import cli from 'cli-ux';
68
export class Helpers {
79
static validateFile(filePath: string): string {
810
if (!path.isAbsolute(filePath)) {
@@ -92,6 +94,22 @@ export class Helpers {
9294
}
9395
}
9496

97+
static async executeChildProcess2(
98+
command: string,
99+
options: {},
100+
stdout = true
101+
): Promise<string> {
102+
try {
103+
const childProcess = await exec(command, options);
104+
if (stdout) {
105+
return Promise.resolve(childProcess.stdout);
106+
}
107+
return Promise.reject(childProcess.stderr);
108+
} catch (err) {
109+
throw new Error(err);
110+
}
111+
}
112+
95113
static async copyFiles(source: string, destination: string) {
96114
try {
97115
if (!fs.existsSync(source)) {
@@ -193,4 +211,127 @@ export class Helpers {
193211
}
194212
return true;
195213
}
214+
215+
static createCLIOutput(
216+
slsinfo: string,
217+
apiAuth: boolean,
218+
enableSwagger: boolean
219+
) {
220+
const rows = JSON.stringify(slsinfo).split('\\n') as any[];
221+
const createKeyValues = rows.map((x, i, rows) => {
222+
if (x.startsWith(' ANY -')) {
223+
x = {
224+
name: x.split(' - ')[0],
225+
value: x.split(' - ')[1],
226+
};
227+
} else {
228+
x = {
229+
name: x.split(':')[0],
230+
value: x.split(':')[1],
231+
};
232+
}
233+
return x;
234+
});
235+
236+
const outputJson = createKeyValues
237+
.map((x, i, rows) => {
238+
if (rows[i + 1] && rows[i + 1].name.startsWith(' ')) {
239+
x.value = rows[i + 1].value;
240+
}
241+
if (x && x.name.startsWith(' ')) {
242+
return null;
243+
}
244+
if (x && x.name) {
245+
x.name = x.name.replace(/\s/g, '');
246+
}
247+
if (x && x.value) {
248+
x.value = x.value.replace(/\s/g, '');
249+
}
250+
251+
return x;
252+
})
253+
.filter(
254+
(item) =>
255+
item != null &&
256+
item.hasOwnProperty('value') &&
257+
item.value != undefined
258+
)
259+
.reduce(
260+
(obj, item) => Object.assign(obj, { [item.name]: item.value }),
261+
{}
262+
);
263+
console.log();
264+
console.log(
265+
'The Api ' + outputJson.service + ' has been successfully deployed'
266+
);
267+
console.log();
268+
console.log('Further details:');
269+
cli.table(
270+
[
271+
{
272+
text: `${chalk.blueBright('Stage')}`,
273+
link: outputJson.stage,
274+
},
275+
{
276+
text: `${chalk.blueBright('Region')}`,
277+
link: outputJson.region,
278+
},
279+
{
280+
text: `${chalk.blueBright('Cloudformation Stack')}`,
281+
link: outputJson.stack,
282+
},
283+
],
284+
{ text: { minWidth: 30 }, link: { minWidth: 20 } },
285+
{ 'no-header': true }
286+
);
287+
288+
console.log();
289+
console.log();
290+
if (apiAuth) {
291+
console.log(
292+
`${chalk.green(
293+
'Please use the following apiKey (x-api-key) to authenticate:'
294+
)} ` + outputJson.apikeys
295+
);
296+
}
297+
console.log();
298+
console.log();
299+
if (enableSwagger) {
300+
cli.table(
301+
[
302+
{
303+
text: `${chalk.blueBright('Swagger UI')}`,
304+
link: outputJson.endpoints + '/ui',
305+
},
306+
{
307+
text: `${chalk.blueBright('GraphiQL')}`,
308+
link: outputJson.endpoints + '/graphql',
309+
},
310+
{
311+
text: `${chalk.blueBright('Swagger Specification')}`,
312+
link: outputJson.endpoints + '/api-spec',
313+
},
314+
{
315+
text: `${chalk.blueBright('API Routes')}`,
316+
link: outputJson.endpoints + '/api/{routes}',
317+
},
318+
],
319+
{ text: { minWidth: 30 }, link: { minWidth: 20 } },
320+
{ 'no-header': true }
321+
);
322+
} else {
323+
cli.table(
324+
[
325+
{
326+
text: `${chalk.blueBright('API Routes')}`,
327+
link: outputJson.endpoints + '/api/{routes}',
328+
},
329+
],
330+
{ text: { minWidth: 30 }, link: { minWidth: 20 } },
331+
{ 'no-header': true }
332+
);
333+
}
334+
console.log();
335+
console.log();
336+
}
196337
}

packages/cli/src/commands/create-stack.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,15 +207,29 @@ export class CreateStackCommand extends Command {
207207
},
208208
},
209209
]);
210+
let slsinfo = '';
210211
try {
211212
await tasks.run();
212-
await Helpers.executeChildProcess(
213+
slsinfo = await Helpers.executeChildProcess2(
213214
'node_modules/serverless/bin/serverless info',
214215
{ cwd: stackFolder }
215216
);
216217
} catch (error) {
217218
this.error(`${chalk.red(error.message)}`);
218219
}
220+
try {
221+
const appConfig = JSON.parse(
222+
fs.readFileSync(stackFolder + '/config/appconfig.json', 'UTF-8')
223+
) as AppConfig;
224+
Helpers.createCLIOutput(
225+
slsinfo,
226+
appConfig.enableApiKeyAuth,
227+
appConfig.enableSwagger
228+
);
229+
} catch (error) {
230+
this.log(`${chalk.red(error.message)}`);
231+
this.log(slsinfo);
232+
}
219233
}
220234

221235
private async getRegion() {

packages/cli/src/commands/update-stack.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { Helpers } from '../actions/helpers';
66
import { AWSActions } from '../actions/aws-actions';
77
import chalk from 'chalk';
88
import cli from 'cli-ux';
9+
import { AppConfig } from 'json-serverless-lib';
910

1011
export class UpdateStackCommand extends Command {
1112
static description = 'describe the command here';
@@ -46,6 +47,7 @@ export class UpdateStackCommand extends Command {
4647

4748
async run() {
4849
const logo = await Helpers.generateLogo('json-serverless');
50+
this.log();
4951
this.log(`${chalk.blueBright(logo)}`);
5052
this.log();
5153
const { flags } = this.parse(UpdateStackCommand);
@@ -168,14 +170,28 @@ export class UpdateStackCommand extends Command {
168170
},
169171
},
170172
]);
173+
let slsinfo = '';
171174
try {
172175
await tasks.run();
173-
await Helpers.executeChildProcess(
176+
slsinfo = await Helpers.executeChildProcess2(
174177
'node_modules/serverless/bin/serverless info',
175178
{ cwd: stackFolder }
176179
);
177180
} catch (error) {
178181
this.error(`${chalk.red(error.message)}`);
179182
}
183+
try {
184+
const appConfig = JSON.parse(
185+
fs.readFileSync(stackFolder + '/config/appconfig.json', 'UTF-8')
186+
) as AppConfig;
187+
Helpers.createCLIOutput(
188+
slsinfo,
189+
appConfig.enableApiKeyAuth,
190+
appConfig.enableSwagger
191+
);
192+
} catch (error) {
193+
this.log(`${chalk.red(error.message)}`);
194+
this.log(slsinfo);
195+
}
180196
}
181197
}

0 commit comments

Comments
 (0)