@axinom/mosaic-cli 0.18.4 → 0.18.5-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/msg-codegen/codegen.d.ts +4 -4
- package/dist/commands/msg-codegen/codegen.js +66 -229
- package/dist/commands/msg-codegen/codegen.js.map +1 -1
- package/dist/commands/msg-codegen/presets.d.ts +21 -0
- package/dist/commands/msg-codegen/presets.js +119 -0
- package/dist/commands/msg-codegen/presets.js.map +1 -0
- package/dist/commands/msg-codegen/utils.d.ts +56 -0
- package/dist/commands/msg-codegen/utils.js +220 -0
- package/dist/commands/msg-codegen/utils.js.map +1 -0
- package/dist/commands/msg-diff/msg-diff.d.ts +3 -3
- package/dist/commands/msg-diff/msg-diff.js +28 -15
- package/dist/commands/msg-diff/msg-diff.js.map +1 -1
- package/package.json +7 -7
- package/src/commands/msg-codegen/codegen.ts +84 -248
- package/src/commands/msg-codegen/presets.ts +138 -0
- package/src/commands/msg-codegen/utils.ts +258 -0
- package/src/commands/msg-diff/msg-diff.spec.ts +44 -27
- package/src/commands/msg-diff/msg-diff.ts +48 -22
- package/src/commands/msg-diff/test-resources/0/1-asyncapi.yml +2 -2
- package/src/commands/msg-diff/test-resources/0/2-asyncapi.yml +2 -2
- package/src/commands/msg-diff/test-resources/1/1-asyncapi.yml +1 -1
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ConstrainedArrayModel,
|
|
3
|
+
ConstrainedMetaModel,
|
|
4
|
+
ConstrainedObjectPropertyModel,
|
|
5
|
+
ConstrainedUnionModel,
|
|
6
|
+
FormatHelpers,
|
|
7
|
+
} from '@asyncapi/modelina';
|
|
8
|
+
import {
|
|
9
|
+
AsyncAPIDocumentInterface,
|
|
10
|
+
ChannelInterface,
|
|
11
|
+
MessageInterface,
|
|
12
|
+
SpecTypesV2,
|
|
13
|
+
} from '@asyncapi/parser';
|
|
14
|
+
import * as fs from 'fs';
|
|
15
|
+
import * as path from 'path';
|
|
16
|
+
|
|
17
|
+
export function getRelativeDir(from: string, to: string): string {
|
|
18
|
+
return fs.statSync(to).isFile()
|
|
19
|
+
? path.dirname(path.relative(from, to))
|
|
20
|
+
: path.relative(from, to);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function getMessageTitle(message: MessageInterface): string {
|
|
24
|
+
const messageTitle =
|
|
25
|
+
message.payload()?.title() ??
|
|
26
|
+
message.extensions().get('x-parser-message-name')?.value() ??
|
|
27
|
+
message.payload()?.extensions().get('x-parser-schema-id')?.value();
|
|
28
|
+
|
|
29
|
+
if (messageTitle === undefined) {
|
|
30
|
+
throw new Error('Unable to determine message title.');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return messageTitle;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Retrieve Service Title from AsyncAPI document.
|
|
38
|
+
* As Title returned value set in info.title property of document.
|
|
39
|
+
* @param asyncAPIDocument - AsyncAPI document.
|
|
40
|
+
*/
|
|
41
|
+
export function getServiceTitle(
|
|
42
|
+
asyncAPIDocument: AsyncAPIDocumentInterface,
|
|
43
|
+
): string {
|
|
44
|
+
return asyncAPIDocument.info().title();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Retrieve Service Id from AsyncAPI document.
|
|
49
|
+
* As Id returned value set in extension property `x-service-id`.
|
|
50
|
+
* If extension property is not set - returned Service Title in lower-kebab-case.
|
|
51
|
+
* @param asyncAPIDocument - AsyncAPI document.
|
|
52
|
+
*/
|
|
53
|
+
export function getServiceId(
|
|
54
|
+
asyncAPIDocument: AsyncAPIDocumentInterface,
|
|
55
|
+
): string {
|
|
56
|
+
const serviceId =
|
|
57
|
+
asyncAPIDocument.extensions().get('x-service-id')?.value() ??
|
|
58
|
+
asyncAPIDocument.info().title();
|
|
59
|
+
|
|
60
|
+
return FormatHelpers.toParamCase(serviceId);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Retrieves whether a channel is for subscribing or publishing.
|
|
65
|
+
* Currently, only channels with a single operation are supported.
|
|
66
|
+
* @param channel - Channel object.
|
|
67
|
+
*/
|
|
68
|
+
export function getChannelAction(
|
|
69
|
+
channel: ChannelInterface,
|
|
70
|
+
): 'subscribe' | 'publish' {
|
|
71
|
+
const operations = channel.operations();
|
|
72
|
+
if (operations.length === 0) {
|
|
73
|
+
throw new Error('Channel has no operations');
|
|
74
|
+
}
|
|
75
|
+
if (operations.length > 1) {
|
|
76
|
+
throw new Error('Channel has more than one operation');
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const action = operations[0].action();
|
|
80
|
+
|
|
81
|
+
if (action !== 'subscribe' && action !== 'publish') {
|
|
82
|
+
throw new Error(`Channel has unsupported action: ${action}`);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return action;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Retrieves the payload model name for a channel.
|
|
90
|
+
* Currently, only channels with a single message are supported.
|
|
91
|
+
* @param channel - Channel object.
|
|
92
|
+
*/
|
|
93
|
+
export function getPayloadTitle(channel: ChannelInterface): string | undefined {
|
|
94
|
+
const messages = channel.messages();
|
|
95
|
+
if (messages.length === 0) {
|
|
96
|
+
throw new Error('Channel has no messages');
|
|
97
|
+
}
|
|
98
|
+
if (messages.length > 1) {
|
|
99
|
+
throw new Error('Channel has more than one message');
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return messages[0].payload()?.title();
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Converts a path into a POSIX path by replacing current path separator with `/`.
|
|
107
|
+
* @param p - Path to convert.
|
|
108
|
+
*/
|
|
109
|
+
export function toPosixPath(p: string): string {
|
|
110
|
+
return path.posix.join(...p.split(path.sep));
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Generating the path prefix for model.
|
|
115
|
+
* model name ends with "command" - prefix "commands"
|
|
116
|
+
* model name ends with "event" - prefix "events"
|
|
117
|
+
* default prefix "types"
|
|
118
|
+
* @param modelName - name of the model, defined in json schema, or AsyncAPI document
|
|
119
|
+
*/
|
|
120
|
+
export function getModelPathPrefix(modelName: string): string {
|
|
121
|
+
return modelName
|
|
122
|
+
? modelName.toLowerCase().endsWith('command')
|
|
123
|
+
? 'commands'
|
|
124
|
+
: modelName.toLowerCase().endsWith('event')
|
|
125
|
+
? 'events'
|
|
126
|
+
: 'types'
|
|
127
|
+
: 'types';
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export function removeXParserProperties(
|
|
131
|
+
obj: SpecTypesV2.AsyncAPISchemaObject,
|
|
132
|
+
): SpecTypesV2.AsyncAPISchemaObject {
|
|
133
|
+
if (Array.isArray(obj)) {
|
|
134
|
+
return obj.map(removeXParserProperties);
|
|
135
|
+
} else if (obj !== null && typeof obj === 'object') {
|
|
136
|
+
const newObj = {};
|
|
137
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
138
|
+
if (!key.startsWith('x-parser-')) {
|
|
139
|
+
newObj[key] = removeXParserProperties(value);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return newObj;
|
|
143
|
+
} else {
|
|
144
|
+
return obj;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Replaces the `any` type in a type string.
|
|
150
|
+
*/
|
|
151
|
+
export function replaceAnyType(type: string, replacement: string): string {
|
|
152
|
+
const pattern = /\b(any)\b/g;
|
|
153
|
+
return type.replace(pattern, replacement);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export function indexOfNullPlain(
|
|
157
|
+
model: ConstrainedObjectPropertyModel,
|
|
158
|
+
): number {
|
|
159
|
+
if (
|
|
160
|
+
model.property instanceof ConstrainedMetaModel &&
|
|
161
|
+
model.property.originalInput?.nullable === true
|
|
162
|
+
) {
|
|
163
|
+
return 1; // Append null to the end of the type.
|
|
164
|
+
}
|
|
165
|
+
return -1;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export function indexOfNullUnion(
|
|
169
|
+
model: ConstrainedObjectPropertyModel,
|
|
170
|
+
): number {
|
|
171
|
+
if (model.property instanceof ConstrainedUnionModel) {
|
|
172
|
+
return model.property.originalInput?.type?.indexOf('null') ?? -1;
|
|
173
|
+
}
|
|
174
|
+
return -1;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export function indexOfNullOneOf(
|
|
178
|
+
model: ConstrainedObjectPropertyModel,
|
|
179
|
+
): number {
|
|
180
|
+
if (model.property instanceof ConstrainedUnionModel) {
|
|
181
|
+
const types = model.property.originalInput?.oneOf?.map((m) => m.type);
|
|
182
|
+
return types?.indexOf('null') ?? -1;
|
|
183
|
+
}
|
|
184
|
+
return -1;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export function indexOfNullArrayPlain(
|
|
188
|
+
model: ConstrainedObjectPropertyModel,
|
|
189
|
+
): number {
|
|
190
|
+
if (
|
|
191
|
+
model.property instanceof ConstrainedArrayModel &&
|
|
192
|
+
model.property.originalInput?.items?.nullable === true
|
|
193
|
+
) {
|
|
194
|
+
return 1; // Append null to the end of the type.
|
|
195
|
+
}
|
|
196
|
+
return -1;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export function indexOfNullArrayUnion(
|
|
200
|
+
model: ConstrainedObjectPropertyModel,
|
|
201
|
+
): number {
|
|
202
|
+
if (model.property instanceof ConstrainedArrayModel) {
|
|
203
|
+
return model.property.originalInput?.items?.type?.indexOf('null') ?? -1;
|
|
204
|
+
}
|
|
205
|
+
return -1;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
export function indexOfNullArrayOneOf(
|
|
209
|
+
model: ConstrainedObjectPropertyModel,
|
|
210
|
+
): number {
|
|
211
|
+
if (model.property instanceof ConstrainedArrayModel) {
|
|
212
|
+
const types = model.property.originalInput?.items?.oneOf?.map(
|
|
213
|
+
(m) => m.type,
|
|
214
|
+
);
|
|
215
|
+
return types?.indexOf('null') ?? -1;
|
|
216
|
+
}
|
|
217
|
+
return -1;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export function indexOfNullObjectProperty(
|
|
221
|
+
model: ConstrainedObjectPropertyModel,
|
|
222
|
+
): number {
|
|
223
|
+
if (indexOfNullPlain(model) > -1) {
|
|
224
|
+
return indexOfNullPlain(model);
|
|
225
|
+
}
|
|
226
|
+
if (indexOfNullUnion(model) > -1) {
|
|
227
|
+
return indexOfNullUnion(model);
|
|
228
|
+
}
|
|
229
|
+
if (indexOfNullOneOf(model) > -1) {
|
|
230
|
+
return indexOfNullOneOf(model);
|
|
231
|
+
}
|
|
232
|
+
return -1;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
export function indexOfNullArrayProperty(
|
|
236
|
+
model: ConstrainedObjectPropertyModel,
|
|
237
|
+
): number {
|
|
238
|
+
if (indexOfNullArrayPlain(model) > -1) {
|
|
239
|
+
return indexOfNullArrayPlain(model);
|
|
240
|
+
}
|
|
241
|
+
if (indexOfNullArrayUnion(model) > -1) {
|
|
242
|
+
return indexOfNullArrayUnion(model);
|
|
243
|
+
}
|
|
244
|
+
if (indexOfNullArrayOneOf(model) > -1) {
|
|
245
|
+
return indexOfNullArrayOneOf(model);
|
|
246
|
+
}
|
|
247
|
+
return -1;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
export function ensureNullable(type: string, index: number): string {
|
|
251
|
+
const types = type.split('|').map((t) => t.trim());
|
|
252
|
+
if (types[index] === 'any') {
|
|
253
|
+
types[index] = replaceAnyType(types[index], 'null');
|
|
254
|
+
} else {
|
|
255
|
+
types.splice(index, 0, 'null');
|
|
256
|
+
}
|
|
257
|
+
return types.join(' | ');
|
|
258
|
+
}
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
AsyncAPIDocumentInterface,
|
|
3
|
+
Diagnostic,
|
|
4
|
+
fromFile,
|
|
5
|
+
Parser,
|
|
6
|
+
} from '@asyncapi/parser';
|
|
2
7
|
import * as fs from 'fs';
|
|
3
8
|
import 'jest-extended';
|
|
4
9
|
import { MessageDiffOptions } from './message-diff-options';
|
|
@@ -23,16 +28,28 @@ describe('sanity', () => {
|
|
|
23
28
|
const loadDocument = async (
|
|
24
29
|
file: string,
|
|
25
30
|
editJson?: (any) => void,
|
|
26
|
-
): Promise<
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
31
|
+
): Promise<AsyncAPIDocumentInterface> => {
|
|
32
|
+
let document: AsyncAPIDocumentInterface | undefined;
|
|
33
|
+
let diagnostics: Diagnostic[] | undefined;
|
|
34
|
+
const parser = new Parser();
|
|
35
|
+
({ document, diagnostics } = await fromFile(parser, file).parse());
|
|
36
|
+
if (document === undefined) {
|
|
37
|
+
throw new Error(`Failed to parse ${file}: ${diagnostics}`);
|
|
38
|
+
}
|
|
39
|
+
|
|
30
40
|
if (!editJson) {
|
|
31
|
-
return
|
|
41
|
+
return document;
|
|
32
42
|
}
|
|
33
|
-
const json =
|
|
43
|
+
const json = document.json();
|
|
34
44
|
editJson(json);
|
|
35
|
-
|
|
45
|
+
|
|
46
|
+
({ document, diagnostics } = await parser.parse(JSON.stringify(json)));
|
|
47
|
+
|
|
48
|
+
if (document === undefined) {
|
|
49
|
+
throw new Error(`Failed to parse edited JSON: ${diagnostics}`);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return document;
|
|
36
53
|
};
|
|
37
54
|
|
|
38
55
|
beforeEach(async () => {
|
|
@@ -127,7 +144,7 @@ describe('sanity', () => {
|
|
|
127
144
|
`${resources}/0/1-asyncapi.yml`,
|
|
128
145
|
(json) => {
|
|
129
146
|
// remove an event
|
|
130
|
-
delete json.channels['evt-channel']
|
|
147
|
+
delete json.channels['evt-channel']?.publish?.message;
|
|
131
148
|
},
|
|
132
149
|
);
|
|
133
150
|
|
|
@@ -246,8 +263,8 @@ describe('sanity', () => {
|
|
|
246
263
|
|
|
247
264
|
// Act
|
|
248
265
|
const result = await msgDiff.payloadDiff(
|
|
249
|
-
document1.channels()
|
|
250
|
-
document2.channels()
|
|
266
|
+
document1.channels().get('evt-channel'),
|
|
267
|
+
document2.channels().get('evt-channel'),
|
|
251
268
|
);
|
|
252
269
|
|
|
253
270
|
// Assert
|
|
@@ -272,8 +289,8 @@ describe('sanity', () => {
|
|
|
272
289
|
|
|
273
290
|
// Act
|
|
274
291
|
const result = await msgDiff.payloadDiff(
|
|
275
|
-
document1.channels()
|
|
276
|
-
document2.channels()
|
|
292
|
+
document1.channels().get('evt-channel'),
|
|
293
|
+
document2.channels().get('evt-channel'),
|
|
277
294
|
);
|
|
278
295
|
|
|
279
296
|
// Assert
|
|
@@ -291,11 +308,11 @@ describe('sanity', () => {
|
|
|
291
308
|
},
|
|
292
309
|
);
|
|
293
310
|
|
|
311
|
+
const channel1 = document1.channels().get('evt-channel');
|
|
312
|
+
const channel2 = document2.channels().get('evt-channel');
|
|
313
|
+
|
|
294
314
|
// Act
|
|
295
|
-
const result = await msgDiff.payloadDiff(
|
|
296
|
-
document1.channels()['evt-channel'],
|
|
297
|
-
document2.channels()['evt-channel'],
|
|
298
|
-
);
|
|
315
|
+
const result = await msgDiff.payloadDiff(channel1, channel2);
|
|
299
316
|
|
|
300
317
|
// Assert
|
|
301
318
|
expect(result).toBe('changed');
|
|
@@ -314,8 +331,8 @@ describe('sanity', () => {
|
|
|
314
331
|
|
|
315
332
|
// Act
|
|
316
333
|
const result = await msgDiff.payloadDiff(
|
|
317
|
-
document1.channels()
|
|
318
|
-
document2.channels()
|
|
334
|
+
document1.channels().get('evt-channel'),
|
|
335
|
+
document2.channels().get('evt-channel'),
|
|
319
336
|
);
|
|
320
337
|
|
|
321
338
|
// Assert
|
|
@@ -338,8 +355,8 @@ describe('sanity', () => {
|
|
|
338
355
|
|
|
339
356
|
// Act
|
|
340
357
|
const result = await msgDiff.payloadDiff(
|
|
341
|
-
document1.channels()
|
|
342
|
-
document2.channels()
|
|
358
|
+
document1.channels().get('evt-channel'),
|
|
359
|
+
document2.channels().get('evt-channel'),
|
|
343
360
|
);
|
|
344
361
|
|
|
345
362
|
// Assert
|
|
@@ -359,8 +376,8 @@ describe('sanity', () => {
|
|
|
359
376
|
|
|
360
377
|
// Act
|
|
361
378
|
const result = await msgDiff.payloadDiff(
|
|
362
|
-
document1.channels()
|
|
363
|
-
document2.channels()
|
|
379
|
+
document1.channels().get('evt-channel'),
|
|
380
|
+
document2.channels().get('evt-channel'),
|
|
364
381
|
);
|
|
365
382
|
|
|
366
383
|
// Assert
|
|
@@ -380,8 +397,8 @@ describe('sanity', () => {
|
|
|
380
397
|
|
|
381
398
|
// Act
|
|
382
399
|
const result = await msgDiff.payloadDiff(
|
|
383
|
-
document1.channels()
|
|
384
|
-
document2.channels()
|
|
400
|
+
document1.channels().get('evt-channel'),
|
|
401
|
+
document2.channels().get('evt-channel'),
|
|
385
402
|
);
|
|
386
403
|
|
|
387
404
|
// Assert
|
|
@@ -401,8 +418,8 @@ describe('sanity', () => {
|
|
|
401
418
|
|
|
402
419
|
// Act
|
|
403
420
|
const result = await msgDiff.payloadDiff(
|
|
404
|
-
document1.channels()
|
|
405
|
-
document2.channels()
|
|
421
|
+
document1.channels().get('evt-channel'),
|
|
422
|
+
document2.channels().get('evt-channel'),
|
|
406
423
|
);
|
|
407
424
|
|
|
408
425
|
// Assert
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
2
|
/* eslint-disable no-console */
|
|
3
3
|
import { diff, DiffOutputItem } from '@asyncapi/diff';
|
|
4
|
-
import
|
|
4
|
+
import Parser, {
|
|
5
|
+
AsyncAPIDocumentInterface,
|
|
6
|
+
ChannelInterface,
|
|
7
|
+
fromFile,
|
|
8
|
+
SchemaInterface,
|
|
9
|
+
} from '@asyncapi/parser';
|
|
5
10
|
import { green, red, white } from 'chalk';
|
|
6
11
|
import * as jsonDiff from 'diff';
|
|
7
12
|
import * as fs from 'fs';
|
|
@@ -177,13 +182,17 @@ export class MessageDiff {
|
|
|
177
182
|
console.log(
|
|
178
183
|
`Comparing asyncapi document '${file2}'. Changes from branch '${this.branch}':`,
|
|
179
184
|
);
|
|
180
|
-
let document1:
|
|
181
|
-
let document2:
|
|
185
|
+
let document1: AsyncAPIDocumentInterface;
|
|
186
|
+
let document2: AsyncAPIDocumentInterface;
|
|
182
187
|
|
|
183
188
|
// load asyncapi document from git
|
|
184
189
|
try {
|
|
185
|
-
const
|
|
186
|
-
|
|
190
|
+
const parser = new Parser();
|
|
191
|
+
const { document, diagnostics } = await fromFile(parser, file1).parse();
|
|
192
|
+
if (!document) {
|
|
193
|
+
throw `Error parsing ${file1}: ${diagnostics}`;
|
|
194
|
+
}
|
|
195
|
+
document1 = document;
|
|
187
196
|
} catch (e: any) {
|
|
188
197
|
throw `Error reading ${file1}: ${e}`;
|
|
189
198
|
}
|
|
@@ -199,8 +208,12 @@ export class MessageDiff {
|
|
|
199
208
|
this.results.breaking++;
|
|
200
209
|
return;
|
|
201
210
|
}
|
|
202
|
-
const
|
|
203
|
-
|
|
211
|
+
const parser = new Parser();
|
|
212
|
+
const { document, diagnostics } = await fromFile(parser, file2).parse();
|
|
213
|
+
if (!document) {
|
|
214
|
+
throw `Error parsing ${file2}: ${diagnostics}`;
|
|
215
|
+
}
|
|
216
|
+
document2 = document;
|
|
204
217
|
} catch (e: any) {
|
|
205
218
|
throw `Error reading ${file2}: ${e}`;
|
|
206
219
|
}
|
|
@@ -214,14 +227,16 @@ export class MessageDiff {
|
|
|
214
227
|
|
|
215
228
|
// diff payloads for channels which exist in both documents
|
|
216
229
|
// removed / renamed channels are already marked as breaking
|
|
217
|
-
for (const
|
|
218
|
-
if (
|
|
230
|
+
for (const channel1 of channels1) {
|
|
231
|
+
if (channels2.has(channel1.id()) === false) {
|
|
219
232
|
continue;
|
|
220
233
|
}
|
|
221
234
|
console.log(
|
|
222
|
-
`Comparing payload for channel ${
|
|
235
|
+
`Comparing payload for channel ${channel1.id()} in document ${file2}. Changes from branch ${
|
|
236
|
+
this.branch
|
|
237
|
+
}`,
|
|
223
238
|
);
|
|
224
|
-
const channel2 = channels2
|
|
239
|
+
const channel2 = channels2.get(channel1.id());
|
|
225
240
|
const resultKey = await this.payloadDiff(channel1, channel2);
|
|
226
241
|
this.results[resultKey]++;
|
|
227
242
|
}
|
|
@@ -232,8 +247,8 @@ export class MessageDiff {
|
|
|
232
247
|
* Note: non standard rules are defined in file: asyncapi-override.ts
|
|
233
248
|
*/
|
|
234
249
|
public async documentDiff(
|
|
235
|
-
document1:
|
|
236
|
-
document2:
|
|
250
|
+
document1: AsyncAPIDocumentInterface,
|
|
251
|
+
document2: AsyncAPIDocumentInterface,
|
|
237
252
|
): Promise<keyof Results> {
|
|
238
253
|
// generate diff
|
|
239
254
|
// overrides are applied through options here:
|
|
@@ -291,27 +306,38 @@ export class MessageDiff {
|
|
|
291
306
|
* If any other version is used (in local file or git) then the comparison result will be 'skipped'.
|
|
292
307
|
*/
|
|
293
308
|
public async payloadDiff(
|
|
294
|
-
channel1:
|
|
295
|
-
channel2:
|
|
309
|
+
channel1: ChannelInterface | undefined,
|
|
310
|
+
channel2: ChannelInterface | undefined,
|
|
296
311
|
): Promise<keyof Results> {
|
|
297
|
-
const getChannelPayload = (
|
|
298
|
-
|
|
299
|
-
|
|
312
|
+
const getChannelPayload = (
|
|
313
|
+
channel: ChannelInterface | undefined,
|
|
314
|
+
): SchemaInterface | undefined => {
|
|
315
|
+
if (channel === undefined) {
|
|
316
|
+
return undefined;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
const messages = channel.messages();
|
|
320
|
+
if (messages.length > 1) {
|
|
321
|
+
throw new Error(
|
|
322
|
+
`Channel ${channel.id()} has more than one message. This is currently not supported.`,
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
return messages[0].payload();
|
|
300
326
|
};
|
|
301
327
|
const schema1 = getChannelPayload(channel1);
|
|
302
328
|
const schema2 = getChannelPayload(channel2);
|
|
303
329
|
if (schema1 === undefined) {
|
|
304
|
-
throw `Could not find payload schema in ${this.branch}
|
|
330
|
+
throw new Error(`Could not find payload schema in ${this.branch}`);
|
|
305
331
|
}
|
|
306
332
|
if (schema2 === undefined) {
|
|
307
|
-
throw `Could not find payload schema
|
|
333
|
+
throw new Error(`Could not find payload schema`);
|
|
308
334
|
}
|
|
309
335
|
|
|
310
336
|
let result: jsonSchemaDiff.DiffResult;
|
|
311
337
|
try {
|
|
312
338
|
result = await jsonSchemaDiff.diffSchemas({
|
|
313
|
-
sourceSchema: schema1,
|
|
314
|
-
destinationSchema: schema2,
|
|
339
|
+
sourceSchema: schema1.json(),
|
|
340
|
+
destinationSchema: schema2.json(),
|
|
315
341
|
});
|
|
316
342
|
} catch (e: any) {
|
|
317
343
|
// Skip if unsupported schema version is used by either payload
|