├── .gitignore ├── .prettierrc ├── .travis.yml ├── .yarnrc ├── README.md ├── jest-e2e.json ├── jest.json ├── lerna.json ├── package.json ├── packages ├── api │ ├── package.json │ ├── src │ │ ├── app.controller.spec.ts │ │ ├── app.controller.ts │ │ ├── app.module.ts │ │ ├── index.ts │ │ └── main.ts │ ├── test │ │ └── api.e2e-spec.ts │ └── tsconfig.json ├── cli │ ├── package.json │ ├── src │ │ └── cli.ts │ └── tsconfig.json ├── core │ ├── package.json │ ├── src │ │ ├── core.module.ts │ │ ├── core.service.spec.ts │ │ ├── core.service.ts │ │ └── index.ts │ └── tsconfig.json ├── tsconfig.json └── tsconfig.settings.json ├── renovate.json ├── tsconfig.spec.json ├── tslint.json └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/node 3 | 4 | ### Node ### 5 | # Logs 6 | logs 7 | *.log 8 | npm-debug.log* 9 | yarn-debug.log* 10 | yarn-error.log* 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | 24 | # nyc test coverage 25 | .nyc_output 26 | 27 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 28 | .grunt 29 | 30 | # Bower dependency directory (https://bower.io/) 31 | bower_components 32 | 33 | # node-waf configuration 34 | .lock-wscript 35 | 36 | # Compiled binary addons (http://nodejs.org/api/addons.html) 37 | build/Release 38 | 39 | # Dependency directories 40 | node_modules/ 41 | jspm_packages/ 42 | 43 | # Typescript v1 declaration files 44 | typings/ 45 | 46 | # Optional npm cache directory 47 | .npm 48 | 49 | # Optional eslint cache 50 | .eslintcache 51 | 52 | # Optional REPL history 53 | .node_repl_history 54 | 55 | # Output of 'npm pack' 56 | *.tgz 57 | 58 | # Yarn Integrity file 59 | .yarn-integrity 60 | 61 | # dotenv environment variables file 62 | .env 63 | 64 | 65 | # End of https://www.gitignore.io/api/node 66 | 67 | lib/ -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "all" 4 | } -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | cache: 2 | yarn: true 3 | directories: 4 | - node_modules 5 | language: node_js 6 | 7 | before_install: 8 | - npm install -g yarn@1.12.3 9 | 10 | node_js: 11 | - "8" 12 | - "10" 13 | - "12" -------------------------------------------------------------------------------- /.yarnrc: -------------------------------------------------------------------------------- 1 | workspaces-experimental true -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NestJS mono-repo starter 2 | 3 | [Nest](https://github.com/nestjs/nest) framework TypeScript monorepo starter repository. 4 | 5 | ## Architecture 6 | 7 | ![Architecture](https://i.imgur.com/beFeCec.png) 8 | 9 | ## Prerequisites 10 | 11 | - [yarn](https://yarnpkg.com) >= 1.4.2 12 | - [node](https://nodejs.org/) >= 10 13 | - [lerna](https://github.com/lerna/lerna) >= 3.0.0 14 | 15 | ## Installation 16 | 17 | ```bash 18 | 19 | yarn 20 | 21 | ``` 22 | 23 | ## Running the cli 24 | 25 | ```bash 26 | 27 | yarn run build 28 | yarn run start 29 | # Open up on http://localhost:3000 30 | 31 | # Run help 32 | yarn run start --help 33 | 34 | ``` 35 | -------------------------------------------------------------------------------- /jest-e2e.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "moduleFileExtensions": ["js", "json", "ts"], 4 | "rootDir": ".", 5 | "testEnvironment": "node", 6 | "testRegex": ".e2e-spec.ts$", 7 | "transform": { 8 | "^.+\\.(t|j)s$": "ts-jest" 9 | }, 10 | "globals": { 11 | "ts-jest": { 12 | "tsConfig": "tsconfig.spec.json" 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /jest.json: -------------------------------------------------------------------------------- 1 | { 2 | "moduleFileExtensions": [ 3 | "js", 4 | "json", 5 | "ts" 6 | ], 7 | "rootDir": "packages/", 8 | "testRegex": ".spec.ts$", 9 | "transform": { 10 | "^.+\\.(t|j)s$": "ts-jest" 11 | }, 12 | "coverageDirectory": "../coverage", 13 | "coveragePathIgnorePatterns": [ 14 | "lib" 15 | ], 16 | "testEnvironment": "node", 17 | "globals": { 18 | "ts-jest": { 19 | "tsConfig": "tsconfig.spec.json" 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.8.1", 3 | "packages": [ 4 | "packages/*" 5 | ], 6 | "npmClient": "yarn", 7 | "publishConfig": { 8 | "access": "public" 9 | }, 10 | "useWorkspaces": true, 11 | "lerna": "2.9.0" 12 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "monoapp", 3 | "version": "1.0.0", 4 | "private": true, 5 | "license": "MIT", 6 | "main": "main.js", 7 | "workspaces": { 8 | "packages": [ 9 | "packages/*" 10 | ], 11 | "nohoist": [ 12 | "**/@nestjs", 13 | "**/@nestjs/**" 14 | ] 15 | }, 16 | "scripts": { 17 | "bootstrap": "lerna bootstrap", 18 | "build": "tsc -b packages/core packages/cli packages/api", 19 | "clean": "rimraf packages/**/lib", 20 | "start": "node packages/cli/lib/cli.js", 21 | "pretest": "yarn run build", 22 | "test": "jest --config ./jest.json", 23 | "test:cov": "jest --config ./jest.json --coverage", 24 | "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --config ./jest.json --runInBand", 25 | "test:e2e": "jest --config ./jest-e2e.json", 26 | "test:watch": "jest --config ./jest.json --watch" 27 | }, 28 | "devDependencies": { 29 | "@nestjs/testing": "6.3.1", 30 | "@types/express": "4.17.0", 31 | "@types/jest": "25.2.3", 32 | "@types/node": "13.13.5", 33 | "jest": "25.5.4", 34 | "lerna": "3.15.0", 35 | "prettier": "1.18.2", 36 | "rimraf": "3.0.2", 37 | "supertest": "4.0.2", 38 | "ts-jest": "25.5.1", 39 | "tslint": "6.1.2", 40 | "typescript": "3.9.5" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /packages/api/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@monoapp/api", 3 | "version": "1.0.0", 4 | "license": "MIT", 5 | "main": "lib/index.js", 6 | "dependencies": { 7 | "@monoapp/common": "1.0.0", 8 | "@monoapp/core": "1.0.0", 9 | "@nestjs/common": "^6.3.1", 10 | "@nestjs/core": "^6.3.1", 11 | "@nestjs/platform-express": "^6.3.1", 12 | "reflect-metadata": "^0.1.13", 13 | "rxjs": "^6.5.2" 14 | }, 15 | "devDependencies": { 16 | "@nestjs/testing": "6.3.1" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/api/src/app.controller.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { AppController } from './app.controller'; 3 | import { CoreService } from '@monoapp/core'; 4 | 5 | describe('AppController', () => { 6 | let app: TestingModule; 7 | 8 | beforeAll(async () => { 9 | app = await Test.createTestingModule({ 10 | controllers: [AppController], 11 | providers: [CoreService], 12 | }).compile(); 13 | }); 14 | 15 | describe('getHello', () => { 16 | it('should return "Hello World!"', () => { 17 | const appController = app.get(AppController); 18 | expect(appController.getHello()).toBe('Hello World!'); 19 | }); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /packages/api/src/app.controller.ts: -------------------------------------------------------------------------------- 1 | 2 | import { Get, Controller } from '@nestjs/common'; 3 | import { CoreService } from '@monoapp/core'; 4 | 5 | @Controller() 6 | export class AppController { 7 | constructor(private readonly coreSerivce: CoreService) {} 8 | 9 | @Get() 10 | getHello(): string { 11 | return this.coreSerivce.getHello(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/api/src/app.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { AppController } from './app.controller'; 3 | import { CoreModule } from '@monoapp/core'; 4 | 5 | @Module({ 6 | imports: [CoreModule], 7 | controllers: [AppController], 8 | }) 9 | export class AppModule {} 10 | -------------------------------------------------------------------------------- /packages/api/src/index.ts: -------------------------------------------------------------------------------- 1 | export { startApi } from './main'; 2 | -------------------------------------------------------------------------------- /packages/api/src/main.ts: -------------------------------------------------------------------------------- 1 | import { NestFactory } from '@nestjs/core'; 2 | import { AppModule } from './app.module'; 3 | 4 | export async function startApi(port: number = 3000): Promise { 5 | const app = await NestFactory.create(AppModule); 6 | await app.listen(port); 7 | return port; 8 | } 9 | -------------------------------------------------------------------------------- /packages/api/test/api.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import * as request from 'supertest'; 2 | import { Test } from '@nestjs/testing'; 3 | import { AppModule } from './../src/app.module'; 4 | import { INestApplication } from '@nestjs/common'; 5 | 6 | describe('AppController (e2e)', () => { 7 | let app: INestApplication; 8 | 9 | beforeAll(async () => { 10 | const moduleFixture = await Test.createTestingModule({ 11 | imports: [AppModule], 12 | }).compile(); 13 | 14 | app = moduleFixture.createNestApplication(); 15 | await app.init(); 16 | }); 17 | 18 | it('/ (GET)', () => { 19 | return request(app.getHttpServer()) 20 | .get('/') 21 | .expect(200) 22 | .expect('Hello World!'); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /packages/api/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.settings.json", 3 | "compilerOptions": { 4 | "rootDir": "src", 5 | "outDir": "lib", 6 | "composite": true 7 | }, 8 | "references": [{ "path": "../core" }], 9 | "exclude": ["lib", "test"] 10 | } 11 | -------------------------------------------------------------------------------- /packages/cli/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@monoapp/common", 3 | "version": "1.0.0", 4 | "license": "MIT", 5 | "main": "lib/index.js", 6 | "bin": { 7 | "monoapp": "./lib/cli.js" 8 | }, 9 | "dependencies": { 10 | "@monoapp/api": "1.0.0", 11 | "commander": "^4.0.0" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/cli/src/cli.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import * as program from 'commander'; 4 | import { startApi } from '@monoapp/api'; 5 | 6 | program 7 | .version('0.1.0') 8 | .option('-p, --port ', 'server port', parseInt) 9 | .parse(process.argv); 10 | 11 | startApi(program.port).then(port => console.log(`Listening on port ${port}`)); 12 | -------------------------------------------------------------------------------- /packages/cli/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.settings.json", 3 | "compilerOptions": { 4 | "rootDir": "src", 5 | "outDir": "lib" 6 | }, 7 | "references": [ 8 | { "path": "../api" } 9 | ], 10 | "exclude": ["lib"] 11 | } -------------------------------------------------------------------------------- /packages/core/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@monoapp/core", 3 | "version": "1.0.0", 4 | "license": "MIT", 5 | "main": "lib/index.js", 6 | "dependencies": { 7 | "@nestjs/common": "^6.3.1", 8 | "@nestjs/core": "^6.3.1", 9 | "reflect-metadata": "^0.1.13", 10 | "rxjs": "^6.5.2" 11 | }, 12 | "devDependencies": { 13 | "@nestjs/testing": "6.3.1" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/core/src/core.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { CoreService } from './core.service'; 3 | 4 | @Module({ 5 | providers: [CoreService], 6 | exports: [CoreService], 7 | }) 8 | export class CoreModule { } 9 | -------------------------------------------------------------------------------- /packages/core/src/core.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { CoreService } from './core.service'; 3 | 4 | describe('AppController', () => { 5 | let app: TestingModule; 6 | 7 | beforeAll(async () => { 8 | app = await Test.createTestingModule({ 9 | providers: [CoreService], 10 | }).compile(); 11 | }); 12 | 13 | describe('getHello', () => { 14 | it('should return "Hello World!"', () => { 15 | const coreService = app.get(CoreService); 16 | expect(coreService.getHello()).toBe('Hello World!'); 17 | }); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /packages/core/src/core.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | 3 | @Injectable() 4 | export class CoreService { 5 | getHello(): string { 6 | return 'Hello World!'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/core/src/index.ts: -------------------------------------------------------------------------------- 1 | export { CoreService } from './core.service'; 2 | export { CoreModule } from './core.module'; 3 | -------------------------------------------------------------------------------- /packages/core/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.settings.json", 3 | "compilerOptions": { 4 | "rootDir": "src", 5 | "outDir": "lib", 6 | "composite": true 7 | }, 8 | "exclude": ["lib"] 9 | } -------------------------------------------------------------------------------- /packages/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [], 3 | "references": [ 4 | { 5 | "path": "api" 6 | }, 7 | { 8 | "path": "core" 9 | }, 10 | { 11 | "path": "common" 12 | } 13 | ], 14 | "exclude": [] 15 | } -------------------------------------------------------------------------------- /packages/tsconfig.settings.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "compilerOptions": { 4 | "module": "commonjs", 5 | "declaration": true, 6 | "noImplicitAny": false, 7 | "removeComments": true, 8 | "noLib": false, 9 | "allowSyntheticDefaultImports": true, 10 | "emitDecoratorMetadata": true, 11 | "experimentalDecorators": true, 12 | "target": "es6", 13 | "sourceMap": true, 14 | "outDir": "./dist", 15 | "baseUrl": "./" 16 | }, 17 | "exclude": ["node_modules"], 18 | "paths": { 19 | "@monoapp/*": ["./*/src"] 20 | } 21 | } -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "semanticCommits": true, 4 | "packageRules": [{ 5 | "depTypeList": ["devDependencies"], 6 | "automerge": true 7 | }], 8 | "extends": [ 9 | "config:base" 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./packages/tsconfig.settings.json", 3 | "compilerOptions": { 4 | "types": ["jest", "node"], 5 | "lib": ["es2018"], 6 | "allowJs": true 7 | }, 8 | "include": ["**/*.spec.ts", "**/*.d.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "defaultSeverity": "error", 4 | "extends": ["tslint:recommended"], 5 | "jsRules": { 6 | "no-unused-expression": true 7 | }, 8 | "rules": { 9 | "quotemark": [true, "single"], 10 | "member-access": [false], 11 | "ordered-imports": [false], 12 | "max-line-length": [true, 150], 13 | "member-ordering": [false], 14 | "interface-name": [false], 15 | "arrow-parens": false, 16 | "object-literal-sort-keys": false 17 | }, 18 | "rulesDirectory": [] 19 | } --------------------------------------------------------------------------------