diff --git a/src/rewriters/FieldNameRewriter.ts b/src/rewriters/FieldNameRewriter.ts new file mode 100644 index 0000000..3b9de93 --- /dev/null +++ b/src/rewriters/FieldNameRewriter.ts @@ -0,0 +1,41 @@ +import { ASTNode, FieldNode } from 'graphql'; +import Rewriter, { RewriterOpts } from './Rewriter'; +import { NodeAndVarDefs } from '../ast'; + +interface FieldNameRewriterOpts extends RewriterOpts { + newFieldName: string; +} + +export default class FieldNameRewriter extends Rewriter { + protected newFieldName: string; + + constructor(options: FieldNameRewriterOpts) { + super(options); + this.newFieldName = options.newFieldName; + } + + public matches(nodeAndVars: NodeAndVarDefs, parents: ASTNode[]) { + if (!super.matches(nodeAndVars, parents)) return false; + const node = nodeAndVars.node as FieldNode; + if (node.kind !== 'Field') return false; + if (node.name.value !== this.fieldName) return false; + return true; + } + + public rewriteQuery(nodeAndVarDefs: NodeAndVarDefs): NodeAndVarDefs { + const node = nodeAndVarDefs.node as FieldNode; + const { variableDefinitions } = nodeAndVarDefs; + const updatedNode = { + ...node, + name: { kind: 'Name', value: this.newFieldName } + } as FieldNode; + + return { node: updatedNode, variableDefinitions }; + } + + public rewriteResponse(response: any, key: string, index?: number): any { + const element = super.extractReponseElement(response, key, index); + super.rewriteResponseElement(response, element, this.fieldName, index); + return super.deleteResponseElement(response, this.newFieldName, index); + } +} diff --git a/src/rewriters/Rewriter.ts b/src/rewriters/Rewriter.ts index f33d659..e52702d 100644 --- a/src/rewriters/Rewriter.ts +++ b/src/rewriters/Rewriter.ts @@ -109,6 +109,23 @@ abstract class Rewriter { return response; } + + protected deleteResponseElement(response: any, key: string, index?: number): any { + // Verify the response format + if (response === null || typeof response !== 'object') return response; + + // Extract the key + const element = response[key]; + + // Extract the position + if (Array.isArray(element)) { + element.splice(index!, 1); + } else { + delete response[key]; + } + + return response; + } } export default Rewriter; diff --git a/src/rewriters/index.ts b/src/rewriters/index.ts index 35376e3..a28d431 100644 --- a/src/rewriters/index.ts +++ b/src/rewriters/index.ts @@ -2,6 +2,7 @@ export { default as Rewriter, RewriterOpts } from './Rewriter'; export { default as FieldArgNameRewriter } from './FieldArgNameRewriter'; export { default as FieldArgsToInputTypeRewriter } from './FieldArgsToInputTypeRewriter'; export { default as FieldArgTypeRewriter } from './FieldArgTypeRewriter'; +export { default as FieldNameRewriter } from './FieldNameRewriter'; export { default as NestFieldOutputsRewriter } from './NestFieldOutputsRewriter'; export { default as ScalarFieldToObjectFieldRewriter } from './ScalarFieldToObjectFieldRewriter'; export { default as JsonToTypedObjectRewriter } from './JsonToTypedObjectRewriter'; diff --git a/test/functional/rewriteFieldName.test.ts b/test/functional/rewriteFieldName.test.ts new file mode 100644 index 0000000..3e37e50 --- /dev/null +++ b/test/functional/rewriteFieldName.test.ts @@ -0,0 +1,101 @@ +import RewriteHandler from '../../src/RewriteHandler'; +import FieldNameRewriter from '../../src/rewriters/FieldNameRewriter'; +import { gqlFmt } from '../testUtils'; + +describe('Rewrite field name', () => { + it('allows rewriting the name of a field', () => { + const handler = new RewriteHandler([ + new FieldNameRewriter({ + fieldName: 'createThing', + newFieldName: 'thingCreate' + }) + ]); + + const query = gqlFmt` + mutation createMyThings { + createThing { + myThingId + } + otherMutation { + otherField + } + } + `; + const expectedRewritenQuery = gqlFmt` + mutation createMyThings { + thingCreate { + myThingId + } + otherMutation { + otherField + } + } + `; + expect(handler.rewriteRequest(query)).toEqual({ + query: expectedRewritenQuery, + variables: undefined + }); + + const response = { + thingCreate: { + myThingId: 'meh' + }, + otherMutation: { + otherField: 18 + } + }; + const expectedResponse = { + createThing: { + myThingId: 'meh' + }, + otherMutation: { + otherField: 18 + } + }; + expect(handler.rewriteResponse(response)).toEqual(expectedResponse); + }); + + it('allows rewriting the name of a field in array', () => { + const handler = new RewriteHandler([ + new FieldNameRewriter({ + fieldName: 'myThingId', + newFieldName: 'id' + }) + ]); + + const query = gqlFmt` + mutation createMyThings { + createThings { + myThingId + } + } + `; + const expectedRewritenQuery = gqlFmt` + mutation createMyThings { + createThings { + id + } + } + `; + expect(handler.rewriteRequest(query)).toEqual({ + query: expectedRewritenQuery, + variables: undefined + }); + + const response = { + createThings: [ + { + id: '1' + } + ] + }; + const expectedResponse = { + createThings: [ + { + myThingId: '1' + } + ] + }; + expect(handler.rewriteResponse(response)).toEqual(expectedResponse); + }); +});