From 4f3654e79607048c1e95bef7aec3a4029083d699 Mon Sep 17 00:00:00 2001 From: Cecil Tantay Date: Tue, 12 Sep 2023 08:35:50 -0700 Subject: [PATCH 01/11] fix(core): allow sync handlers --- packages/core/index.d.ts | 2 +- packages/core/index.test-d.ts | 184 +++++++++++++++++++++++++++++++++- 2 files changed, 184 insertions(+), 2 deletions(-) diff --git a/packages/core/index.d.ts b/packages/core/index.d.ts index 69f71fd26..d565547dd 100644 --- a/packages/core/index.d.ts +++ b/packages/core/index.d.ts @@ -68,7 +68,7 @@ type MiddyInputHandler< context: TContext, callback: LambdaCallback ) => // eslint-disable-next-line @typescript-eslint/no-invalid-void-type -void | Promise +void | Promise | TResult type MiddyInputPromiseHandler< TEvent, TResult, diff --git a/packages/core/index.test-d.ts b/packages/core/index.test-d.ts index f1a289c1e..0ce57126a 100644 --- a/packages/core/index.test-d.ts +++ b/packages/core/index.test-d.ts @@ -3,10 +3,19 @@ import middy from '.' import { APIGatewayProxyEvent, APIGatewayProxyResult, + Callback, Context, - Handler as LambdaHandler } from 'aws-lambda' +// extended Handler type from aws-lambda +// to include non Async TResult +type LambdaHandler = ( + event: TEvent, + context: Context, + callback: Callback, +) => void | Promise | TResult; + + const lambdaHandler: LambdaHandler = async (event) => { return { statusCode: 200, @@ -196,3 +205,176 @@ expectType>(streamifiedResponseHandler) streamifiedResponseHandler.handler(lambdaHandler) streamifiedResponseHandler.use(middlewareObj) + +// non async handler +const syncedLambdaHandler: LambdaHandler = async (event) => { + return { + statusCode: 200, + body: `Hello from ${event.path}` + } +} + +// initialize +let syncedHandler = middy(syncedLambdaHandler) +expectType(handler) + +// initialize with empty plugin +syncedHandler = middy(syncedLambdaHandler, {}) +expectType(syncedHandler) + +// initialize with plugin with few hooks +syncedHandler = middy(syncedLambdaHandler, { + beforePrefetch () { console.log('beforePrefetch') } +}) +expectType(syncedHandler) + +// initialize with plugin with all hooks +syncedHandler = middy(syncedLambdaHandler, { + beforePrefetch () { console.log('beforePrefetch') }, + requestStart () { console.log('requestStart') }, + beforeMiddleware (name: string) { console.log('beforeMiddleware', name) }, + afterMiddleware (name: string) { console.log('afterMiddleware', name) }, + beforeHandler () { console.log('beforeHandler') }, + afterHandler () { console.log('afterHandler') }, + async requestEnd () { console.log('requestEnd') } +}) +expectType(syncedHandler) + +// invokes the handler to test that it is callable +// eslint-disable-next-line @typescript-eslint/no-invalid-void-type +async function invokSyncedHandler (): Promise { + const sampleEvent: APIGatewayProxyEvent = { + resource: '/', + path: '/', + httpMethod: 'GET', + requestContext: { + resourcePath: '/', + httpMethod: 'GET', + path: '/Prod/', + accountId: 'x', + apiId: 'y', + authorizer: {}, + protocol: 'p', + identity: { + accessKey: '', + accountId: '', + apiKey: '', + apiKeyId: '', + caller: '', + clientCert: null, + cognitoAuthenticationProvider: '', + cognitoAuthenticationType: '', + cognitoIdentityId: '', + cognitoIdentityPoolId: '', + principalOrgId: '', + sourceIp: '', + user: '', + userAgent: '', + userArn: '' + }, + stage: '', + requestId: '', + requestTimeEpoch: 12345567, + resourceId: '' + }, + headers: { + accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', + 'accept-encoding': 'gzip, deflate, br', + Host: '70ixmpl4fl.execute-api.us-east-2.amazonaws.com', + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36', + 'X-Amzn-Trace-Id': 'Root=1-5e66d96f-7491f09xmpl79d18acf3d050' + }, + multiValueHeaders: { + accept: [ + 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9' + ], + 'accept-encoding': [ + 'gzip, deflate, br' + ] + }, + queryStringParameters: null, + multiValueQueryStringParameters: null, + pathParameters: null, + stageVariables: null, + body: null, + isBase64Encoded: false + } + const sampleContext: Context = { + callbackWaitsForEmptyEventLoop: true, + functionName: '', + functionVersion: '', + invokedFunctionArn: '', + memoryLimitInMB: '234', + awsRequestId: '', + logGroupName: '', + logStreamName: '', + getRemainingTimeInMillis: (): number => 1, + done: () => { }, + fail: (_) => { }, + succeed: () => { } + } + return handler(sampleEvent, sampleContext, () => {}) // synced handler +} +invokSyncedHandler().catch(console.error) + +// use with 1 middleware +syncedHandler = syncedHandler.use(middlewareObj) +expectType(syncedHandler) + +// use with array of middlewares +syncedHandler = syncedHandler.use([middlewareObj]) +expectType(syncedHandler) + +// before +syncedHandler = syncedHandler.before((request: Request) => { console.log('Before', request) }) +expectType(syncedHandler) + +// after +syncedHandler = syncedHandler.after((request: Request) => { console.log('After', request) }) +expectType(syncedHandler) + +// error +syncedHandler = syncedHandler.onError((request: Request) => { console.log('OnError', request) }) +expectType(syncedHandler) + +interface MutableContext extends Context { + name: string +} + +function syncedMutableContextDependantHandler (event: APIGatewayProxyEvent, context: MutableContext): APIGatewayProxyResult { + return { + statusCode: 200, + body: `Hello from ${context.name}` + } +} + +let customSyncedCtxHandler = middy(syncedMutableContextDependantHandler) +expectType(customSyncedCtxHandler) + +// @ts-expect-error +customSyncedCtxHandler = middy(syncedMutableContextDependantHandler) + +const mutableSyncedContextMiddleware = { + before: (request: MutableContextRequest) => { + request.context.name = 'Foo' + } +} + +customSyncedCtxHandler = customSyncedCtxHandler.use(mutableSyncedContextMiddleware) +expectType(customSyncedCtxHandler) + +const syncedTypeErrorMiddleware = { + before: (request: MutableContextRequest) => { + // @ts-expect-error + request.context.test = 'Bar' + } +} + +customSyncedCtxHandler = customSyncedCtxHandler.use(syncedTypeErrorMiddleware) +expectType(customSyncedCtxHandler) + +const syncedStreamifiedResponseHandler = middy({ streamifyResponse: true }) +expectType>(syncedStreamifiedResponseHandler) + +syncedStreamifiedResponseHandler.handler(syncedLambdaHandler) +syncedStreamifiedResponseHandler.use(middlewareObj) \ No newline at end of file From de0cc9560dc4dff454fc83565d67d280cd98df21 Mon Sep 17 00:00:00 2001 From: Cecil Tantay Date: Tue, 12 Sep 2023 08:43:19 -0700 Subject: [PATCH 02/11] fix(core): added new line --- packages/core/index.test-d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/index.test-d.ts b/packages/core/index.test-d.ts index 0ce57126a..06c39618e 100644 --- a/packages/core/index.test-d.ts +++ b/packages/core/index.test-d.ts @@ -377,4 +377,4 @@ const syncedStreamifiedResponseHandler = middy({ streamifyResponse: true }) expectType>(syncedStreamifiedResponseHandler) syncedStreamifiedResponseHandler.handler(syncedLambdaHandler) -syncedStreamifiedResponseHandler.use(middlewareObj) \ No newline at end of file +syncedStreamifiedResponseHandler.use(middlewareObj) From c96ea15302396a654ced85274106ae06304d5f16 Mon Sep 17 00:00:00 2001 From: Cecil Tantay Date: Tue, 12 Sep 2023 08:44:50 -0700 Subject: [PATCH 03/11] fix(core): update async func to sync func --- packages/core/index.test-d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/index.test-d.ts b/packages/core/index.test-d.ts index 06c39618e..cdc742aec 100644 --- a/packages/core/index.test-d.ts +++ b/packages/core/index.test-d.ts @@ -207,7 +207,7 @@ streamifiedResponseHandler.handler(lambdaHandler) streamifiedResponseHandler.use(middlewareObj) // non async handler -const syncedLambdaHandler: LambdaHandler = async (event) => { +const syncedLambdaHandler: LambdaHandler = (event) => { return { statusCode: 200, body: `Hello from ${event.path}` From 7390b7c5ea58530a8c96fce3f0c6c113dd5b71f1 Mon Sep 17 00:00:00 2001 From: Cecil Tantay Date: Tue, 12 Sep 2023 08:50:10 -0700 Subject: [PATCH 04/11] fix(core): lint fixes --- packages/core/index.test-d.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/core/index.test-d.ts b/packages/core/index.test-d.ts index cdc742aec..62fcbfa13 100644 --- a/packages/core/index.test-d.ts +++ b/packages/core/index.test-d.ts @@ -4,17 +4,17 @@ import { APIGatewayProxyEvent, APIGatewayProxyResult, Callback, - Context, + Context } from 'aws-lambda' // extended Handler type from aws-lambda // to include non Async TResult +// eslint-disable-next-line @typescript-eslint/no-invalid-void-type type LambdaHandler = ( event: TEvent, context: Context, callback: Callback, -) => void | Promise | TResult; - +) => void | Promise | TResult const lambdaHandler: LambdaHandler = async (event) => { return { @@ -313,7 +313,7 @@ async function invokSyncedHandler (): Promise { fail: (_) => { }, succeed: () => { } } - return handler(sampleEvent, sampleContext, () => {}) // synced handler + return syncedHandler(sampleEvent, sampleContext, () => {}) // synced handler } invokSyncedHandler().catch(console.error) From b5bd082d7339e02ccb6b089bca43dbb76e66906e Mon Sep 17 00:00:00 2001 From: Cecil Tantay Date: Tue, 12 Sep 2023 08:56:09 -0700 Subject: [PATCH 05/11] fix(core): more lint fixes --- packages/core/index.test-d.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/core/index.test-d.ts b/packages/core/index.test-d.ts index 62fcbfa13..557f41ba0 100644 --- a/packages/core/index.test-d.ts +++ b/packages/core/index.test-d.ts @@ -9,11 +9,11 @@ import { // extended Handler type from aws-lambda // to include non Async TResult -// eslint-disable-next-line @typescript-eslint/no-invalid-void-type type LambdaHandler = ( event: TEvent, context: Context, callback: Callback, +// eslint-disable-next-line @typescript-eslint/no-invalid-void-type ) => void | Promise | TResult const lambdaHandler: LambdaHandler = async (event) => { @@ -313,7 +313,9 @@ async function invokSyncedHandler (): Promise { fail: (_) => { }, succeed: () => { } } - return syncedHandler(sampleEvent, sampleContext, () => {}) // synced handler + // synced handler but could be void | Promise | TResult + // so it needs to be awaited + return await syncedHandler(sampleEvent, sampleContext, () => {}) } invokSyncedHandler().catch(console.error) From 90330cefacc92bf0f5906ba34168bea6907d6f41 Mon Sep 17 00:00:00 2001 From: Cecil Tantay Date: Tue, 12 Sep 2023 09:05:59 -0700 Subject: [PATCH 06/11] fix(core): added missed changes --- packages/core/index.test-d.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/core/index.test-d.ts b/packages/core/index.test-d.ts index 557f41ba0..f588c6ece 100644 --- a/packages/core/index.test-d.ts +++ b/packages/core/index.test-d.ts @@ -8,7 +8,7 @@ import { } from 'aws-lambda' // extended Handler type from aws-lambda -// to include non Async TResult +// to include synced TResult type LambdaHandler = ( event: TEvent, context: Context, @@ -216,7 +216,7 @@ const syncedLambdaHandler: LambdaHandler(handler) +expectType(syncedHandler) // initialize with empty plugin syncedHandler = middy(syncedLambdaHandler, {}) From 4921659207824a835f252005825c86ca7af710f7 Mon Sep 17 00:00:00 2001 From: Cecil Tantay Date: Tue, 12 Sep 2023 10:33:06 -0700 Subject: [PATCH 07/11] fix(core): update comments --- packages/core/index.test-d.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/core/index.test-d.ts b/packages/core/index.test-d.ts index f588c6ece..af6d4c9fe 100644 --- a/packages/core/index.test-d.ts +++ b/packages/core/index.test-d.ts @@ -313,8 +313,6 @@ async function invokSyncedHandler (): Promise { fail: (_) => { }, succeed: () => { } } - // synced handler but could be void | Promise | TResult - // so it needs to be awaited return await syncedHandler(sampleEvent, sampleContext, () => {}) } invokSyncedHandler().catch(console.error) From b865361a22d7836c5c2e716c8e05935337fc324f Mon Sep 17 00:00:00 2001 From: Cecil Tantay Date: Tue, 12 Sep 2023 22:20:16 -0700 Subject: [PATCH 08/11] fix(core): added utility type to add to return type --- packages/core/index.test-d.ts | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/core/index.test-d.ts b/packages/core/index.test-d.ts index af6d4c9fe..e9410b842 100644 --- a/packages/core/index.test-d.ts +++ b/packages/core/index.test-d.ts @@ -3,18 +3,18 @@ import middy from '.' import { APIGatewayProxyEvent, APIGatewayProxyResult, - Callback, - Context + Context, + Handler as AWSLambdaHandler } from 'aws-lambda' +type ModifyReturnType = T extends ( + ...args: infer A +) => infer R + ? (...args: A) => R | NewReturn + : never; + // extended Handler type from aws-lambda -// to include synced TResult -type LambdaHandler = ( - event: TEvent, - context: Context, - callback: Callback, -// eslint-disable-next-line @typescript-eslint/no-invalid-void-type -) => void | Promise | TResult +type LambdaHandler = ModifyReturnType, TResult> const lambdaHandler: LambdaHandler = async (event) => { return { @@ -206,7 +206,7 @@ expectType>(streamifiedResponseHandler) streamifiedResponseHandler.handler(lambdaHandler) streamifiedResponseHandler.use(middlewareObj) -// non async handler +// synced handler const syncedLambdaHandler: LambdaHandler = (event) => { return { statusCode: 200, From f4f0e1f856e13aea5de30dadd09e36a4b729b091 Mon Sep 17 00:00:00 2001 From: Cecil Tantay Date: Tue, 12 Sep 2023 22:25:49 -0700 Subject: [PATCH 09/11] fix(core): cleanup --- packages/core/index.test-d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/index.test-d.ts b/packages/core/index.test-d.ts index e9410b842..79c3ac7a0 100644 --- a/packages/core/index.test-d.ts +++ b/packages/core/index.test-d.ts @@ -7,13 +7,13 @@ import { Handler as AWSLambdaHandler } from 'aws-lambda' +// extends Handler type from aws-lambda type ModifyReturnType = T extends ( ...args: infer A ) => infer R ? (...args: A) => R | NewReturn : never; -// extended Handler type from aws-lambda type LambdaHandler = ModifyReturnType, TResult> const lambdaHandler: LambdaHandler = async (event) => { From e80e9c2c878edf302e9315661da4d8977effded9 Mon Sep 17 00:00:00 2001 From: Cecil Tantay Date: Tue, 12 Sep 2023 22:28:34 -0700 Subject: [PATCH 10/11] fix(core): fix lint issues --- packages/core/index.test-d.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/core/index.test-d.ts b/packages/core/index.test-d.ts index 79c3ac7a0..2659198a2 100644 --- a/packages/core/index.test-d.ts +++ b/packages/core/index.test-d.ts @@ -12,8 +12,8 @@ type ModifyReturnType = T extends ( ...args: infer A ) => infer R ? (...args: A) => R | NewReturn - : never; - + : never + type LambdaHandler = ModifyReturnType, TResult> const lambdaHandler: LambdaHandler = async (event) => { From 28f2e1ded0eae7a619d42af0b0e2e75475505690 Mon Sep 17 00:00:00 2001 From: Cecil Tantay Date: Tue, 12 Sep 2023 22:53:21 -0700 Subject: [PATCH 11/11] fix(core): added excplicit typing --- packages/core/index.test-d.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/core/index.test-d.ts b/packages/core/index.test-d.ts index 2659198a2..a40d464b7 100644 --- a/packages/core/index.test-d.ts +++ b/packages/core/index.test-d.ts @@ -8,13 +8,15 @@ import { } from 'aws-lambda' // extends Handler type from aws-lambda -type ModifyReturnType = T extends ( - ...args: infer A +type EnhanceHandlerType = T extends ( + event: infer TEvent, + context: infer TContextType, + callback: infer TCallbackType ) => infer R - ? (...args: A) => R | NewReturn + ? (event: TEvent, context: TContextType, callback: TCallbackType) => R | NewReturn : never -type LambdaHandler = ModifyReturnType, TResult> +type LambdaHandler = EnhanceHandlerType, TResult> const lambdaHandler: LambdaHandler = async (event) => { return {