Skip to content

Commit d1f085a

Browse files
committed
chore: merge branch 'develop' into feature/move-prefix-from-server-to-path
2 parents 9a4ce06 + a47a940 commit d1f085a

File tree

26 files changed

+1021
-71
lines changed

26 files changed

+1021
-71
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
"fast-equals": "4.0.3"
3333
},
3434
"devDependencies": {
35-
"@netcracker/qubership-apihub-compatibility-suites": "2.3.0",
35+
"@netcracker/qubership-apihub-compatibility-suites": "dev",
3636
"@netcracker/qubership-apihub-graphapi": "feature-performance-optimization",
3737
"@netcracker/qubership-apihub-npm-gitflow": "3.1.0",
3838
"@types/jest": "29.5.11",

src/api.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,24 @@ function areSpecTypesCompatible(beforeType: SpecType, afterType: SpecType): bool
2626
if (beforeType === afterType) {
2727
return true
2828
}
29-
29+
3030
// Allow comparison between different OpenAPI versions
3131
return isOpenApiSpecVersion(beforeType) && isOpenApiSpecVersion(afterType)
3232
}
3333

34+
function selectEngineSpecType(beforeType: SpecType, afterType: SpecType): SpecType {
35+
// For OpenAPI version comparisons, use the higher version
36+
if (isOpenApiSpecVersion(beforeType) && isOpenApiSpecVersion(afterType)) {
37+
if (beforeType === SPEC_TYPE_OPEN_API_31 || afterType === SPEC_TYPE_OPEN_API_31) {
38+
return SPEC_TYPE_OPEN_API_31
39+
}
40+
return SPEC_TYPE_OPEN_API_30
41+
}
42+
43+
// For same spec types or other compatible types, use the before type
44+
return beforeType
45+
}
46+
3447
export const COMPARE_ENGINES_MAP: Record<SpecType, CompareEngine> = {
3548
[SPEC_TYPE_JSON_SCHEMA_04]: compareJsonSchema(SPEC_TYPE_JSON_SCHEMA_04),
3649
[SPEC_TYPE_JSON_SCHEMA_06]: compareJsonSchema(SPEC_TYPE_JSON_SCHEMA_06),
@@ -48,7 +61,7 @@ export function apiDiff(before: unknown, after: unknown, options: CompareOptions
4861
if (!areSpecTypesCompatible(beforeSpec.type, afterSpec.type)) {
4962
throw new Error(`Specification cannot be different. Got ${beforeSpec.type} and ${afterSpec.type}`)
5063
}
51-
const engine = COMPARE_ENGINES_MAP[beforeSpec.type]
64+
const engine = COMPARE_ENGINES_MAP[selectEngineSpecType(beforeSpec.type, afterSpec.type)]
5265
return engine(before, after, {
5366
mode: COMPARE_MODE_DEFAULT,
5467
normalizedResult: DEFAULT_NORMALIZED_RESULT,

src/core/compare.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ import {
3434
} from '../types'
3535
import { getObjectValue, isArray, isDiffAdd, isDiffRemove, isDiffReplace, isNumber, isObject, typeOf } from '../utils'
3636
import { ANY_COMBINER_PATH, DiffAction, JSO_ROOT } from './constants'
37-
import { addDiffObjectToContainer, diffFactory, NEVER_KEY } from './diff'
37+
import { addDiffObjectToContainer, createDiffEntry, diffFactory, NEVER_KEY } from './diff'
3838
import { arrayMappingResolver, objectMappingResolver } from './mapping'
3939

4040
const extractDeclarationPaths = (jso: Record<PropertyKey, unknown>, originMetaKey: symbol, property: PropertyKey): JsonPath[] => {
@@ -156,21 +156,24 @@ const cleanUpRecursive = (ctx: NodeContext): NodeContext => {
156156
}
157157

158158
export const getOrCreateChildDiffAdd = (diffUniquenessCache: EvaluationCacheService, childCtx: CompareContext) => {
159-
return diffUniquenessCache.cacheEvaluationResultByFootprint<[unknown, string, CompareScope, typeof DiffAction.add], DiffEntry<DiffAdd>>([childCtx.after.value, buildPathsIdentifier(childCtx.after.declarativePaths), childCtx.scope, DiffAction.add], () => {
159+
const diff = diffUniquenessCache.cacheEvaluationResultByFootprint<[unknown, string, CompareScope, typeof DiffAction.add], DiffAdd>([childCtx.after.value, buildPathsIdentifier(childCtx.after.declarativePaths), childCtx.scope, DiffAction.add], () => {
160160
return diffFactory.added(childCtx)
161-
}, {} as DiffEntry<DiffAdd>, (result, guard) => {
161+
}, {} as DiffAdd, (result, guard) => {
162162
Object.assign(guard, result)
163163
return guard
164164
})
165+
166+
return createDiffEntry(childCtx, diff)
165167
}
166168

167169
export const getOrCreateChildDiffRemove = (diffUniquenessCache: EvaluationCacheService, childCtx: CompareContext) => {
168-
return diffUniquenessCache.cacheEvaluationResultByFootprint<[unknown, string, CompareScope, typeof DiffAction.remove], DiffEntry<DiffRemove>>([childCtx.before.value, buildPathsIdentifier(childCtx.before.declarativePaths), childCtx.scope, DiffAction.remove], () => {
170+
const diff = diffUniquenessCache.cacheEvaluationResultByFootprint<[unknown, string, CompareScope, typeof DiffAction.remove], DiffRemove>([childCtx.before.value, buildPathsIdentifier(childCtx.before.declarativePaths), childCtx.scope, DiffAction.remove], () => {
169171
return diffFactory.removed(childCtx)
170-
}, {} as DiffEntry<DiffRemove>, (result, guard) => {
172+
}, {} as DiffRemove, (result, guard) => {
171173
Object.assign(guard, result)
172174
return guard
173175
})
176+
return createDiffEntry(childCtx, diff)
174177
}
175178

176179
const adaptValues = (beforeJso: JsonNode, beforeKey: PropertyKey, afterJso: JsonNode, afterKey: PropertyKey, adapter: AdapterResolver[] | undefined, options: InternalCompareOptions) => {
@@ -235,7 +238,7 @@ const useMergeFactory = (onDiff: DiffCallback, options: InternalCompareOptions):
235238

236239
const beforeKey = unsafeKey ?? (isArray(beforeJso) ? +Object.keys(keyMap).pop()! : Object.keys(keyMap).pop())
237240
const afterKey = keyMap[beforeKey]
238-
const mergeKey = isArray(mergedJso) && isNumber(beforeKey) ? beforeKey : afterKey//THIS IS VERY FRAGILE. Cause this logic duplicate this line mergedJsoValue[keyInMerge] = afterValue[keyInAfter]
241+
const mergeKey = isArray(mergedJso) && isNumber(beforeKey) ? beforeKey : afterKey //gitleaks:allow //THIS IS VERY FRAGILE. Cause this logic duplicate this line mergedJsoValue[keyInMerge] = afterValue[keyInAfter]
239242

240243
// skip if node was removed
241244
if (!(beforeKey in keyMap)) {
@@ -265,7 +268,7 @@ const useMergeFactory = (onDiff: DiffCallback, options: InternalCompareOptions):
265268

266269
const reuseResult: ReusableMergeResult = mergedJsoCache.cacheEvaluationResultByFootprint<[typeof ctx.before.value, typeof ctx.after.value, typeof beforeDeclarativePathsId, typeof afterDeclarativePathsId, CompareScope], ReusableMergeResult>([ctx.before.value, ctx.after.value, beforeDeclarativePathsId, afterDeclarativePathsId, ctx.scope], ([beforeValue, afterValue]) => {
267270
if (!ignoreKeyDifference && beforeKey !== afterKey) {
268-
const diffEntry = diffFactory.renamed(ctx)
271+
const diffEntry = createDiffEntry(ctx, diffFactory.renamed(ctx))
269272
addDiff(diffEntry.diff)
270273
addDiffObjectToContainer(mergedJso, metaKey, [diffEntry])
271274
}
@@ -279,7 +282,7 @@ const useMergeFactory = (onDiff: DiffCallback, options: InternalCompareOptions):
279282

280283
// types are different
281284
if (typeOf(beforeValue) !== typeOf(afterValue)) {
282-
const diffEntry = diffFactory.replaced(ctx)
285+
const diffEntry = createDiffEntry(ctx, diffFactory.replaced(ctx))
283286
addDiff(diffEntry.diff)
284287
return { diffsToPullUp: [diffEntry], mergedValue: afterValue } satisfies ReusableMergeResult
285288
}
@@ -336,7 +339,7 @@ const useMergeFactory = (onDiff: DiffCallback, options: InternalCompareOptions):
336339
diffsToPullUp: diffsToPullUp,
337340
}
338341
if (beforeValue !== afterValue) {
339-
const diffEntry = diffFactory.replaced(ctx)
342+
const diffEntry = createDiffEntry(ctx, diffFactory.replaced(ctx))
340343
diffsToPullUp.push(diffEntry)
341344
addDiff(diffEntry.diff)
342345
}

src/core/diff.ts

Lines changed: 39 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -31,51 +31,46 @@ export const createDiff = <D extends Diff>(diff: Omit<D, 'type'>, ctx: CompareCo
3131
return mutableDiffCopy
3232
}
3333

34-
export const diffFactory: DiffFactory = {
35-
added: (ctx) => ({
36-
propertyKey: ctx.mergeKey,
37-
diff: createDiff({
38-
afterValue: ctx.after?.value,
39-
afterNormalizedValue: ctx.after?.value,
40-
action: DiffAction.add,
41-
afterDeclarationPaths: ctx.after.declarativePaths,
42-
scope: ctx.scope,
43-
}, ctx),
44-
}),
45-
removed: (ctx) => ({
46-
propertyKey: ctx.mergeKey,
47-
diff: createDiff({
48-
beforeValue: ctx.before.value,
49-
beforeNormalizedValue: ctx.before.value,
50-
action: DiffAction.remove,
51-
beforeDeclarationPaths: ctx.before.declarativePaths,
52-
scope: ctx.scope,
53-
}, ctx),
54-
}),
55-
replaced: (ctx) => ({
56-
propertyKey: ctx.mergeKey,
57-
diff: createDiff({
58-
beforeValue: ctx.before.value,
59-
beforeNormalizedValue: ctx.before.value,
60-
afterValue: ctx.after.value,
61-
afterNormalizedValue: ctx.after.value,
62-
action: DiffAction.replace,
63-
afterDeclarationPaths: ctx.after.declarativePaths,
64-
beforeDeclarationPaths: ctx.before.declarativePaths,
65-
scope: ctx.scope,
66-
}, ctx),
67-
}),
68-
renamed: (ctx) => ({
34+
export function createDiffEntry(ctx: CompareContext, diff: Diff): DiffEntry<Diff> {
35+
return ({
6936
propertyKey: ctx.mergeKey,
70-
diff: createDiff({
71-
beforeKey: ctx.before?.key,
72-
afterKey: ctx.after?.key,
73-
action: DiffAction.rename,
74-
afterDeclarationPaths: ctx.after?.declarativePaths ?? [],
75-
beforeDeclarationPaths: ctx.before?.declarativePaths ?? [],
76-
scope: ctx.scope,
77-
}, ctx),
78-
}),
37+
diff: diff,
38+
})
39+
}
40+
41+
export const diffFactory: DiffFactory = {
42+
added: (ctx) => createDiff({
43+
afterValue: ctx.after?.value,
44+
afterNormalizedValue: ctx.after?.value,
45+
action: DiffAction.add,
46+
afterDeclarationPaths: ctx.after.declarativePaths,
47+
scope: ctx.scope,
48+
}, ctx),
49+
removed: (ctx) => createDiff({
50+
beforeValue: ctx.before.value,
51+
beforeNormalizedValue: ctx.before.value,
52+
action: DiffAction.remove,
53+
beforeDeclarationPaths: ctx.before.declarativePaths,
54+
scope: ctx.scope,
55+
}, ctx),
56+
replaced: (ctx) => createDiff({
57+
beforeValue: ctx.before.value,
58+
beforeNormalizedValue: ctx.before.value,
59+
afterValue: ctx.after.value,
60+
afterNormalizedValue: ctx.after.value,
61+
action: DiffAction.replace,
62+
afterDeclarationPaths: ctx.after.declarativePaths,
63+
beforeDeclarationPaths: ctx.before.declarativePaths,
64+
scope: ctx.scope,
65+
}, ctx),
66+
renamed: (ctx) => createDiff({
67+
beforeKey: ctx.before?.key,
68+
afterKey: ctx.after?.key,
69+
action: DiffAction.rename,
70+
afterDeclarationPaths: ctx.after?.declarativePaths ?? [],
71+
beforeDeclarationPaths: ctx.before?.declarativePaths ?? [],
72+
scope: ctx.scope,
73+
}, ctx),
7974
}
8075

8176
export const addDiffObjectToContainer = (

src/graphapi/graphapi.resolver.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { diffFactory } from '../core'
1+
import { createDiffEntry, diffFactory } from '../core'
22
import { CompareResolver } from '../types/rules'
33
import { isObject, isString } from '../utils'
44

@@ -9,17 +9,17 @@ export const complexTypeCompareResolver: CompareResolver = (ctx) => {
99
const afterValue = after.value
1010

1111
if (!isObject(beforeValue) || !isObject(afterValue) || !isString(beforeValue.kind) || !isString(afterValue.kind)) {
12-
const diffEntry = diffFactory.replaced(ctx)
12+
const diffEntry = createDiffEntry(ctx, diffFactory.replaced(ctx))
1313
// actually we don't make deep copy here and create "way to modify" original source. But fix not so trivial and expensive for performance
1414
return { diffs: [diffEntry.diff], ownerDiffEntry: diffEntry, merged: after.value }
1515
}
1616

17-
if (beforeValue.kind === afterValue.kind) {
17+
if (beforeValue.kind === afterValue.kind) {
1818
return undefined
1919
}
2020

2121
//TODO add more better way to compare interface vs type
2222

23-
const diffEntry = diffFactory.replaced(ctx)
23+
const diffEntry = createDiffEntry(ctx, diffFactory.replaced(ctx))
2424
return { diffs: [diffEntry.diff], ownerDiffEntry: diffEntry, merged: after.value }
2525
}

src/jsonSchema/jsonSchema.resolver.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
getOrCreateChildDiffAdd,
99
getOrCreateChildDiffRemove,
1010
nestedCompare,
11+
createDiffEntry,
1112
} from '../core'
1213
import type { CompareResolver, Diff, DiffEntry } from '../types'
1314
import { isArray, isObject, onlyExistedArrayIndexes } from '../utils'
@@ -21,7 +22,7 @@ export const combinersCompareResolver: CompareResolver = (ctx) => {
2122
}
2223

2324
if (!isArray(before.value) || !isArray(after.value)) {
24-
const diffEntry = diffFactory.replaced(ctx)
25+
const diffEntry = createDiffEntry(ctx, diffFactory.replaced(ctx))
2526
// actually we don't make deep copy here and create "way to modify" original source
2627
return { diffs: [diffEntry.diff], ownerDiffEntry: diffEntry, merged: after.value }
2728
}

0 commit comments

Comments
 (0)