Repository: rdlabo-team/serverless-nestjs Branch: master Commit: 9d2a0a77d622 Files: 19 Total size: 10.5 KB Directory structure: gitextract_8vmkf7io/ ├── .eslintrc.js ├── .github/ │ └── FUNDING.yml ├── .gitignore ├── .prettierrc ├── README.md ├── nest-cli.json ├── package.json ├── serverless.yml ├── src/ │ ├── app.controller.spec.ts │ ├── app.controller.ts │ ├── app.module.ts │ ├── app.service.ts │ ├── index.ts │ ├── main.ts │ └── swagger.ts ├── test/ │ ├── app.e2e-spec.ts │ └── jest-e2e.json ├── tsconfig.build.json └── tsconfig.json ================================================ FILE CONTENTS ================================================ ================================================ FILE: .eslintrc.js ================================================ module.exports = { parser: '@typescript-eslint/parser', parserOptions: { project: 'tsconfig.json', sourceType: 'module', }, plugins: ['@typescript-eslint/eslint-plugin'], extends: [ 'plugin:@typescript-eslint/recommended', 'plugin:prettier/recommended', ], root: true, env: { node: true, jest: true, }, ignorePatterns: ['.eslintrc.js'], rules: { '@typescript-eslint/interface-name-prefix': 'off', '@typescript-eslint/explicit-function-return-type': 'off', '@typescript-eslint/explicit-module-boundary-types': 'off', '@typescript-eslint/no-explicit-any': 'off', }, }; ================================================ FILE: .github/FUNDING.yml ================================================ # These are supported funding model platforms github: rdlabo ================================================ FILE: .gitignore ================================================ # compiled output /dist /node_modules # Logs logs *.log npm-debug.log* yarn-debug.log* yarn-error.log* lerna-debug.log* # OS .DS_Store # Tests /coverage /.nyc_output # IDEs and editors /.idea .project .classpath .c9/ *.launch .settings/ *.sublime-workspace # IDE - VSCode .vscode/* !.vscode/settings.json !.vscode/tasks.json !.vscode/launch.json !.vscode/extensions.json ================================================ FILE: .prettierrc ================================================ { "singleQuote": true, "trailingComma": "all" } ================================================ FILE: README.md ================================================ # serverless-nestjs This is an example of creating a function that runs as nestjs using the serverless framework. Sample publish. https://mmjdx4zxmc.execute-api.ap-northeast-1.amazonaws.com/dev/ ## What is changed. ### add - `src/index.ts` - `src/swagger.ts` - `serverless.yml` ### change - `package.json` ## How to use ### Prepare ``` $ npm install @nestjs/cli serverless -g $ git clone git@github.com:rdlabo/serverless-nestjs.git 【projectName】 $ cd 【projectName】 $ npm install $ npm start ``` ### Development #### use NestCLI ``` $ npm start ``` ``` $ npm start > serverless-nestjs@0.0.0 start /Users/sakakibara/dev/serverless-nestjs > nest start [Nest] 3905 - 11/29/2019, 4:40:49 PM [NestFactory] Starting Nest application... [Nest] 3905 - 11/29/2019, 4:40:49 PM [InstanceLoader] AppModule dependencies initialized +20ms [Nest] 3905 - 11/29/2019, 4:40:49 PM [RoutesResolver] AppController {/}: +6ms [Nest] 3905 - 11/29/2019, 4:40:49 PM [RouterExplorer] Mapped {/, GET} route +3ms [Nest] 3905 - 11/29/2019, 4:40:49 PM [NestApplication] Nest application successfully started +4ms ``` Then browse http://localhost:3000 #### use serverless-offline __after also doing an: `npm run build`__ ```bash $ sls offline ``` ``` $ sls offline Serverless: Starting Offline: dev/us-east-1. Serverless: Routes for index: Serverless: ANY / Serverless: ANY /{proxy*} Serverless: Offline listening on http://localhost:3000 ``` Then browse http://localhost:3000 ## How to Deploy ```bash $ npm run build && sls deploy ``` ## Options ### Hot start See : https://serverless.com/blog/keep-your-lambdas-warm/ These behavior can be fixed with the plugin serverless-plugin-warmup 1 Install the plugin ``` $ npm install serverless-plugin-warmup --save-dev ``` 2 Enable the plugin ``` plugins: - '@hewmen/serverless-plugin-typescript' - serverless-plugin-optimize - serverless-offline - serverless-plugin-warmup custom: # Enable warmup on all functions (only for production and staging) warmup: - production - staging ``` ### Use Swagger for development ``` $ npx ts-node src/swagger.ts ``` ``` [Nest] 6890 - 2019-03-24 15:11 [NestFactory] Starting Nest application... [Nest] 6890 - 2019-03-24 15:11 [InstanceLoader] AppModule dependencies initialized +11ms [Nest] 6890 - 2019-03-24 15:11 [RoutesResolver] AppController {/}: +224ms [Nest] 6890 - 2019-03-24 15:11 [RouterExplorer] Mapped {/, GET} route +2ms [Nest] 6890 - 2019-03-24 15:11 [NestApplication] Nest application successfully started +2ms ``` Then browse http://localhost:3001/api **This function is for development.** If you want to use production, change package.json dependencies and serverless.yml. ================================================ FILE: nest-cli.json ================================================ { "collection": "@nestjs/schematics", "sourceRoot": "src" } ================================================ FILE: package.json ================================================ { "name": "serverless-nestjs", "version": "0.0.0", "description": "description", "author": "", "license": "MIT", "scripts": { "prebuild": "rimraf dist", "build": "nest build", "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", "start": "nest start", "start:dev": "nest start --watch", "start:debug": "nest start --debug --watch", "start:prod": "node dist/main", "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", "test": "jest", "test:watch": "jest --watch", "test:cov": "jest --coverage", "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", "test:e2e": "jest --config ./test/jest-e2e.json" }, "dependencies": { "@nestjs/common": "^8.1.1", "@nestjs/core": "^8.1.1", "@nestjs/platform-express": "^8.1.1", "aws-serverless-express": "^3.4.0", "express": "^4.17.1", "reflect-metadata": "^0.1.13", "rimraf": "^3.0.2", "rxjs": "^7.4.0" }, "devDependencies": { "@nestjs/cli": "^8.1.3", "@nestjs/schematics": "^8.0.4", "@nestjs/swagger": "^5.2.0", "@nestjs/testing": "^8.1.1", "@types/aws-lambda": "^8.10.59", "@types/express": "^4.17.13", "@types/jest": "^27.0.2", "@types/node": "^16.11.1", "@types/supertest": "^2.0.11", "@typescript-eslint/eslint-plugin": "^4.29.2", "@typescript-eslint/parser": "^4.29.2", "eslint": "^7.32.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-import": "^2.25.4", "eslint-plugin-prettier": "^3.4.1", "jest": "^27.3.0", "prettier": "^2.4.1", "serverless-offline": "^6.9.0", "source-map-support": "^0.5.20", "supertest": "^6.1.6", "swagger-ui-express": "^4.3.0", "ts-jest": "^27.0.7", "ts-loader": "^9.2.6", "ts-node": "^10.3.0", "tsconfig-paths": "^3.11.0", "typescript": "^4.4.4" }, "jest": { "moduleFileExtensions": [ "js", "json", "ts" ], "rootDir": "src", "testRegex": ".spec.ts$", "transform": { "^.+\\.(t|j)s$": "ts-jest" }, "coverageDirectory": "../coverage", "testEnvironment": "node" } } ================================================ FILE: serverless.yml ================================================ service: serverless-nestjs provider: name: aws runtime: nodejs12.x region: us-east-1 plugins: - serverless-offline package: exclude: - .git/** - src/** - test/** - e2e/** - nodemon.json - README.md functions: index: handler: dist/index.handler events: - http: cors: true path: '/' method: any - http: cors: true path: '{proxy+}' method: any ================================================ FILE: src/app.controller.spec.ts ================================================ import { Test, TestingModule } from '@nestjs/testing'; import { AppController } from './app.controller'; import { AppService } from './app.service'; describe('AppController', () => { let app: TestingModule; beforeAll(async () => { app = await Test.createTestingModule({ controllers: [AppController], providers: [AppService], }).compile(); }); describe('getHello', () => { it('should return "Hello World!"', () => { const appController = app.get(AppController); expect(appController.getHello()).toBe('Hello World!'); }); }); }); ================================================ FILE: src/app.controller.ts ================================================ import { Controller, Get } from '@nestjs/common'; import { AppService } from './app.service'; @Controller() export class AppController { constructor(private readonly appService: AppService) {} @Get() getHello(): string { return this.appService.getHello(); } } ================================================ FILE: src/app.module.ts ================================================ import { Module } from '@nestjs/common'; import { AppController } from './app.controller'; import { AppService } from './app.service'; @Module({ imports: [], controllers: [AppController], providers: [AppService], }) export class AppModule {} ================================================ FILE: src/app.service.ts ================================================ import { Injectable } from '@nestjs/common'; @Injectable() export class AppService { getHello(): string { return 'Hello World!'; } } ================================================ FILE: src/index.ts ================================================ import { APIGatewayProxyHandler } from 'aws-lambda'; import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; import { Server } from 'http'; import { ExpressAdapter } from '@nestjs/platform-express'; import * as awsServerlessExpress from 'aws-serverless-express'; import * as express from 'express'; let cachedServer: Server; const bootstrapServer = async (): Promise => { const expressApp = express(); const adapter = new ExpressAdapter(expressApp); const app = await NestFactory.create(AppModule, adapter); app.enableCors(); await app.init(); return awsServerlessExpress.createServer(expressApp); } export const handler: APIGatewayProxyHandler = async (event, context) => { if (!cachedServer) { cachedServer = await bootstrapServer() } return awsServerlessExpress.proxy(cachedServer, event, context, 'PROMISE') .promise; }; ================================================ FILE: src/main.ts ================================================ import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; async function bootstrap() { const app = await NestFactory.create(AppModule); await app.listen(3000); } bootstrap(); ================================================ FILE: src/swagger.ts ================================================ import { NestFactory } from '@nestjs/core'; import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger'; import { AppModule } from './app.module'; async function bootstrap() { const app = await NestFactory.create(AppModule); const options = new DocumentBuilder() .setTitle('Cats example') .setDescription('The cats API description') .setVersion('1.0') .addTag('cats') .build(); const document = SwaggerModule.createDocument(app, options); SwaggerModule.setup('api', app, document); await app.listen(3001); } bootstrap(); ================================================ FILE: test/app.e2e-spec.ts ================================================ import * as request from 'supertest'; import { Test } from '@nestjs/testing'; import { AppModule } from './../src/app.module'; import { INestApplication } from '@nestjs/common'; describe('AppController (e2e)', () => { let app: INestApplication; beforeAll(async () => { const moduleFixture = await Test.createTestingModule({ imports: [AppModule], }).compile(); app = moduleFixture.createNestApplication(); await app.init(); }); it('/ (GET)', () => { return request(app.getHttpServer()) .get('/') .expect(200) .expect('Hello World!'); }); }); ================================================ FILE: test/jest-e2e.json ================================================ { "moduleFileExtensions": ["js", "json", "ts"], "rootDir": ".", "testEnvironment": "node", "testRegex": ".e2e-spec.ts$", "transform": { "^.+\\.(t|j)s$": "ts-jest" } } ================================================ FILE: tsconfig.build.json ================================================ { "extends": "./tsconfig.json", "exclude": ["node_modules", "dist", "test", "**/*spec.ts"] } ================================================ FILE: tsconfig.json ================================================ { "compilerOptions": { "module": "commonjs", "declaration": true, "removeComments": true, "emitDecoratorMetadata": true, "experimentalDecorators": true, "allowSyntheticDefaultImports": true, "target": "es2017", "sourceMap": true, "outDir": "./dist", "baseUrl": "./", "incremental": true, "skipLibCheck": true } }