Skip to content

Commit

Permalink
feat(serverless): Add @tsed/platform-serverless-http package
Browse files Browse the repository at this point in the history
  • Loading branch information
Romakita committed Nov 28, 2021
1 parent 7bc75d8 commit 4a8f26a
Show file tree
Hide file tree
Showing 24 changed files with 4,268 additions and 187 deletions.
2 changes: 2 additions & 0 deletions .nycrc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
"packages/**/RouteService.ts",
"packages/platform/platform-test-utils",
"packages/platform/platform-serverless",
"packages/platform/platform-serverless-http",
"packages/platform/platform-serverless-testing",
"packages/platform/platform-log-middleware",
"packages/security/oidc-provider",
"packages/orm",
Expand Down
115 changes: 80 additions & 35 deletions docs/tutorials/aws.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
---
meta:
- name: description
- name: description
content: Guide to deploy your Ts.ED application on AWS.
- name: keywords
content: ts.ed express typescript aws node.js javascript decorators
---

# Serverless HTTP

<Banner src="https://upload.wikimedia.org/wikipedia/commons/thumb/9/93/Amazon_Web_Services_Logo.svg/langfr-220px-Amazon_Web_Services_Logo.svg.png" href="https://aws.amazon.com/fr/" :height="180" />

Amazon Web Services is one possible way to host your Node.js application.

