Skip to content

Commit 341081f

Browse files
authored
feat: add the main diff function (#30)
1 parent deaf355 commit 341081f

13 files changed

+554
-25
lines changed
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
# Disable specific duplicate code since it would introduce more complexity to reduce it.
22
sonar.cpd.exclusions=src/standard.ts
3-
sonar.exclusions=src/standard.ts

src/asyncapidiff.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Output, DiffOutputItem } from './types';
2+
import { breaking, nonBreaking, unclassified } from './constants';
23

34
/**
45
* Implements functions to deal with the diff.
@@ -10,28 +11,28 @@ export default class AsyncAPIDiff {
1011

1112
constructor(output: string) {
1213
// output is a stringified JSON
13-
this.output= JSON.parse(output);
14+
this.output = JSON.parse(output);
1415
}
1516

1617
/**
1718
* @returns All the breaking changes
1819
*/
1920
breaking(): DiffOutputItem[] {
20-
return this.output.changes.filter((diff) => diff.type === 'breaking');
21+
return this.output.changes.filter((diff) => diff.type === breaking);
2122
}
2223

2324
/**
2425
* @returns All the non-breaking changes
2526
*/
2627
nonBreaking(): DiffOutputItem[] {
27-
return this.output.changes.filter((diff) => diff.type === 'non-breaking');
28+
return this.output.changes.filter((diff) => diff.type === nonBreaking);
2829
}
2930

3031
/**
3132
* @returns All the unclassified changes
3233
*/
3334
unclassified(): DiffOutputItem[] {
34-
return this.output.changes.filter((diff) => diff.type === 'unclassified');
35+
return this.output.changes.filter((diff) => diff.type === unclassified);
3536
}
3637

