Skip to content

Commit df62a63

Browse files
sekiknasyncapi-botSouvikns
authored
fix: generate optimized output corresponding to the input format (#1908)
Co-authored-by: Kengo Seki <sekikn@apache.org> Co-authored-by: asyncapi-bot <info@asyncapi.io> Co-authored-by: Souvik De <souvikde.ns@gmail.com>
1 parent ffb0f49 commit df62a63

File tree

4 files changed

+174
-8
lines changed

4 files changed

+174
-8
lines changed

.changeset/1908.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
'@asyncapi/cli': patch
3+
---
4+
5+
fix: generate optimized output corresponding to the input format
6+
7+
- c756765: fix: generate optimized output corresponding to the input format
8+
9+

src/apps/cli/commands/optimize.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Args } from '@oclif/core';
22
import { Optimizer, Output, Report, ReportElement } from '@asyncapi/optimizer';
33
import Command from '@cli/internal/base';
44
import { ValidationError } from '@errors/validation-error';
5-
import { load } from '@models/SpecificationFile';
5+
import { load, retrieveFileFormat } from '@models/SpecificationFile';
66
import * as inquirer from 'inquirer';
77
import chalk from 'chalk';
88
import { promises } from 'fs';
@@ -127,7 +127,8 @@ export default class Optimize extends Command {
127127
}
128128

