Skip to content

Commit 342070f

Browse files
authored
Merge pull request #357 from Yelp/support-nested-keys
Add support for nested paths to reorderResultsByKey
2 parents c365b73 + 9cf0790 commit 342070f

File tree

4 files changed

+55
-20
lines changed

4 files changed

+55
-20
lines changed

API_DOCS.md

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -176,20 +176,20 @@ Describes the shape and behaviour of the resources object you will pass to `getL
176176

177177
#### `resources` Parameters
178178

179-
| Key | Value Description |
180-
| ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
181-
| `isBatchResource` | Is this a batch resource? (Can you pass it a list of keys and get a list of results back?) |
182-
| `docsLink` | The URL for the documentation of the resource. Useful for others to verify information is correct, and may be used in stack traces. |
183-
| `batchKey` | The argument to the resource that represents the list of entities we want to fetch. (e.g. 'user_ids') |
184-
| `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. |
186-
| `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'). |
187-
| `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 |
188-
| `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 |
189-
| `isBatchKeyASet` | (Optional) Set to true if the interface of the resource takes the batch key as a set (rather than an array). For example, when using a generated clientlib based on swagger where `uniqueItems: true` is set for the batchKey parameter. Default: false. |
190-
| `propertyBatchKey` | (Optional) The argument to the resource that represents the optional properties we want to fetch. (e.g. usually 'properties' or 'features'). |
191-
| `maxBatchSize` | (Optional) Limits the number of items that can be batched together in a single request. When more items are requested than this limit, multiple requests will be made. This can help prevent hitting URI length limits or timeouts for large batches. |
192-
| `responseKey` | (Non-optional when propertyBatchKey is used) The key in the response objects corresponds to `batchKey`. This should be the only field that are marked as required in your swagger endpoint response, except nestedPath. |
179+
| Key | Value Description |
180+
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
181+
| `isBatchResource` | Is this a batch resource? (Can you pass it a list of keys and get a list of results back?) |
182+
| `docsLink` | The URL for the documentation of the resource. Useful for others to verify information is correct, and may be used in stack traces. |
183+
| `batchKey` | The argument to the resource that represents the list of entities we want to fetch. (e.g. 'user_ids') |
184+
| `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. Can be a dot separated nested path. |
186+
| `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'). |
187+
| `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 |
188+
| `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 |
189+
| `isBatchKeyASet` | (Optional) Set to true if the interface of the resource takes the batch key as a set (rather than an array). For example, when using a generated clientlib based on swagger where `uniqueItems: true` is set for the batchKey parameter. Default: false. |
190+
| `propertyBatchKey` | (Optional) The argument to the resource that represents the optional properties we want to fetch. (e.g. usually 'properties' or 'features'). |
191+
| `maxBatchSize` | (Optional) Limits the number of items that can be batched together in a single request. When more items are requested than this limit, multiple requests will be made. This can help prevent hitting URI length limits or timeouts for large batches. |
192+
| `responseKey` | (Non-optional when propertyBatchKey is used) The key in the response objects corresponds to `batchKey`. This should be the only field that are marked as required in your swagger endpoint response, except nestedPath. |
193193
194194
### `typings`
195195

__tests__/implementation.test.js

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

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