Skip to content

Commit 291d507

Browse files
committed
fix: enhance type safety for onQuery and onMutation handlers with generic parameters
1 parent 881138f commit 291d507

File tree

2 files changed

+68
-20
lines changed

2 files changed

+68
-20
lines changed

packages/event-handler/src/appsync-graphql/Router.ts

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,23 @@ class Router {
7878
* return payload;
7979
* });
8080
81+
* export const handler = async (event, context) =>
82+
* app.resolve(event, context);
83+
* ```
84+
*
85+
* You can also specify the type of the arguments using a generic type parameter:
86+
*
87+
* @example
88+
* ```ts
89+
* import { AppSyncGraphQLResolver } from '@aws-lambda-powertools/event-handler/appsync-graphql';
90+
*
91+
* const app = new AppSyncGraphQLResolver();
92+
*
93+
* app.onQuery<{ postId: string }>('getPost', async ({ postId }) => {
94+
* // postId is now typed as string
95+
* return { id: postId };
96+
* });
97+
8198
* export const handler = async (event, context) =>
8299
* app.resolve(event, context);
83100
* ```
@@ -111,24 +128,24 @@ class Router {
111128
* @param options - Optional route options.
112129
* @param options.typeName - The name of the GraphQL type to use for the resolver (defaults to 'Query').
113130
*/
114-
public onQuery(
131+
public onQuery<TParams extends Record<string, unknown>>(
115132
fieldName: string,
116-
handler: OnQueryHandler,
133+
handler: OnQueryHandler<TParams>,
117134
options?: GraphQlRouteOptions
118135
): void;
119136
public onQuery(
120137
fieldName: string,
121138
options?: GraphQlRouteOptions
122139
): MethodDecorator;
123-
public onQuery(
140+
public onQuery<TParams extends Record<string, unknown>>(
124141
fieldName: string,
125-
handler?: OnQueryHandler | GraphQlRouteOptions,
142+
handler?: OnQueryHandler<TParams> | GraphQlRouteOptions,
126143
options?: GraphQlRouteOptions
127144
): MethodDecorator | undefined {
128145
if (handler && typeof handler === 'function') {
129146
this.onQueryRegistry.register({
130147
fieldName,
131-
handler,
148+
handler: handler as OnQueryHandler<Record<string, unknown>>,
132149
typeName: options?.typeName ?? 'Query',
133150
});
134151
return;
@@ -138,7 +155,7 @@ class Router {
138155
const routeOptions = isRecord(handler) ? handler : options;
139156
this.onQueryRegistry.register({
140157
fieldName,
141-
handler: descriptor.value,
158+
handler: descriptor.value as OnQueryHandler<Record<string, unknown>>,
142159
typeName: routeOptions?.typeName ?? 'Query',
143160
});
144161
return descriptor;
@@ -166,6 +183,23 @@ class Router {
166183
* app.resolve(event, context);
167184
* ```
168185
*
186+
* You can also specify the type of the arguments using a generic type parameter:
187+
*
188+
* @example
189+
* ```ts
190+
* import { AppSyncGraphQLResolver } from '@aws-lambda-powertools/event-handler/appsync-graphql';
191+
*
192+
* const app = new AppSyncGraphQLResolver();
193+
*
194+
* app.onMutation<{ title: string; content: string }>('createPost', async ({ title, content }) => {
195+
* // title and content are now typed as string
196+
* return { id: '123', title, content };
197+
* });
198+
*
199+
* export const handler = async (event, context) =>
200+
* app.resolve(event, context);
201+
* ```
202+
*
169203
* As a decorator:
170204
*
171205
* @example
@@ -195,24 +229,24 @@ class Router {
195229
* @param options - Optional route options.
196230
* @param options.typeName - The name of the GraphQL type to use for the resolver (defaults to 'Mutation').
197231
*/
198-
public onMutation(
232+
public onMutation<TParams extends Record<string, unknown>>(
199233
fieldName: string,
200-
handler: OnMutationHandler,
234+
handler: OnMutationHandler<TParams>,
201235
options?: GraphQlRouteOptions
202236
): void;
203237
public onMutation(
204238
fieldName: string,
205239
options?: GraphQlRouteOptions
206240
): MethodDecorator;
207-
public onMutation(
241+
public onMutation<TParams extends Record<string, unknown>>(
208242
fieldName: string,
209-
handler?: OnMutationHandler | GraphQlRouteOptions,
243+
handler?: OnMutationHandler<TParams> | GraphQlRouteOptions,
210244
options?: GraphQlRouteOptions
211245
): MethodDecorator | undefined {
212246
if (handler && typeof handler === 'function') {
213247
this.onMutationRegistry.register({
214248
fieldName,
215-
handler,
249+
handler: handler as OnMutationHandler<Record<string, unknown>>,
216250
typeName: options?.typeName ?? 'Mutation',
217251
});
218252
return;
@@ -222,7 +256,7 @@ class Router {
222256
const routeOptions = isRecord(handler) ? handler : options;
223257
this.onMutationRegistry.register({
224258
fieldName,
225-
handler: descriptor.value,
259+
handler: descriptor.value as OnMutationHandler<Record<string, unknown>>,
226260
typeName: routeOptions?.typeName ?? 'Mutation',
227261
});
228262
return descriptor;

packages/event-handler/src/types/appsync-graphql.ts

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,33 @@
11
import type { RouteHandlerRegistry } from '../appsync-graphql/RouteHandlerRegistry.js';
2-
import type { Anything, GenericLogger } from './common.js';
2+
import type { GenericLogger } from './common.js';
33

44
// #region OnQuery fn
55

6-
type OnQuerySyncHandlerFn = ({ ...args }: Anything) => unknown;
6+
type OnQuerySyncHandlerFn<TParams extends Record<string, unknown>> = (
7+
args: TParams
8+
) => unknown;
79

8-
type OnQueryHandlerFn = ({ ...args }: Anything) => Promise<unknown>;
10+
type OnQueryHandlerFn<TParams extends Record<string, unknown>> = (
11+
args: TParams
12+
) => Promise<unknown>;
913

10-
type OnQueryHandler = OnQuerySyncHandlerFn | OnQueryHandlerFn;
14+
type OnQueryHandler<TParams extends Record<string, unknown>> =
15+
| OnQuerySyncHandlerFn<TParams>
16+
| OnQueryHandlerFn<TParams>;
1117

1218
// #region OnMutation fn
1319

14-
type OnMutationSyncHandlerFn = ({ ...args }: Anything) => unknown;
20+
type OnMutationSyncHandlerFn<TParams extends Record<string, unknown>> = (
21+
args: TParams
22+
) => unknown;
1523

16-
type OnMutationHandlerFn = ({ ...args }: Anything) => Promise<unknown>;
24+
type OnMutationHandlerFn<TParams extends Record<string, unknown>> = (
25+
args: TParams
26+
) => Promise<unknown>;
1727

18-
type OnMutationHandler = OnMutationSyncHandlerFn | OnMutationHandlerFn;
28+
type OnMutationHandler<TParams extends Record<string, unknown>> =
29+
| OnMutationSyncHandlerFn<TParams>
30+
| OnMutationHandlerFn<TParams>;
1931

2032
// #region Resolver registry
2133

@@ -47,7 +59,9 @@ type RouteHandlerOptions = {
4759
/**
4860
* The handler function to be called when the event is received
4961
*/
50-
handler: OnQueryHandler | OnMutationHandler;
62+
handler:
63+
| OnQueryHandler<Record<string, unknown>>
64+
| OnMutationHandler<Record<string, unknown>>;
5165
/**
5266
* The field name of the event to be registered
5367
*/

0 commit comments

Comments
 (0)