129129
try {
130-
const optimizedDocument = optimizer.getOptimizedDocument({
130+
const fileFormat = retrieveFileFormat(this.specFile.text());
131+
let optimizedDocument = optimizer.getOptimizedDocument({
131132
rules: {
132133
moveDuplicatesToComponents: this.selectedOptimizations.includes(
133134
Optimizations.MOVE_DUPLICATES_TO_COMPONENTS,
@@ -147,8 +148,11 @@ export default class Optimize extends Command {
147148
DisableOptimizations.SCHEMA,
148149
),
149150
},
150-
output: Output.YAML,
151+
output: fileFormat === 'json' ? Output.JSON : Output.YAML,
151152
});
153+
if (fileFormat === 'json') {
154+
optimizedDocument = JSON.stringify((JSON.parse(optimizedDocument)), null, 2);
155+
}
152156

153157
this.collectMetricsData(report);
154158

@@ -159,7 +163,7 @@ export default class Optimize extends Command {
159163
const pos = specPath.lastIndexOf('.');
160164
newPath = `${specPath.substring(0, pos)}_optimized.${specPath.substring(pos + 1)}`;
161165
} else {
162-
newPath = 'optimized-asyncapi.yaml';
166+
newPath = `optimized-asyncapi.${fileFormat}`;
163167
}
164168

165169
switch (this.outputMethod) {
@@ -174,7 +178,7 @@ export default class Optimize extends Command {
174178
);
175179
break;
176180
case Outputs.OVERWRITE:
177-
await writeFile(specPath ?? 'asyncapi.yaml', optimizedDocument, {
181+
await writeFile(specPath ?? `asyncapi.${fileFormat}`, optimizedDocument, {
178182
encoding: 'utf8',
179183
});
180184
this.log(
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
{
2+
"asyncapi": "2.0.0",
3+
"info": {
4+
"title": "Streetlights API",
5+
"version": "1.0.0"
6+
},
7+
"channels": {
8+
"smartylighting/event/{streetlightId}/lighting/measured": {
9+
"parameters": {
10+
"streetlightId": {
11+
"schema": {
12+
"type": "string"
13+
}
14+
}
15+
},
16+
"subscribe": {
17+
"operationId": "receiveLightMeasurement",
18+
"traits": [
19+
{
20+
"bindings": {
21+
"kafka": {
22+
"clientId": "my-app-id"
23+
}
24+
}
25+
}
26+
],
27+
"message": {
28+
"name": "lightMeasured",
29+
"title": "Light measured",
30+
"contentType": "application/json",
31+
"traits": [
32+
{
33+
"headers": {
34+
"type": "object",
35+
"properties": {
36+
"my-app-header": {
37+
"type": "integer",
38+
"minimum": 0,
39+
"maximum": 100
40+
}
41+
}
42+
}
43+
}
44+
],
45+
"payload": {
46+
"type": "object",
47+
"properties": {
48+
"lumens": {
49+
"type": "integer",
50+
"minimum": 0
51+
},
52+
"sentAt": {
53+
"type": "string",
54+
"format": "date-time"
55+
}
56+
}
57+
}
58+
}
59+
}
60+
},
61+
"smartylighting/action/{streetlightId}/turn/on": {
62+
"parameters": {
63+
"streetlightId": {
64+
"schema": {
65+
"type": "string"
66+
}
67+
}
68+
},
69+
"publish": {
70+
"operationId": "turnOn",
71+
"traits": [
72+
{
73+
"bindings": {
74+
"kafka": {
75+
"clientId": "my-app-id"
76+
}
77+
}
78+
}
79+
],
80+
"message": {
81+
"name": "turnOnOff",
82+
"title": "Turn on/off",
83+
"traits": [
84+
{
85+
"headers": {
86+
"type": "object",
87+
"properties": {
88+
"my-app-header": {
89+
"type": "integer",
90+
"minimum": 0,
91+
"maximum": 100
92+
}
93+
}
94+
}
95+
}
96+
],
97+
"payload": {
98+
"type": "object",
99+
"properties": {
100+
"sentAt": {
101+
"$ref": "#/components/schemas/sentAt"
102+
}
103+
}
104+
}
105+
}
106+
}
107+
}
108+
},
109+
"components": {
110+
"messages": {
111+
"unusedMessage": {
112+
"name": "unusedMessage",
113+
"title": "This message is not used in any channel."
114+
}
115+
},
116+
"schemas": {
117+
"sentAt": {
118+
"type": "string",
119+
"format": "date-time"
120+
}
121+
}
122+
}
123+
}

test/integration/optimize.test.ts

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
import path from 'path';
22
import { test } from '@oclif/test';
33
import TestHelper, { createMockServer, stopMockServer } from '../helpers';
4+
import fs from 'fs-extra';
45
import inquirer from 'inquirer';
56
import {Optimizations, Outputs} from '../../src/apps/cli/commands/optimize';
67
import { expect } from '@oclif/test';
78

89
const testHelper = new TestHelper();
910
const optimizedFilePath = './test/fixtures/specification.yml';
10-
const unoptimizedFile = './test/fixtures/dummyspec/unoptimizedSpec.yml';
11+
const unoptimizedYamlFile = './test/fixtures/dummyspec/unoptimizedSpec.yml';
12+
const unoptimizedJsonFile = './test/fixtures/dummyspec/unoptimizedSpec.json';
1113
const invalidFile = './test/fixtures/specification-invalid.yml';
1214
const asyncapiv3 = './test/fixtures/specification-v3.yml';
1315

@@ -130,12 +132,40 @@ describe('optimize', () => {
130132
test
131133
.stderr()
132134
.stdout()
133-
.command(['optimize', unoptimizedFile, '--no-tty'])
135+
.command(['optimize', unoptimizedYamlFile, '--no-tty'])
134136
.it('process without going to interactive mode.', (ctx, done) => {
135137
expect(ctx.stdout).to.contain('asyncapi: 2.0.0');
136138
expect(ctx.stderr).to.equal('');
137139
done();
138140
});
141+
142+
test
143+
.stderr()
144+
.stdout()
145+
.command(['optimize', unoptimizedYamlFile, '--no-tty', '-o', 'new-file'])
146+
.it('generate YAML output against YAML input.', (ctx, done) => {
147+
const pos = unoptimizedYamlFile.lastIndexOf('.');
148+
const optimizedFile = `${unoptimizedYamlFile.substring(0, pos)}_optimized.${unoptimizedYamlFile.substring(pos + 1)}`;
149+
expect(ctx.stdout).to.contain('✅ Success! Your optimized file has been created at ');
150+
expect(ctx.stderr).to.equal('');
151+
expect(fs.readFileSync(optimizedFile, 'utf8')).to.contain('asyncapi: 2.0.0');
152+
fs.unlinkSync(optimizedFile);
153+
done();
154+
});
155+
156+
test
157+
.stderr()
158+
.stdout()
159+
.command(['optimize', unoptimizedJsonFile, '--no-tty', '-o', 'new-file'])
160+
.it('generate JSON output against JSON input.', (ctx, done) => {
161+
const pos = unoptimizedJsonFile.lastIndexOf('.');
162+
const optimizedFile = `${unoptimizedJsonFile.substring(0, pos)}_optimized.${unoptimizedJsonFile.substring(pos + 1)}`;
163+
expect(ctx.stdout).to.contain('✅ Success! Your optimized file has been created at ');
164+
expect(ctx.stderr).to.equal('');
165+
expect(fs.readFileSync(optimizedFile, 'utf8')).to.contain('"asyncapi": "2.0.0"');
166+
fs.unlinkSync(optimizedFile);
167+
done();
168+
});
139169
});
140170

141171
describe('interactive terminal', () => {
@@ -145,7 +175,7 @@ describe('optimize', () => {
145175
})
146176
.stderr()
147177
.stdout()
148-
.command(['optimize', unoptimizedFile])
178+
.command(['optimize', unoptimizedYamlFile])
149179
.it('interactive terminal, only remove components and outputs to terminal', (ctx, done) => {
150180
expect(ctx.stdout).to.contain('asyncapi: 2.0.0');
151181
expect(ctx.stderr).to.equal('');

0 commit comments

Comments
 (0)