-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(adapters): added apollo server mutation adapter
- Loading branch information
Showing
4 changed files
with
468 additions
and
0 deletions.
There are no files selected for viewing
134 changes: 134 additions & 0 deletions
134
src/adapters/apollo-server/apollo-server-mutation.adapter.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
//#region Imports | ||
|
||
import { | ||
AdapterContract, | ||
AdapterRequest, | ||
GetResponseAdapterProps, | ||
OnErrorProps, | ||
} from '../../contracts'; | ||
import { | ||
ILogger, | ||
getDefaultIfUndefined, | ||
getEventBodyAsBuffer, | ||
} from '../../core'; | ||
|
||
//#endregion | ||
|
||
/** | ||
* The options for {@link ApolloServerMutationAdapter} | ||
*/ | ||
export type ApolloServerMutationAdapterOptions = { | ||
/** | ||
* Specify the name of mutation that will be called when an event was received | ||
*/ | ||
mutationName: string; | ||
|
||
/** | ||
* Specify the mutation result schema. | ||
* Use this to customize the behavior when you need to return a specific object to be handled by the Adapter, like SQS with Batch Mode. | ||
* | ||
* @defaultValue `{ __typename }` | ||
*/ | ||
mutationResultQuery?: string; | ||
}; | ||
|
||
/** | ||
* The adapter that wraps another adapter to force a transformation of the event data as a mutation to Apollo Server be able to handle. | ||
*/ | ||
export class ApolloServerMutationAdapter< | ||
TEvent, | ||
TContext, | ||
TResponse, | ||
TBaseAdapter extends AdapterContract<TEvent, TContext, TResponse>, | ||
> implements AdapterContract<TEvent, TContext, TResponse> | ||
{ | ||
//#region Constructor | ||
|
||
/** | ||
* The default constructor | ||
*/ | ||
constructor( | ||
protected readonly baseAdapter: TBaseAdapter, | ||
protected readonly options: ApolloServerMutationAdapterOptions, | ||
) {} | ||
|
||
//#endregion | ||
|
||
//#region Public Methods | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
public canHandle(event: unknown, context: TContext, log: ILogger): boolean { | ||
return this.baseAdapter.canHandle(event, context, log); | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
public getAdapterName(): string { | ||
return this.baseAdapter.getAdapterName() + 'Mutation'; | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
public getRequest( | ||
event: TEvent, | ||
context: TContext, | ||
log: ILogger, | ||
): AdapterRequest { | ||
const request = this.baseAdapter.getRequest(event, context, log); | ||
|
||
request.method = 'POST'; | ||
|
||
const operationName = this.options.mutationName; | ||
const mutationResultQuery = getDefaultIfUndefined( | ||
this.options.mutationResultQuery, | ||
'{ __typename }', | ||
); | ||
|
||
const mutationBody = JSON.stringify({ | ||
operationName, | ||
query: `mutation ${operationName} ($event: String) { ${operationName} (event: $event) ${mutationResultQuery} }`, | ||
variables: { | ||
event: request.body?.toString() || '', | ||
}, | ||
}); | ||
|
||
const [buffer, contentLength] = getEventBodyAsBuffer(mutationBody, false); | ||
|
||
request.body = buffer; | ||
request.headers['content-type'] = 'application/json'; | ||
request.headers['content-length'] = String(contentLength); | ||
|
||
return request; | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
public getResponse(props: GetResponseAdapterProps<TEvent>): TResponse { | ||
const { data, errors } = JSON.parse(props.body); | ||
|
||
if (!errors) { | ||
return this.baseAdapter.getResponse({ | ||
...props, | ||
body: JSON.stringify(data[this.options.mutationName]), | ||
}); | ||
} | ||
|
||
// when error happens, is the responsability of base adapter | ||
// to deal with error status code. | ||
return this.baseAdapter.getResponse(props); | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
public onErrorWhileForwarding(props: OnErrorProps<TEvent, TResponse>): void { | ||
return this.baseAdapter.onErrorWhileForwarding(props); | ||
} | ||
|
||
//#endregion | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './apollo-server-mutation.adapter'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
describe('ApolloServerMutationAdapter', () => { | ||
// very ugly, i know, but i didn't find any other way, sorry | ||
if (process.env.TEST_NODE_VERSION === '12.x') { | ||
it('when nodejs is 12.x', () => { | ||
expect(true).toEqual(true); | ||
}); | ||
} else require('./utils-apollo-mutation').runApolloServerTests(); | ||
}); |
Oops, something went wrong.