@@ -21,10 +21,10 @@ import {
2121  IGNORE_PATH_PARAM_UNIFIED_PLACEHOLDER , 
2222  isEmpty , 
2323  isOperationRemove , 
24-   isPathParamRenameDiff , 
2524  normalizePath , 
2625  removeFirstSlash , 
2726  slugify , 
27+   trimSlashes , 
2828}  from  '../../utils' 
2929import  { 
3030  apiDiff , 
@@ -56,7 +56,12 @@ import { findRequiredRemovedProperties } from './rest.required'
5656import  {  calculateObjectHash  }  from  '../../utils/hashes' 
5757import  {  REST_API_TYPE  }  from  './rest.consts' 
5858import  {  OpenAPIV3  }  from  'openapi-types' 
59- import  {  extractRootSecurityDiffs ,  extractRootServersDiffs ,  getOperationBasePath  }  from  './rest.utils' 
59+ import  { 
60+   extractPathParamRenameDiff , 
61+   extractRootSecurityDiffs , 
62+   extractRootServersDiffs , 
63+   getOperationBasePath , 
64+ }  from  './rest.utils' 
6065import  {  createOperationChange ,  getOperationTags ,  OperationsMap  }  from  '../../components' 
6166
6267export  const  compareDocuments  =  async  ( 
@@ -83,7 +88,7 @@ export const compareDocuments = async (
8388  let  prevDocData  =  prevFile  &&  JSON . parse ( await  prevFile . text ( ) ) 
8489  let  currDocData  =  currFile  &&  JSON . parse ( await  currFile . text ( ) ) 
8590
86-   const  isChangedOperations  =  prevDoc  &&  currDoc 
91+   const  collectOnlyChangedOperations  =  Boolean ( prevDoc  &&  currDoc ) 
8792
8893  if  ( prevDocData  &&  previousGroup )  { 
8994    prevDocData  =  createCopyWithCurrentGroupOperationsOnly ( prevDocData ,  previousGroup ) 
@@ -142,29 +147,25 @@ export const compareDocuments = async (
142147      const  normalizedOperationId  =  slugify ( `${ normalizePath ( operationPath ) } ${ inferredMethod }  ,  [ ] ,  IGNORE_PATH_PARAM_UNIFIED_PLACEHOLDER ) 
143148
144149      const  {  current,  previous }  =  operationsMap [ normalizedOperationId ]  ??  operationsMap [ operationId ]  ??  { } 
150+       if  ( ! current  &&  ! previous )  { 
151+         throw  new  Error ( `Can't find the operation ${ operationId } ${ prevDoc ?. fileId } ${ currDoc ?. fileId }  ) 
152+       } 
153+       const  operationChanged  =  Boolean ( current  &&  previous ) 
154+       const  operationAddedOrRemoved  =  ! operationChanged 
145155
146156      let  operationDiffs : Diff [ ]  =  [ ] 
147-       if  ( current  &&  previous   &&   isChangedOperations )  { 
157+       if  ( operationChanged  &&  collectOnlyChangedOperations )  { 
148158        operationDiffs  =  [ 
149159          ...( methodData  as  WithAggregatedDiffs < OpenAPIV3 . OperationObject > ) [ DIFFS_AGGREGATED_META_KEY ] , 
150160          ...extractRootServersDiffs ( merged ) , 
151161          ...extractRootSecurityDiffs ( merged ) , 
162+           ...extractPathParamRenameDiff ( merged ,  path ) , 
152163          // parameters, servers, summary, description and extensionKeys are moved from path to method in pathItemsUnification during normalization in apiDiff, so no need to aggregate them here 
153164        ] 
154- 
155-         const  diff  =  ( merged . paths  as  WithDiffMetaRecord < OpenAPIV3 . PathsObject > ) [ DIFF_META_KEY ] ?. [ path ] 
156-         if  ( diff  &&  isPathParamRenameDiff ( diff ) )  { 
157-           // ignore removed and added operations, they'll be handled in a separate docs comparison??? 
158-           operationDiffs . push ( diff ) 
159-         } 
160165      } 
161-       if  ( ( ! ! current  !==  ! ! previous )  &&  ! isChangedOperations )  { 
162-         const  operationDiff  =  ( merged . paths [ path ]  as  WithDiffMetaRecord < OpenAPIV3 . PathsObject > ) [ DIFF_META_KEY ] ?. [ inferredMethod ] 
163-         if  ( ! operationDiff )  { 
164-           // ignore removed and added operations, they'll be handled in a separate docs comparison 
165-           continue 
166-         } 
167-         operationDiffs . push ( operationDiff ) 
166+       if  ( operationAddedOrRemoved  &&  ! collectOnlyChangedOperations )  { 
167+         const  operationAddedOrRemovedDiff  =  ( merged . paths [ path ]  as  WithDiffMetaRecord < OpenAPIV3 . PathsObject > ) [ DIFF_META_KEY ] ?. [ inferredMethod ] 
168+         operationDiffs  =  operationAddedOrRemovedDiff  ? [ operationAddedOrRemovedDiff ]  : [ ] 
168169      } 
169170
170171      if  ( isEmpty ( operationDiffs ) )  { 
@@ -277,16 +278,16 @@ export function createCopyWithEmptyPathItems(template: RestOperationData): RestO
277278
278279export  function  createCopyWithCurrentGroupOperationsOnly ( template : RestOperationData ,  group : string ) : RestOperationData  { 
279280  const  {  paths,  ...rest  }  =  template 
280-   const  groupWithoutLeadingSlash  =  removeFirstSlash ( group ) 
281+   const  groupWithoutEdgeSlashes  =  trimSlashes ( group ) 
281282
282283  return  { 
283284    paths : { 
284285      ...Object . fromEntries ( 
285286        Object . entries ( paths ) 
286-           . filter ( ( [ key ] )  =>  removeFirstSlash ( key ) . startsWith ( groupWithoutLeadingSlash ) ) 
287+           . filter ( ( [ key ] )  =>  removeFirstSlash ( key ) . startsWith ( ` ${ groupWithoutEdgeSlashes } /` ) )   // note that 'api/v10' is a substring of 'api/v1000' 
287288          // remove prefix group for correct path mapping in apiDiff 
288289          // todo support the most common case when a group is in servers instead of hardcoded in path, add a test 
289-           . map ( ( [ key ,  value ] )  =>  [ removeFirstSlash ( key ) . substring ( groupWithoutLeadingSlash . length ) ,  value ] ) , 
290+           . map ( ( [ key ,  value ] )  =>  [ removeFirstSlash ( key ) . substring ( groupWithoutEdgeSlashes . length ) ,  value ] ) , 
290291      ) , 
291292    } , 
292293    ...rest , 
0 commit comments