Skip to content

Commit e4219c5

Browse files
committed
Add support for nested paths to reorderResultsByKey
1 parent c365b73 commit e4219c5

File tree

4 files changed

+43
-7
lines changed

4 files changed

+43
-7
lines changed

API_DOCS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ Describes the shape and behaviour of the resources object you will pass to `getL
182182
| `docsLink` | The URL for the documentation of the resource. Useful for others to verify information is correct, and may be used in stack traces. |
183183
| `batchKey` | The argument to the resource that represents the list of entities we want to fetch. (e.g. 'user_ids') |
184184
| `newKey` | The argument we'll replace the batchKey with - should be a singular version of the `batchKey` (e.g. 'user_id') |
185-
| `reorderResultsByKey` | (Optional) If the resource itself does not guarantee ordering, use this to specify which key in the response objects corresponds to an element in `batchKey`. Transforms and re-order the response to the same order as requested from the DataLoaders. |
185+
| `reorderResultsByKey` | (Optional) If the resource itself does not guarantee ordering, use this to specify which key in the response objects corresponds to an element in `batchKey`. Transforms and re-order the response to the same order as requested from the DataLoaders. Can be a dot separated nested path. |
186186
| `nestedPath` | (Optional) If the resource returns the list of results in a nested path (e.g. `{ results: [ 1, 2, 3 ] }`), this tells the DataLoader where in the response to find the results. (e.g. 'results'). |
187187
| `commaSeparatedBatchKey` | (Optional) Set to true if the interface of the resource takes the batch key as a comma separated list (rather than an array of IDs, as is more common). Default: false |
188188
| `isResponseDictionary` | (Optional) Set to true if the batch resource returns the results as a dictionary with key mapped to values (instead of a list of items). If this option is supplied `reorderResultsByKey` should not be. Default: false |

__tests__/implementation.test.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,43 @@ test('batch endpoint (with reorderResultsByKey)', async () => {
196196
});
197197
});
198198

199+
200+
test('batch endpoint (with nested reorderResultsByKey path)', async () => {
201+
const config = {
202+
resources: {
203+
foo: {
204+
isBatchResource: true,
205+
docsLink: 'example.com/docs/bar',
206+
batchKey: 'foo_ids',
207+
newKey: 'foo_id',
208+
reorderResultsByKey: 'nested.foo_id',
209+
},
210+
},
211+
};
212+
213+
const resources = {
214+
foo: ({ foo_ids }) => {
215+
expect(foo_ids).toEqual([1, 2, 3]);
216+
return Promise.resolve([
217+
{ nested: { foo_id: 2, foo_value: 'world' } },
218+
{ nested: { foo_id: 1, foo_value: 'hello' } },
219+
{ nested: { foo_id: 3, foo_value: '!' } },
220+
]);
221+
},
222+
};
223+
224+
await createDataLoaders(config, async (getLoaders) => {
225+
const loaders = getLoaders(resources);
226+
227+
const results = await loaders.foo.loadMany([{ foo_id: 1 }, { foo_id: 2 }, { foo_id: 3 }]);
228+
expect(results).toEqual([
229+
{ nested: { foo_id: 1, foo_value: 'hello' } },
230+
{ nested: { foo_id: 2, foo_value: 'world' } },
231+
{ nested: { foo_id: 3, foo_value: '!' } },
232+
]);
233+
});
234+
});
235+
199236
test('batch endpoint (with nestedPath)', async () => {
200237
const config = {
201238
resources: {

schema.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@
8080
},
8181
"reorderResultsByKey": {
8282
"type": "string",
83-
"description": "(Optional) If the resource itself does not guarantee ordering, this key specifies which key in the response objects corresponds to an element in `batchKey`. We use this to transfrom and re-order the response to the same order as in batchKey."
83+
"description": "(Optional) If the resource itself does not guarantee ordering, this key specifies which key in the response objects corresponds to an element in `batchKey`. We use this to transfrom and re-order the response to the same order as in batchKey. Can be a dot separated nested path."
8484
},
8585
"nestedPath": {
8686
"type": "string",

src/runtimeHelpers.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ export function sortByKeys<V>({
169169
items,
170170
/** The IDs we originally requested from the endpoint */
171171
keys,
172-
/** The attribute of each element in `items` that maps it to an element in `keys`. */
172+
/** The attribute of each element in `items` that maps it to an element in `keys`. Can be a dot-separated nested path. */
173173
prop,
174174
/** Some path that indicates what resource this is being used on. Used for stack traces. */
175175
resourcePath,
@@ -212,10 +212,9 @@ export function sortByKeys<V>({
212212

213213
itemsMap.set(String(reorderResultsByValue), item);
214214
} else {
215-
// @ts-ignore: TODO: Work how to tell typescript item[prop] exists
216-
invariant(item[prop] != null, `${errorPrefix(resourcePath)} Could not find property "${prop}" in item`);
217-
// @ts-ignore: TODO: Work how to tell typescript item[prop] exists
218-
itemsMap.set(String(item[prop]), item);
215+
const sortKey = _.get(item, prop);
216+
invariant(sortKey != null, `${errorPrefix(resourcePath)} Could not find property "${prop}" in item`);
217+
itemsMap.set(String(sortKey), item);
219218
}
220219
});
221220

0 commit comments

Comments
 (0)