Skip to content

Commit

Permalink
feat: add the main diff function (#30)
Browse files Browse the repository at this point in the history
  • Loading branch information
aayushmau5 authored Aug 18, 2021
1 parent deaf355 commit 341081f
Show file tree
Hide file tree
Showing 13 changed files with 554 additions and 25 deletions.
1 change: 0 additions & 1 deletion sonar-project.properties → .sonarcloud.properties
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
# Disable specific duplicate code since it would introduce more complexity to reduce it.
sonar.cpd.exclusions=src/standard.ts
sonar.exclusions=src/standard.ts
9 changes: 5 additions & 4 deletions src/asyncapidiff.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Output, DiffOutputItem } from './types';
import { breaking, nonBreaking, unclassified } from './constants';

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

constructor(output: string) {
// output is a stringified JSON
this.output= JSON.parse(output);
this.output = JSON.parse(output);
}

/**
* @returns All the breaking changes
*/
breaking(): DiffOutputItem[] {
return this.output.changes.filter((diff) => diff.type === 'breaking');
return this.output.changes.filter((diff) => diff.type === breaking);
}

/**
* @returns All the non-breaking changes
*/
nonBreaking(): DiffOutputItem[] {
return this.output.changes.filter((diff) => diff.type === 'non-breaking');
return this.output.changes.filter((diff) => diff.type === nonBreaking);
}

/**
* @returns All the unclassified changes
*/
unclassified(): DiffOutputItem[] {
return this.output.changes.filter((diff) => diff.type === 'unclassified');
return this.output.changes.filter((diff) => diff.type === unclassified);
}

