Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/collierrgbsitisfise/serverless-bonk-template

Serverless boilerplate based on serverless-webpack + typescript.
https://github.com/collierrgbsitisfise/serverless-bonk-template

aws boilerplate cloudprovider lambda schemas serverless serverless-plugins

Last synced: 29 days ago
JSON representation

Serverless boilerplate based on serverless-webpack + typescript.

Awesome Lists containing this project

README

        

# ⚡️ Serverless-Bonk-Boilerplate (aws cloud provider) ⚡️

[![serverless](http://public.serverless.com/badges/v3.svg)](http://www.serverless.com) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Contributors][ico-contributors]][link-contributors] [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](#contributing) [![node](https://img.shields.io/node/v/gh-badges.svg)]() ![master status](https://github.com/collierrgbsitisfise/serverless-bonk-template/actions/workflows/main.yaml/badge.svg?branch=master) ![AWS](https://img.shields.io/badge/AWS%20-%23FF9900.svg?&style=for-the-badge&logo=amazon-aws&logoColor=black) ![JEST](https://img.shields.io/badge/-jest-%23C21325?&style=for-the-badge&logo=jest&logoColor=white) ![NODEJS](https://img.shields.io/badge/node.js%20-%2343853D.svg?&style=for-the-badge&logo=node.js&logoColor=white) ![TypeScript](https://img.shields.io/badge/typescript%20-%23007ACC.svg?&style=for-the-badge&logo=typescript&logoColor=white)

_ _ _



[Serverless](https://www.serverless.com/) boilerplate based on [serverless-webpack](https://github.com/serverless-heaven/serverless-webpack) + [typescript](https://www.typescriptlang.org/). Define ready to deploy project with predefined  **scripts**, **linter-prettier rules**, **basic lib** and **helpers**. Based on pseudo [Onion Architecture](https://jeffreypalermo.com/2008/07/the-onion-architecture-part-1/): **lambda[controller]** -> (**services** + **helpers**)[[**domain layer]**] -> **repositories**.

In order to dig deeper in onion architecture check this boilerplate: https://github.com/Melzar/onion-architecture-boilerplate
_ _ _

content

Usage 👨‍💻/👩‍💻

```bash
$: npm i -g serverless # install serverless framework
$: sls create --template https://github.com/collierrgbsitisfise/serverless-bonk-template --path
```

Next serverless plugins are used 🔌

- [serverless-webpack](https://github.com/serverless-heaven/serverless-webpack)
- [serverless-offline](https://github.com/dherault/serverless-offline)
- [serverless-dotenv-plugin](https://github.com/neverendingqs/serverless-dotenv-plugin)
- [serverless-prune-plugin](https://github.com/claygregory/serverless-prune-plugin)
- [serverless-iam-roles-per-function](https://github.com/functionalone/serverless-iam-roles-per-function)

___

File structure 📁

```dotnetcli
.
├── resources # resources such as VPC, DynamoDB Tables etc.
├── scripts # will be used in CI/CD, development process - should not be part of production bundle.
├── schemas # schemas to validate API request on API gateway level.
├── @mocks # mocks which will be used in tests/development.
├── @types # types.
├── env # env files.
├── lib # helpers to operate with lambdas itself, should not be used inside lambda, should not operate somehow with business logic.
├── apiGatewayLambdaWrapper.ts # wrap lambdas which are linked to api gateway.
├── cloudWatchLambdaWrapper.ts # wrap lambdas which are subscribed to cloud watch event.
├── snsLambdaWrapper.ts # wrap lambdas which are subscribed to sns message.
├── sqsLambdaWrapper.ts # wrap lambdas which are subscribed to sqs message.
└── dynamoDBStreamLambdaWrapper.ts # wrap lambdas which are subscribed to dynamoDB stream.
├── src
│ ├── functions # lambda fucntions.
│ │ ├── example
│ │ │ ├── example.ts # `Example` lambda source code.
│ │ │ └── example.yaml # `Example` function template part.
│ │ │
│ │ └── index.ts # import/export all lambdas.
│ │
│ ├── helpers # helpers which are used inside src folder.
│ ├── services # services logic which will operate with external API/repositories, will contain domain logic.
│ └── repositories # operate with database.

├── package.json
├── serverless.ts # serverless service file.
├── tsconfig.json # typescript compiler configuration
├── tsconfig.paths.json # typescript paths
├── webpack.config.js # webpack configuration
├── .eslintrc.js # ESlint config
└── .prettierrc.js # prettier config
```

___

Scripts 📜

| Command | Script |
| :--------------: | :-------------------------------------------------------------: |
| Lint | `npm run lint` |
| Prettier | `npm run prettier` |
| Typescript check | `npm run ts-check` |
| Test | `npm run test` |
| Setup env | `ENV= npm run setup # will create .env on root level` |

___

How to deploy 🚀

- [Setup aws credentials](https://www.serverless.com/framework/docs/providers/aws/guide/credentials/)

- Run next commands
```bash
$: ENV= npm run setup # setup env file
$: npm run deploy # deploy
```

___

Folders purpose 📂

libs ⚙️

On the `libs` folder are defined **utils** which will operate with lambda itself. The libs **utils** should't be used inside handler. In boilerplate are predefined lambda wrappers for base case scenario lambda use:
- [lambda tied to dynamodb stream](https://docs.aws.amazon.com/lambda/latest/dg/with-ddb.html)
- [lambda tied to sns](https://docs.aws.amazon.com/lambda/latest/dg/with-sns.html)
- [lambda tied to sqs](https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html)
- [lambda tied to cloudwatch event](https://docs.aws.amazon.com/lambda/latest/dg/services-cloudwatchevents.html)
- [lambda tied to ApiGateway](https://docs.aws.amazon.com/lambda/latest/dg/services-apigateway.html)

Wrapper for lambda tied to dynamoDB stream

```javascript
import { DynamoDBStreamEvent, Context, Callback } from 'aws-lambda';

export const dynamoDblambdaWrapper = (
lambda: (event: DynamoDBStreamEvent, context: Context, callback: Callback) => Promise,
onSucces: (event: DynamoDBStreamEvent, result: any) => any | PromiseLike,
onError: (event: DynamoDBStreamEvent, error: Error) => any | PromiseLike,
) => {
return function wrapp(event: DynamoDBStreamEvent, context?: Context, callback?: Callback): Promise {
return Promise.resolve()
.then(() => lambda(event, context, callback))
.then((res: any) => onSucces(event, res))
.catch((err: Error) => onError(event, err));
};
};

```

Wrapper for lambda tied to ApiGateway

```javascript
export type Headers = { [key: string]: string };

export type LambdaFunction = (
event: APIGatewayEvent,
context?: Context,
callback?: Callback,
) => [any, number, Headers] | Promise<[any, number, Headers]>;

export type OnSuccesHandler = (
value: any,
statusCode: number,
headers?: Headers,
) => APIGatewayProxyResult | PromiseLike;

export type OnErrorHandle = (error: Error) => Promise;

const defaultHeaders = {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Credentials': true,
};

const onSuccesHandler = (
data: any,
statusCode: number,
headers?: Headers,
): APIGatewayProxyResult | PromiseLike => ({
statusCode,
headers: {
...defaultHeaders,
...headers,
},
body: JSON.stringify(data),
});

const onErrorHandler = async (error: Error): Promise => {
return {
statusCode: 500,
headers: defaultHeaders,
body: JSON.stringify(error),
};
};

export const apiGatewayLambdaWrapper = (
lambda: LambdaFunction,
onSucces: OnSuccesHandler = onSuccesHandler,
onError: OnErrorHandle = onErrorHandler,
) => {
return function wrapp(event: APIGatewayEvent, context: Context, callback: Callback): Promise {
return Promise.resolve()
.then(() => lambda(event, context, callback))
.then(([res, code, headers]: [any, number, Headers]) => onSucces(res, code, headers))
.catch(onError);
};
};

```

@mocks 🗒️

Some raw data(example of **sns message**, **api request**, **sqs message**, etc) which could be used during local development or for test.

@types 📚

general types, which will be used across project..

env ⚆

For each environment should be predefined `.env` file, which will be used by `setup-script` before deploy.

**Should't contain sensitive info such as secrets , db passwords, etc. Such kind of info must be retrived from secret-manager in runtime**

resources 🔆

Define resources which will be created/updated on deploy, such as **dynamodb table**, **SqlRDSInstance**, etc.

schemas ✅

Define request schemas by which ApiGateway will validate request. Also could be defined response schemas. All of them could be used in test or/and for [documentation](https://swagger.io/)

scripts 📜

`.js` files which usually are used in **CI/CD**. Also it could be used in development purpose.

Scripts examples example:
- setup .env variables
- setup development webhooks using ngrok
- adding additional `.env` variables on **CI/CD**
- purge cloudfront cache

src 🗄️

Internal logic of application **services**, **repository**, **helpers**.

[There is an article which describes one of the predefined helpers](https://vadim-vicolaev-v.medium.com/better-way-to-get-secrets-in-serverless-world-1aba8a71b3a1)

[ico-contributors]: https://img.shields.io/github/contributors/collierrgbsitisfise/serverless-bonk-template.svg

[link-contributors]: https://github.com/collierrgbsitisfise/serverless-bonk-template