├── .gitignore ├── .prettierrc ├── LICENSE ├── README.md ├── nodemon-debug.json ├── nodemon.json ├── package.json ├── src ├── app.module.ts ├── clients │ ├── GithubClient.ts │ └── index.ts ├── config.production.yaml ├── config.yaml ├── controllers │ ├── GithubController.ts │ ├── HelloWorldController.ts │ ├── ProxyController.ts │ └── index.ts ├── lb-rules │ └── CustomLoadbalanceRule.ts ├── main.ts ├── proxy-filters │ ├── CustomProxyFilter.ts │ ├── ProxyFilterRegister.ts │ └── index.ts ├── registrars │ ├── LoadbalanceRuleRegistrar.ts │ └── index.ts └── services │ ├── ScheduleService.ts │ └── index.ts ├── test ├── app.e2e-spec.ts └── jest-e2e.json ├── tsconfig.build.json ├── tsconfig.json ├── tsconfig.spec.json ├── tslint.json └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### JetBrains template 3 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm 4 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 5 | 6 | # User-specific stuff: 7 | .idea/**/workspace.xml 8 | .idea/**/tasks.xml 9 | .idea/dictionaries 10 | 11 | # Sensitive or high-churn files: 12 | .idea/**/dataSources/ 13 | .idea/**/dataSources.ids 14 | .idea/**/dataSources.xml 15 | .idea/**/dataSources.local.xml 16 | .idea/**/sqlDataSources.xml 17 | .idea/**/dynamic.xml 18 | .idea/**/uiDesigner.xml 19 | 20 | # Gradle: 21 | .idea/**/gradle.xml 22 | .idea/**/libraries 23 | 24 | # CMake 25 | cmake-build-debug/ 26 | 27 | # Mongo Explorer plugin: 28 | .idea/**/mongoSettings.xml 29 | 30 | ## File-based project format: 31 | *.iws 32 | 33 | ## Plugin-specific files: 34 | 35 | # IntelliJ 36 | out/ 37 | 38 | # mpeltonen/sbt-idea plugin 39 | .idea_modules/ 40 | 41 | # JIRA plugin 42 | atlassian-ide-plugin.xml 43 | 44 | # Cursive Clojure plugin 45 | .idea/replstate.xml 46 | 47 | # Crashlytics plugin (for Android Studio and IntelliJ) 48 | com_crashlytics_export_strings.xml 49 | crashlytics.properties 50 | crashlytics-build.properties 51 | fabric.properties 52 | ### VisualStudio template 53 | ## Ignore Visual Studio temporary files, build results, and 54 | ## files generated by popular Visual Studio add-ons. 55 | ## 56 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 57 | 58 | # User-specific files 59 | *.suo 60 | *.user 61 | *.userosscache 62 | *.sln.docstates 63 | 64 | # User-specific files (MonoDevelop/Xamarin Studio) 65 | *.userprefs 66 | 67 | # Build results 68 | [Dd]ebug/ 69 | [Dd]ebugPublic/ 70 | [Rr]elease/ 71 | [Rr]eleases/ 72 | x64/ 73 | x86/ 74 | bld/ 75 | [Bb]in/ 76 | [Oo]bj/ 77 | [Ll]og/ 78 | 79 | # Visual Studio 2015 cache/options directory 80 | .vs/ 81 | # Uncomment if you have tasks that create the project's static files in wwwroot 82 | #wwwroot/ 83 | 84 | # MSTest test Results 85 | [Tt]est[Rr]esult*/ 86 | [Bb]uild[Ll]og.* 87 | 88 | # NUNIT 89 | *.VisualState.xml 90 | TestResult.xml 91 | 92 | # Build Results of an ATL Project 93 | [Dd]ebugPS/ 94 | [Rr]eleasePS/ 95 | dlldata.c 96 | 97 | # Benchmark Results 98 | BenchmarkDotNet.Artifacts/ 99 | 100 | # .NET Core 101 | project.lock.json 102 | project.fragment.lock.json 103 | artifacts/ 104 | **/Properties/launchSettings.json 105 | 106 | *_i.c 107 | *_p.c 108 | *_i.h 109 | *.ilk 110 | *.meta 111 | *.obj 112 | *.pch 113 | *.pdb 114 | *.pgc 115 | *.pgd 116 | *.rsp 117 | *.sbr 118 | *.tlb 119 | *.tli 120 | *.tlh 121 | *.tmp 122 | *.tmp_proj 123 | *.log 124 | *.vspscc 125 | *.vssscc 126 | .builds 127 | *.pidb 128 | *.svclog 129 | *.scc 130 | 131 | # Chutzpah Test files 132 | _Chutzpah* 133 | 134 | # Visual C++ cache files 135 | ipch/ 136 | *.aps 137 | *.ncb 138 | *.opendb 139 | *.opensdf 140 | *.sdf 141 | *.cachefile 142 | *.VC.db 143 | *.VC.VC.opendb 144 | 145 | # Visual Studio profiler 146 | *.psess 147 | *.vsp 148 | *.vspx 149 | *.sap 150 | 151 | # Visual Studio Trace Files 152 | *.e2e 153 | 154 | # TFS 2012 Local Workspace 155 | $tf/ 156 | 157 | # Guidance Automation Toolkit 158 | *.gpState 159 | 160 | # ReSharper is a .NET coding add-in 161 | _ReSharper*/ 162 | *.[Rr]e[Ss]harper 163 | *.DotSettings.user 164 | 165 | # JustCode is a .NET coding add-in 166 | .JustCode 167 | 168 | # TeamCity is a build add-in 169 | _TeamCity* 170 | 171 | # DotCover is a Code Coverage Tool 172 | *.dotCover 173 | 174 | # AxoCover is a Code Coverage Tool 175 | .axoCover/* 176 | !.axoCover/settings.json 177 | 178 | # Visual Studio code coverage results 179 | *.coverage 180 | *.coveragexml 181 | 182 | # NCrunch 183 | _NCrunch_* 184 | .*crunch*.local.xml 185 | nCrunchTemp_* 186 | 187 | # MightyMoose 188 | *.mm.* 189 | AutoTest.Net/ 190 | 191 | # Web workbench (sass) 192 | .sass-cache/ 193 | 194 | # Installshield output folder 195 | [Ee]xpress/ 196 | 197 | # DocProject is a documentation generator add-in 198 | DocProject/buildhelp/ 199 | DocProject/Help/*.HxT 200 | DocProject/Help/*.HxC 201 | DocProject/Help/*.hhc 202 | DocProject/Help/*.hhk 203 | DocProject/Help/*.hhp 204 | DocProject/Help/Html2 205 | DocProject/Help/html 206 | 207 | # Click-Once directory 208 | publish/ 209 | 210 | # Publish Web Output 211 | *.[Pp]ublish.xml 212 | *.azurePubxml 213 | # Note: Comment the next line if you want to checkin your web deploy settings, 214 | # but database connection strings (with potential passwords) will be unencrypted 215 | *.pubxml 216 | *.publishproj 217 | 218 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 219 | # checkin your Azure Web App publish settings, but sensitive information contained 220 | # in these scripts will be unencrypted 221 | PublishScripts/ 222 | 223 | # NuGet Packages 224 | *.nupkg 225 | # The packages folder can be ignored because of Package Restore 226 | **/[Pp]ackages/* 227 | # except build/, which is used as an MSBuild target. 228 | !**/[Pp]ackages/build/ 229 | # Uncomment if necessary however generally it will be regenerated when needed 230 | #!**/[Pp]ackages/repositories.config 231 | # NuGet v3's project.json files produces more ignorable files 232 | *.nuget.props 233 | *.nuget.targets 234 | 235 | # Microsoft Azure Build Output 236 | csx/ 237 | *.build.csdef 238 | 239 | # Microsoft Azure Emulator 240 | ecf/ 241 | rcf/ 242 | 243 | # Windows Store app package directories and files 244 | AppPackages/ 245 | BundleArtifacts/ 246 | Package.StoreAssociation.xml 247 | _pkginfo.txt 248 | *.appx 249 | 250 | # Visual Studio cache files 251 | # files ending in .cache can be ignored 252 | *.[Cc]ache 253 | # but keep track of directories ending in .cache 254 | !*.[Cc]ache/ 255 | 256 | # Others 257 | ClientBin/ 258 | ~$* 259 | *~ 260 | *.dbmdl 261 | *.dbproj.schemaview 262 | *.jfm 263 | *.pfx 264 | *.publishsettings 265 | orleans.codegen.cs 266 | 267 | # Since there are multiple workflows, uncomment next line to ignore bower_components 268 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 269 | #bower_components/ 270 | 271 | # RIA/Silverlight projects 272 | Generated_Code/ 273 | 274 | # Backup & report files from converting an old project file 275 | # to a newer Visual Studio version. Backup files are not needed, 276 | # because we have git ;-) 277 | _UpgradeReport_Files/ 278 | Backup*/ 279 | UpgradeLog*.XML 280 | UpgradeLog*.htm 281 | 282 | # SQL Server files 283 | *.mdf 284 | *.ldf 285 | *.ndf 286 | 287 | # Business Intelligence projects 288 | *.rdl.data 289 | *.bim.layout 290 | *.bim_*.settings 291 | 292 | # Microsoft Fakes 293 | FakesAssemblies/ 294 | 295 | # GhostDoc plugin setting file 296 | *.GhostDoc.xml 297 | 298 | # Node.js Tools for Visual Studio 299 | .ntvs_analysis.dat 300 | node_modules/ 301 | 302 | # Typescript v1 declaration files 303 | typings/ 304 | 305 | # Visual Studio 6 build log 306 | *.plg 307 | 308 | # Visual Studio 6 workspace options file 309 | *.opt 310 | 311 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 312 | *.vbw 313 | 314 | # Visual Studio LightSwitch build output 315 | **/*.HTMLClient/GeneratedArtifacts 316 | **/*.DesktopClient/GeneratedArtifacts 317 | **/*.DesktopClient/ModelManifest.xml 318 | **/*.Server/GeneratedArtifacts 319 | **/*.Server/ModelManifest.xml 320 | _Pvt_Extensions 321 | 322 | # Paket dependency manager 323 | .paket/paket.exe 324 | paket-files/ 325 | 326 | # FAKE - F# Make 327 | .fake/ 328 | 329 | # JetBrains Rider 330 | .idea/ 331 | *.sln.iml 332 | 333 | # CodeRush 334 | .cr/ 335 | 336 | # Python Tools for Visual Studio (PTVS) 337 | __pycache__/ 338 | *.pyc 339 | 340 | # Cake - Uncomment if you are using it 341 | # tools/** 342 | # !tools/packages.config 343 | 344 | # Tabs Studio 345 | *.tss 346 | 347 | # Telerik's JustMock configuration file 348 | *.jmconfig 349 | 350 | # BizTalk build output 351 | *.btp.cs 352 | *.btm.cs 353 | *.odx.cs 354 | *.xsd.cs 355 | 356 | # OpenCover UI analysis results 357 | OpenCover/ 358 | coverage/ 359 | 360 | ### macOS template 361 | # General 362 | .DS_Store 363 | .AppleDouble 364 | .LSOverride 365 | 366 | # Icon must end with two \r 367 | Icon 368 | 369 | # Thumbnails 370 | ._* 371 | 372 | # Files that might appear in the root of a volume 373 | .DocumentRevisions-V100 374 | .fseventsd 375 | .Spotlight-V100 376 | .TemporaryItems 377 | .Trashes 378 | .VolumeIcon.icns 379 | .com.apple.timemachine.donotpresent 380 | 381 | # Directories potentially created on remote AFP share 382 | .AppleDB 383 | .AppleDesktop 384 | Network Trash Folder 385 | Temporary Items 386 | .apdisk 387 | 388 | ======= 389 | # Local 390 | docker-compose.yml 391 | .env 392 | build 393 | logs 394 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "all" 4 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | (The MIT License) 2 | 3 | Copyright (c) 2017-2019 Kamil Myśliwiec 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | 'Software'), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | [travis-image]: https://api.travis-ci.org/nest-cloud/nestcloud.svg?branch=master 3 | [travis-url]: https://travis-ci.org/nest-cloud/nestcloud 4 | [linux-image]: https://img.shields.io/travis/nest-cloud/nestcloud/master.svg?label=linux 5 | [linux-url]: https://travis-ci.org/nest-cloud/nestcloud 6 | 7 | # NestCloud 8 | 9 |

