-
-
Notifications
You must be signed in to change notification settings - Fork 175
/
format.ts
121 lines (106 loc) · 3.6 KB
/
format.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/* eslint-disable @typescript-eslint/ban-ts-comment */
import { promises as fPromises } from 'fs';
import { Args } from '@oclif/core';
import Command from '../core/base';
import {
convertToJSON,
convertToYaml,
load,
retrieveFileFormat,
} from '../core/models/SpecificationFile';
import { SpecificationWrongFileFormat } from '../core/errors/specification-file';
import { cyan, green } from 'picocolors';
import { convertFormatFlags, fileFormat } from '../core/flags/format.flags';
export default class Convert extends Command {
static specFile: any;
static metricsMetadata: any = {};
static description =
'Convert asyncapi documents from any format to yaml, yml or JSON';
static flags = convertFormatFlags();
static args = {
'spec-file': Args.string({
description: 'spec path, url, or context-name',
required: false,
}),
};
async run() {
const { args, flags } = await this.parse(Convert);
const filePath = args['spec-file'];
const outputFileFormat = flags['format'] as fileFormat;
let convertedFile;
try {
this.specFile = await load(filePath);
// eslint-disable-next-line sonarjs/no-duplicate-string
this.metricsMetadata.to_version = flags['target-version'];
const ff = retrieveFileFormat(this.specFile.text());
const isSpecFileJson = ff === 'json';
const isSpecFileYaml = ff === 'yaml';
if (!isSpecFileJson && !isSpecFileYaml) {
throw new SpecificationWrongFileFormat(filePath);
}
convertedFile = this.handleConversion(
isSpecFileJson,
isSpecFileYaml,
outputFileFormat,
);
if (!convertedFile) {
return;
}
await this.handleOutput(flags.output, convertedFile, outputFileFormat);
} catch (err) {
this.error(err as Error);
}
}
private handleConversion(
isSpecFileJson: boolean,
isSpecFileYaml: boolean,
outputFileFormat: fileFormat,
): string | undefined {
const text = this.specFile?.text();
if (isSpecFileJson && text) {
if (outputFileFormat === 'json') {
throw new Error(`Your document is already a ${cyan('JSON')}`);
}
return convertToYaml(text);
}
if (isSpecFileYaml && text) {
if (outputFileFormat === 'yaml' || outputFileFormat === 'yml') {
throw new Error(`Your document is already a ${cyan('YAML')}`);
}
return convertToJSON(text);
}
}
private async handleOutput(
outputPath: string | undefined,
formattedFile: string,
outputFileFormat: fileFormat,
) {
if (outputPath) {
outputPath = this.removeExtensionFromOutputPath(outputPath);
const finalFileName = `${outputPath}.${outputFileFormat}`;
await fPromises.writeFile(finalFileName, formattedFile, {
encoding: 'utf8',
});
this.log(
`succesfully formatted to ${outputFileFormat} at ${green(finalFileName)} ✅`,
);
} else {
this.log(formattedFile);
this.log(`succesfully logged after formatting to ${outputFileFormat} ✅`);
}
}
private removeExtensionFromOutputPath(filename: string): string {
// Removes the extension from a filename if it is .json, .yaml, or .yml
// this is so that we can remove the provided extension name in the -o flag and
// apply our own extension name according to the content of the file
const validExtensions = ['json', 'yaml', 'yml'];
const parts = filename.split('.');
if (parts.length > 1) {
const extension = parts.pop()?.toLowerCase();
if (extension && validExtensions.includes(extension)) {
return parts.join('.');
}
}
return filename;
}
}