Skip to content

Commit 62e8211

Browse files
authored
feat(rewriter): expose parent object and element path to rewriter (#20)
* feat(rewriter): expose parent object and element path to rewriter This changes the implementation of `rewriteResultsAtPath` so that now the parent and path of the element is exposed to `Rewriter`.`rewriteResponse` instead of the element itself. This should support implement field name response rewrites. BREAKING CHANGE: This changes the definition of `Rewriter`.`rewriteResponse`. The `path` references the location of the element while the `response` points to the parent of the element. Combining these will result in the original behavior. * refactor: rename property to fix shallowing * refactor: rename variable for clarity
1 parent 42c05c8 commit 62e8211

File tree

6 files changed

+65
-40
lines changed

6 files changed

+65
-40
lines changed

src/RewriteHandler.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@ export default class RewriteHandler {
7272
let rewrittenResponse = response;
7373
this.matches.reverse().forEach(({ rewriter, paths }) => {
7474
paths.forEach(path => {
75-
rewrittenResponse = rewriteResultsAtPath(rewrittenResponse, path, responseAtPath =>
76-
rewriter.rewriteResponse(responseAtPath)
75+
rewrittenResponse = rewriteResultsAtPath(rewrittenResponse, path, (parentResponse, key) =>
76+
rewriter.rewriteResponse(parentResponse, key)
7777
);
7878
});
7979
});

src/ast.ts

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -261,24 +261,38 @@ interface ResultObj {
261261
export const rewriteResultsAtPath = (
262262
results: ResultObj,
263263
path: ReadonlyArray<string>,
264-
callback: (resultsAtPath: any) => any
264+
callback: (parentResult: any, key: string | number) => any
265265
): ResultObj => {
266-
if (path.length === 0) return callback(results);
266+
if (path.length === 0) return results;
267+
267268
const curPathElm = path[0];
268-
const remainingPath = path.slice(1);
269269
const newResults = { ...results };
270270
const curResults = results[curPathElm];
271+
272+
if (path.length === 1) {
273+
if (Array.isArray(curResults)) {
274+
newResults[curPathElm] = curResults.map((_, index) => {
275+
const newValue = callback(curResults, index);
276+
return newValue;
277+
});
278+
} else {
279+
newResults[curPathElm] = callback(results, curPathElm);
280+
}
281+
282+
return newResults;
283+
}
284+
285+
const remainingPath = path.slice(1);
271286
// if the path stops here, just return results without any rewriting
272287
if (curResults === undefined || curResults === null) return results;
273288

274289
if (Array.isArray(curResults)) {
275-
newResults[curPathElm] = curResults.reduce((acc, resultElm) => {
276-
const elmResults = rewriteResultsAtPath(resultElm, remainingPath, callback);
277-
return acc.concat(elmResults);
278-
}, []);
279-
return newResults;
290+
newResults[curPathElm] = curResults.map(result =>
291+
rewriteResultsAtPath(result, remainingPath, callback)
292+
);
293+
} else {
294+
newResults[curPathElm] = rewriteResultsAtPath(curResults, remainingPath, callback);
280295
}
281296

282-
newResults[curPathElm] = rewriteResultsAtPath(curResults, remainingPath, callback);
283297
return newResults;
284298
};

src/rewriters/NestFieldOutputsRewriter.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,16 +65,21 @@ class NestFieldOutputsRewriter extends Rewriter {
6565
} as NodeAndVarDefs;
6666
}
6767

68-
public rewriteResponse(response: any) {
69-
if (typeof response === 'object') {
68+
public rewriteResponse(response: any, key: string | number) {
69+
const pathResponse = super.rewriteResponse(response, key);
70+
71+
if (typeof pathResponse === 'object') {
7072
// undo the nesting in the response so it matches the original query
71-
if (response[this.newOutputName] && typeof response[this.newOutputName] === 'object') {
72-
const rewrittenResponse = { ...response, ...response[this.newOutputName] };
73+
if (
74+
pathResponse[this.newOutputName] &&
75+
typeof pathResponse[this.newOutputName] === 'object'
76+
) {
77+
const rewrittenResponse = { ...pathResponse, ...pathResponse[this.newOutputName] };
7378
delete rewrittenResponse[this.newOutputName];
7479
return rewrittenResponse;
7580
}
7681
}
77-
return response;
82+
return pathResponse;
7883
}
7984
}
8085

src/rewriters/Rewriter.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ abstract class Rewriter {
5656
return variables;
5757
}
5858

59-
public rewriteResponse(response: any): any {
60-
return response;
59+
public rewriteResponse(response: any, key: string | number): any {
60+
return response[key];
6161
}
6262
}
6363

src/rewriters/ScalarFieldToObjectFieldRewriter.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,15 @@ class ScalarFieldToObjectFieldRewriter extends Rewriter {
4848
} as NodeAndVarDefs;
4949
}
5050

51-
public rewriteResponse(response: any) {
51+
public rewriteResponse(response: any, key: string | number) {
52+
const pathResponse = super.rewriteResponse(response, key);
53+
5254
if (typeof response === 'object') {
5355
// undo the nesting in the response so it matches the original query
54-
return response[this.objectFieldName];
56+
return pathResponse[this.objectFieldName];
5557
}
56-
return response;
58+
59+
return pathResponse;
5760
}
5861
}
5962

test/ast.test.ts

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@ describe('ast utils', () => {
1616
moreThings: [{ type: 'dog' }, { type: 'cat' }, { type: 'lion' }]
1717
}
1818
};
19-
expect(rewriteResultsAtPath(obj, ['thing1', 'moreThings', 'type'], elm => elm + '!')).toEqual(
20-
{
21-
thing1: {
22-
moreThings: [{ type: 'dog!' }, { type: 'cat!' }, { type: 'lion!' }]
23-
}
19+
expect(
20+
rewriteResultsAtPath(obj, ['thing1', 'moreThings', 'type'], (elm, path) => elm[path] + '!')
21+
).toEqual({
22+
thing1: {
23+
moreThings: [{ type: 'dog!' }, { type: 'cat!' }, { type: 'lion!' }]
2424
}
25-
);
25+
});
2626
});
2727

2828
it("doesn't include null or undefined results", () => {
@@ -49,20 +49,23 @@ describe('ast utils', () => {
4949
}
5050
]
5151
};
52-
expect(rewriteResultsAtPath(obj, ['things', 'moreThings', 'type'], elm => elm + '!')).toEqual(
53-
{
54-
things: [
55-
{
56-
moreThings: [{ type: 'dog!' }, { type: 'cat!' }]
57-
},
58-
{
59-
moreThings: [{ type: 'bear!' }, { type: 'cat!' }]
60-
}
61-
]
62-
}
63-
);
6452
expect(
65-
rewriteResultsAtPath(obj, ['things', 'moreThings'], elm => ({ ...elm, meh: '7' }))
53+
rewriteResultsAtPath(obj, ['things', 'moreThings', 'type'], (elm, path) => elm[path] + '!')
54+
).toEqual({
55+
things: [
56+
{
57+
moreThings: [{ type: 'dog!' }, { type: 'cat!' }]
58+
},
59+
{
60+
moreThings: [{ type: 'bear!' }, { type: 'cat!' }]
61+
}
62+
]
63+
});
64+
expect(
65+
rewriteResultsAtPath(obj, ['things', 'moreThings'], (elm, path) => ({
66+
...elm[path],
67+
meh: '7'
68+
}))
6669
).toEqual({
6770
things: [
6871
{

0 commit comments

Comments
 (0)