Serverless Node TypeScript is a starter kit to write serverless applications in Node.js and TypeScript and deploying them by using the Serverless Framework. It comes with several configurations set up out of the box, such as MongoDB, a GraphQL API server, a REST endpoint and Domain Events via AWS SNS.
Serverless Node TypeScript is a starter kit for serverless applications written in TypeScript and using the Serverless Framework to bundle the Lambda functions.
The application is structured with Domain-Driven Design in mind.
It comes with the following features out of the box:
src/config/index.ts
)First, edit the application name in the name
field of the package.json
file.
Then run npm install
or yarn install
.
To run the application locally, just run npm run offline
.
When interacting with other AWS services such as SNS, SQS or S3, running the application offline is not enough to check that all binding we specified in the serverless.yml
file are working as expected.
A way to check whether the application would behave like expected once deployed to AWS, without really deploying it, is to deploy it locally by using Localstack.
In order to deploy the application locally you need to:
docker network create aws-nodejs
docker-compose up
(TMPDIR=/private$TMPDIR docker-compose up
in MacOs)npm run deploy-local
Postman
) to the deployed url http://localhost:4567/restapis/<CODE>/local/_user_request_/hello
where <CODE>
is found in the endpoints
section of the console output given by serverless in step 3. Eg. if the output containsendpoints:
http://localhost:4567/restapis/trcki9mhws/local/_user_request_
then <CODE>
is trcki9mhws
. The <CODE>
changes after every local deployment!
Deleting the Application or re-deploying
Due to limitations to Localstack, the best way to re-deploy the application effectively is to first stop and start Docker Compose and then deploying the application again.
Network name
The network name used in step 1 can be customised as preferred. However, change it accordingly also in the docker-compose.yaml
file under networks.default.external.name
and in LAMBDA_DOCKER_NETWORK
.
Custom Authorizers
At the moment, Lambda Authorizers are completely ignored by Localstack.
Connecting to other AWS services from inside the application
Due to how Docker Compose works, in order to connect to the AWS services hosted in the Localstack container, all calls to these services need to the redirected manually to http://localstack:XXXX
(instead than http://localhost:XXXX
).
For SNS, this is done at the very top of the handler.ts
file, by setting the SNS_ENDPOINT
env variable.
If willing to use other services, for example S3, you’ll need to manually set the endpoint
option key to point to http://localstack:4572
.
NODE_ENV
: Set the environment name, not used in the codeENV
: Set the environment name, this is the variable used throughout the code and set via the Serverless CLIMONGO_URI
: Set the complete MongoDB connection string. Default mongodb://localhost:27017/sls-node-ts-<ENV>}
, where <ENV>
in the ENV
env variable valueREGION
: AWS region, default eu-west-1
SEND_DOMAIN_EVENTS
: if set to true
, the application will effectively emit the Domain Events of the related Aggregate to its AWS SNS topic. Default is undefined
SNS_ENDPOINT
: in non staging
or production
environments, you can send Domain Events to a local implementation of AWS SNS. Default is http://localhost:4575
, i.e. the local url for the Localstack implementationThe deployment is handled by the Serverless Framework.
In order to deploy to a staging
environment, run npm run deploy-staging
. Instead, to deploy to a production
environment, run npm run deploy-production
.
To completely remove the deployed application, run npm run remove-staging
or npm run remove-production
.
Authentication is handled via Lambda Authorizers, easily configurable via Serverless Framework.
In practice, before starting our Lambda function, the Lambda Authorizer in src/api/authorizer/index.ts
will run. Inside it, custom code can be added, for example, to check or introspect an input Authorization Token.
Serverless Node TypeScript comes with an Apollo Server configured out of the box.
The default endpoint is /graphql
and you can use a [GraphQL Introspector] to see the available Queries and Mutations.
For example, the following Query lists the available Users:
query fetchUsers {
getUsers {
_id
createdAt
email
username
}
}
and the following Mutation creates a new User:
mutation CreateNewUser {
createUser(userData: {
email: "test6@test.com"
username: "Test6"
}) {
_id
createdAt
email
username
}
}
CORS is setup out of the box, allowing access from all websites, by setting the Access-Control-Allow-Origin
header equal to '*'
.
In order to customise the CORS response, check the Middy CORS middleware. and the handler.ts
file.
Furthermore, in order to properly use CORS with lambda authorizers, their headers must be configured manually in the serverless.yml
file.
Serverless Node TypeScript is configured to emit Domain Events to AWS SNS out of the box. In order to enable this feature, set the SEND_DOMAIN_EVENTS
environment variable to true
(default is undefined
).
Following DDD, each Aggregate must emit its events to its own topic. Hence the User
aggregate has its own topic configured in the src/config/index.ts
file.
The serverless.yml
file takes care about
resources
;iamRoleStatements
section.In order to develop locally, the other environments other than staging
and development
the events will be send to a local implementation of AWS SNS, running on http://localhost:4575
. This is the default URL of Localstack.
The local endpoint can be customized via the SNS_ENDPOINT
environment variable.
For topic naming conventions, take a look at this article.
All error messages have the following format:
{
"code": (string),
"error": (string),
"hasError": 1,
"statusCode": (number)
}
Monitoring Serverless applications is generally harder than usual. For this reason new tools are needed.
Amazon developed AWS X-Ray to improve the monitoring of the flow of the events in a serverless environment. This provides useful information about the events that trigger the lambdas and other services.
In order to enable X-Ray, simply set the tracing.apiGateway
and tracing.lambda
keys to true
in the serverless.yml
file,
MongoDB is the chosen default database. The connection string can be configured by setting the MONGO_URI
env variable.
The default connection string is mongodb://localhost:27017/sls-node-ts-<ENV>
, where <ENV>
in the ENV
env variable. In order to change it, head to the src/infrastructure/mongo/index.ts
file.
In the staging
and production
environments, secrets are fetched from AWS Secrets Manager and saved into local environment variables.
A single JSON formatted Secret per environment must be created, named sls-node-ts/<ENV>
(where <ENV>
is either staging
or production
). Each secret per environment must contain all the necessary key value pairs in the format <env variable>: <Secret Name>
, eg.
{
"MONGO_URI": "<THE MONGODB CONNECTION STRING>"
}
and they will be injected as environment variable in the application.
In order to create, for example, the new secret for the staging
environment containing, for example, the MongoDB connection string, which must be supplied through the MONGO_URI
environment variable, perform the following steps:
Secrets
Store a new secret
buttonOther type of secrets
Specify the key/value pairs to be stored in this secret
section, enter MONGO_URI
as key and your full Mongo URI as value. Then click Next
Secret name
field, enter sls-node-ts/staging
and click Next
to complete the creation(!) The name of the secret (in the above example sls-node-ts/staging
) is bound to the application name, the one defined in the name
field of the package.json
.
Run npm test
to run the tests or npm run watch-test
to run the tests with the watcher.
Pull requests are welcome.
Author: micheleangioni
Source Code: https://github.com/micheleangioni/sls-node-ts
#nodejs #node #javascript #typescript