Skip to content

Commit 8b726d6

Browse files
authored
refactor: Switch to jsonpathly library (#191)
* refactor: Switch to jsonpathly library
1 parent 60258a7 commit 8b726d6

5 files changed

Lines changed: 248 additions & 86 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
## unreleased
22

3+
## [1.29.4] - 2026-02-23
4+
5+
- Overlay: refactor: Switch to jsonpathly library for RFC 9535 compliance (#190)
6+
37
## [1.29.3] - 2026-01-11
48

59
- CLI: Fix optional config file boolean options (#188)

package-lock.json

Lines changed: 10 additions & 74 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
"@stoplight/yaml": "^4.3.0",
3939
"api-ref-bundler": "^0.4.3",
4040
"case-anything": "2.1.10",
41-
"jsonpath-plus": "^10.3.0",
41+
"jsonpathly": "^3.0.0",
4242
"neotraverse": "^0.6.18"
4343
},
4444
"devDependencies": {

test/overlay.test.js

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
'use strict';
22

3+
const path = require('path');
4+
35
const {openapiOverlay, resolveJsonPathValue, deepMerge} = require('../utils/overlay');
6+
const {parseFile} = require('../openapi-format');
47

58
const {describe, it, expect} = require('@jest/globals');
69

@@ -404,6 +407,12 @@ describe('resolveJsonPathValue tests', () => {
404407
expect(result).toEqual([{id: 2}]);
405408
});
406409

410+
it('should handle RFC 9535 filtering without surrounding parentheses', () => {
411+
const obj = {items: [{id: 1}, {id: 2}, {id: 3}]};
412+
const result = resolveJsonPathValue(obj, '$.items[?@.id==2]');
413+
expect(result).toEqual([{id: 2}]);
414+
});
415+
407416
it('should handle array slicing', () => {
408417
const obj = {items: [1, 2, 3, 4, 5]};
409418
const result = resolveJsonPathValue(obj, '$.items[1:4]');
@@ -427,4 +436,59 @@ describe('resolveJsonPathValue tests', () => {
427436
const result = resolveJsonPathValue(obj, '$.paths..summary');
428437
expect(result).toEqual([]);
429438
});
439+
440+
it('should apply overlay action using RFC 9535 filter without parentheses', async () => {
441+
const baseOAS = {
442+
security: [{cookieAuth: []}, {bearerAuth: []}]
443+
};
444+
const overlaySet = {
445+
actions: [
446+
{
447+
target: '$.security[?@.cookieAuth]',
448+
update: {'x-applied': true}
449+
}
450+
]
451+
};
452+
453+
const result = await openapiOverlay(baseOAS, {overlaySet});
454+
expect(result.data.security).toEqual([{cookieAuth: [], 'x-applied': true}, {bearerAuth: []}]);
455+
expect(result.resultData.totalUsedActions).toBe(1);
456+
});
457+
458+
it('should apply overlay action to an escaped key path', async () => {
459+
const baseOAS = {
460+
'x.map': {
461+
value: 1
462+
}
463+
};
464+
const overlaySet = {
465+
actions: [
466+
{
467+
target: "$['x.map']",
468+
update: {updated: true}
469+
}
470+
]
471+
};
472+
473+
const result = await openapiOverlay(baseOAS, {overlaySet});
474+
expect(result.data['x.map']).toEqual({value: 1, updated: true});
475+
expect(result.resultData.totalUsedActions).toBe(1);
476+
});
477+
478+
it('should preserve independent copies when applying a second overlay to prior overlay results', async () => {
479+
const dir = path.join(__dirname, 'overlay-previous-overlay');
480+
const input = await parseFile(path.join(dir, 'input.yaml'));
481+
const overlaySet = await parseFile(path.join(dir, 'overlay.yaml'));
482+
483+
const firstPass = await openapiOverlay(input, {overlaySet: {actions: [overlaySet.actions[0]]}});
484+
const firstPassMatches = resolveJsonPathValue(firstPass.data, '$..child.oneOf[0].properties.a');
485+
expect(firstPassMatches.length).toBe(3);
486+
487+
const result = await openapiOverlay(input, {overlaySet});
488+
const aBranches = result.data.properties.parent.properties;
489+
490+
expect(aBranches.one.properties.child.oneOf[0].properties.a.oneOf).toBeDefined();
491+
expect(aBranches.two.properties.child.oneOf[0].properties.a.oneOf).toBeDefined();
492+
expect(aBranches.three.properties.child.oneOf[0].properties.a.oneOf).toBeDefined();
493+
});
430494
});

0 commit comments

Comments
 (0)