Skip to content

Use strict types #38

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Oct 29, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,6 @@ jobs:
env:
NPM_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
- name: Bump versions
run: node ./common/scripts/install-run-rush.js rush version --bump --target-branch main
run: node ./common/scripts/install-run-rush.js version --bump --target-branch main
- name: publish
run: node ./common/scripts/install-run-rush.js publish -a -b main -p --set-access-level public --include-all
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,6 @@ jspm_packages/
# Rush temporary files
common/temp/
**/.rush/temp/

# JetBrains IDEs
.idea
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,24 @@ export const handler = compose(
})
```

There's a [known issue with TypeScript](https://github.com/microsoft/TypeScript/issues/29904) that pipe and compose functions cannot
infer types correctly if the innermost function is generic (in this case the last argument to `compose`).
If you use TypeScript in strict mode, you can instead use the `composeHandler` function exported from `@lambda-middleware/compose`:

```typescript
export const handler = composeHandler(
someMiddleware(),
someOtherMiddleware(),
aThirdMiddleware(),
() => {
return {
body: '',
statusCode: 200
}
}
)
```

Composing middleware is equivalent to calling it nested:
```typescript
export const handler =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"changes": [
{
"packageName": "@lambda-middleware/class-validator",
"comment": "Make compatible with TypeScript strict mode",
"type": "patch"
}
],
"packageName": "@lambda-middleware/class-validator",
"email": "[email protected]"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"changes": [
{
"packageName": "@lambda-middleware/compose",
"comment": "Add composeHandler function",
"type": "minor"
}
],
"packageName": "@lambda-middleware/compose",
"email": "[email protected]"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"changes": [
{
"packageName": "@lambda-middleware/http-header-normalizer",
"comment": "Make compatible with TypeScript strict mode",
"type": "patch"
}
],
"packageName": "@lambda-middleware/http-header-normalizer",
"email": "[email protected]"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"changes": [
{
"packageName": "@lambda-middleware/middy-adaptor",
"comment": "Make compatible with TypeScript strict mode",
"type": "patch"
}
],
"packageName": "@lambda-middleware/middy-adaptor",
"email": "[email protected]"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"changes": [
{
"packageName": "@lambda-middleware/utils",
"comment": "Make compatible with TypeScript strict mode",
"type": "patch"
}
],
"packageName": "@lambda-middleware/utils",
"email": "[email protected]"
}
31 changes: 19 additions & 12 deletions common/config/rush/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 13 additions & 7 deletions internal/e2e-tests/examples/helloWorld.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import "reflect-metadata";

import { classValidator } from "@lambda-middleware/class-validator";
import { compose } from "@lambda-middleware/compose";
import { composeHandler } from "@lambda-middleware/compose";
import { cors } from "@lambda-middleware/cors";
import { errorHandler } from "@lambda-middleware/http-error-handler";
import { jsonSerializer } from "@lambda-middleware/json-serializer";
Expand All @@ -11,6 +11,11 @@ import { IsString } from "class-validator";

// Define a validator for the body via class-validator
class NameBody {
constructor(firstName: string, lastName: string) {
this.firstName = firstName;
this.lastName = lastName;
}

@IsString()
public firstName: string;

Expand All @@ -19,14 +24,16 @@ class NameBody {
}

// This is your AWS handler
async function helloWorld(event: { body: NameBody }) {
async function helloWorld(event: {
body: NameBody;
}): Promise<{ message: string }> {
// Thanks to the validation middleware you can be sure body is typed correctly
return {
message: `Hello ${event.body.firstName} ${event.body.lastName}`,
};
}

const wrapper = compose(
export const handler = composeHandler(
// add cors headers last so even error responses from the
// errorHandler middleware have cors headers applied
cors(),
Expand All @@ -48,7 +55,6 @@ const wrapper = compose(
// and other middlewares might not be able to handle the modified event
classValidator({
bodyType: NameBody,
})
)(helloWorld);

export const handler = wrapper;
}),
helloWorld
);
14 changes: 10 additions & 4 deletions packages/class-validator/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,17 @@ This middleware is part of the [lambda middleware series](https://dbartholomae.g
import "reflect-metadata";

import { classValidator } from '@lambda-middleware/class-validator'
import { compose } from "@lambda-middleware/compose";
import { composeHandler } from "@lambda-middleware/compose";
import { errorHandler } from "@lambda-middleware/http-error-handler";
import { IsString } from "class-validator";

// Define a validator for the body via class-validator
class NameBody {
constructor(firstName: string, lastName: string) {
this.firstName = firstName;
this.lastName = lastName;
}

@IsString()
public firstName: string;

Expand All @@ -48,7 +53,7 @@ async function helloWorld(event: { body: NameBody }) {
}

// Let's add middleware to our handler, then we will be able to attach middlewares to it
export const handler = compose(
export const handler = composeHandler(
// The class validator throws validation errors from http-errors which are compatible with
// the error handler middlewares for middy
errorHandler(),
Expand All @@ -63,6 +68,7 @@ export const handler = compose(
// to set it to true manually as the default for class-validator would be
// false
validator: {},
})
)(helloWorld);
}),
helloWorld
);
```
19 changes: 14 additions & 5 deletions packages/class-validator/examples/helloWorld.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,18 @@
import "reflect-metadata";

import { classValidator } from "../";
import { compose } from "@lambda-middleware/compose";
import { composeHandler } from "@lambda-middleware/compose";
import { errorHandler } from "@lambda-middleware/http-error-handler";
import { IsString } from "class-validator";
import { APIGatewayProxyResult } from "aws-lambda";

// Define a validator for the body via class-validator
class NameBody {
constructor(firstName: string, lastName: string) {
this.firstName = firstName;
this.lastName = lastName;
}

@IsString()
public firstName: string;

Expand All @@ -16,7 +22,9 @@ class NameBody {
}

// This is your AWS handler
async function helloWorld(event: { body: NameBody }) {
async function helloWorld(event: {
body: NameBody;
}): Promise<APIGatewayProxyResult> {
// Thanks to the validation middleware you can be sure body is typed correctly
return {
body: `Hello ${event.body.firstName} ${event.body.lastName}`,
Expand All @@ -28,7 +36,7 @@ async function helloWorld(event: { body: NameBody }) {
}

// Let's add middleware to our handler, then we will be able to attach middlewares to it
export const handler = compose(
export const handler = composeHandler(
// The class validator throws validation errors from http-errors which are compatible with
// the error handler middlewares for middy
errorHandler(),
Expand All @@ -43,5 +51,6 @@ export const handler = compose(
// to set it to true manually as the default for class-validator would be
// false
validator: {},
})
)(helloWorld);
}),
helloWorld
);
5 changes: 5 additions & 0 deletions packages/class-validator/src/classValidator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ import { IsOptional, IsString } from "class-validator";
import { createEvent } from "@lambda-middleware/utils";

class NameBody {
constructor(firstName: string, lastName: string) {
this.firstName = firstName;
this.lastName = lastName;
}

@IsString()
public firstName: string;

Expand Down
Loading