3738
/**

src/classifier.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Disabling this since the property we are accessing will always have `/` as the prefix
33
// Thus preventing the prototype chain attacks
44

5+
import { unclassified } from './constants';
56
import { generateClassifierPath } from './helpers/ClassifierHelpers';
67
import { Classifier, OverrideStandard } from './types';
78

@@ -18,9 +19,9 @@ export default function classifier(
1819
const classifierPath = generateClassifierPath(standard, path);
1920
if (!classifierPath) {
2021
return {
21-
add: 'unclassified',
22-
remove: 'unclassified',
23-
edit: 'unclassified',
22+
add: unclassified,
23+
remove: unclassified,
24+
edit: unclassified,
2425
};
2526
}
2627
return standard[classifierPath];

src/constants.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export const breaking = 'breaking';
2+
export const nonBreaking = 'non-breaking';
3+
export const unclassified = 'unclassified';

src/diff.ts renamed to src/generateDiff.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { DiffOutput } from './types';
99
* @param {*} secondDocument The second document in JSON format
1010
* @returns {DiffOutput[]} An array containing all the diffs
1111
*/
12-
export default function diff(
12+
export default function generateDiff(
1313
firstDocument: any,
1414
secondDocument: any
1515
): DiffOutput[] {

src/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
export {};
1+
export * from './main';
2+
export * from './types';

src/main.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { Config, OverrideStandard } from './types';
2+
import generateDiff from './generateDiff';
3+
import { standard } from './standard';
4+
import categorizeChanges from './categorizeChanges';
5+
import AsyncAPIDiff from './asyncapidiff';
6+
import { mergeStandard } from './mergeStandard';
7+
8+
/**
9+
* Generates diff between two AsyncAPI documents
10+
* @param firstDocument The parsed AsyncAPI document
11+
* @param secondDocument The parsed AsyncAPI document
12+
* @param {Object} config Configuration options
13+
* @param {Object} [config.override] Object to override the standard
14+
* @returns {AsyncAPIDiff} The diff data
15+
*
16+
* @example
17+
* const output = diff(firstDocument, secondDocument, {
18+
* override: {
19+
* '/servers': {
20+
* add: 'non-breaking', // when a property has been added in the AsyncAPI document
21+
* remove: 'breaking', // when a property has been removed from the AsyncAPI document
22+
* edit: 'unclassified' // when a property has been edited in the AsyncAPI document
23+
* }
24+
* }
25+
* })
26+
*/
27+
export function diff(
28+
firstDocument: any,
29+
secondDocument: any,
30+
config: Config = {}
31+
): AsyncAPIDiff {
32+
if (config.override) {
33+
if (typeof config.override !== 'object') {
34+
throw new TypeError('Override data must be an object');
35+
}
36+
mergeStandard(standard, config.override);
37+
}
38+
39+
const diffOutput = generateDiff(firstDocument, secondDocument);
40+
const output = categorizeChanges(standard as OverrideStandard, diffOutput);
41+
return new AsyncAPIDiff(JSON.stringify(output));
42+
}

src/standard.ts

Lines changed: 96 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
const breaking = 'breaking';
2-
const nonBreaking = 'non-breaking';
3-
const unclassified = 'unclassified';
1+
import { breaking, nonBreaking, unclassified } from './constants';
42

53
/**
64
* The standard object
@@ -126,6 +124,11 @@ export const standard = {
126124
remove: breaking,
127125
edit: breaking,
128126
},
127+
'/servers/*/variables/*/enum/*': {
128+
add: nonBreaking,
129+
remove: breaking,
130+
edit: breaking,
131+
},
129132
'/servers/*/variables/*/default': {
130133
add: breaking,
131134
remove: breaking,
@@ -141,11 +144,21 @@ export const standard = {
141144
remove: nonBreaking,
142145
edit: nonBreaking,
143146
},
147+
'/servers/*/variables/*/examples/*': {
148+
add: nonBreaking,
149+
remove: nonBreaking,
150+
edit: nonBreaking,
151+
},
144152
'/servers/*/security': {
145153
add: breaking,
146154
remove: breaking,
147155
edit: breaking,
148156
},
157+
'/servers/*/security/*': {
158+
add: breaking,
159+
remove: breaking,
160+
edit: breaking,
161+
},
149162
'/servers/*/bindings': {
150163
add: unclassified,
151164
remove: unclassified,
@@ -196,6 +209,11 @@ export const standard = {
196209
remove: nonBreaking,
197210
edit: nonBreaking,
198211
},
212+
'/channels/*/subscribe/tags/*': {
213+
add: nonBreaking,
214+
remove: nonBreaking,
215+
edit: nonBreaking,
216+
},
199217
'/channels/*/subscribe/externalDocs': {
200218
add: nonBreaking,
201219
remove: nonBreaking,
@@ -211,6 +229,11 @@ export const standard = {
211229
remove: breaking,
212230
edit: breaking,
213231
},
232+
'/channels/*/subscribe/traits/*': {
233+
add: nonBreaking,
234+
remove: breaking,
235+
edit: breaking,
236+
},
214237
'/channels/*/subscribe/traits/operationId': {
215238
add: nonBreaking,
216239
remove: breaking,
@@ -231,6 +254,11 @@ export const standard = {
231254
remove: nonBreaking,
232255
edit: nonBreaking,
233256
},
257+
'/channels/*/subscribe/traits/tags/*': {
258+
add: nonBreaking,
259+
remove: nonBreaking,
260+
edit: nonBreaking,
261+
},
234262
'/channels/*/subscribe/traits/externalDocs': {
235263
add: nonBreaking,
236264
remove: nonBreaking,
@@ -296,6 +324,11 @@ export const standard = {
296324
remove: nonBreaking,
297325
edit: nonBreaking,
298326
},
327+
'/channels/*/subscribe/message/tags/*': {
328+
add: nonBreaking,
329+
remove: nonBreaking,
330+
edit: nonBreaking,
331+
},
299332
'/channels/*/subscribe/message/externalDocs': {
300333
add: nonBreaking,
301334
remove: nonBreaking,
@@ -311,11 +344,21 @@ export const standard = {
311344
remove: nonBreaking,
312345
edit: nonBreaking,
313346
},
347+
'/channels/*/subscribe/message/examples/*': {
348+
add: nonBreaking,
349+
remove: nonBreaking,
350+
edit: nonBreaking,
351+
},
314352
'/channels/*/subscribe/message/traits': {
315353
add: nonBreaking,
316354
remove: breaking,
317355
edit: breaking,
318356
},
357+
'/channels/*/subscribe/message/traits/*': {
358+
add: nonBreaking,
359+
remove: breaking,
360+
edit: breaking,
361+
},
319362
'/channels/*/subscribe/message/traits/headers': {
320363
add: unclassified,
321364
remove: unclassified,
@@ -366,6 +409,11 @@ export const standard = {
366409
remove: nonBreaking,
367410
edit: nonBreaking,
368411
},
412+
'/channels/*/subscribe/message/traits/tags/*': {
413+
add: nonBreaking,
414+
remove: nonBreaking,
415+
edit: nonBreaking,
416+
},
369417
'/channels/*/subscribe/message/traits/externalDocs': {
370418
add: nonBreaking,
371419
remove: nonBreaking,
@@ -381,6 +429,11 @@ export const standard = {
381429
remove: nonBreaking,
382430
edit: nonBreaking,
383431
},
432+
'/channels/*/subscribe/message/traits/examples/*': {
433+
add: nonBreaking,
434+
remove: nonBreaking,
435+
edit: nonBreaking,
436+
},
384437
'/channels/*/subscribe/message/description': {
385438
add: nonBreaking,
386439
remove: nonBreaking,
@@ -416,6 +469,11 @@ export const standard = {
416469
remove: nonBreaking,
417470
edit: nonBreaking,
418471
},
472+
'/channels/*/publish/tags/*': {
473+
add: nonBreaking,
474+
remove: nonBreaking,
475+
edit: nonBreaking,
476+
},
419477
'/channels/*/publish/externalDocs': {
420478
add: nonBreaking,
421479
remove: nonBreaking,
@@ -431,6 +489,11 @@ export const standard = {
431489
remove: breaking,
432490
edit: breaking,
433491
},
492+
'/channels/*/publish/traits/*': {
493+
add: nonBreaking,
494+
remove: breaking,
495+
edit: breaking,
496+
},
434497
'/channels/*/publish/traits/operationId': {
435498
add: nonBreaking,
436499
remove: breaking,
@@ -451,6 +514,11 @@ export const standard = {
451514
remove: nonBreaking,
452515
edit: nonBreaking,
453516
},
517+
'/channels/*/publish/traits/tags/*': {
518+
add: nonBreaking,
519+
remove: nonBreaking,
520+
edit: nonBreaking,
521+
},
454522
'/channels/*/publish/traits/externalDocs': {
455523
add: nonBreaking,
456524
remove: nonBreaking,
@@ -516,6 +584,11 @@ export const standard = {
516584
remove: nonBreaking,
517585
edit: nonBreaking,
518586
},
587+
'/channels/*/publish/message/tags/*': {
588+
add: nonBreaking,
589+
remove: nonBreaking,
590+
edit: nonBreaking,
591+
},
519592
'/channels/*/publish/message/externalDocs': {
520593
add: nonBreaking,
521594
remove: nonBreaking,
@@ -531,11 +604,21 @@ export const standard = {
531604
remove: nonBreaking,
532605
edit: nonBreaking,
533606
},
607+
'/channels/*/publish/message/examples/*': {
608+
add: nonBreaking,
609+
remove: nonBreaking,
610+
edit: nonBreaking,
611+
},
534612
'/channels/*/publish/message/traits': {
535613
add: nonBreaking,
536614
remove: breaking,
537615
edit: breaking,
538616
},
617+
'/channels/*/publish/message/traits/*': {
618+
add: nonBreaking,
619+
remove: breaking,
620+
edit: breaking,
621+
},
539622
'/channels/*/publish/message/traits/headers': {
540623
add: unclassified,
541624
remove: unclassified,
@@ -586,6 +669,11 @@ export const standard = {
586669
remove: nonBreaking,
587670
edit: nonBreaking,
588671
},
672+
'/channels/*/publish/message/traits/tags/*': {
673+
add: nonBreaking,
674+
remove: nonBreaking,
675+
edit: nonBreaking,
676+
},
589677
'/channels/*/publish/message/traits/externalDocs': {
590678
add: nonBreaking,
591679
remove: nonBreaking,
@@ -601,6 +689,11 @@ export const standard = {
601689
remove: nonBreaking,
602690
edit: nonBreaking,
603691
},
692+
'/channels/*/publish/message/traits/examples/*': {
693+
add: nonBreaking,
694+
remove: nonBreaking,
695+
edit: nonBreaking,
696+
},
604697
'/channels/*/publish/message/description': {
605698
add: nonBreaking,
606699
remove: nonBreaking,

src/types.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
import { ReplaceOperation, AddOperation } from 'fast-json-patch';
22

33
import { standard } from './standard';
4+
import { breaking, nonBreaking, unclassified } from './constants';
45

56
export type ActionType = 'add' | 'remove' | 'edit';
67

7-
export type ChangeType = 'breaking' | 'non-breaking' | 'unclassified';
8+
export type ChangeType =
9+
| typeof breaking
10+
| typeof nonBreaking
11+
| typeof unclassified;
812

913
export interface Classifier {
1014
add: ChangeType;
@@ -38,6 +42,5 @@ export interface OverrideObject {
3842
export type OverrideStandard = StandardType & OverrideObject;
3943

4044
export interface Config {
41-
parse?: boolean;
4245
override?: OverrideObject;
4346
}

0 commit comments

Comments
 (0)