openapi-diff
Advanced tools
Comparing version 0.10.0 to 0.11.0
@@ -0,1 +1,11 @@ | ||
<a name="0.11.0"></a> | ||
# [0.11.0](https://bitbucket.org/atlassian/openapi-diff/compare/0.10.0...0.11.0) (2018-07-06) | ||
### Features | ||
* add support for methods ([a1ad740](https://bitbucket.org/atlassian/openapi-diff/commits/a1ad740)) | ||
<a name="0.10.0"></a> | ||
@@ -2,0 +12,0 @@ # [0.10.0](https://bitbucket.org/atlassian/openapi-diff/compare/0.9.0...0.10.0) (2018-07-03) |
@@ -9,2 +9,4 @@ // tslint:disable:no-namespace | ||
'path.remove' | | ||
'method.add' | | ||
'method.remove' | | ||
'unclassified.add' | | ||
@@ -15,2 +17,3 @@ 'unclassified.remove'; | ||
'path' | | ||
'method' | | ||
'unclassified'; | ||
@@ -25,3 +28,3 @@ | ||
export interface Difference { | ||
export interface DiffResult<T extends DiffResultType> { | ||
action: DiffResultAction; | ||
@@ -34,8 +37,5 @@ code: DiffResultCode; | ||
details?: any; | ||
type: T; | ||
} | ||
export interface DiffResult extends Difference { | ||
type: DiffResultType; | ||
} | ||
export interface DiffResultSpecEntityDetails { | ||
@@ -54,8 +54,8 @@ location?: string; | ||
export interface DiffOutcomeFailure { | ||
breakingDifferences: DiffResult[]; | ||
breakingDifferences: Array<DiffResult<'breaking'>>; | ||
breakingDifferencesFound: true; | ||
destinationSpecDetails: SpecDetails; | ||
nonBreakingDifferences: DiffResult[]; | ||
nonBreakingDifferences: Array<DiffResult<'non-breaking'>>; | ||
sourceSpecDetails: SpecDetails; | ||
unclassifiedDifferences: DiffResult[]; | ||
unclassifiedDifferences: Array<DiffResult<'unclassified'>>; | ||
} | ||
@@ -66,5 +66,5 @@ | ||
breakingDifferencesFound: false; | ||
nonBreakingDifferences: DiffResult[]; | ||
nonBreakingDifferences: Array<DiffResult<'non-breaking'>>; | ||
sourceSpecDetails: SpecDetails; | ||
unclassifiedDifferences: DiffResult[]; | ||
unclassifiedDifferences: Array<DiffResult<'unclassified'>>; | ||
} | ||
@@ -71,0 +71,0 @@ |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const result_type_finder_1 = require("./result-type-finder"); | ||
const isBreakingDiffResult = (diffResult) => { | ||
return diffResult.type === 'breaking'; | ||
}; | ||
const isNonBreakingDiffResult = (diffResult) => { | ||
return diffResult.type === 'non-breaking'; | ||
}; | ||
const isUnclassifiedDiffResult = (diffResult) => { | ||
return diffResult.type === 'unclassified'; | ||
}; | ||
class DiffClassifier { | ||
@@ -14,13 +23,11 @@ static classifyDifferences(differences) { | ||
.forEach((diffResult) => { | ||
switch (diffResult.type) { | ||
case 'breaking': | ||
classifiedDiffResults.breakingDifferences.push(diffResult); | ||
break; | ||
case 'non-breaking': | ||
classifiedDiffResults.nonBreakingDifferences.push(diffResult); | ||
break; | ||
case 'unclassified': | ||
classifiedDiffResults.unclassifiedDifferences.push(diffResult); | ||
break; | ||
if (isBreakingDiffResult(diffResult)) { | ||
classifiedDiffResults.breakingDifferences.push(diffResult); | ||
} | ||
else if (isNonBreakingDiffResult(diffResult)) { | ||
classifiedDiffResults.nonBreakingDifferences.push(diffResult); | ||
} | ||
else if (isUnclassifiedDiffResult(diffResult)) { | ||
classifiedDiffResults.unclassifiedDifferences.push(diffResult); | ||
} | ||
}); | ||
@@ -27,0 +34,0 @@ return classifiedDiffResults; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const _ = require("lodash"); | ||
const get_added_keys_from_objects_1 = require("./common/get-added-keys-from-objects"); | ||
const get_common_keys_from_objects_1 = require("./common/get-common-keys-from-objects"); | ||
const get_removed_keys_from_objects_1 = require("./common/get-removed-keys-from-objects"); | ||
const create_difference_1 = require("./create-difference"); | ||
const find_diffs_in_operations_1 = require("./find-diffs-in-operations"); | ||
const normalize_path_1 = require("./normalize-path"); | ||
const findAddedPathDifferences = (sourcePathItems, destinationPathItems) => { | ||
const sourcePathNames = getPathNames(sourcePathItems); | ||
return destinationPathItems | ||
.filter((pathItem) => !_.includes(sourcePathNames, pathItem.pathName)) | ||
.map((pathItem) => create_difference_1.createDifference({ | ||
action: 'add', | ||
destinationObject: pathItem.originalValue, | ||
propertyName: 'path' | ||
})); | ||
return get_added_keys_from_objects_1.getAddedKeysFromObjects(sourcePathItems, destinationPathItems) | ||
.map((addedPathName) => { | ||
const addedDestinationPathItem = destinationPathItems[addedPathName]; | ||
return create_difference_1.createDifference({ | ||
action: 'add', | ||
destinationObject: addedDestinationPathItem.originalValue, | ||
propertyName: 'path' | ||
}); | ||
}); | ||
}; | ||
const findRemovedPathDifferences = (sourcePathItems, destinationPathItems) => { | ||
const destinationPathNames = getPathNames(destinationPathItems); | ||
return sourcePathItems | ||
.filter((pathItem) => !_.includes(destinationPathNames, pathItem.pathName)) | ||
.map((pathItem) => create_difference_1.createDifference({ | ||
action: 'remove', | ||
propertyName: 'path', | ||
sourceObject: pathItem.originalValue | ||
})); | ||
return get_removed_keys_from_objects_1.getRemovedKeysFromObjects(sourcePathItems, destinationPathItems) | ||
.map((removedPathName) => { | ||
const removedSourcePathItem = sourcePathItems[removedPathName]; | ||
return create_difference_1.createDifference({ | ||
action: 'remove', | ||
propertyName: 'path', | ||
sourceObject: removedSourcePathItem.originalValue | ||
}); | ||
}); | ||
}; | ||
const getPathNames = (pathItems) => pathItems.map((pathItem) => pathItem.pathName); | ||
const normalizePathItems = (pathItems) => pathItems.map((pathItem) => (Object.assign({}, pathItem, { pathName: normalize_path_1.normalizePath(pathItem.pathName) }))); | ||
const findMatchingPathDifferences = (sourcePathItems, destinationPathItems) => { | ||
const matchingPaths = get_common_keys_from_objects_1.getCommonKeysFromObjects(sourcePathItems, destinationPathItems); | ||
return matchingPaths.reduce((allDifferences, matchingPathItem) => { | ||
const differencesInOperations = find_diffs_in_operations_1.findDifferencesInOperations(sourcePathItems[matchingPathItem].operations, destinationPathItems[matchingPathItem].operations); | ||
return [...allDifferences, ...differencesInOperations]; | ||
}, []); | ||
}; | ||
const normalizePathItems = (parsedPathItems) => Object.keys(parsedPathItems).reduce((normalizedParsedPathItems, pathName) => { | ||
const parsedPathItem = parsedPathItems[pathName]; | ||
const normalizedPathName = normalize_path_1.normalizePath(pathName); | ||
normalizedParsedPathItems[normalizedPathName] = Object.assign({}, parsedPathItem, { pathName: normalizedPathName }); | ||
return normalizedParsedPathItems; | ||
}, {}); | ||
exports.findDiffsInPaths = (sourcePathItems, destinationPathItems) => { | ||
const normalisedSourcePathItems = normalizePathItems(sourcePathItems); | ||
const normalisedDestinationPathItems = normalizePathItems(destinationPathItems); | ||
const addedPaths = findAddedPathDifferences(normalisedSourcePathItems, normalisedDestinationPathItems); | ||
const removedPaths = findRemovedPathDifferences(normalisedSourcePathItems, normalisedDestinationPathItems); | ||
return [...addedPaths, ...removedPaths]; | ||
const normalizedSourcePathItems = normalizePathItems(sourcePathItems); | ||
const normalizedDestinationPathItems = normalizePathItems(destinationPathItems); | ||
const addedPaths = findAddedPathDifferences(normalizedSourcePathItems, normalizedDestinationPathItems); | ||
const removedPaths = findRemovedPathDifferences(normalizedSourcePathItems, normalizedDestinationPathItems); | ||
const matchingPaths = findMatchingPathDifferences(normalizedSourcePathItems, normalizedDestinationPathItems); | ||
return [...addedPaths, ...removedPaths, ...matchingPaths]; | ||
}; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const codeToTypeMap = { | ||
'method.add': 'non-breaking', | ||
'method.remove': 'breaking', | ||
'path.add': 'non-breaking', | ||
@@ -5,0 +7,0 @@ 'path.remove': 'breaking', |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const parse_x_properties_1 = require("./common/parse-x-properties"); | ||
const parsePaths = (paths) => Object.keys(paths).map((pathName) => ({ | ||
originalValue: { | ||
originalPath: ['paths', pathName], | ||
value: paths[pathName] | ||
}, | ||
pathName | ||
})); | ||
const typeCheckedOpenApi3Methods = { | ||
delete: undefined, | ||
get: undefined, | ||
head: undefined, | ||
options: undefined, | ||
patch: undefined, | ||
post: undefined, | ||
put: undefined, | ||
trace: undefined | ||
}; | ||
const isOpenApi3Method = (propertyName) => Object.keys(typeCheckedOpenApi3Methods).indexOf(propertyName) >= 0; | ||
const parseOperations = (pathItemObject, pathItemOriginalPath) => { | ||
return Object.keys(pathItemObject) | ||
.filter(isOpenApi3Method) | ||
.reduce((accumulator, method) => { | ||
accumulator[method] = { | ||
originalValue: { | ||
originalPath: [...pathItemOriginalPath, method], | ||
value: pathItemObject[method] | ||
} | ||
}; | ||
return accumulator; | ||
}, {}); | ||
}; | ||
const parsePaths = (paths) => Object.keys(paths).reduce((accumulator, pathName) => { | ||
const pathItemObject = paths[pathName]; | ||
const originalPath = ['paths', pathName]; | ||
accumulator[pathName] = { | ||
operations: parseOperations(pathItemObject, originalPath), | ||
originalValue: { | ||
originalPath, | ||
value: pathItemObject | ||
}, | ||
pathName | ||
}; | ||
return accumulator; | ||
}, {}); | ||
const validateOpenApi3 = (openApi3Spec) => openApi3Spec; | ||
@@ -15,14 +45,6 @@ exports.parseOpenApi3Spec = (openApi3Spec) => { | ||
return { | ||
basePath: { | ||
originalPath: ['basePath'], | ||
value: undefined | ||
}, | ||
format: 'openapi3', | ||
paths: parsePaths(validatedOpenApi3Spec.paths), | ||
schemes: { | ||
originalPath: ['schemes'], | ||
value: undefined | ||
}, | ||
xProperties: parse_x_properties_1.parseXPropertiesInObject(validatedOpenApi3Spec) | ||
}; | ||
}; |
@@ -14,33 +14,42 @@ "use strict"; | ||
const parse_x_properties_1 = require("./common/parse-x-properties"); | ||
const parseTopLevelArrayProperties = (arrayName, inputArray) => { | ||
const parsedSchemesArray = []; | ||
if (inputArray.length) { | ||
inputArray.forEach((value, index) => { | ||
parsedSchemesArray.push({ | ||
originalPath: [arrayName, index.toString()], | ||
value | ||
}); | ||
}); | ||
} | ||
return parsedSchemesArray; | ||
const typeCheckedSwagger2Methods = { | ||
delete: undefined, | ||
get: undefined, | ||
head: undefined, | ||
options: undefined, | ||
patch: undefined, | ||
post: undefined, | ||
put: undefined | ||
}; | ||
const parsePaths = (paths) => Object.keys(paths).map((pathName) => ({ | ||
originalValue: { | ||
originalPath: ['paths', pathName], | ||
value: paths[pathName] | ||
}, | ||
pathName | ||
})); | ||
const isSwagger2Method = (propertyName) => Object.keys(typeCheckedSwagger2Methods).indexOf(propertyName) >= 0; | ||
const parseOperations = (pathItemObject, pathItemOriginalPath) => { | ||
return Object.keys(pathItemObject) | ||
.filter(isSwagger2Method) | ||
.reduce((accumulator, method) => { | ||
accumulator[method] = { | ||
originalValue: { | ||
originalPath: [...pathItemOriginalPath, method], | ||
value: pathItemObject[method] | ||
} | ||
}; | ||
return accumulator; | ||
}, {}); | ||
}; | ||
const parsePaths = (paths) => Object.keys(paths).reduce((accumulator, pathName) => { | ||
const pathItemObject = paths[pathName]; | ||
const originalPath = ['paths', pathName]; | ||
accumulator[pathName] = { | ||
operations: parseOperations(pathItemObject, originalPath), | ||
originalValue: { | ||
originalPath, | ||
value: paths[pathName] | ||
}, | ||
pathName | ||
}; | ||
return accumulator; | ||
}, {}); | ||
const parseSwagger2Spec = (swagger2Spec) => { | ||
return { | ||
basePath: { | ||
originalPath: ['basePath'], | ||
value: swagger2Spec.basePath | ||
}, | ||
format: 'swagger2', | ||
paths: parsePaths(swagger2Spec.paths), | ||
schemes: { | ||
originalPath: ['schemes'], | ||
value: swagger2Spec.schemes ? parseTopLevelArrayProperties('schemes', swagger2Spec.schemes) : undefined | ||
}, | ||
xProperties: parse_x_properties_1.parseXPropertiesInObject(swagger2Spec) | ||
@@ -47,0 +56,0 @@ }; |
{ | ||
"name": "openapi-diff", | ||
"version": "0.10.0", | ||
"version": "0.11.0", | ||
"description": "A CLI tool to identify differences between Swagger/OpenAPI specs.", | ||
@@ -5,0 +5,0 @@ "bin": { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
46324
34
853