/**
Expand Down
7 changes: 4 additions & 3 deletions src/classifier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Disabling this since the property we are accessing will always have `/` as the prefix
// Thus preventing the prototype chain attacks

import { unclassified } from './constants';
import { generateClassifierPath } from './helpers/ClassifierHelpers';
import { Classifier, OverrideStandard } from './types';

Expand All @@ -18,9 +19,9 @@ export default function classifier(
const classifierPath = generateClassifierPath(standard, path);
if (!classifierPath) {
return {
add: 'unclassified',
remove: 'unclassified',
edit: 'unclassified',
add: unclassified,
remove: unclassified,
edit: unclassified,
};
}
return standard[classifierPath];
Expand Down
3 changes: 3 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const breaking = 'breaking';
export const nonBreaking = 'non-breaking';
export const unclassified = 'unclassified';
2 changes: 1 addition & 1 deletion src/diff.ts → src/generateDiff.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { DiffOutput } from './types';
* @param {*} secondDocument The second document in JSON format
* @returns {DiffOutput[]} An array containing all the diffs
*/
export default function diff(
export default function generateDiff(
firstDocument: any,
secondDocument: any
): DiffOutput[] {
Expand Down
3 changes: 2 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export {};
export * from './main';
export * from './types';
42 changes: 42 additions & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { Config, OverrideStandard } from './types';
import generateDiff from './generateDiff';
import { standard } from './standard';
import categorizeChanges from './categorizeChanges';
import AsyncAPIDiff from './asyncapidiff';
import { mergeStandard } from './mergeStandard';

/**
* Generates diff between two AsyncAPI documents
* @param firstDocument The parsed AsyncAPI document
* @param secondDocument The parsed AsyncAPI document
* @param {Object} config Configuration options
* @param {Object} [config.override] Object to override the standard
* @returns {AsyncAPIDiff} The diff data
*
* @example
* const output = diff(firstDocument, secondDocument, {
* override: {
* '/servers': {
* add: 'non-breaking', // when a property has been added in the AsyncAPI document
* remove: 'breaking', // when a property has been removed from the AsyncAPI document
* edit: 'unclassified' // when a property has been edited in the AsyncAPI document
* }
* }
* })
*/
export function diff(
firstDocument: any,
secondDocument: any,
config: Config = {}
): AsyncAPIDiff {
if (config.override) {
if (typeof config.override !== 'object') {
throw new TypeError('Override data must be an object');
}
mergeStandard(standard, config.override);
}

const diffOutput = generateDiff(firstDocument, secondDocument);
const output = categorizeChanges(standard as OverrideStandard, diffOutput);
return new AsyncAPIDiff(JSON.stringify(output));
}
99 changes: 96 additions & 3 deletions src/standard.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
const breaking = 'breaking';
const nonBreaking = 'non-breaking';
const unclassified = 'unclassified';
import { breaking, nonBreaking, unclassified } from './constants';

/**
* The standard object
Expand Down Expand Up @@ -126,6 +124,11 @@ export const standard = {
remove: breaking,
edit: breaking,
},
'/servers/*/variables/*/enum/*': {
add: nonBreaking,
remove: breaking,
edit: breaking,
},
'/servers/*/variables/*/default': {
add: breaking,
remove: breaking,
Expand All @@ -141,11 +144,21 @@ export const standard = {
remove: nonBreaking,
edit: nonBreaking,
},
'/servers/*/variables/*/examples/*': {
add: nonBreaking,
remove: nonBreaking,
edit: nonBreaking,
},
'/servers/*/security': {
add: breaking,
remove: breaking,
edit: breaking,
},
'/servers/*/security/*': {
add: breaking,
remove: breaking,
edit: breaking,
},
'/servers/*/bindings': {
add: unclassified,
remove: unclassified,
Expand Down Expand Up @@ -196,6 +209,11 @@ export const standard = {
remove: nonBreaking,
edit: nonBreaking,
},
'/channels/*/subscribe/tags/*': {
add: nonBreaking,
remove: nonBreaking,
edit: nonBreaking,
},
'/channels/*/subscribe/externalDocs': {
add: nonBreaking,
remove: nonBreaking,
Expand All @@ -211,6 +229,11 @@ export const standard = {
remove: breaking,
edit: breaking,
},
'/channels/*/subscribe/traits/*': {
add: nonBreaking,
remove: breaking,
edit: breaking,
},
'/channels/*/subscribe/traits/operationId': {
add: nonBreaking,
remove: breaking,
Expand All @@ -231,6 +254,11 @@ export const standard = {
remove: nonBreaking,
edit: nonBreaking,
},
'/channels/*/subscribe/traits/tags/*': {
add: nonBreaking,
remove: nonBreaking,
edit: nonBreaking,
},
'/channels/*/subscribe/traits/externalDocs': {
add: nonBreaking,
remove: nonBreaking,
Expand Down Expand Up @@ -296,6 +324,11 @@ export const standard = {
remove: nonBreaking,
edit: nonBreaking,
},
'/channels/*/subscribe/message/tags/*': {
add: nonBreaking,
remove: nonBreaking,
edit: nonBreaking,
},
'/channels/*/subscribe/message/externalDocs': {
add: nonBreaking,
remove: nonBreaking,
Expand All @@ -311,11 +344,21 @@ export const standard = {
remove: nonBreaking,
edit: nonBreaking,
},
'/channels/*/subscribe/message/examples/*': {
add: nonBreaking,
remove: nonBreaking,
edit: nonBreaking,
},
'/channels/*/subscribe/message/traits': {
add: nonBreaking,
remove: breaking,
edit: breaking,
},
'/channels/*/subscribe/message/traits/*': {
add: nonBreaking,
remove: breaking,
edit: breaking,
},
'/channels/*/subscribe/message/traits/headers': {
add: unclassified,
remove: unclassified,
Expand Down Expand Up @@ -366,6 +409,11 @@ export const standard = {
remove: nonBreaking,
edit: nonBreaking,
},
'/channels/*/subscribe/message/traits/tags/*': {
add: nonBreaking,
remove: nonBreaking,
edit: nonBreaking,
},
'/channels/*/subscribe/message/traits/externalDocs': {
add: nonBreaking,
remove: nonBreaking,
Expand All @@ -381,6 +429,11 @@ export const standard = {
remove: nonBreaking,
edit: nonBreaking,
},
'/channels/*/subscribe/message/traits/examples/*': {
add: nonBreaking,
remove: nonBreaking,
edit: nonBreaking,
},
'/channels/*/subscribe/message/description': {
add: nonBreaking,
remove: nonBreaking,
Expand Down Expand Up @@ -416,6 +469,11 @@ export const standard = {
remove: nonBreaking,
edit: nonBreaking,
},
'/channels/*/publish/tags/*': {
add: nonBreaking,
remove: nonBreaking,
edit: nonBreaking,
},
'/channels/*/publish/externalDocs': {
add: nonBreaking,
remove: nonBreaking,
Expand All @@ -431,6 +489,11 @@ export const standard = {
remove: breaking,
edit: breaking,
},
'/channels/*/publish/traits/*': {
add: nonBreaking,
remove: breaking,
edit: breaking,
},
'/channels/*/publish/traits/operationId': {
add: nonBreaking,
remove: breaking,
Expand All @@ -451,6 +514,11 @@ export const standard = {
remove: nonBreaking,
edit: nonBreaking,
},
'/channels/*/publish/traits/tags/*': {
add: nonBreaking,
remove: nonBreaking,
edit: nonBreaking,
},
'/channels/*/publish/traits/externalDocs': {
add: nonBreaking,
remove: nonBreaking,
Expand Down Expand Up @@ -516,6 +584,11 @@ export const standard = {
remove: nonBreaking,
edit: nonBreaking,
},
'/channels/*/publish/message/tags/*': {
add: nonBreaking,
remove: nonBreaking,
edit: nonBreaking,
},
'/channels/*/publish/message/externalDocs': {
add: nonBreaking,
remove: nonBreaking,
Expand All @@ -531,11 +604,21 @@ export const standard = {
remove: nonBreaking,
edit: nonBreaking,
},
'/channels/*/publish/message/examples/*': {
add: nonBreaking,
remove: nonBreaking,
edit: nonBreaking,
},
'/channels/*/publish/message/traits': {
add: nonBreaking,
remove: breaking,
edit: breaking,
},
'/channels/*/publish/message/traits/*': {
add: nonBreaking,
remove: breaking,
edit: breaking,
},
'/channels/*/publish/message/traits/headers': {
add: unclassified,
remove: unclassified,
Expand Down Expand Up @@ -586,6 +669,11 @@ export const standard = {
remove: nonBreaking,
edit: nonBreaking,
},
'/channels/*/publish/message/traits/tags/*': {
add: nonBreaking,
remove: nonBreaking,
edit: nonBreaking,
},
'/channels/*/publish/message/traits/externalDocs': {
add: nonBreaking,
remove: nonBreaking,
Expand All @@ -601,6 +689,11 @@ export const standard = {
remove: nonBreaking,
edit: nonBreaking,
},
'/channels/*/publish/message/traits/examples/*': {
add: nonBreaking,
remove: nonBreaking,
edit: nonBreaking,
},
'/channels/*/publish/message/description': {
add: nonBreaking,
remove: nonBreaking,
Expand Down
7 changes: 5 additions & 2 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import { ReplaceOperation, AddOperation } from 'fast-json-patch';

import { standard } from './standard';
import { breaking, nonBreaking, unclassified } from './constants';

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

export type ChangeType = 'breaking' | 'non-breaking' | 'unclassified';
export type ChangeType =
| typeof breaking
| typeof nonBreaking
| typeof unclassified;

export interface Classifier {
add: ChangeType;
Expand Down Expand Up @@ -38,6 +42,5 @@ export interface OverrideObject {
export type OverrideStandard = StandardType & OverrideObject;

export interface Config {
parse?: boolean;
override?: OverrideObject;
}
Loading

0 comments on commit 341081f

Please sign in to comment.