Skip to content

Commit

Permalink
fix: implicitly handle nested keys that are an array of values again
Browse files Browse the repository at this point in the history
  • Loading branch information
mart-jansink committed Dec 28, 2020
1 parent 1db161b commit 3030099
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 12 deletions.
45 changes: 45 additions & 0 deletions src/__tests__/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,21 @@ const tests: Record<string, TestCase> = {
{favoriteIceCream: ['mint', 'chocolate']},
],
},
'can handle nested keys that are an array of values': {
input: [
[
{favorite: {iceCream: ['mint', 'chocolate']}},
{favorite: {iceCream: ['candy cane', 'brownie']}},
{favorite: {iceCream: ['birthday cake', 'rocky road', 'strawberry']}},
],
'cc',
{keys: ['favorite.iceCream']},
],
output: [
{favorite: {iceCream: ['candy cane', 'brownie']}},
{favorite: {iceCream: ['mint', 'chocolate']}},
],
},
'can handle nested keys that are an array of values with a wildcard': {
input: [
[
Expand All @@ -213,6 +228,36 @@ const tests: Record<string, TestCase> = {
{favorite: {iceCream: ['mint', 'chocolate']}},
],
},
'can handle nested keys that are an array of objects with a single wildcard': {
input: [
[
{favorite: {iceCream: [{tastes: ['vanilla', 'mint']}, {tastes: ['vanilla', 'chocolate']}]}},
{favorite: {iceCream: [{tastes: ['vanilla', 'candy cane']}, {tastes: ['vanilla', 'brownie']}]}},
{favorite: {iceCream: [{tastes: ['vanilla', 'birthday cake']}, {tastes: ['vanilla', 'rocky road']}, {tastes: ['strawberry']}]}},
],
'cc',
{keys: ['favorite.iceCream.*.tastes']},
],
output: [
{favorite: {iceCream: [{tastes:['vanilla', 'candy cane']}, {tastes:['vanilla', 'brownie']}]}},
{favorite: {iceCream: [{tastes:['vanilla', 'mint']}, {tastes:['vanilla', 'chocolate']}]}},
],
},
'can handle nested keys that are an array of objects with two wildcards': {
input: [
[
{favorite: {iceCream: [{tastes: ['vanilla', 'mint']}, {tastes: ['vanilla', 'chocolate']}]}},
{favorite: {iceCream: [{tastes: ['vanilla', 'candy cane']}, {tastes: ['vanilla', 'brownie']}]}},
{favorite: {iceCream: [{tastes: ['vanilla', 'birthday cake']}, {tastes: ['vanilla', 'rocky road']}, {tastes: ['strawberry']}]}},
],
'cc',
{keys: ['favorite.iceCream.*.tastes.*']},
],
output: [
{favorite: {iceCream: [{tastes:['vanilla', 'candy cane']}, {tastes:['vanilla', 'brownie']}]}},
{favorite: {iceCream: [{tastes:['vanilla', 'mint']}, {tastes:['vanilla', 'chocolate']}]}},
],
},
'can handle keys with a maxRanking': {
input: [
[
Expand Down
28 changes: 17 additions & 11 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -362,8 +362,14 @@ function getItemValues<ItemType>(
// @ts-expect-error just like below...
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
value = item[key];
} else {
value = getNestedValue<ItemType>(key, item)
} else if (key.includes(".")) {
// flatten the result to remain compatible with the implicit wildcard that's
// allowed when there's an array of strings at the end of the path
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
return getNestedValue<ItemType>(key, item).flat()
}
else {
value = null
}

// because `value` can also be undefined
Expand All @@ -377,27 +383,23 @@ function getItemValues<ItemType>(
}

/**
* Given key: "foo.bar.baz"
* Given path: "foo.bar.baz"
* And item: {foo: {bar: {baz: 'buzz'}}}
* -> 'buzz'
* @param key a dot-separated set of keys
* @param path a dot-separated set of keys
* @param item the item to get the value from
*/
function getNestedValue<ItemType>(
key: string,
path: string,
item: ItemType,
): string | Array<string> | null {
): Array<string> {
// @ts-expect-error really have no idea how to type this properly...
return key.split('.').reduce((nestedItems: Array<object | string | null>, nestedKey: string): Array<object | string> => {
return path.split('.').reduce((nestedItems: Array<object | string | null>, nestedKey: string): Array<object | string> => {
return nestedItems.reduce((values: Array<object | string>, nestedItem: Array<object | string> | object | string | null): Array<object | string> => {
if (nestedItem == null) {
return values
}

if (nestedKey === "*") {
return values.concat(nestedItem)
}

if (Object.hasOwnProperty.call(nestedItem,nestedKey)) {
// @ts-expect-error and here again...
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
Expand All @@ -406,6 +408,10 @@ function getNestedValue<ItemType>(
values.push(nestedValue)
}
}
else if (nestedKey === "*") {
// ensure that values is an array
values = values.concat(nestedItem)
}

return values
}, [])
Expand Down
5 changes: 4 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
{
"extends": "./node_modules/kcd-scripts/shared-tsconfig.json"
"extends": "./node_modules/kcd-scripts/shared-tsconfig.json",
"compilerOptions": {
"lib": ["es2019"]
}
}

0 comments on commit 3030099

Please sign in to comment.