10 | NestCloud is a Node.js micro-service solution, writing by Typescript language and Nest.js framework.

11 |

12 | 13 |

14 | NPM Version 15 | Package License 16 | NPM Downloads 17 | Travis 18 | Linux 19 | Coverage 20 | Backers on Open Collective 21 | Sponsors on Open Collective 22 |

23 | 25 | 26 | ## Installation 27 | 28 | ```bash 29 | $ yarn install 30 | ``` 31 | 32 | ## Dependencies 33 | 34 | - Consul 35 | 36 | ## Running the app 37 | 38 | ```bash 39 | # development 40 | $ npm run start 41 | 42 | # watch mode 43 | $ npm run start:dev 44 | 45 | # production mode 46 | npm run start:prod 47 | ``` 48 | 49 | After run the starter app, you can visit this urls in browser: 50 | 51 | http://localhost:3000 52 | 53 | http://localhost:3000/github 54 | 55 | http://localhost:3000/proxy/github 56 | 57 | ## Stay in touch 58 | 59 | - Author - [NestCloud](https://github.com/nest-cloud) 60 | 61 | ## License 62 | 63 | Nest is [MIT licensed](LICENSE). 64 | -------------------------------------------------------------------------------- /nodemon-debug.json: -------------------------------------------------------------------------------- 1 | { 2 | "watch": ["src"], 3 | "ext": "ts", 4 | "ignore": ["src/**/*.spec.ts"], 5 | "exec": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register src/main.ts" 6 | } -------------------------------------------------------------------------------- /nodemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "watch": ["src"], 3 | "ext": "ts", 4 | "ignore": ["src/**/*.spec.ts"], 5 | "exec": "ts-node -r tsconfig-paths/register src/main.ts" 6 | } 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nestcloud-consul-starter", 3 | "version": "1.0.0", 4 | "description": "NestCloud Consul starter repository", 5 | "license": "MIT", 6 | "scripts": { 7 | "build": "tsc -p tsconfig.build.json", 8 | "format": "prettier --write \"src/**/*.ts\"", 9 | "start": "ts-node -r tsconfig-paths/register src/main.ts", 10 | "start:dev": "nodemon", 11 | "start:debug": "nodemon --config nodemon-debug.json", 12 | "prestart:prod": "rimraf dist && tsc", 13 | "start:prod": "node dist/main.js", 14 | "lint": "tslint -p tsconfig.json -c tslint.json", 15 | "test": "jest", 16 | "test:watch": "jest --watch", 17 | "test:cov": "jest --coverage", 18 | "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", 19 | "test:e2e": "jest --config ./test/jest-e2e.json" 20 | }, 21 | "dependencies": { 22 | "@godaddy/terminus": "^4.1.2", 23 | "@nestcloud/boot": "^0.7.15", 24 | "@nestcloud/common": "^0.7.15", 25 | "@nestcloud/config": "^0.7.15", 26 | "@nestcloud/consul": "^0.7.15", 27 | "@nestcloud/http": "^0.7.15", 28 | "@nestcloud/loadbalance": "^0.7.15", 29 | "@nestcloud/logger": "^0.7.15", 30 | "@nestcloud/proxy": "^0.7.15", 31 | "@nestcloud/schedule": "^0.7.15", 32 | "@nestcloud/service": "^0.7.15", 33 | "@nestjs/common": "^6.10.14", 34 | "@nestjs/core": "^6.10.14", 35 | "@nestjs/microservices": "^6.10.14", 36 | "@nestjs/platform-express": "^6.10.14", 37 | "@nestjs/swagger": "^4.1.12", 38 | "@nestjs/terminus": "^6.5.5", 39 | "@nestjs/testing": "^6.10.14", 40 | "@nestjs/websockets": "^6.10.14", 41 | "consul": "^0.34.1", 42 | "mysql": "^2.17.1", 43 | "reflect-metadata": "^0.1.13", 44 | "rimraf": "^2.6.3", 45 | "rxjs": "^6.5.2", 46 | "rxjs-compat": "^6.5.2", 47 | "typeorm": "^0.2.18" 48 | }, 49 | "devDependencies": { 50 | "@types/express": "^4.17.0", 51 | "@types/jest": "^24.0.15", 52 | "@types/node": "^12.6.8", 53 | "@types/supertest": "^2.0.8", 54 | "@types/winston": "^2.4.4", 55 | "jest": "^24.8.0", 56 | "nodemon": "^1.19.1", 57 | "prettier": "^1.18.2", 58 | "supertest": "^4.0.2", 59 | "ts-jest": "^24.0.2", 60 | "ts-node": "^8.3.0", 61 | "tsconfig-paths": "^3.8.0", 62 | "tslint": "5.18.0", 63 | "typescript": "^3.5.3" 64 | }, 65 | "jest": { 66 | "moduleFileExtensions": [ 67 | "js", 68 | "json", 69 | "ts" 70 | ], 71 | "rootDir": "src", 72 | "testRegex": ".spec.ts$", 73 | "transform": { 74 | "^.+\\.(t|j)s$": "ts-jest" 75 | }, 76 | "coverageDirectory": "../coverage", 77 | "testEnvironment": "node" 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/app.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { BootModule } from '@nestcloud/boot'; 3 | import { ConsulModule } from '@nestcloud/consul'; 4 | import { ConfigModule } from '@nestcloud/config'; 5 | import { ServiceModule } from '@nestcloud/service'; 6 | import { LoadbalanceModule } from '@nestcloud/loadbalance'; 7 | import { HttpModule } from '@nestcloud/http'; 8 | import { ScheduleModule } from '@nestcloud/schedule'; 9 | import { BOOT, LOADBALANCE, components, CONSUL } from '@nestcloud/common'; 10 | import { TypeOrmHealthIndicator, TerminusModule } from '@nestjs/terminus'; 11 | import { ProxyModule } from '@nestcloud/proxy'; 12 | 13 | import * as controllers from './controllers'; 14 | import * as services from './services'; 15 | import * as clients from './clients'; 16 | import * as registrars from 'registrars'; 17 | import { LoggerModule } from '@nestcloud/logger'; 18 | import { resolve } from 'path'; 19 | 20 | @Module({ 21 | imports: [ 22 | LoggerModule.forRoot(), 23 | ScheduleModule.forRoot(), 24 | BootModule.forRoot({ 25 | filePath: resolve(__dirname, 'config.yaml'), 26 | }), 27 | ConsulModule.forRootAsync({ inject: [BOOT] }), 28 | ConfigModule.forRootAsync({ inject: [BOOT, CONSUL] }), 29 | ServiceModule.forRootAsync({ inject: [BOOT, CONSUL] }), 30 | LoadbalanceModule.forRootAsync({ inject: [BOOT] }), 31 | HttpModule.forRootAsync({ inject: [LOADBALANCE] }), 32 | ProxyModule.forRootAsync({ inject: [BOOT, LOADBALANCE] }), 33 | TerminusModule.forRootAsync({ 34 | inject: [TypeOrmHealthIndicator], 35 | useFactory: () => ({ endpoints: [{ url: '/health', healthIndicators: [] }] }), 36 | }), 37 | ], 38 | controllers: components(controllers), 39 | providers: components(services, clients, registrars), 40 | }) 41 | export class AppModule { 42 | } 43 | -------------------------------------------------------------------------------- /src/clients/GithubClient.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | import { Get } from '@nestcloud/http'; 3 | 4 | @Injectable() 5 | export class GithubClient { 6 | @Get('https://api.github.com') 7 | getGithubAPI() { 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/clients/index.ts: -------------------------------------------------------------------------------- 1 | export * from './GithubClient'; 2 | -------------------------------------------------------------------------------- /src/config.production.yaml: -------------------------------------------------------------------------------- 1 | consul: 2 | host: localhost 3 | port: 8500 4 | service: 5 | name: nestcloud-starter-service 6 | port: 3000 7 | healthCheck: 8 | ttl: 20 9 | config: 10 | name: ${{ service.name }}-config 11 | loadbalance: 12 | rule: RandomRule 13 | services: 14 | - name: nestcloud-starter-service 15 | rule: CustomLoadbalanceRule 16 | proxy: 17 | routes: 18 | - id: starter 19 | uri: lb://${{ service.name }} 20 | filters: 21 | - name: CustomProxyFilter 22 | parameters: 23 | test-header: test 24 | - name: ResponseHeaderFilter 25 | parameters: 26 | custom-data: hello-world 27 | - id: github 28 | uri: https://api.github.com 29 | logger: 30 | level: info 31 | transports: 32 | - transport: console 33 | colorize: true 34 | datePattern: YYYY-MM-DD h:mm:ss 35 | label: ${{ service.name }} 36 | -------------------------------------------------------------------------------- /src/config.yaml: -------------------------------------------------------------------------------- 1 | consul: 2 | host: localhost 3 | port: 8500 4 | service: 5 | name: nestcloud-starter-service 6 | port: 3000 7 | healthCheck: 8 | ttl: 20 9 | config: 10 | name: ${{ service.name }}-config 11 | loadbalance: 12 | rule: RandomRule 13 | services: 14 | - name: nestcloud-starter-service 15 | rule: CustomLoadbalanceRule 16 | proxy: 17 | routes: 18 | - id: starter 19 | uri: lb://${{ service.name }} 20 | filters: 21 | - name: CustomProxyFilter 22 | parameters: 23 | test-header: test 24 | - name: ResponseHeaderFilter 25 | parameters: 26 | custom-data: hello-world 27 | - id: github 28 | uri: https://api.github.com 29 | logger: 30 | level: info 31 | transports: 32 | - transport: console 33 | colorize: true 34 | datePattern: YYYY-MM-DD h:mm:ss 35 | label: ${{ service.name }} 36 | -------------------------------------------------------------------------------- /src/controllers/GithubController.ts: -------------------------------------------------------------------------------- 1 | import { Controller, Get } from '@nestjs/common'; 2 | import { GithubClient } from '../clients'; 3 | 4 | @Controller('/github') 5 | export class GithubController { 6 | constructor( 7 | private readonly githubClient: GithubClient, 8 | ) { 9 | } 10 | 11 | @Get() 12 | async getGithubAPI() { 13 | return this.githubClient.getGithubAPI(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/controllers/HelloWorldController.ts: -------------------------------------------------------------------------------- 1 | import { Controller, Get } from '@nestjs/common'; 2 | 3 | @Controller() 4 | export class HelloWorldController { 5 | @Get() 6 | async getHelloWorld() { 7 | return { message: 'hello world!' }; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/controllers/ProxyController.ts: -------------------------------------------------------------------------------- 1 | import { All, Controller, Param, Req, Res } from '@nestjs/common'; 2 | import { Request, Response } from 'express'; 3 | import { Proxy, InjectProxy } from '@nestcloud/proxy'; 4 | 5 | @Controller('/proxy/:service') 6 | export class ProxyController { 7 | constructor( 8 | @InjectProxy() private readonly proxy: Proxy, 9 | ) { 10 | } 11 | 12 | @All() 13 | async do(@Req() req: Request, @Res() res: Response, @Param('service') id) { 14 | return await this.proxy.forward(req, res, id); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/controllers/index.ts: -------------------------------------------------------------------------------- 1 | export * from './HelloWorldController'; 2 | export * from './GithubController'; 3 | export * from './ProxyController'; 4 | -------------------------------------------------------------------------------- /src/lb-rules/CustomLoadbalanceRule.ts: -------------------------------------------------------------------------------- 1 | import { Rule } from '@nestcloud/loadbalance'; 2 | import { ILoadbalancer, IServer } from '@nestcloud/common'; 3 | import { Injectable } from '@nestjs/common'; 4 | 5 | @Injectable() 6 | export class CustomLoadbalanceRule implements Rule { 7 | private loadbalancer: ILoadbalancer; 8 | 9 | choose(): IServer { 10 | return this.loadbalancer.servers[0]; 11 | } 12 | 13 | init(loadbalancer: ILoadbalancer): any { 14 | this.loadbalancer = loadbalancer; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { NestFactory } from '@nestjs/core'; 2 | import { AppModule } from './app.module'; 3 | import { NestLogger } from '@nestcloud/logger'; 4 | import { BOOT, IBoot } from '@nestcloud/common'; 5 | import { resolve } from 'path'; 6 | 7 | async function bootstrap() { 8 | const app = await NestFactory.create(AppModule, { 9 | logger: new NestLogger({ 10 | filePath: resolve(__dirname, './config.yaml'), 11 | }), 12 | }); 13 | 14 | process.on('SIGINT', async () => { 15 | setTimeout(() => process.exit(1), 5000); 16 | await app.close(); 17 | process.exit(0); 18 | }); 19 | 20 | // kill -15 21 | process.on('SIGTERM', async () => { 22 | setTimeout(() => process.exit(1), 5000); 23 | await app.close(); 24 | process.exit(0); 25 | }); 26 | 27 | const boot = app.get(BOOT); 28 | await app.listen(boot.get('service.port', 3000)); 29 | } 30 | 31 | bootstrap(); 32 | -------------------------------------------------------------------------------- /src/proxy-filters/CustomProxyFilter.ts: -------------------------------------------------------------------------------- 1 | import { Filter, ProxyErrorException, Request, Response } from '@nestcloud/proxy'; 2 | import { ClientRequest, IncomingMessage } from 'http'; 3 | import { Injectable } from '@nestjs/common'; 4 | 5 | @Injectable() 6 | export class CustomProxyFilter implements Filter { 7 | before(request: Request, response: Response): boolean | Promise { 8 | return true; 9 | } 10 | 11 | error(error: ProxyErrorException, request: Request, response: Response): any { 12 | } 13 | 14 | request(proxyReq: ClientRequest, request: Request, response: Response): any { 15 | } 16 | 17 | response(proxyRes: IncomingMessage, request: Request, response: Response): any { 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/proxy-filters/ProxyFilterRegister.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | import { UseFilters } from '@nestcloud/proxy'; 3 | import { CustomProxyFilter } from './CustomProxyFilter'; 4 | import { Choose } from '@nestcloud/loadbalance'; 5 | 6 | @Injectable() 7 | @UseFilters(CustomProxyFilter) 8 | export class ProxyFilterRegister { 9 | @Choose('yrcloudfile-user-service') 10 | private readonly userServiceNode; 11 | 12 | constructor() { 13 | // setInterval(() => console.log(this.userServiceNode), 1000); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/proxy-filters/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ProxyFilterRegister'; 2 | -------------------------------------------------------------------------------- /src/registrars/LoadbalanceRuleRegistrar.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | import { UseRules } from '@nestcloud/loadbalance'; 3 | import { CustomLoadbalanceRule } from '../lb-rules/CustomLoadbalanceRule'; 4 | 5 | @Injectable() 6 | @UseRules(CustomLoadbalanceRule) 7 | export class LoadbalanceRuleRegistrar { 8 | } 9 | -------------------------------------------------------------------------------- /src/registrars/index.ts: -------------------------------------------------------------------------------- 1 | export * from './LoadbalanceRuleRegistrar'; 2 | -------------------------------------------------------------------------------- /src/services/ScheduleService.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, Logger, OnModuleInit } from '@nestjs/common'; 2 | import { Interval } from '@nestcloud/schedule'; 3 | import { InjectLogger } from '@nestcloud/logger'; 4 | import { BootValue } from '@nestcloud/boot'; 5 | import { ConfigValue } from '@nestcloud/config'; 6 | import { Schedule } from '@nestcloud/schedule'; 7 | 8 | @Injectable() 9 | export class ScheduleService implements OnModuleInit { 10 | @BootValue('custom.data', 'default custom data') 11 | private readonly customData: string; 12 | 13 | // In this project, the consul key is 'nestcloud-starter-service-config' 14 | // Please insert data in it. 15 | @ConfigValue('test', 'default custom data') 16 | private readonly consulCustomData: string; 17 | 18 | public constructor( 19 | @InjectLogger() private readonly logger: Logger, 20 | private schedule: Schedule, 21 | ) { 22 | } 23 | 24 | onModuleInit(): any { 25 | this.schedule.createTimeoutJob(() => { 26 | this.logger.log('execute timeout job'); 27 | }, 3000); 28 | } 29 | 30 | @Interval(2000) 31 | intervalBootJob() { 32 | this.logger.log(`interval get custom data from boot: ${this.customData}`); 33 | } 34 | 35 | @Interval(2000) 36 | intervalConsulConfigJob() { 37 | this.logger.log(`interval get custom from consul config: ${this.consulCustomData}`); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/services/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ScheduleService'; 2 | -------------------------------------------------------------------------------- /test/app.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 | // @ts-ignore 10 | beforeAll(async () => { 11 | const moduleFixture = await Test.createTestingModule({ 12 | imports: [AppModule], 13 | }).compile(); 14 | 15 | app = moduleFixture.createNestApplication(); 16 | await app.init(); 17 | }); 18 | 19 | it('/users (GET)', () => { 20 | return request(app.getHttpServer()) 21 | .get('/users') 22 | .expect(200); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /test/jest-e2e.json: -------------------------------------------------------------------------------- 1 | { 2 | "moduleFileExtensions": ["js", "json", "ts"], 3 | "rootDir": ".", 4 | "testEnvironment": "node", 5 | "testRegex": ".e2e-spec.ts$", 6 | "transform": { 7 | "^.+\\.(t|j)s$": "ts-jest" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": ["src/**/*"], 4 | "exclude": ["node_modules", "**/*.spec.ts"] 5 | } 6 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "declaration": false, 5 | "noImplicitAny": false, 6 | "removeComments": true, 7 | "noLib": false, 8 | "allowSyntheticDefaultImports": true, 9 | "emitDecoratorMetadata": true, 10 | "experimentalDecorators": true, 11 | "target": "es6", 12 | "sourceMap": true, 13 | "allowJs": true, 14 | "outDir": "./build", 15 | "baseUrl": "./src" 16 | }, 17 | "include": [ 18 | "src/**/*" 19 | ], 20 | "exclude": [ 21 | "node_modules", 22 | "**/*.spec.ts" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "types": ["jest", "node"] 5 | }, 6 | "include": ["**/*.spec.ts", "**/*.d.ts"] 7 | } 8 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "defaultSeverity": "error", 3 | "extends": ["tslint:recommended"], 4 | "jsRules": { 5 | "no-unused-expression": true 6 | }, 7 | "rules": { 8 | "no-empty": false, 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 | } 20 | --------------------------------------------------------------------------------