forked from extern/bruno
chore(#197): ran prettier on packages/bruno-query
This commit is contained in:
parent
116e050987
commit
f68eacfe0d
@ -6,10 +6,10 @@ function normalize(value: any) {
|
|||||||
|
|
||||||
const values = [] as any[];
|
const values = [] as any[];
|
||||||
|
|
||||||
value.forEach(item => {
|
value.forEach((item) => {
|
||||||
const value = normalize(item);
|
const value = normalize(item);
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
values.push(...Array.isArray(value) ? value : [value]);
|
values.push(...(Array.isArray(value) ? value : [value]));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -18,11 +18,11 @@ function normalize(value: any) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets value of a prop from source.
|
* Gets value of a prop from source.
|
||||||
*
|
*
|
||||||
* If source is an array get value from each item.
|
* If source is an array get value from each item.
|
||||||
*
|
*
|
||||||
* If deep is true then recursively gets values for prop in nested objects.
|
* If deep is true then recursively gets values for prop in nested objects.
|
||||||
*
|
*
|
||||||
* Once a value is found will not recurse further into that value.
|
* Once a value is found will not recurse further into that value.
|
||||||
*/
|
*/
|
||||||
function getValue(source: any, prop: string, deep = false): any {
|
function getValue(source: any, prop: string, deep = false): any {
|
||||||
@ -31,7 +31,7 @@ function getValue(source: any, prop: string, deep = false): any {
|
|||||||
let value;
|
let value;
|
||||||
|
|
||||||
if (Array.isArray(source)) {
|
if (Array.isArray(source)) {
|
||||||
value = source.map(item => getValue(item, prop, deep));
|
value = source.map((item) => getValue(item, prop, deep));
|
||||||
} else {
|
} else {
|
||||||
value = source[prop];
|
value = source[prop];
|
||||||
if (deep) {
|
if (deep) {
|
||||||
@ -63,7 +63,7 @@ function objectPredicate(obj: Record<string, any>) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply filter on source array or object
|
* Apply filter on source array or object
|
||||||
*
|
*
|
||||||
* If the filter returns a non boolean non null value it is treated as a mapped value
|
* If the filter returns a non boolean non null value it is treated as a mapped value
|
||||||
*/
|
*/
|
||||||
function filterOrMap(source: any, funOrObj: PredicateOrMapper) {
|
function filterOrMap(source: any, funOrObj: PredicateOrMapper) {
|
||||||
@ -75,7 +75,7 @@ function filterOrMap(source: any, funOrObj: PredicateOrMapper) {
|
|||||||
if (item == null) continue;
|
if (item == null) continue;
|
||||||
const value = fun(item);
|
const value = fun(item);
|
||||||
if (value === true) {
|
if (value === true) {
|
||||||
result.push(item); // predicate
|
result.push(item); // predicate
|
||||||
} else if (value != null && value !== false) {
|
} else if (value != null && value !== false) {
|
||||||
result.push(value); // mapper
|
result.push(value); // mapper
|
||||||
}
|
}
|
||||||
@ -85,7 +85,7 @@ function filterOrMap(source: any, funOrObj: PredicateOrMapper) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Getter with deep navigation, filter and map support
|
* Getter with deep navigation, filter and map support
|
||||||
*
|
*
|
||||||
* 1. Easy array navigation
|
* 1. Easy array navigation
|
||||||
* ```js
|
* ```js
|
||||||
* get(data, 'customer.orders.items.amount')
|
* get(data, 'customer.orders.items.amount')
|
||||||
@ -100,48 +100,49 @@ function filterOrMap(source: any, funOrObj: PredicateOrMapper) {
|
|||||||
* ```
|
* ```
|
||||||
* 4. Array filtering [?] with corresponding filter function
|
* 4. Array filtering [?] with corresponding filter function
|
||||||
* ```js
|
* ```js
|
||||||
* get(data, '..items[?].amount', i => i.amount > 20)
|
* get(data, '..items[?].amount', i => i.amount > 20)
|
||||||
* ```
|
* ```
|
||||||
* 5. Array filtering [?] with simple object predicate, same as (i => i.id === 2 && i.amount === 20)
|
* 5. Array filtering [?] with simple object predicate, same as (i => i.id === 2 && i.amount === 20)
|
||||||
* ```js
|
* ```js
|
||||||
* get(data, '..items[?]', { id: 2, amount: 20 })
|
* get(data, '..items[?]', { id: 2, amount: 20 })
|
||||||
* ```
|
* ```
|
||||||
* 6. Array mapping [?] with corresponding mapper function
|
* 6. Array mapping [?] with corresponding mapper function
|
||||||
* ```js
|
* ```js
|
||||||
* get(data, '..items[?].amount', i => i.amount + 10)
|
* get(data, '..items[?].amount', i => i.amount + 10)
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export function get(source: any, path: string, ...fns: PredicateOrMapper[]) {
|
export function get(source: any, path: string, ...fns: PredicateOrMapper[]) {
|
||||||
const paths = path
|
const paths = path
|
||||||
.replace(/\s+/g, '')
|
.replace(/\s+/g, '')
|
||||||
.split(/(\.{1,2}|\[\?\]|\[\d+\])/g) // ["..", "items", "[?]", ".", "amount", "[0]" ]
|
.split(/(\.{1,2}|\[\?\]|\[\d+\])/g) // ["..", "items", "[?]", ".", "amount", "[0]" ]
|
||||||
.filter(s => s.length > 0)
|
.filter((s) => s.length > 0)
|
||||||
.map(str => {
|
.map((str) => {
|
||||||
str = str.replace(/\[|\]/g, '');
|
str = str.replace(/\[|\]/g, '');
|
||||||
const index = parseInt(str);
|
const index = parseInt(str);
|
||||||
return isNaN(index) ? str : index;
|
return isNaN(index) ? str : index;
|
||||||
});
|
});
|
||||||
|
|
||||||
let index = 0, lookbehind = '' as string | number, funIndex = 0;
|
let index = 0,
|
||||||
|
lookbehind = '' as string | number,
|
||||||
|
funIndex = 0;
|
||||||
|
|
||||||
while (source != null && index < paths.length) {
|
while (source != null && index < paths.length) {
|
||||||
const token = paths[index++];
|
const token = paths[index++];
|
||||||
|
|
||||||
switch (true) {
|
switch (true) {
|
||||||
case token === "..":
|
case token === '..':
|
||||||
case token === ".":
|
case token === '.':
|
||||||
break;
|
break;
|
||||||
case token === "?":
|
case token === '?':
|
||||||
const fun = fns[funIndex++];
|
const fun = fns[funIndex++];
|
||||||
if (fun == null)
|
if (fun == null) throw new Error(`missing function for ${lookbehind}`);
|
||||||
throw new Error(`missing function for ${lookbehind}`);
|
|
||||||
source = filterOrMap(source, fun);
|
source = filterOrMap(source, fun);
|
||||||
break;
|
break;
|
||||||
case typeof token === 'number':
|
case typeof token === 'number':
|
||||||
source = normalize(source[token]);
|
source = normalize(source[token]);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
source = getValue(source, token as string, lookbehind === "..");
|
source = getValue(source, token as string, lookbehind === '..');
|
||||||
}
|
}
|
||||||
|
|
||||||
lookbehind = token;
|
lookbehind = token;
|
||||||
|
@ -5,57 +5,56 @@ import { get } from '../src/index';
|
|||||||
const data = {
|
const data = {
|
||||||
customer: {
|
customer: {
|
||||||
address: {
|
address: {
|
||||||
city: "bangalore"
|
city: 'bangalore'
|
||||||
},
|
},
|
||||||
orders: [
|
orders: [
|
||||||
{
|
{
|
||||||
id: "order-1",
|
id: 'order-1',
|
||||||
items: [
|
items: [
|
||||||
{ id: 1, amount: 10 },
|
{ id: 1, amount: 10 },
|
||||||
{ id: 2, amount: 20 },
|
{ id: 2, amount: 20 }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "order-2",
|
id: 'order-2',
|
||||||
items: [
|
items: [
|
||||||
{ id: 3, amount: 30, },
|
{ id: 3, amount: 30 },
|
||||||
{ id: 4, amount: 40 }
|
{ id: 4, amount: 40 }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
describe("get", () => {
|
describe('get', () => {
|
||||||
it.each([
|
it.each([
|
||||||
["customer.address.city", "bangalore"],
|
['customer.address.city', 'bangalore'],
|
||||||
["customer.orders.items.amount", [10, 20, 30, 40]],
|
['customer.orders.items.amount', [10, 20, 30, 40]],
|
||||||
["customer.orders.items.amount[0]", 10],
|
['customer.orders.items.amount[0]', 10],
|
||||||
["..items.amount", [10, 20, 30, 40]],
|
['..items.amount', [10, 20, 30, 40]],
|
||||||
["..amount", [10, 20, 30, 40]],
|
['..amount', [10, 20, 30, 40]],
|
||||||
["..items.amount[0]", 10],
|
['..items.amount[0]', 10],
|
||||||
["..items[0].amount", 10],
|
['..items[0].amount', 10],
|
||||||
["..items[5].amount", undefined], // invalid index
|
['..items[5].amount', undefined], // invalid index
|
||||||
["..id", ["order-1", 1, 2, "order-2", 3, 4]], // all ids
|
['..id', ['order-1', 1, 2, 'order-2', 3, 4]], // all ids
|
||||||
["customer.orders.foo", undefined],
|
['customer.orders.foo', undefined],
|
||||||
["..customer.foo", undefined],
|
['..customer.foo', undefined],
|
||||||
["..address", [{ city: "bangalore" }]], // .. will return array
|
['..address', [{ city: 'bangalore' }]], // .. will return array
|
||||||
["..address[0]", { city: "bangalore" }],
|
['..address[0]', { city: 'bangalore' }]
|
||||||
])("%s should be %j", (expr, result) => {
|
])('%s should be %j', (expr, result) => {
|
||||||
expect(get(data, expr)).toEqual(result);
|
expect(get(data, expr)).toEqual(result);
|
||||||
});
|
});
|
||||||
|
|
||||||
// filter and map
|
// filter and map
|
||||||
it.each([
|
it.each([
|
||||||
["..items[?].amount", [40], (i: any) => i.amount > 30], // [?] filter
|
['..items[?].amount', [40], (i: any) => i.amount > 30], // [?] filter
|
||||||
["..items[?].amount", [40], { id: 4, amount: 40 }], // object filter
|
['..items[?].amount', [40], { id: 4, amount: 40 }], // object filter
|
||||||
["..items[?].amount", undefined, { id: 5, amount: 40 }],
|
['..items[?].amount', undefined, { id: 5, amount: 40 }],
|
||||||
["..items..amount[?][0]", 40, (amt: number) => amt > 30],
|
['..items..amount[?][0]', 40, (amt: number) => amt > 30],
|
||||||
["..items..amount[0][?]", undefined, (amt: number) => amt > 30], // filter on single value
|
['..items..amount[0][?]', undefined, (amt: number) => amt > 30], // filter on single value
|
||||||
["..items..amount[?]", [11, 21, 31, 41], (amt: number) => amt + 1], // [?] mapper
|
['..items..amount[?]', [11, 21, 31, 41], (amt: number) => amt + 1], // [?] mapper
|
||||||
["..items..amount[0][?]", 11, (amt: number) => amt + 1], // [?] map on single value
|
['..items..amount[0][?]', 11, (amt: number) => amt + 1] // [?] map on single value
|
||||||
])("%s should be %j for %s", (expr, result, filter) => {
|
])('%s should be %j for %s', (expr, result, filter) => {
|
||||||
expect(get(data, expr, filter)).toEqual(result);
|
expect(get(data, expr, filter)).toEqual(result);
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user