Skip to content

Commit 757c289

Browse files
committed
feat: path change due to moving a prefix from server.url to path classified as annotation
1 parent dd3512d commit 757c289

File tree

2 files changed

+39
-9
lines changed

2 files changed

+39
-9
lines changed

src/openapi/openapi3.classify.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,16 @@ import {
55
breakingIfAfterTrue,
66
nonBreaking,
77
PARENT_JUMP,
8-
strictResolveValueFromContext,
98
reverseClassifyRule,
9+
strictResolveValueFromContext,
1010
transformClassifyRule,
1111
unclassified,
1212
} from '../core'
1313
import { getKeyValue, isExist, isNotEmptyArray } from '../utils'
1414
import { emptySecurity, includeSecurity } from './openapi3.utils'
1515
import type { ClassifyRule, CompareContext } from '../types'
1616
import { DiffType } from '../types'
17-
import { hidePathParamNames } from './openapi3.mapping'
17+
import { unifyPath } from './openapi3.mapping'
1818

1919
export const paramClassifyRule: ClassifyRule = [
2020
({ after }) => {
@@ -143,9 +143,9 @@ export const pathChangeClassifyRule: ClassifyRule = [
143143
({ before, after }) => {
144144
const beforePath = before.key as string
145145
const afterPath = after.key as string
146-
const unifiedBeforePath = hidePathParamNames(beforePath)
147-
const unifiedAfterPath = hidePathParamNames(afterPath)
148-
146+
const unifiedBeforePath = unifyPath(before)(beforePath)
147+
const unifiedAfterPath = unifyPath(after)(afterPath)
148+
149149
// If unified paths are the same, it means only parameter names changed
150150
return unifiedBeforePath === unifiedAfterPath ? annotation : breaking
151151
}

src/openapi/openapi3.mapping.ts

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import type { MapKeysResult, MappingResolver } from '../types'
1+
import { MapKeysResult, MappingResolver, NodeContext } from '../types'
22
import { getStringValue, objectKeys, onlyExistedArrayIndexes } from '../utils'
33
import { mapPathParams } from './openapi3.utils'
4+
import { OpenAPIV3 } from 'openapi-types'
45

56
export const singleOperationPathMappingResolver: MappingResolver<string> = (before, after) => {
67

@@ -23,18 +24,18 @@ export const singleOperationPathMappingResolver: MappingResolver<string> = (befo
2324
return result
2425
}
2526

26-
export const pathMappingResolver: MappingResolver<string> = (before, after) => {
27+
export const pathMappingResolver: MappingResolver<string> = (before, after, ctx) => {
2728

2829
const result: MapKeysResult<string> = { added: [], removed: [], mapped: {} }
2930

3031
const originalBeforeKeys = objectKeys(before)
3132
const originalAfterKeys = objectKeys(after)
32-
const unifiedAfterKeys = originalAfterKeys.map(hidePathParamNames)
33+
const unifiedAfterKeys = originalAfterKeys.map(unifyPath(ctx.after))
3334

3435
const notMappedAfterIndices = new Set(originalAfterKeys.keys())
3536

3637
originalBeforeKeys.forEach(beforeKey => {
37-
const unifiedBeforePath = hidePathParamNames(beforeKey)
38+
const unifiedBeforePath = unifyPath(ctx.before)(beforeKey)
3839
const index = unifiedAfterKeys.indexOf(unifiedBeforePath)
3940

4041
if (index < 0) {
@@ -175,6 +176,35 @@ function isWildcardCompatible(beforeType: string, afterType: string): boolean {
175176
return true
176177
}
177178

179+
// todo copy-paste from api-processor
180+
export const extractOperationBasePath = (servers?: OpenAPIV3.ServerObject[]): string => {
181+
if (!Array.isArray(servers) || !servers.length) { return '' }
182+
183+
try {
184+
const [firstServer] = servers
185+
let serverUrl = firstServer.url
186+
const { variables = {} } = firstServer
187+
188+
for (const param of Object.keys(variables)) {
189+
serverUrl = serverUrl.replace(new RegExp(`{${param}}`, 'g'), variables[param].default)
190+
}
191+
192+
const { pathname } = new URL(serverUrl, 'https://localhost')
193+
return pathname.slice(-1) === '/' ? pathname.slice(0, -1) : pathname
194+
} catch (error) {
195+
return ''
196+
}
197+
}
198+
199+
export function unifyPath(nodeContext: NodeContext): (path: string) => string {
200+
const serverPrefix = extractOperationBasePath((nodeContext.root as OpenAPIV3.Document).servers) // /api/v2
201+
return (path) => (
202+
serverPrefix
203+
? `${serverPrefix}${hidePathParamNames(path)}`
204+
: hidePathParamNames(path)
205+
)
206+
}
207+
178208
export function hidePathParamNames(path: string): string {
179209
return path.replace(PATH_PARAMETER_REGEXP, PATH_PARAM_UNIFIED_PLACEHOLDER)
180210
}

0 commit comments

Comments
 (0)