{"id":17402262,"url":"https://github.com/collierrgbsitisfise/serverless-bonk-template","last_synced_at":"2025-04-15T17:34:31.419Z","repository":{"id":46765017,"uuid":"337844097","full_name":"collierrgbsitisfise/serverless-bonk-template","owner":"collierrgbsitisfise","description":"Serverless boilerplate based on serverless-webpack + typescript.","archived":false,"fork":false,"pushed_at":"2021-09-27T13:20:41.000Z","size":2497,"stargazers_count":24,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-02-23T14:12:16.318Z","etag":null,"topics":["aws","boilerplate","cloudprovider","lambda","schemas","serverless","serverless-plugins"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/collierrgbsitisfise.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-02-10T20:23:52.000Z","updated_at":"2022-09-07T13:20:09.000Z","dependencies_parsed_at":"2022-09-14T22:54:51.323Z","dependency_job_id":null,"html_url":"https://github.com/collierrgbsitisfise/serverless-bonk-template","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/collierrgbsitisfise%2Fserverless-bonk-template","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/collierrgbsitisfise%2Fserverless-bonk-template/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/collierrgbsitisfise%2Fserverless-bonk-template/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/collierrgbsitisfise%2Fserverless-bonk-template/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/collierrgbsitisfise","download_url":"https://codeload.github.com/collierrgbsitisfise/serverless-bonk-template/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241106084,"owners_count":19910756,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws","boilerplate","cloudprovider","lambda","schemas","serverless","serverless-plugins"],"created_at":"2024-10-16T17:09:02.742Z","updated_at":"2025-02-28T05:30:36.677Z","avatar_url":"https://github.com/collierrgbsitisfise.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ⚡️ Serverless-Bonk-Boilerplate (aws cloud provider) ⚡️\n\n\n[![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?\u0026style=for-the-badge\u0026logo=amazon-aws\u0026logoColor=black) ![JEST](https://img.shields.io/badge/-jest-%23C21325?\u0026style=for-the-badge\u0026logo=jest\u0026logoColor=white) ![NODEJS](https://img.shields.io/badge/node.js%20-%2343853D.svg?\u0026style=for-the-badge\u0026logo=node.js\u0026logoColor=white) ![TypeScript](https://img.shields.io/badge/typescript%20-%23007ACC.svg?\u0026style=for-the-badge\u0026logo=typescript\u0026logoColor=white)\n\n_ _ _\n\n\u003cdiv style=\"text-align:center\"\u003e\n  \u003cimg src=\"https://github.com/collierrgbsitisfise/serverless-bonk-template/blob/master/docs/bonk-logo.png\" align=\"center\"/\u003e\n\u003c/div\u003e\n\n\n\n[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]** -\u003e (**services** + **helpers**)[[**domain layer]**] -\u003e **repositories**.\n\nIn order to dig deeper in onion architecture check this boilerplate: https://github.com/Melzar/onion-architecture-boilerplate\n_ _ _\n\n\u003ch2 id=\"plugins\"\u003econtent\u003c/h2\u003e\n\n\u003cul\u003e\n    \u003cli\u003e\u003ca href=\"#usage\"\u003eUsage 👨‍💻/👩‍💻\u003c/a\u003e\u003c/li\u003e\n    \u003cli\u003e\u003ca href=\"#plugins\"\u003ePlugins 🔌\u003c/a\u003e\u003c/li\u003e\n    \u003cli\u003e\u003ca href=\"#file-structure\"\u003eFile structure 📁\u003c/a\u003e\u003c/li\u003e\n    \u003cli\u003e\u003ca href=\"#scripts\"\u003eScripts 📜\u003c/a\u003e\u003c/li\u003e\n    \u003cli\u003e\u003ca href=\"#deploy\"\u003eHow to deploy 🚀\u003c/a\u003e\u003c/li\u003e\n    \u003cli\u003e\n      \u003ca href=\"#folders\"\u003eFolders purpose 📂\u003c/a\u003e\n      \u003cdetails\u003e\n        \u003csummary\u003emore\u003c/summary\u003e\n        \u003cul\u003e\n          \u003cli\u003e\u003ca href=\"#folders-libs\"\u003elibs ⚙️\u003c/a\u003e\u003c/li\u003e\n          \u003cli\u003e\u003ca href=\"#folders-mocks\"\u003e@mocks 🗒️\u003c/a\u003e\u003c/li\u003e\n          \u003cli\u003e\u003ca href=\"#folders-types\"\u003e@types 📚\u003c/li\u003e\n          \u003cli\u003e\u003ca href=\"#folders-env\"\u003eenv ⚆\u003c/a\u003e\u003c/li\u003e\n          \u003cli\u003e\u003ca href=\"#folders-resources\"\u003eresources 🔆\u003c/a\u003e\u003c/li\u003e\n          \u003cli\u003e\u003ca href=\"#folders-schemas\"\u003eschemas ✅\u003c/a\u003e\u003c/li\u003e\n          \u003cli\u003e\u003ca href=\"#folders-scripts\"\u003escripts 📜\u003c/a\u003e\u003c/li\u003e\n          \u003cli\u003e\u003ca href=\"#folders-src\"\u003esrc 🗄️\u003c/a\u003e\u003c/li\u003e\n        \u003c/ul\u003e\n      \u003c/details\u003e\n    \u003c/li\u003e\n    \n\u003c/ul\u003e\n\n\u003ch2 id=\"usage\"\u003eUsage 👨‍💻/👩‍💻\u003c/h2\u003e\n\n```bash\n$: npm i -g serverless # install serverless framework\n$: sls create --template https://github.com/collierrgbsitisfise/serverless-bonk-template --path \u003cdir name\u003e\n```\n\u003ch2 id=\"plugins\"\u003eNext serverless plugins are used 🔌\u003c/h2\u003e\n\n  - [serverless-webpack](https://github.com/serverless-heaven/serverless-webpack)\n  - [serverless-offline](https://github.com/dherault/serverless-offline)\n  - [serverless-dotenv-plugin](https://github.com/neverendingqs/serverless-dotenv-plugin)\n  - [serverless-prune-plugin](https://github.com/claygregory/serverless-prune-plugin)\n  - [serverless-iam-roles-per-function](https://github.com/functionalone/serverless-iam-roles-per-function)\n\n___\n\u003ch2 id=\"file-structure\"\u003eFile structure 📁\u003c/h2\u003e\n\n```dotnetcli\n.\n├── resources                           # resources such as VPC, DynamoDB Tables etc.\n├── scripts                             # will be used in CI/CD, development process - should not be part of production bundle.\n├── schemas                             # schemas to validate API request on API gateway level.\n├── @mocks                              # mocks which will be used in tests/development.\n├── @types                              # types.\n├── env                                 # env files.\n├── lib                                 # helpers to operate with lambdas itself, should not be used inside lambda, should not operate somehow with business logic.\n    ├── apiGatewayLambdaWrapper.ts      # wrap lambdas which are linked to api gateway.\n    ├── cloudWatchLambdaWrapper.ts      # wrap lambdas which are subscribed to cloud watch event.\n    ├── snsLambdaWrapper.ts             # wrap lambdas which are subscribed to sns message.\n    ├── sqsLambdaWrapper.ts             # wrap lambdas which are subscribed to sqs message.\n    └── dynamoDBStreamLambdaWrapper.ts  # wrap lambdas which are subscribed to dynamoDB stream.\n├── src\n│   ├── functions                       # lambda fucntions.\n│   │   ├── example\n│   │   │   ├── example.ts              # `Example` lambda source code.\n│   │   │   └── example.yaml            # `Example` function template part.\n│   │   │\n│   │   └── index.ts                    # import/export all lambdas.\n│   │\n│   ├── helpers                         # helpers which are used inside src folder.\n│   ├── services                        # services logic which will operate with external API/repositories, will contain domain logic.\n│   └── repositories                    # operate with database.\n│\n├── package.json\n├── serverless.ts                       # serverless service file.\n├── tsconfig.json                       # typescript compiler configuration\n├── tsconfig.paths.json                 # typescript paths\n├── webpack.config.js                   # webpack configuration\n├── .eslintrc.js                        # ESlint config\n└── .prettierrc.js                      # prettier config\n```\n\n___\n\n\u003ch2 id=\"scripts\"\u003eScripts 📜\u003c/h2\u003e\n\n\n|     Command      |                             Script                              |\n| :--------------: | :-------------------------------------------------------------: |\n| Lint             | `npm run lint`                                                  |\n| Prettier         | `npm run prettier`                                              |\n| Typescript check | `npm run ts-check`                                              |\n| Test             | `npm run test`                                                  |\n| Setup env        | `ENV=\u003cenvValue\u003e npm run setup # will create .env on root level` |\n\n___\n\n\u003ch2 id=\"deploy\"\u003eHow to deploy 🚀\u003c/h2\u003e\n\n- [Setup aws credentials](https://www.serverless.com/framework/docs/providers/aws/guide/credentials/)\n\n- Run next commands\n```bash\n$: ENV=\u003cenvValue\u003e npm run setup # setup env file\n$: npm run deploy # deploy\n```\n\n___\n\n\u003ch2 id=\"folders\"\u003eFolders purpose 📂\u003c/h2\u003e\n\n\u003ch3 id=\"folders-libs\"\u003elibs ⚙️\u003c/h3\u003e\n\nOn 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: \n- [lambda tied to dynamodb stream](https://docs.aws.amazon.com/lambda/latest/dg/with-ddb.html)\n- [lambda tied to sns](https://docs.aws.amazon.com/lambda/latest/dg/with-sns.html)\n- [lambda tied to sqs](https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html)\n- [lambda tied to cloudwatch event](https://docs.aws.amazon.com/lambda/latest/dg/services-cloudwatchevents.html)\n- [lambda tied to ApiGateway](https://docs.aws.amazon.com/lambda/latest/dg/services-apigateway.html)\n\n\u003cdetails\u003e\n  \u003csummary\u003eWrapper for lambda tied to dynamoDB stream\u003c/summary\u003e\n  \u003cp\u003e\n\n\n```javascript\nimport { DynamoDBStreamEvent, Context, Callback } from 'aws-lambda';\n\nexport const dynamoDblambdaWrapper = (\n  lambda: (event: DynamoDBStreamEvent, context: Context, callback: Callback) =\u003e Promise\u003cany\u003e,\n  onSucces: (event: DynamoDBStreamEvent, result: any) =\u003e any | PromiseLike\u003cany\u003e,\n  onError: (event: DynamoDBStreamEvent, error: Error) =\u003e any | PromiseLike\u003cany\u003e,\n) =\u003e {\n  return function wrapp(event: DynamoDBStreamEvent, context?: Context, callback?: Callback): Promise\u003cany\u003e {\n    return Promise.resolve()\n      .then(() =\u003e lambda(event, context, callback))\n      .then((res: any) =\u003e onSucces(event, res))\n      .catch((err: Error) =\u003e onError(event, err));\n  };\n};\n\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eWrapper for lambda tied to ApiGateway\u003c/summary\u003e\n  \u003cp\u003e\n\n\n```javascript\nexport type Headers = { [key: string]: string };\n\nexport type LambdaFunction = (\n  event: APIGatewayEvent,\n  context?: Context,\n  callback?: Callback,\n) =\u003e [any, number, Headers] | Promise\u003c[any, number, Headers]\u003e;\n\nexport type OnSuccesHandler = (\n  value: any,\n  statusCode: number,\n  headers?: Headers,\n) =\u003e APIGatewayProxyResult | PromiseLike\u003cAPIGatewayProxyResult\u003e;\n\nexport type OnErrorHandle = (error: Error) =\u003e Promise\u003cAPIGatewayProxyResult\u003e;\n\nconst defaultHeaders = {\n  'Content-Type': 'application/json',\n  'Access-Control-Allow-Origin': '*',\n  'Access-Control-Allow-Credentials': true,\n};\n\nconst onSuccesHandler = (\n  data: any,\n  statusCode: number,\n  headers?: Headers,\n): APIGatewayProxyResult | PromiseLike\u003cAPIGatewayProxyResult\u003e =\u003e ({\n  statusCode,\n  headers: {\n    ...defaultHeaders,\n    ...headers,\n  },\n  body: JSON.stringify(data),\n});\n\nconst onErrorHandler = async (error: Error): Promise\u003cAPIGatewayProxyResult\u003e =\u003e {\n  return {\n    statusCode: 500,\n    headers: defaultHeaders,\n    body: JSON.stringify(error),\n  };\n};\n\nexport const apiGatewayLambdaWrapper = (\n  lambda: LambdaFunction,\n  onSucces: OnSuccesHandler = onSuccesHandler,\n  onError: OnErrorHandle = onErrorHandler,\n) =\u003e {\n  return function wrapp(event: APIGatewayEvent, context: Context, callback: Callback): Promise\u003cAPIGatewayProxyResult\u003e {\n    return Promise.resolve()\n      .then(() =\u003e lambda(event, context, callback))\n      .then(([res, code, headers]: [any, number, Headers]) =\u003e onSucces(res, code, headers))\n      .catch(onError);\n  };\n};\n\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n\u003ch3 id=\"folders-mocks\"\u003e@mocks 🗒️\u003c/h3\u003e\n\nSome raw data(example of **sns message**, **api request**, **sqs message**, etc) which could be used during local development or for test.\n\n\u003ch3 id=\"folders-types\"\u003e@types 📚\u003c/h3\u003e\n\ngeneral types, which will be used across project..\n\n\u003ch3 id=\"folders-env\"\u003eenv ⚆\u003c/h3\u003e\n\n\nFor each environment should be predefined `\u003cENV\u003e.env` file, which will be used by `setup-script` before deploy.\n\n**Should't contain sensitive info such as secrets , db passwords, etc. Such kind of info must be retrived from secret-manager in runtime**\n\n\u003ch3 id=\"folders-resources\"\u003eresources 🔆\u003c/h3\u003e\n\nDefine resources which will be created/updated on deploy, such as **dynamodb table**, **SqlRDSInstance**, etc.\n \n\u003ch3 id=\"folders-schemas\"\u003eschemas ✅\u003c/h3\u003e\n\nDefine 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/)\n\n\u003ch3 id=\"folders-scripts\"\u003escripts 📜\u003c/h3\u003e\n\n`.js` files which usually are used in **CI/CD**. Also it could be used in development purpose. \n\nScripts examples example:\n - setup .env variables\n - setup development webhooks using ngrok\n - adding additional `.env` variables on **CI/CD**\n - purge cloudfront cache\n\u003ch3 id=\"folders-src\"\u003esrc 🗄️\u003c/h3\u003e\n\nInternal logic of application **services**, **repository**, **helpers**.\n\n[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)\n\n[ico-contributors]: https://img.shields.io/github/contributors/collierrgbsitisfise/serverless-bonk-template.svg\n\n[link-contributors]: https://github.com/collierrgbsitisfise/serverless-bonk-template\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcollierrgbsitisfise%2Fserverless-bonk-template","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcollierrgbsitisfise%2Fserverless-bonk-template","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcollierrgbsitisfise%2Fserverless-bonk-template/lists"}