Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# @digitalbazaar/oid4-client Changelog

## 5.13.2 - 2026-mm-dd

### Fixed
- Fix `@context` matching in `credentialMatches()`. Now non-flat JSON pointer
maps properly preserve `@context` inputs as ordered lists (using arrays)
instead of expressing them as sets.

## 5.13.1 - 2026-06-09

### Fixed
Expand Down
8 changes: 8 additions & 0 deletions lib/query/match.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,14 @@ function _match({cursor, matchValue, options}) {
}
// normalize value to an array for matching
const values = Array.isArray(value) ? value : [value];
// `matchValue` can only be an array for the `@context` case
if(Array.isArray(matchValue)) {
// each element of `matchValue` must be equal to the element in
// `values` at the same index (note: `values` may have more elements
// than `matchValue` and still match)
return matchValue.every((mv, i) => values[i] === mv);
}
// handle matching each individual value on its own
return values.some(v => _match({cursor: v, matchValue, options}));
});
}
Expand Down
2 changes: 1 addition & 1 deletion lib/query/presentationExchange.js
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ export function _fromQueryByExampleQuery({credentialQuery, prefixJwtVcPath}) {
field.path.push(JSONPath.toPathString(['$', 'vc', ...path]));
}

if(value instanceof Set) {
if(Array.isArray(value) || value instanceof Set) {
field.filter = {
type: 'array',
allOf: [...value].map(value => ({
Expand Down
23 changes: 18 additions & 5 deletions lib/query/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,26 @@ function _toPointers({
cursor, map, tokens = [], pointer = '/', flat = false
}) {
if(!flat && Array.isArray(cursor)) {
const set = new Set();
// when `map` is not set, case is array of arrays; return a new map
const result = map ? set : (map = new Map());
map.set(pointer, set);
// when producing non-flat output, every array is treated as a `Set` except
// if the pointer points at an `@context` array (this is the only ordered
// list case)
let container;
let add;
if(pointer.endsWith('/@context')) {
container = [];
add = container.push;
} else {
container = new Set();
add = container.add;
}
add = add.bind(container);
// result is `container` if `map` is defined, if not, then case is
// array of arrays and result is a new map
const result = map ? container : (map = new Map());
map.set(pointer, container);
for(const element of cursor) {
// reset map, tokens, and pointer for array elements
set.add(_toPointers({cursor: element, flat}));
add(_toPointers({cursor: element, flat}));
}
return result;
}
Expand Down
Loading