├── .editorconfig ├── .env ├── .eslintrc.json ├── .github └── workflows │ ├── codeql-analysis.yml │ └── main.yml ├── .gitignore ├── .husky ├── .gitignore └── pre-commit ├── .nvmrc ├── .prettierignore ├── .prettierrc ├── .yarn └── releases │ └── yarn-4.6.0.cjs ├── .yarnrc.yml ├── LICENSE ├── README.md ├── jest.config.ts ├── jest.preset.js ├── libs └── .gitkeep ├── nx.json ├── package.json ├── renovate.json ├── serverless.base.ts ├── stacks └── .gitkeep ├── tools ├── tsconfig.tools.json └── workspace-plugin │ ├── .eslintrc.json │ ├── generators.json │ ├── jest.config.ts │ ├── package.json │ ├── project.json │ ├── src │ ├── generators │ │ └── serverless │ │ │ ├── files │ │ │ ├── .eslintrc.json__tmpl__ │ │ │ ├── README.md │ │ │ ├── serverless.ts__tmpl__ │ │ │ ├── src │ │ │ │ └── handler.ts__tmpl__ │ │ │ ├── tsconfig.app.json │ │ │ ├── tsconfig.json │ │ │ └── tsconfig.spec.json │ │ │ ├── index.ts │ │ │ ├── jest-config.ts │ │ │ ├── schema.json │ │ │ ├── schema.ts │ │ │ └── workspace-config.ts │ └── index.ts │ ├── tsconfig.json │ ├── tsconfig.lib.json │ └── tsconfig.spec.json ├── tsconfig.base.json └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | max_line_length = off 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | # Nx 18 enables using plugins to infer targets by default 2 | # This is disabled for existing workspaces to maintain compatibility 3 | # For more info, see: https://nx.dev/concepts/inferred-tasks 4 | NX_ADD_PLUGINS=false -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "ignorePatterns": ["**/*"], 4 | "plugins": ["@nx"], 5 | "overrides": [ 6 | { 7 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 8 | "rules": { 9 | "@nx/enforce-module-boundaries": [ 10 | "error", 11 | { 12 | "enforceBuildableLibDependency": true, 13 | "allow": [], 14 | "depConstraints": [ 15 | { 16 | "sourceTag": "stack", 17 | "onlyDependOnLibsWithTags": ["stack", "lib"] 18 | }, 19 | { 20 | "sourceTag": "lib", 21 | "onlyDependOnLibsWithTags": ["lib"] 22 | } 23 | ] 24 | } 25 | ] 26 | } 27 | }, 28 | { 29 | "files": ["*.ts", "*.tsx"], 30 | "extends": ["plugin:@nx/typescript"], 31 | "rules": {} 32 | }, 33 | { 34 | "files": ["*.js", "*.jsx"], 35 | "extends": ["plugin:@nx/javascript"], 36 | "rules": {} 37 | }, 38 | { 39 | "files": "*.json", 40 | "parser": "jsonc-eslint-parser", 41 | "rules": {} 42 | } 43 | ] 44 | } 45 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ main ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ main ] 20 | schedule: 21 | - cron: '15 4 * * 4' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'javascript' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] 37 | # Learn more: 38 | # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed 39 | 40 | steps: 41 | - name: Checkout repository 42 | uses: actions/checkout@v4 43 | 44 | # Initializes the CodeQL tools for scanning. 45 | - name: Initialize CodeQL 46 | uses: github/codeql-action/init@v3 47 | with: 48 | languages: ${{ matrix.language }} 49 | # If you wish to specify custom queries, you can do so here or in a config file. 50 | # By default, queries listed here will override any specified in a config file. 51 | # Prefix the list here with "+" to use these queries and those in the config file. 52 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 53 | 54 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 55 | # If this step fails, then you should remove it and run the build manually (see below) 56 | - name: Autobuild 57 | uses: github/codeql-action/autobuild@v3 58 | 59 | # ℹ️ Command-line programs to run using the OS shell. 60 | # 📚 https://git.io/JvXDl 61 | 62 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 63 | # and modify them (or add more) to build your code if your project 64 | # uses a compiled language 65 | 66 | #- run: | 67 | # make bootstrap 68 | # make release 69 | 70 | - name: Perform CodeQL Analysis 71 | uses: github/codeql-action/analyze@v3 72 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow to help you get started with Actions 2 | 3 | name: CI 4 | 5 | # Controls when the workflow will run 6 | on: 7 | # Triggers the workflow on push or pull request events but only for the main branch 8 | push: 9 | branches: [main] 10 | pull_request: 11 | branches: [main] 12 | 13 | # Allows you to run this workflow manually from the Actions tab 14 | workflow_dispatch: 15 | 16 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 17 | jobs: 18 | # This workflow contains a single job called "build" 19 | build: 20 | # The type of runner that the job will run on 21 | runs-on: ubuntu-latest 22 | 23 | # Steps represent a sequence of tasks that will be executed as part of the job 24 | steps: 25 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 26 | - uses: actions/checkout@v4 27 | - uses: actions/setup-node@v4 28 | with: 29 | node-version-file: '.nvmrc' 30 | cache: 'yarn' 31 | 32 | - name: Install packages 33 | run: yarn install --immutable 34 | 35 | - name: Generate stack 36 | run: npx nx g serverless test-stack 37 | 38 | - name: Generate library 39 | run: npx nx g @nx/node:lib test-lib --tags lib 40 | 41 | - name: Linting 42 | run: npx nx run-many --target=lint --all 43 | 44 | - name: Run tests 45 | run: npx nx run-many --target=test --all 46 | 47 | - name: Sls package 48 | run: npx nx run-many --target=build --all --stage=ci 49 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | 8 | # dependencies 9 | /node_modules 10 | 11 | # IDEs and editors 12 | /.idea 13 | .project 14 | .classpath 15 | .c9/ 16 | *.launch 17 | .settings/ 18 | *.sublime-workspace 19 | 20 | # IDE - VSCode 21 | .vscode/* 22 | !.vscode/settings.json 23 | !.vscode/tasks.json 24 | !.vscode/launch.json 25 | !.vscode/extensions.json 26 | 27 | # misc 28 | /.sass-cache 29 | /connect.lock 30 | /coverage 31 | /libpeerconnection.log 32 | npm-debug.log 33 | yarn-error.log 34 | testem.log 35 | /typings 36 | 37 | # System Files 38 | .DS_Store 39 | Thumbs.db 40 | 41 | .serverless 42 | .vscode 43 | .dynamodb 44 | .webpack 45 | 46 | # Nx 47 | migrations.json 48 | 49 | # Yarn 50 | .pnp.* 51 | .yarn/* 52 | !.yarn/patches 53 | !.yarn/plugins 54 | !.yarn/releases 55 | !.yarn/sdks 56 | !.yarn/versions 57 | 58 | .nx/cache -------------------------------------------------------------------------------- /.husky/.gitignore: -------------------------------------------------------------------------------- 1 | _ 2 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | yarn lint-staged --concurrent 5 5 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | lts/Iron 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # Add files here to ignore them from prettier formatting 2 | 3 | /dist 4 | /coverage 5 | 6 | /.nx/cache -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true 3 | } 4 | -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | compressionLevel: mixed 2 | 3 | enableGlobalCache: false 4 | 5 | nodeLinker: node-modules 6 | 7 | yarnPath: .yarn/releases/yarn-4.6.0.cjs 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 sudokar 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nx-serverless-monorepo 2 | 3 | [![serverless](http://public.serverless.com/badges/v3.svg)](http://www.serverless.com) 4 | [![](https://img.shields.io/badge/monorepo-Nx-blue)](https://nx.dev/) 5 | ![esbuild](https://badges.aleen42.com/src/esbuild.svg) 6 | ![npm peer dependency version (scoped)](https://img.shields.io/npm/dependency-version/eslint-config-prettier/peer/eslint) 7 | ![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square) 8 | [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/sudokar/nx-serverless/blob/master/LICENSE) 9 | [![Percentage of issues still open](http://isitmaintained.com/badge/open/Naereen/badges.svg)](http://isitmaintained.com/project/Naereen/badges 'Percentage of issues still open') 10 | [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/sudokar/nx-serverless) 11 | ![Maintained](https://img.shields.io/maintenance/yes/2024.svg) 12 | 13 | ![TypeScript](https://img.shields.io/badge/typescript-%23007ACC.svg?style=for-the-badge&logo=typescript&logoColor=white) 14 | ![GitHub Actions](https://img.shields.io/badge/github%20actions-%232671E5.svg?style=for-the-badge&logo=githubactions&logoColor=white) 15 | 16 | A monrepo style, modern boilerplate or template project for [Serverless framework](https://www.serverless.com/) using [Nx](https://nx.dev) monorepo toolkit 🛠 and `aws-nodejs-typescript` serverless template 17 | 18 | ## Table of contents 19 | 20 | - [Whats Included](#whats-included) 21 | - [Template Layout](#template-layout) 22 | - [Prerequisites](#prerequisites) 23 | - [Usage](#usage) 24 | - [Further help](#further-help) 25 | - [Nx Cloud](#nx-cloud) 26 | - [Contribution](#contribution) 27 | - [Support](#support) 28 | - [Maintainer](#maintainer) 29 | - [License](#license) 30 | 31 | ## Whats Included 32 | 33 | - A template project layout using latest version of Nx and Servrless framework 34 | - An easy to use workspace generator to generate a template/stack with Serverless framework files and related Nx configuration 35 | - Configured with AWS provider and it can be easily adopted to any cloud provider 36 | 37 | ## Template Layout 38 | 39 | ```shell 40 | . 41 | ├── stacks/ # stack for each serverless configuration/template and its associated files 42 | ├── libs/ # shared libraries 43 | ├── tools/ 44 | ├── README.md 45 | ├── jest.config.js 46 | ├── jest.preset.js 47 | ├── nx.json 48 | ├── package.json 49 | ├── serverless.base.ts # base configuration for serverless 50 | ├── tsconfig.base.json 51 | ├── workspace.json 52 | ├── .editorconfig 53 | ├── .eslintrc.json 54 | ├── .gitignore 55 | ├── .husky # git hooks 56 | ├── .nvmrc 57 | ├── .prettierignore 58 | ├── .prettierrc 59 | ``` 60 | 61 | ## Prerequisites 62 | 63 | - [Nodejs](https://nodejs.org/) `protip: use nvm` 64 | 65 | > :warning: **Version**: `lts/iron (v20)`. If you're using [nvm](https://github.com/nvm-sh/nvm), run `nvm use` to ensure you're using the same Node version in local and in your lambda's runtime. 66 | 67 | - :package: Package Manager 68 | 69 | - [Yarn](https://yarnpkg.com) 70 | 71 | - 💅 Code format plugins 72 | 73 | - [Eslint](https://eslint.org/) 74 | - [Prettier](https://prettier.io/) 75 | - [EditorConfig](https://editorconfig.org/) 76 | 77 | > On your preferred code editor, Install plugins for the above list of tools 78 | 79 | ## Usage 80 | 81 | Depending on your prefrered package manager, follow the instructions below to build and deploy serverless stack(s). 82 | 83 | - **Install project dependencies** 84 | 85 | ```shell 86 | yarn install 87 | ``` 88 | 89 | - **Generate a new stack** 90 | 91 | ```shell 92 | nx g serverless 93 | ``` 94 | 95 | > Run with `-d` or `--dry-run` flag for dry run 96 | 97 | - **Generate a new library** 98 | 99 | ```shell 100 | nx g @nx/node:lib --skipBabelrc --tags lib 101 | ``` 102 | 103 | > Run with `-d` or `--dry-run` flag for dry run 104 | 105 | - **Package stack** 106 | 107 | - To package single stack 108 | 109 | ```shell 110 | nx run :build --stage= 111 | ``` 112 | 113 | - To package stack affected by a change 114 | 115 | ```shell 116 | nx affected:build --stage= 117 | ``` 118 | 119 | - To package all stacks 120 | 121 | ```shell 122 | nx run-many --target=build --stage= 123 | ``` 124 | 125 | - **Deploy stack to cloud** 126 | 127 | - To deploy single stack 128 | 129 | ```shell 130 | nx run :deploy --stage= 131 | ``` 132 | 133 | - To deploy stack affected by a change 134 | 135 | ```shell 136 | nx affected:deploy --stage= 137 | ``` 138 | 139 | - To deploy all stacks 140 | 141 | ```shell 142 | nx run-many --target=deploy --all --stage= 143 | ``` 144 | 145 | - **Remove stack from cloud** 146 | 147 | - To remove single stack 148 | 149 | ```shell 150 | nx run :remove --stage= 151 | ``` 152 | 153 | - To remove stack affected by a change 154 | 155 | ```shell 156 | nx affected:remove --stage= 157 | ``` 158 | 159 | - To remove all stacks 160 | 161 | ```shell 162 | nx run-many --target=remove --all --stage= 163 | ``` 164 | 165 | - **Run tests** 166 | 167 | - To run tests in single stack 168 | 169 | ```shell 170 | nx run :test --stage= 171 | ``` 172 | 173 | - To run tests affected by a change 174 | 175 | ```shell 176 | nx affected:test --stage= 177 | ``` 178 | 179 | - To run tests in all stacks 180 | 181 | ```shell 182 | nx run-many --target=test --all --stage= 183 | ``` 184 | 185 | - **Run offline / locally** 186 | 187 | - To run offlline, configure `serverless-offline` plugin as documented [here](https://github.com/dherault/serverless-offline) and run below command 188 | 189 | ```shell 190 | nx run :serve --stage= 191 | ``` 192 | 193 | - **Understand your workspace** 194 | 195 | ``` 196 | nx dep-graph 197 | ``` 198 | 199 | ## Further help 200 | 201 | - Visit [Serverless Documentation](https://www.serverless.com/framework/docs/) to learn more about Serverless framework 202 | - Visit [Nx Documentation](https://nx.dev) to learn more about Nx dev toolkit 203 | - Why NX, not Lerna? Lerna is no longer maintained 204 | 205 | ## Nx Cloud 206 | 207 | ##### Computation Memoization in the Cloud 208 | 209 | ​ Nx Cloud pairs with Nx in order to enable you to build and test code more rapidly, by up to 10 times. 210 | 211 | ​ Visit [Nx Cloud](https://nx.app/) to learn more and enable it 212 | 213 | ## Contribution 214 | 215 | Found an issue? feel free to raise an issue with information to reproduce. 216 | 217 | Pull requests are welcome to improve. 218 | 219 | ## Support 220 | 221 | Like the template? 222 | 223 | Click to Buy Me A Coffee 224 | 225 | Or, Add a star :star: to the repository 226 | 227 | ## Maintainer 228 | 229 | This template is authored and maintained by [sudokar](https://github.com/sudokar) 230 | 231 | ## License 232 | 233 | MIT 234 | -------------------------------------------------------------------------------- /jest.config.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | projects: [], 3 | }; 4 | -------------------------------------------------------------------------------- /jest.preset.js: -------------------------------------------------------------------------------- 1 | const nxPreset = require('@nx/jest/preset').default; 2 | 3 | module.exports = { ...nxPreset }; 4 | -------------------------------------------------------------------------------- /libs/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sudokar/nx-serverless/e9e984b2da038c2b897469429d987f56a35b8cf5/libs/.gitkeep -------------------------------------------------------------------------------- /nx.json: -------------------------------------------------------------------------------- 1 | { 2 | "affected": { 3 | "defaultBase": "main" 4 | }, 5 | "tasksRunnerOptions": { 6 | "default": { 7 | "runner": "@nx/workspace/tasks-runners/default", 8 | "options": {} 9 | } 10 | }, 11 | "workspaceLayout": { 12 | "appsDir": "stacks" 13 | }, 14 | "$schema": "./node_modules/nx/schemas/nx-schema.json", 15 | "namedInputs": { 16 | "default": ["{projectRoot}/**/*", "sharedGlobals"], 17 | "sharedGlobals": [ 18 | "{workspaceRoot}/workspace.json", 19 | "{workspaceRoot}/tsconfig.base.json", 20 | "{workspaceRoot}/tslint.json", 21 | "{workspaceRoot}/nx.json" 22 | ], 23 | "production": ["default", "!{projectRoot}/.eslintrc.json"] 24 | }, 25 | "targetDefaults": { 26 | "build": { 27 | "cache": true 28 | }, 29 | "@nx/jest:jest": { 30 | "cache": true, 31 | "inputs": ["default", "^production", "{workspaceRoot}/jest.preset.js"], 32 | "options": { 33 | "passWithNoTests": true 34 | }, 35 | "configurations": { 36 | "ci": { 37 | "ci": true, 38 | "codeCoverage": true 39 | } 40 | } 41 | }, 42 | "@nx/eslint:lint": { 43 | "cache": true, 44 | "inputs": [ 45 | "default", 46 | "{workspaceRoot}/.eslintrc.json", 47 | "{workspaceRoot}/tools/eslint-rules/**/*" 48 | ] 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nx-serverless-template", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "nx": "nx", 7 | "build": "nx build", 8 | "test": "nx test", 9 | "lint": "nx workspace-lint && nx lint", 10 | "e2e": "nx e2e", 11 | "affected:stacks": "nx affected:apps", 12 | "affected:libs": "nx affected:libs", 13 | "affected:build": "nx affected:build", 14 | "affected:e2e": "nx affected:e2e", 15 | "affected:test": "nx affected:test", 16 | "affected:lint": "nx affected:lint", 17 | "affected:dep-graph": "nx affected:dep-graph", 18 | "affected": "nx affected", 19 | "format": "nx format:write", 20 | "format:write": "nx format:write", 21 | "format:check": "nx format:check", 22 | "update": "nx migrate latest", 23 | "workspace-generator": "nx workspace-generator", 24 | "dep-graph": "nx dep-graph", 25 | "help": "nx help", 26 | "prepare": "husky install" 27 | }, 28 | "devDependencies": { 29 | "@aws-sdk/types": "3.723.0", 30 | "@jest/transform": "29.7.0", 31 | "@nrwl/tao": "18.3.5", 32 | "@nx/devkit": "18.3.5", 33 | "@nx/eslint": "18.3.5", 34 | "@nx/eslint-plugin": "18.3.5", 35 | "@nx/jest": "18.3.5", 36 | "@nx/js": "18.3.5", 37 | "@nx/node": "18.3.5", 38 | "@nx/plugin": "18.3.5", 39 | "@nx/workspace": "18.3.5", 40 | "@swc-node/register": "1.9.0", 41 | "@swc/cli": "0.3.9", 42 | "@swc/core": "1.4.8", 43 | "@swc/jest": "0.2.36", 44 | "@types/aws-lambda": "8.10.147", 45 | "@types/jest": "29.5.14", 46 | "@types/node": "20.17.12", 47 | "@types/serverless": "3.12.26", 48 | "@typescript-eslint/eslint-plugin": "7.18.0", 49 | "@typescript-eslint/parser": "7.18.0", 50 | "esbuild": "0.20.0", 51 | "eslint": "8.57.1", 52 | "eslint-config-prettier": "9.1.0", 53 | "husky": "9.1.7", 54 | "jest": "29.7.0", 55 | "jest-environment-node": "29.7.0", 56 | "lint-staged": "15.3.0", 57 | "nx-cloud": "18.0.1", 58 | "prettier": "3.4.2", 59 | "serverless": "3.40.0", 60 | "serverless-esbuild": "1.54.6", 61 | "serverless-jest-plugin": "0.4.0", 62 | "serverless-offline": "13.9.0", 63 | "ts-jest": "29.2.5", 64 | "ts-loader": "9.5.2", 65 | "ts-node": "10.9.2", 66 | "typescript": "5.7.3" 67 | }, 68 | "engines": { 69 | "node": "20" 70 | }, 71 | "lint-staged": { 72 | "*.{js,jsx,ts,tsx}": [ 73 | "eslint --fix", 74 | "prettier --write" 75 | ], 76 | "*.{md,json,yml,yaml,html}": [ 77 | "prettier --write" 78 | ] 79 | }, 80 | "packageManager": "yarn@4.6.0", 81 | "dependencies": { 82 | "@swc/helpers": "0.5.6", 83 | "tslib": "2.8.1" 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["config:base"], 3 | "packageRules": [ 4 | { 5 | "matchUpdateTypes": ["minor", "patch"], 6 | "matchCurrentVersion": "!/^0/", 7 | "automerge": true 8 | } 9 | ], 10 | "lockFileMaintenance": { 11 | "enabled": true, 12 | "automerge": true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /serverless.base.ts: -------------------------------------------------------------------------------- 1 | import type { Serverless } from 'serverless/aws'; 2 | 3 | export const baseServerlessConfiguration: Partial = { 4 | frameworkVersion: '3', 5 | package: { 6 | individually: true, 7 | excludeDevDependencies: true, 8 | }, 9 | plugins: ['serverless-esbuild', 'serverless-offline'], 10 | custom: { 11 | esbuild: { 12 | bundle: true, 13 | minify: true, 14 | target: 'node20', 15 | packager: 'yarn', 16 | sourcemap: true, 17 | sourcesContent: false, 18 | }, 19 | }, 20 | provider: { 21 | name: 'aws', 22 | runtime: 'nodejs20.x', 23 | memorySize: 128, 24 | apiGateway: { 25 | minimumCompressionSize: 1024, 26 | }, 27 | stage: '${opt:stage}', 28 | environment: { 29 | AWS_NODEJS_CONNECTION_REUSE_ENABLED: '1', 30 | }, 31 | region: 'eu-west-1', 32 | }, 33 | }; 34 | -------------------------------------------------------------------------------- /stacks/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sudokar/nx-serverless/e9e984b2da038c2b897469429d987f56a35b8cf5/stacks/.gitkeep -------------------------------------------------------------------------------- /tools/tsconfig.tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "../dist/out-tsc/tools", 5 | "rootDir": ".", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "types": ["node"], 9 | "importHelpers": false 10 | }, 11 | "include": ["**/*.ts"] 12 | } 13 | -------------------------------------------------------------------------------- /tools/workspace-plugin/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 | "rules": {} 8 | }, 9 | { 10 | "files": ["*.ts", "*.tsx"], 11 | "rules": {} 12 | }, 13 | { 14 | "files": ["*.js", "*.jsx"], 15 | "rules": {} 16 | }, 17 | { 18 | "files": ["./package.json", "./generators.json"], 19 | "parser": "jsonc-eslint-parser", 20 | "rules": { 21 | "@nx/nx-plugin-checks": "error" 22 | } 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /tools/workspace-plugin/generators.json: -------------------------------------------------------------------------------- 1 | { 2 | "generators": { 3 | "serverless": { 4 | "implementation": "./src/generators/serverless", 5 | "schema": "./src/generators/serverless/schema.json", 6 | "description": "Generator serverless" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tools/workspace-plugin/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | export default { 3 | displayName: 'workspace-plugin', 4 | preset: '../../jest.preset.js', 5 | transform: { 6 | '^.+\\.[tj]s$': ['ts-jest', { tsconfig: '/tsconfig.spec.json' }], 7 | }, 8 | moduleFileExtensions: ['ts', 'js', 'html'], 9 | coverageDirectory: '../../coverage/tools/workspace-plugin', 10 | }; 11 | -------------------------------------------------------------------------------- /tools/workspace-plugin/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@nx-serverless-template/workspace-plugin", 3 | "version": "0.0.1", 4 | "type": "commonjs", 5 | "generators": "./generators.json" 6 | } 7 | -------------------------------------------------------------------------------- /tools/workspace-plugin/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "workspace-plugin", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "tools/workspace-plugin/src", 5 | "projectType": "library", 6 | "targets": { 7 | "build": { 8 | "executor": "@nx/js:tsc", 9 | "outputs": ["{options.outputPath}"], 10 | "options": { 11 | "outputPath": "dist/tools/workspace-plugin", 12 | "main": "tools/workspace-plugin/src/index.ts", 13 | "tsConfig": "tools/workspace-plugin/tsconfig.lib.json", 14 | "assets": [ 15 | { 16 | "input": "./tools/workspace-plugin/src", 17 | "glob": "**/!(*.ts)", 18 | "output": "./src" 19 | }, 20 | { 21 | "input": "./tools/workspace-plugin/src", 22 | "glob": "**/*.d.ts", 23 | "output": "./src" 24 | }, 25 | { 26 | "input": "./tools/workspace-plugin", 27 | "glob": "generators.json", 28 | "output": "." 29 | }, 30 | { 31 | "input": "./tools/workspace-plugin", 32 | "glob": "executors.json", 33 | "output": "." 34 | } 35 | ] 36 | } 37 | }, 38 | "lint": { 39 | "executor": "@nx/eslint:lint", 40 | "outputs": ["{options.outputFile}"] 41 | }, 42 | "test": { 43 | "executor": "@nx/jest:jest", 44 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 45 | "options": { 46 | "jestConfig": "tools/workspace-plugin/jest.config.ts" 47 | } 48 | } 49 | }, 50 | "tags": [] 51 | } 52 | -------------------------------------------------------------------------------- /tools/workspace-plugin/src/generators/serverless/files/.eslintrc.json__tmpl__: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../.eslintrc.json", 3 | "ignorePatterns": ["!**/*"], 4 | "rules": {} 5 | } 6 | -------------------------------------------------------------------------------- /tools/workspace-plugin/src/generators/serverless/files/README.md: -------------------------------------------------------------------------------- 1 | # <%= name %> 2 | 3 | This stack was generated with [Nx](https://nx.dev). 4 | 5 | ## Running unit tests 6 | 7 | Run `nx test <%= name %>` to execute the unit tests via [Jest](https://jestjs.io). 8 | -------------------------------------------------------------------------------- /tools/workspace-plugin/src/generators/serverless/files/serverless.ts__tmpl__: -------------------------------------------------------------------------------- 1 | import type { Serverless } from 'serverless/aws'; 2 | // eslint-disable-next-line @nx/enforce-module-boundaries 3 | import { baseServerlessConfiguration } from '../../serverless.base'; 4 | 5 | const serverlessConfiguration = { 6 | ...baseServerlessConfiguration, 7 | service: '<%= name %>', 8 | functions: { 9 | hello: { 10 | handler: 'src/handler.hello', 11 | events: [ 12 | { 13 | http: { 14 | method: 'get', 15 | path: 'hello', 16 | }, 17 | }, 18 | ], 19 | }, 20 | }, 21 | }; 22 | 23 | module.exports = serverlessConfiguration; 24 | -------------------------------------------------------------------------------- /tools/workspace-plugin/src/generators/serverless/files/src/handler.ts__tmpl__: -------------------------------------------------------------------------------- 1 | import { APIGatewayProxyHandler } from 'aws-lambda'; 2 | 3 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 4 | export const hello: APIGatewayProxyHandler = async (event, _context) => { 5 | return { 6 | statusCode: 200, 7 | body: JSON.stringify({ 8 | message: 'Go Serverless Webpack (Typescript) v1.0! Your function executed successfully!', 9 | input: event, 10 | }, null, 2), 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /tools/workspace-plugin/src/generators/serverless/files/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "types": ["node"] 6 | }, 7 | "exclude": ["**/*.spec.ts"], 8 | "include": ["**/*.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /tools/workspace-plugin/src/generators/serverless/files/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "files": [], 4 | "include": [], 5 | "references": [ 6 | { 7 | "path": "./tsconfig.app.json" 8 | }, 9 | { 10 | "path": "./tsconfig.spec.json" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /tools/workspace-plugin/src/generators/serverless/files/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "include": ["**/*.spec.ts", "**/*.d.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /tools/workspace-plugin/src/generators/serverless/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | formatFiles, 3 | generateFiles, 4 | installPackagesTask, 5 | joinPathFragments, 6 | Tree, 7 | } from '@nx/devkit'; 8 | import { Schema } from './schema'; 9 | import { addJest } from './jest-config'; 10 | import { addWorkspaceConfig } from './workspace-config'; 11 | 12 | export default async (host: Tree, schema: Schema) => { 13 | const stackRoot = `stacks/${schema.name}`; 14 | 15 | generateFiles( 16 | host, // the virtual file system 17 | joinPathFragments(__dirname, './files'), // path to the file templates 18 | stackRoot, // destination path of the files 19 | { ...schema, tmpl: '' } // config object to replace variable in file templates 20 | ); 21 | 22 | addWorkspaceConfig(host, schema.name, stackRoot); 23 | 24 | await addJest(host, schema.name); 25 | 26 | await formatFiles(host); 27 | 28 | return () => { 29 | installPackagesTask(host); 30 | }; 31 | }; 32 | -------------------------------------------------------------------------------- /tools/workspace-plugin/src/generators/serverless/jest-config.ts: -------------------------------------------------------------------------------- 1 | import { Tree } from '@nx/devkit'; 2 | import { configurationGenerator } from '@nx/jest'; 3 | import { JestProjectSchema } from '@nx/jest/src/generators/configuration/schema'; 4 | 5 | export const addJest = async (host: Tree, projectName: string) => { 6 | await configurationGenerator(host, { 7 | project: projectName, 8 | setupFile: 'none', 9 | testEnvironment: 'node', 10 | skipSerializers: false, 11 | supportTsx: false, 12 | compiler: 'swc', 13 | skipFormat: true, 14 | }); 15 | }; 16 | -------------------------------------------------------------------------------- /tools/workspace-plugin/src/generators/serverless/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "cli": "nx", 3 | "id": "serverless", 4 | "type": "object", 5 | "properties": { 6 | "name": { 7 | "type": "string", 8 | "description": "Library name", 9 | "$default": { 10 | "$source": "argv", 11 | "index": 0 12 | } 13 | } 14 | }, 15 | "required": ["name"] 16 | } 17 | -------------------------------------------------------------------------------- /tools/workspace-plugin/src/generators/serverless/schema.ts: -------------------------------------------------------------------------------- 1 | export type Schema = { 2 | readonly name: string; 3 | }; 4 | -------------------------------------------------------------------------------- /tools/workspace-plugin/src/generators/serverless/workspace-config.ts: -------------------------------------------------------------------------------- 1 | import { addProjectConfiguration, Tree } from '@nx/devkit'; 2 | 3 | const buildRunCommandConfig = (dir: string, command: string) => ({ 4 | executor: 'nx:run-commands', 5 | options: { 6 | cwd: dir, 7 | color: true, 8 | command: command, 9 | }, 10 | }); 11 | 12 | export const addWorkspaceConfig = ( 13 | host: Tree, 14 | projectName: string, 15 | stackRoot: string, 16 | ) => { 17 | addProjectConfiguration(host, projectName, { 18 | root: stackRoot, 19 | projectType: 'application', 20 | sourceRoot: stackRoot + '/src', 21 | targets: { 22 | build: { 23 | ...buildRunCommandConfig(stackRoot, 'sls package'), 24 | }, 25 | serve: { 26 | ...buildRunCommandConfig(stackRoot, 'sls offline start'), 27 | }, 28 | deploy: { 29 | ...buildRunCommandConfig(stackRoot, 'sls deploy'), 30 | }, 31 | remove: { 32 | ...buildRunCommandConfig(stackRoot, 'sls remove'), 33 | }, 34 | lint: { 35 | executor: '@nx/eslint:lint', 36 | options: { 37 | lintFilePatterns: [stackRoot + '/**/*.ts'], 38 | }, 39 | }, 40 | }, 41 | tags: ['stack'], 42 | }); 43 | }; 44 | -------------------------------------------------------------------------------- /tools/workspace-plugin/src/index.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sudokar/nx-serverless/e9e984b2da038c2b897469429d987f56a35b8cf5/tools/workspace-plugin/src/index.ts -------------------------------------------------------------------------------- /tools/workspace-plugin/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "module": "commonjs" 5 | }, 6 | "files": [], 7 | "include": [], 8 | "references": [ 9 | { 10 | "path": "./tsconfig.lib.json" 11 | }, 12 | { 13 | "path": "./tsconfig.spec.json" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /tools/workspace-plugin/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "declaration": true, 6 | "types": ["node"] 7 | }, 8 | "include": ["src/**/*.ts"], 9 | "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /tools/workspace-plugin/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "include": [ 9 | "jest.config.ts", 10 | "src/**/*.test.ts", 11 | "src/**/*.spec.ts", 12 | "src/**/*.d.ts" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /tsconfig.base.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "rootDir": ".", 5 | "sourceMap": true, 6 | "declaration": false, 7 | "moduleResolution": "node", 8 | "emitDecoratorMetadata": true, 9 | "experimentalDecorators": true, 10 | "importHelpers": false, 11 | "target": "es2022", 12 | "module": "commonjs", 13 | "lib": ["esnext"], 14 | "skipLibCheck": true, 15 | "skipDefaultLibCheck": true, 16 | "baseUrl": ".", 17 | "paths": { 18 | "@nx-serverless-template/workspace-plugin": [ 19 | "tools/workspace-plugin/src/index.ts" 20 | ] 21 | } 22 | }, 23 | "exclude": ["node_modules", "tmp"] 24 | } 25 | --------------------------------------------------------------------------------