This tutorial shows you how to configure Ts.ED application, to be executed as an AWS Lambda Function.
Under the hood, @tsed/platform-aws uses [serverless-http](https://www.npmjs.com/package/serverless-http) to handle AWS event and call Express.js/Koa.js application.
This tutorial shows you how to configure Ts.ED application, to be executed as an AWS Lambda Function. Under the hood,
@tsed/platform-aws uses [serverless-http](https://www.npmjs.com/package/serverless-http) to handle AWS event and call
Express.js/Koa.js application.

::: tip
[Serverless](https://www.serverless.com/) is a free and open-source web framework written using Node.js. Serverless is
Expand All @@ -35,9 +37,6 @@ It supports:
- Operation descriptions like `@Returns`,
- `@tsed/async-hook-context` to inject Context anywhere in your class!

## Installation


## Installation

Generate a new project with the CLI (you can also start from an existing project):
Expand All @@ -54,8 +53,7 @@ tsed init .
? Choose the package manager: Yarn
```

::: tip
This tutorial works also with NPM package manager!
::: tip This tutorial works also with NPM package manager!
:::


Expand Down Expand Up @@ -111,7 +109,8 @@ Remove the http and https port configuration from `Server.ts`:
// httpPort: 8080,
// httpsPort: false
})
export class Server {}
export class Server {
}
```

And add the http port for our local server directly on `index.ts` file:
Expand All @@ -131,16 +130,20 @@ async function bootstrap() {

return platform;
}

bootstrap();
```

Create new `handler.ts` to expose your lambda:

```typescript
import {PlatformServerless} from "@tsed/serverless";
import {PlatformServerlessHttp} from "@tsed/platform-serverless-http";
import {PlatformExpress} from "@tsed/platform-express";
import {Server} from "./Server";

const platform = PlatformServerless.bootstrap(Server, {})
const platform = PlatformServerlessHttp.bootstrap(Server, {
adapter: PlatformExpress
})

export const handler = platform.handler();
```
Expand All @@ -153,12 +156,12 @@ service: timeslots
frameworkVersion: '2'

provider:
name: aws
runtime: nodejs14.x
lambdaHashingVersion: '20201221'
name: aws
runtime: nodejs14.x
lambdaHashingVersion: '20201221'

plugins:
- serverless-offline
- serverless-offline

functions:
any:
Expand All @@ -174,10 +177,12 @@ functions:

## Invoke a lambda with serverless

Serverless provide a plugin named `serverless-offline`. This Serverless plugin emulates AWS λ and API Gateway on your local machine to speed up your development cycles.
To do so, it starts an HTTP server that handles the request's lifecycle like API does and invokes your handlers.
Serverless provide a plugin named `serverless-offline`. This Serverless plugin emulates AWS λ and API Gateway on your
local machine to speed up your development cycles. To do so, it starts an HTTP server that handles the request's
lifecycle like API does and invokes your handlers.

So, by using the `serverless offline` command, we'll be able to invoke our function. For that, we need also to build our code before invoke the lambda.
So, by using the `serverless offline` command, we'll be able to invoke our function. For that, we need also to build our
code before invoke the lambda.

To simplify our workflow, we can add the following npm script command in our `package.json`:

Expand All @@ -201,13 +206,13 @@ You should see in the terminal the following result:

```json
{
"statusCode": 200,
"body": "[{\"id\":\"b6de4fc7-faaa-4cd7-a144-42f6af0dec6b\",\"title\":\"title\",\"description\":\"description\",\"start_date\":\"2021-10-29T10:40:57.019Z\",\"end_date\":\"2021-10-29T10:40:57.019Z\",\"created_at\":\"2021-10-29T10:40:57.019Z\",\"update_at\":\"2021-10-29T10:40:57.019Z\"}]",
"headers": {
"content-type": "application/json",
"x-request-id": "ebb52d5e-113b-40da-b34e-c14811df596b"
},
"isBase64Encoded": false
"statusCode": 200,
"body": "[{\"id\":\"b6de4fc7-faaa-4cd7-a144-42f6af0dec6b\",\"title\":\"title\",\"description\":\"description\",\"start_date\":\"2021-10-29T10:40:57.019Z\",\"end_date\":\"2021-10-29T10:40:57.019Z\",\"created_at\":\"2021-10-29T10:40:57.019Z\",\"update_at\":\"2021-10-29T10:40:57.019Z\"}]",
"headers": {
"content-type": "application/json",
"x-request-id": "ebb52d5e-113b-40da-b34e-c14811df596b"
},
"isBase64Encoded": false
}
```

Expand All @@ -216,22 +221,62 @@ You should see in the terminal the following result:
This package includes decorators to easily get the event object Lambda received from API Gateway:

```typescript
import {Controller, Get} from "@tsed/common";
import {ServerlessEvent, ServerlessContext} from "@tsed/platform-serverless-http";
import {Controller, Get} from "@tsed/common";
import {ServerlessEvent, ServerlessContext} from "@tsed/platform-serverless-http";

@Controller("/")
class MyCtrl {
@Get("/")
get(@ServerlessEvent() event: any, @ServerlessContext() context: any) {
console.log("Event", event);
console.log("Context", context);
return apiGateway;
}
@Get("/")
get(@ServerlessEvent() event: any, @ServerlessContext() context: ServerlessContext) {
console.log("Event", event);
console.log("Context", context);

return { event, context };
}
}
```

## Author
## Testing

Ts.ED provide a way to test you lambda with mocked Aws event and context by using the @@PlatformServerlessTest@@ util.

Here an example to test a Lambda controller:

```typescript
import {PlatformServerless} from "@tsed/platform-serverless-http";
import {PlatformServerlessTest} from "@tsed/platform-serverless-testing";
import {PlatformExpress} from "@tsed/platform-express";
import {Server} from "./Server";

@Controller("/timeslots")
class TimeslotsController {
@Get("/")
getAll() {
return [];
}
}

describe("TimeslotsController", () => {
beforeEach(
PlatformServerlessTest.bootstrap(PlatformServerlessHttp, {
server: Server,
mount: {
"/": [TimeslotsLambdaController]
}
})
);
afterEach(() => PlatformServerlessTest.reset());

it("should call getAll Lambda", async () => {
const response = await PlatformServerlessTest.request.get("/timeslots");

expect(response.statusCode).toEqual(200);
expect(JSON.parse(response.body)).toEqual([]);
});
});
```

## Author

<GithubContributors :users="['Romakita']"/>

Expand Down
7 changes: 5 additions & 2 deletions docs/tutorials/serverless.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ meta:

# Serverless

<Badge text="beta" /> <Badge text="Contributors are welcome" />
<Badge text="Contributors are welcome" />

<Banner src="https://user-images.githubusercontent.com/2752551/30405068-a7733b34-989e-11e7-8f66-7badaf1373ed.png" href="https://www.serverless.com/fr/" :height="180" />

Expand Down Expand Up @@ -320,6 +320,9 @@ Ts.ED provide a way to test you lambda with mocked Aws event and context by usin
Here an example to test a Lambda controller:

```typescript
import {PlatformServerlessTest} from "@tsed/platform-serverless-testing";
import {PlatformServerless} from "@tsed/platform-serverless";

@Controller("/")
class TimeslotsLambdaController {
@Get("/")
Expand All @@ -339,7 +342,7 @@ class TimeslotsLambdaController {

describe("TimeslotsLambdaController", () => {
beforeEach(
PlatformServerlessTest.bootstrap({
PlatformServerlessTest.bootstrap(PlatformServerless, {
lambda: [TimeslotsLambdaController]
})
);
Expand Down
10 changes: 5 additions & 5 deletions packages/platform/platform-serverless-http/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
// https://jestjs.io/docs/en/configuration.html

module.exports = {
...require("@tsed/jest-config")(__dirname, "platform-serverless"),
...require("@tsed/jest-config")(__dirname, "platform-serverless-http"),
coverageThreshold: {
global: {
branches: 83.78,
functions: 98.94,
lines: 99.28,
statements: 98.93
branches: 100,
functions: 100,
lines: 100,
statements: 100
}
}
};
34 changes: 19 additions & 15 deletions packages/platform/platform-serverless-http/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@tsed/platform-serverless-http",
"version": "6.89.0",
"version": "6.90.0",
"description": "Module to support Serverless HTTP function with Ts.ED",
"source": "./src/index.ts",
"main": "./lib/cjs/index.js",
Expand All @@ -14,7 +14,8 @@
"scripts": {
"build": "yarn run build:esm && yarn run build:cjs",
"build:cjs": "tsc --build tsconfig.compile.json",
"build:esm": "tsc --build tsconfig.compile.esm.json"
"build:esm": "tsc --build tsconfig.compile.esm.json",
"test": "cross-env NODE_ENV=test jest"
},
"private": false,
"keywords": [
Expand Down Expand Up @@ -54,23 +55,26 @@
"type": "git",
"url": "git+https://github.com/tsedio/tsed.git"
},
"devDependencies": {
"@tsed/common": "6.89.0",
"@tsed/core": "6.89.0",
"@tsed/di": "6.89.0"
},
"dependencies": {
"serverless-http": "^2.7.0",
"aws-lambda": "^1.0.7",
"tslib": "2.2.0"
},
"devDependencies": {
"@tsed/common": "6.90.0",
"@tsed/core": "6.90.0",
"@tsed/di": "6.90.0",
"@tsed/platform-serverless-testing": "6.90.0",
"aws-lambda": "^1.0.7",
"serverless-http": "^2.7.0"
},
"peerDependencies": {
"@tsed/common": "^6.89.0",
"@tsed/core": "^6.89.0",
"@tsed/di": "^6.89.0",
"@tsed/json-mapper": "^6.89.0",
"@tsed/common": "^6.90.0",
"@tsed/core": "^6.90.0",
"@tsed/di": "^6.90.0",
"@tsed/json-mapper": "^6.90.0",
"@tsed/logger": ">=6.0.0",
"@tsed/openspec": "^6.89.0",
"@tsed/schema": "^6.89.0"
"@tsed/openspec": "^6.90.0",
"@tsed/schema": "^6.90.0",
"aws-lambda": ">=1.0.7",
"serverless-http": ">=2.0.0"
}
}
Loading

0 comments on commit 4a8f26a

Please sign in to comment.