├── .editorconfig ├── .eslintrc.json ├── .gitignore ├── .prettierrc ├── CHANGELOG.md ├── README.md ├── commitlint.config.js ├── package-lock.json ├── package.json ├── src ├── aws.module.ts ├── constants.ts ├── index.ts ├── interfaces │ ├── IFile.ts │ ├── aws-s3-module-options.interface.ts │ ├── aws-ses-module-options.interface.ts │ ├── aws-sns-module-options.interface.ts │ └── s3-get-signed-url-request.interface.ts └── service │ ├── aws-logger.service.ts │ ├── aws.s3.service.ts │ ├── aws.ses.service.ts │ ├── aws.sns.service.ts │ └── generator.service.ts ├── test ├── app.e2e-spec.ts └── jest-e2e.json ├── tsconfig.build.json ├── tsconfig.json └── tslint.json /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 4 7 | insert_final_newline = true 8 | trim_trailing_whitespace = true 9 | 10 | [{src, scripts}/**.{ts, json, js}] 11 | end_of_line = lf 12 | 13 | [*.yml] 14 | indent_size = 2 15 | 16 | [*.md] 17 | max_line_length = off 18 | trim_trailing_whitespace = false 19 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "@typescript-eslint/tslint", 4 | "eslint-plugin-import-helpers" 5 | ], 6 | "parser": "@typescript-eslint/parser", 7 | "parserOptions": { 8 | "ecmaVersion": 2017, 9 | "ecmaFeatures": { 10 | "modules": true 11 | }, 12 | "sourceType": "module", 13 | "project": "tsconfig.json" 14 | }, 15 | "rules": { 16 | "@typescript-eslint/tslint/config": [ 17 | "error", 18 | { 19 | "lintFile": "./tslint.json" 20 | } 21 | ], 22 | "import-helpers/order-imports": [ 23 | "error", 24 | { 25 | // example configuration 26 | "newlinesBetween": "always", 27 | "groups": [ 28 | "module", 29 | "/^@shared/", 30 | [ 31 | "parent", 32 | "sibling", 33 | "index" 34 | ] 35 | ], 36 | "alphabetize": { 37 | "order": "asc", 38 | "ignoreCase": true 39 | } 40 | } 41 | ] 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /.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 | .directory 20 | 21 | # Gradle: 22 | .idea/**/gradle.xml 23 | .idea/**/libraries 24 | 25 | # CMake 26 | cmake-build-debug/ 27 | 28 | # Mongo Explorer plugin: 29 | .idea/**/mongoSettings.xml 30 | 31 | ## File-based project format: 32 | *.iws 33 | 34 | ## Plugin-specific files: 35 | 36 | # IntelliJ 37 | out/ 38 | 39 | # mpeltonen/sbt-idea plugin 40 | .idea_modules/ 41 | 42 | # JIRA plugin 43 | atlassian-ide-plugin.xml 44 | 45 | # Cursive Clojure plugin 46 | .idea/replstate.xml 47 | 48 | # Crashlytics plugin (for Android Studio and IntelliJ) 49 | com_crashlytics_export_strings.xml 50 | crashlytics.properties 51 | crashlytics-build.properties 52 | fabric.properties 53 | ### VisualStudio template 54 | ## Ignore Visual Studio temporary files, build results, and 55 | ## files generated by popular Visual Studio add-ons. 56 | ## 57 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 58 | 59 | # User-specific files 60 | *.suo 61 | *.user 62 | *.userosscache 63 | *.sln.docstates 64 | 65 | # User-specific files (MonoDevelop/Xamarin Studio) 66 | *.userprefs 67 | 68 | # Build results 69 | [Dd]ebug/ 70 | [Dd]ebugPublic/ 71 | [Rr]elease/ 72 | [Rr]eleases/ 73 | x64/ 74 | x86/ 75 | bld/ 76 | [Bb]in/ 77 | [Oo]bj/ 78 | [Ll]og/ 79 | 80 | # Visual Studio 2015 cache/options directory 81 | .vs/ 82 | # Visual Code cache/options directory 83 | .vscode/ 84 | # Uncomment if you have tasks that create the project's static files in wwwroot 85 | #wwwroot/ 86 | 87 | # MSTest test Results 88 | [Tt]est[Rr]esult*/ 89 | [Bb]uild[Ll]og.* 90 | 91 | # NUNIT 92 | *.VisualState.xml 93 | TestResult.xml 94 | 95 | # Build Results of an ATL Project 96 | [Dd]ebugPS/ 97 | [Rr]eleasePS/ 98 | dlldata.c 99 | 100 | # Benchmark Results 101 | BenchmarkDotNet.Artifacts/ 102 | 103 | # .NET Core 104 | project.lock.json 105 | project.fragment.lock.json 106 | artifacts/ 107 | **/Properties/launchSettings.json 108 | 109 | *_i.c 110 | *_p.c 111 | *_i.h 112 | *.ilk 113 | *.meta 114 | *.obj 115 | *.pch 116 | *.pdb 117 | *.pgc 118 | *.pgd 119 | *.rsp 120 | *.sbr 121 | *.tlb 122 | *.tli 123 | *.tlh 124 | *.tmp 125 | *.tmp_proj 126 | *.log 127 | *.vspscc 128 | *.vssscc 129 | .builds 130 | *.pidb 131 | *.svclog 132 | *.scc 133 | 134 | # Chutzpah Test files 135 | _Chutzpah* 136 | 137 | # Visual C++ cache files 138 | ipch/ 139 | *.aps 140 | *.ncb 141 | *.opendb 142 | *.opensdf 143 | *.sdf 144 | *.cachefile 145 | *.VC.db 146 | *.VC.VC.opendb 147 | 148 | # Visual Studio profiler 149 | *.psess 150 | *.vsp 151 | *.vspx 152 | *.sap 153 | 154 | # Visual Studio Trace Files 155 | *.e2e 156 | 157 | # TFS 2012 Local Workspace 158 | $tf/ 159 | 160 | # Guidance Automation Toolkit 161 | *.gpState 162 | 163 | # ReSharper is a .NET coding add-in 164 | _ReSharper*/ 165 | *.[Rr]e[Ss]harper 166 | *.DotSettings.user 167 | 168 | # JustCode is a .NET coding add-in 169 | .JustCode 170 | 171 | # TeamCity is a build add-in 172 | _TeamCity* 173 | 174 | # DotCover is a Code Coverage Tool 175 | *.dotCover 176 | 177 | # AxoCover is a Code Coverage Tool 178 | .axoCover/* 179 | !.axoCover/settings.json 180 | 181 | # Visual Studio code coverage results 182 | *.coverage 183 | *.coveragexml 184 | 185 | # NCrunch 186 | _NCrunch_* 187 | .*crunch*.local.xml 188 | nCrunchTemp_* 189 | 190 | # MightyMoose 191 | *.mm.* 192 | AutoTest.Net/ 193 | 194 | # Web workbench (sass) 195 | .sass-cache/ 196 | 197 | # Installshield output folder 198 | [Ee]xpress/ 199 | 200 | # DocProject is a documentation generator add-in 201 | DocProject/buildhelp/ 202 | DocProject/Help/*.HxT 203 | DocProject/Help/*.HxC 204 | DocProject/Help/*.hhc 205 | DocProject/Help/*.hhk 206 | DocProject/Help/*.hhp 207 | DocProject/Help/Html2 208 | DocProject/Help/html 209 | 210 | # Click-Once directory 211 | publish/ 212 | 213 | # Publish Web Output 214 | *.[Pp]ublish.xml 215 | *.azurePubxml 216 | # Note: Comment the next line if you want to checkin your web deploy settings, 217 | # but database connection strings (with potential passwords) will be unencrypted 218 | *.pubxml 219 | *.publishproj 220 | 221 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 222 | # checkin your Azure Web App publish settings, but sensitive information contained 223 | # in these scripts will be unencrypted 224 | PublishScripts/ 225 | 226 | # NuGet Packages 227 | *.nupkg 228 | # The packages folder can be ignored because of Package Restore 229 | **/[Pp]ackages/* 230 | # except build/, which is used as an MSBuild target. 231 | !**/[Pp]ackages/build/ 232 | # Uncomment if necessary however generally it will be regenerated when needed 233 | #!**/[Pp]ackages/repositories.config 234 | # NuGet v3's project.json files produces more ignorable files 235 | *.nuget.props 236 | *.nuget.targets 237 | 238 | # Microsoft Azure Build Output 239 | csx/ 240 | *.build.csdef 241 | 242 | # Microsoft Azure Emulator 243 | ecf/ 244 | rcf/ 245 | 246 | # Windows Store app package directories and files 247 | AppPackages/ 248 | BundleArtifacts/ 249 | Package.StoreAssociation.xml 250 | _pkginfo.txt 251 | *.appx 252 | 253 | # Visual Studio cache files 254 | # files ending in .cache can be ignored 255 | *.[Cc]ache 256 | # but keep track of directories ending in .cache 257 | !*.[Cc]ache/ 258 | 259 | # Others 260 | ClientBin/ 261 | ~$* 262 | *~ 263 | *.dbmdl 264 | *.dbproj.schemaview 265 | *.jfm 266 | *.pfx 267 | *.publishsettings 268 | orleans.codegen.cs 269 | 270 | # Since there are multiple workflows, uncomment next line to ignore bower_components 271 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 272 | #bower_components/ 273 | 274 | # RIA/Silverlight projects 275 | Generated_Code/ 276 | 277 | # Backup & report files from converting an old project file 278 | # to a newer Visual Studio version. Backup files are not needed, 279 | # because we have git ;-) 280 | _UpgradeReport_Files/ 281 | Backup*/ 282 | UpgradeLog*.XML 283 | UpgradeLog*.htm 284 | 285 | # SQL Server files 286 | *.mdf 287 | *.ldf 288 | *.ndf 289 | 290 | # Business Intelligence projects 291 | *.rdl.data 292 | *.bim.layout 293 | *.bim_*.settings 294 | 295 | # Microsoft Fakes 296 | FakesAssemblies/ 297 | 298 | # GhostDoc plugin setting file 299 | *.GhostDoc.xml 300 | 301 | # Node.js Tools for Visual Studio 302 | .ntvs_analysis.dat 303 | node_modules/ 304 | 305 | # Typescript v1 declaration files 306 | typings/ 307 | 308 | # Visual Studio 6 build log 309 | *.plg 310 | 311 | # Visual Studio 6 workspace options file 312 | *.opt 313 | 314 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 315 | *.vbw 316 | 317 | # Visual Studio LightSwitch build output 318 | **/*.HTMLClient/GeneratedArtifacts 319 | **/*.DesktopClient/GeneratedArtifacts 320 | **/*.DesktopClient/ModelManifest.xml 321 | **/*.Server/GeneratedArtifacts 322 | **/*.Server/ModelManifest.xml 323 | _Pvt_Extensions 324 | 325 | # Paket dependency manager 326 | .paket/paket.exe 327 | paket-files/ 328 | 329 | # FAKE - F# Make 330 | .fake/ 331 | 332 | # JetBrains Rider 333 | .idea/ 334 | *.sln.iml 335 | 336 | # CodeRush 337 | .cr/ 338 | 339 | # Python Tools for Visual Studio (PTVS) 340 | __pycache__/ 341 | *.pyc 342 | 343 | # Cake - Uncomment if you are using it 344 | # tools/** 345 | # !tools/packages.config 346 | 347 | # Tabs Studio 348 | *.tss 349 | 350 | # Telerik's JustMock configuration file 351 | *.jmconfig 352 | 353 | # BizTalk build output 354 | *.btp.cs 355 | *.btm.cs 356 | *.odx.cs 357 | *.xsd.cs 358 | 359 | # OpenCover UI analysis results 360 | OpenCover/ 361 | coverage/ 362 | 363 | ### macOS template 364 | # General 365 | .DS_Store 366 | .AppleDouble 367 | .LSOverride 368 | 369 | # Icon must end with two \r 370 | Icon 371 | 372 | # Thumbnails 373 | ._* 374 | 375 | # Files that might appear in the root of a volume 376 | .DocumentRevisions-V100 377 | .fseventsd 378 | .Spotlight-V100 379 | .TemporaryItems 380 | .Trashes 381 | .VolumeIcon.icns 382 | .com.apple.timemachine.donotpresent 383 | 384 | # Directories potentially created on remote AFP share 385 | .AppleDB 386 | .AppleDesktop 387 | Network Trash Folder 388 | Temporary Items 389 | .apdisk 390 | 391 | ======= 392 | # Local 393 | docker-compose.yml 394 | *.env 395 | dist 396 | logs 397 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "all" 4 | } 5 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 1.0.0 (2019-10-08) 2 | 3 | 4 | ### Bug Fixes 5 | 6 | * **build.sh:** data directory creation ([9d26d6f](https://github.com/0xb4lamx/nestjs-boilerplate-microservice/commit/9d26d6f)) 7 | * **build.sh:** HOST environment variable ([6064305](https://github.com/0xb4lamx/nestjs-boilerplate-microservice/commit/6064305)) 8 | * **build.sh:** installed and loaded node_module from local ([01030bd](https://github.com/0xb4lamx/nestjs-boilerplate-microservice/commit/01030bd)) 9 | * **build.sh:** missing space typo ([dcc9ceb](https://github.com/0xb4lamx/nestjs-boilerplate-microservice/commit/dcc9ceb)) 10 | * **build.sh:** persisted data in eventstore and mysql database ([0e7eed4](https://github.com/0xb4lamx/nestjs-boilerplate-microservice/commit/0e7eed4)) 11 | * **dockerfile:** loaded node_modules from local ([0b36c5d](https://github.com/0xb4lamx/nestjs-boilerplate-microservice/commit/0b36c5d)) 12 | * **Dockerfile:** loaded ormconfig.js ([2650f6b](https://github.com/0xb4lamx/nestjs-boilerplate-microservice/commit/2650f6b)) 13 | * **envVar.sh:** HOST environment variable export ([b7c97c2](https://github.com/0xb4lamx/nestjs-boilerplate-microservice/commit/b7c97c2)) 14 | 15 | 16 | ### Features 17 | 18 | * **cleanup.sh:** added script that cleans up environment ([3456484](https://github.com/0xb4lamx/nestjs-boilerplate-microservice/commit/3456484)) 19 | * **commitlint config:** initiated commitlint configuration ([af81914](https://github.com/0xb4lamx/nestjs-boilerplate-microservice/commit/af81914)) 20 | * **containers:** added adminer ([2634cc2](https://github.com/0xb4lamx/nestjs-boilerplate-microservice/commit/2634cc2)) 21 | * **dockerfile:** prod dockerfile ([7416ea1](https://github.com/0xb4lamx/nestjs-boilerplate-microservice/commit/7416ea1)) 22 | * **package-lock.json:** added dependencies for commit control ([0422d82](https://github.com/0xb4lamx/nestjs-boilerplate-microservice/commit/0422d82)) 23 | * **package.json:** added commit control using conventional comits spex ([533f916](https://github.com/0xb4lamx/nestjs-boilerplate-microservice/commit/533f916)) 24 | * **symanticrelease:** symantic release configuration and script ([26aeec5](https://github.com/0xb4lamx/nestjs-boilerplate-microservice/commit/26aeec5)) 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |
4 | 5 | Nest Logo 6 | 7 |
8 | 9 |

A MODULE FOR AWS SERVICES (sns,s3,ses)

10 | 11 |
12 | 13 | License 14 | npm version Built with NestJS 15 | 16 |
17 | 18 | ### Installation 19 | ##### Installation missing dependencies (aws_sdk , nodeMailer) 20 | > npm install 21 | 22 | ### About AWS SERVICES 23 | 24 | This module is a thin layer on top of the [AWS_SERVICES API](https://aws.amazon.com/fr/#). 25 | 26 | 27 | 28 | ### Quick Start 29 | 30 | To configure your API connection, import the `AWS` module according to the service you want to use by using the appropriate method. For example to use the SMS Service you need to import the module `AWS` with the `forRootSnsAsync()` Method.Basically, you configure the module with a `AwsCredentialsConfigParams` object depending to te Service used. To see the documentation of Api AWS create an account on https://aws.amazon.com/fr/#. 31 | 32 | For example, your `AppModule` might look like this : 33 | 34 | ```typescript 35 | 36 | import { Module } from '@nestjs/common'; 37 | 38 | 39 | 40 | @Module({ 41 | imports: [ 42 | 43 | AwsModule.forRootSnsAsync({ 44 | useFactory: async () => { 45 | return { 46 | 47 | accessKeyId:'YOUR ACCESS KEY ID', 48 | secretAccessKey: 'YOUR SERCRET ACCESS KEY', 49 | region: 'REGION SERVICE', 50 | 51 | }; 52 | }, 53 | inject: [], 54 | }), 55 | controllers: [AppController], 56 | providers: [AppService], 57 | 58 | 59 | }) 60 | export class AppModule { } 61 | ``` 62 | Depending on which service you want to use you have access to the method of the requested service (SNS_SERVICE, S3_SERVICE,SES_SERVICE) which you can inject into any provider. 63 | 64 | HERE AN EXAMPLE OF AN SNS SERVICE : 65 | ```typescript 66 | import { Injectable, Inject, Logger, HttpStatus } from '@nestjs/common'; 67 | import * as AWS from 'aws-sdk'; 68 | import { CONFIG_CONNECTION_OPTIONS } from '../constants'; 69 | import { ConfigurationOptions } from 'aws-sdk/lib/config'; 70 | import { PublishResponse } from 'aws-sdk/clients/sns'; 71 | /** 72 | * @export 73 | * @class AwsSnsService 74 | */ 75 | @Injectable() 76 | export class AwsSnsService { 77 | private readonly _sns: AWS.SNS; 78 | private _smsOptions: AWS.SNS.PublishInput; 79 | constructor( 80 | @Inject(CONFIG_CONNECTION_OPTIONS) private _options: ConfigurationOptions, 81 | ) { 82 | Logger.log('initialising AWS Module', 'SNS SERVICE'); 83 | AWS.config.update(this._options); 84 | this._sns = new AWS.SNS(); 85 | } 86 | 87 | /** 88 | * 89 | * SNS AMAZON SEND SMS 90 | * 91 | * @param {string} mobileNumber 92 | * @param {string} messageToSend 93 | * @param {string} subjectOfSms 94 | * @memberof AwsSnsService 95 | */ 96 | async sendSMS( 97 | mobileNumber: string, 98 | messageToSend: string, 99 | subjectOfSms: string, 100 | ) { 101 | this._smsOptions = { 102 | Message: messageToSend, 103 | Subject: subjectOfSms, 104 | PhoneNumber: mobileNumber, 105 | }; 106 | 107 | return [ 108 | await this._sns.publish( 109 | this._smsOptions).promise().then((info: PublishResponse) => { 110 | console.log('RESPONSE SMS DETAILS ====>', info); 111 | return [ 112 | { 113 | success: HttpStatus.OK, 114 | message: 'SMS SUCCESSFULLY SENDED', 115 | data: info, 116 | }, 117 | ]; 118 | }).catch((err) => { 119 | console.log('ERROR : FAILD REQUEST !! ====>', err); 120 | return [ 121 | { 122 | error: HttpStatus.EXPECTATION_FAILED, 123 | message: ['FAILD TO SEND SMS ', err], 124 | }, 125 | ]; 126 | }), 127 | ]; 128 | } 129 | } 130 | 131 | ``` 132 | 133 | 134 | 135 | ### To Do 136 | 137 | - [x] Tests 138 | 139 | ### Change Log 140 | 141 | See [Changelog](CHANGELOG.md) for more information. 142 | 143 | ### Author 144 | 145 | **ABBES Mohamed Amine** 146 | 147 | ### License 148 | 149 | Licensed under the MIT License - see the [LICENSE](LICENSE) file for details. 150 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { extends: ['@commitlint/config-conventional'] }; 2 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nestjs-aws", 3 | "private": true, 4 | "version": "1.0.0", 5 | "description": "Nest TypeScript AWS Module repository", 6 | "author": "ABBES Mohamed Amine ", 7 | "license": "MIT", 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/box2home/nestjs-aws" 11 | }, 12 | "bugs": "https://github.com/box2home/nestjs-aws/issues", 13 | "main": "dist/index.js", 14 | "files": [ 15 | "dist/**/*", 16 | "*.md" 17 | ], 18 | "scripts": { 19 | "release": "npx -p @semantic-release/changelog -p @semantic-release/git@beta -p semantic-release@beta semantic-release --no-ci", 20 | "commit": "npx git-cz", 21 | "start:dev": "tsc -w", 22 | "prebuild": "rm -rf dist", 23 | "build": "tsc -p tsconfig.json", 24 | "format": "prettier --write \"src/**/*.ts\"", 25 | "lint": "tslint -p tsconfig.json -c tslint.json", 26 | "test": "jest", 27 | "test:watch": "jest --watch", 28 | "test:cov": "jest --coverage", 29 | "test:e2e": "jest --config ./test/jest-e2e.json", 30 | "prepare": "npm run build" 31 | }, 32 | "dependencies": { 33 | "@nestjs/common": "^7.6.13", 34 | "@nestjs/core": "^6.5.3", 35 | "aws-sdk": "^2.795.0", 36 | "class-transformer": "^0.3.1", 37 | "mime-types": "~2.1.24", 38 | "nodemailer": "^6.4.16", 39 | "pretty-error": "^2.1.1", 40 | "reflect-metadata": "~0.1.13", 41 | "rimraf": "2.6.3", 42 | "rxjs": "^6.5.2", 43 | "uuid": "^3.3.3", 44 | "xml2js": "^0.4.21" 45 | }, 46 | "devDependencies": { 47 | "@commitlint/cli": "^12.0.1", 48 | "@commitlint/config-conventional": "^12.0.1", 49 | "@nestjs/testing": "^6.6.4", 50 | "@types/dotenv": "^6.1.1", 51 | "@types/express": "^4.17.0", 52 | "@types/express-rate-limit": "^3.3.0", 53 | "@types/jest": "^24.0.13", 54 | "@types/jquery": "^3.3.31", 55 | "@types/lodash": "^4.14.134", 56 | "@types/mime-types": "^2.1.0", 57 | "@types/morgan": "^1.7.35", 58 | "@types/node": "^12.0.7", 59 | "@types/nodemailer": "^6.2.2", 60 | "@types/supertest": "^2.0.7", 61 | "@types/uuid": "^3.4.4", 62 | "@typescript-eslint/eslint-plugin-tslint": "^1.11.0", 63 | "@typescript-eslint/parser": "^1.11.0", 64 | "cz-conventional-changelog": "^3.0.2", 65 | "eslint": "^6.0.1", 66 | "eslint-plugin-import-helpers": "^1.0.2", 67 | "husky": "^3.0.8", 68 | "jest": "^26.0.1", 69 | "lint-staged": "~8.2.0", 70 | "prettier": "^1.18.2", 71 | "supertest": "^4.0.2", 72 | "ts-jest": "^26.1.0", 73 | "ts-node": "^8.1.0", 74 | "tsc-watch": "^2.2.1", 75 | "tsconfig-paths": "^3.8.0", 76 | "tslint": "^5.17.0", 77 | "tslint-config-prettier": "~1.18.0", 78 | "tslint-consistent-codestyle": "^1.15.1", 79 | "tslint-eslint-rules": "^5.4.0", 80 | "tslint-plugin-prettier": "^2.0.1", 81 | "typescript": "^3.8.3" 82 | }, 83 | "jest": { 84 | "moduleFileExtensions": [ 85 | "js", 86 | "json", 87 | "ts" 88 | ], 89 | "rootDir": "src", 90 | "testRegex": ".spec.ts$", 91 | "transform": { 92 | "^.+\\.(t|j)s$": "ts-jest" 93 | }, 94 | "collectCoverageFrom": [ 95 | "**/*.(t|j)s" 96 | ], 97 | "coverageDirectory": "../coverage", 98 | "testEnvironment": "node" 99 | }, 100 | "lint-staged": { 101 | "*.@(ts)": [ 102 | "tslint --fix -p .", 103 | "git add" 104 | ] 105 | }, 106 | "config": { 107 | "commitizen": { 108 | "path": "./node_modules/cz-conventional-changelog", 109 | "prepare-commit-msg": "exec < /dev/tty && git cz --hook || true" 110 | } 111 | }, 112 | "husky": { 113 | "hooks": { 114 | "commit-msg": "commitlint -E HUSKY_GIT_PARAMS" 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/aws.module.ts: -------------------------------------------------------------------------------- 1 | import { DynamicModule, Module } from '@nestjs/common'; 2 | 3 | import { CONFIG_CONNECTION_OPTIONS } from './constants'; 4 | import { IS3ModuleAsyncOptions } from './interfaces/aws-s3-module-options.interface'; 5 | import { ISESModuleAsyncOptions } from './interfaces/aws-ses-module-options.interface'; 6 | import { ISNSModuleAsyncOptions } from './interfaces/aws-sns-module-options.interface'; 7 | import { AwsS3Service } from './service/aws.s3.service'; 8 | import { AwsSesService } from './service/aws.ses.service'; 9 | import { AwsSnsService } from './service/aws.sns.service'; 10 | import { GeneratorService } from './service/generator.service'; 11 | 12 | /** 13 | * @export 14 | * @class AwsModule 15 | */ 16 | @Module({}) 17 | export class AwsModule { 18 | static forRootSnsAsync(options: ISNSModuleAsyncOptions): DynamicModule { 19 | return { 20 | module: AwsModule, 21 | providers: [ 22 | { 23 | provide: CONFIG_CONNECTION_OPTIONS, 24 | useFactory: options.useFactory, 25 | inject: options.inject || [], 26 | }, 27 | AwsSnsService, 28 | ], 29 | exports: [AwsSnsService], 30 | }; 31 | } 32 | 33 | static forRootSesAsync(options: ISESModuleAsyncOptions): DynamicModule { 34 | return { 35 | module: AwsModule, 36 | providers: [ 37 | { 38 | provide: CONFIG_CONNECTION_OPTIONS, 39 | useFactory: options.useFactory, 40 | inject: options.inject || [], 41 | }, 42 | AwsSesService, 43 | ], 44 | exports: [AwsSesService], 45 | }; 46 | } 47 | 48 | static forRootS3Async(options: IS3ModuleAsyncOptions): DynamicModule { 49 | return { 50 | module: AwsModule, 51 | providers: [ 52 | { 53 | provide: CONFIG_CONNECTION_OPTIONS, 54 | useFactory: options.useFactory, 55 | inject: options.inject || [], 56 | }, 57 | AwsS3Service, 58 | GeneratorService, 59 | ], 60 | exports: [AwsS3Service, GeneratorService], 61 | }; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/constants.ts: -------------------------------------------------------------------------------- 1 | export const CONFIG_CONNECTION_OPTIONS = 'CONFIG_CONNECTION_OPTIONS'; 2 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './constants'; 2 | export * from './service/aws.s3.service'; 3 | export * from './service/aws.ses.service'; 4 | export * from './service/aws.sns.service'; 5 | export * from './service/generator.service'; 6 | export * from './aws.module'; 7 | export * from './interfaces/IFile'; 8 | export * from './interfaces/s3-get-signed-url-request.interface'; 9 | export * from './interfaces/aws-ses-module-options.interface'; 10 | export * from './interfaces/aws-s3-module-options.interface'; 11 | export * from './interfaces/aws-sns-module-options.interface'; 12 | export * from './service/aws-logger.service'; 13 | -------------------------------------------------------------------------------- /src/interfaces/IFile.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * @export 5 | * @interface IFile 6 | */ 7 | export interface IFile { 8 | encoding: string; 9 | buffer: Buffer; 10 | fieldname: string; 11 | mimetype: string; 12 | originalname: string; 13 | size: number; 14 | } 15 | -------------------------------------------------------------------------------- /src/interfaces/aws-s3-module-options.interface.ts: -------------------------------------------------------------------------------- 1 | import { ModuleMetadata } from '@nestjs/common/interfaces'; 2 | import { ConfigurationOptions } from 'aws-sdk'; 3 | 4 | /** 5 | * @export 6 | * @interface IS3ModuleAsyncOptions 7 | * @extends {Pick} 8 | */ 9 | export interface IS3ModuleAsyncOptions extends Pick { 10 | useFactory: (...args: any[]) => Promise | ConfigurationOptions; 11 | inject?: any[]; 12 | } 13 | -------------------------------------------------------------------------------- /src/interfaces/aws-ses-module-options.interface.ts: -------------------------------------------------------------------------------- 1 | import { ModuleMetadata } from '@nestjs/common/interfaces'; 2 | import { Options } from 'nodemailer/lib/smtp-transport'; 3 | 4 | export declare type SMTPTransportOptions = Options; 5 | 6 | /** 7 | * @export 8 | * @interface ISESModuleAsyncOptions 9 | * @extends {Pick} 10 | */ 11 | export interface ISESModuleAsyncOptions extends Pick { 12 | useFactory: (...args: any[]) => Promise | SMTPTransportOptions; 13 | inject?: any[]; 14 | } 15 | -------------------------------------------------------------------------------- /src/interfaces/aws-sns-module-options.interface.ts: -------------------------------------------------------------------------------- 1 | import { ModuleMetadata } from '@nestjs/common/interfaces'; 2 | import { ConfigurationOptions } from 'aws-sdk'; 3 | /** 4 | * @export 5 | * @interface ISNSModuleAsyncOptions 6 | * @extends {Pick} 7 | */ 8 | export interface ISNSModuleAsyncOptions extends Pick { 9 | useFactory: (...args: any[]) => Promise | ConfigurationOptions; 10 | inject?: any[]; 11 | } 12 | -------------------------------------------------------------------------------- /src/interfaces/s3-get-signed-url-request.interface.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * @export 5 | * @interface IGetSignedUrlRequest 6 | */ 7 | export interface IGetSignedUrlRequest { 8 | Bucket: string; 9 | Key: string; 10 | Expires?: number; 11 | } 12 | -------------------------------------------------------------------------------- /src/service/aws-logger.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, Logger } from '@nestjs/common'; 2 | 3 | @Injectable() 4 | export class AwsLogger extends Logger { 5 | error(message: string, trace: any) { 6 | super.error(message, trace); 7 | } 8 | 9 | log(message: string, trace: string) { 10 | super.log(message, trace); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/service/aws.s3.service.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Injectable, 3 | Inject, 4 | Logger, 5 | HttpStatus, 6 | HttpException, 7 | } from '@nestjs/common'; 8 | import * as AWS from 'aws-sdk'; 9 | import { 10 | CopyObjectRequest, 11 | DeleteObjectRequest, 12 | ListObjectsRequest, 13 | } from 'aws-sdk/clients/s3'; 14 | 15 | import { CONFIG_CONNECTION_OPTIONS } from '../constants'; 16 | import { IGetSignedUrlRequest } from '../interfaces/s3-get-signed-url-request.interface'; 17 | 18 | /** 19 | * @export 20 | * @class AwsS3Service 21 | */ 22 | @Injectable() 23 | export class AwsS3Service { 24 | private readonly _s3: AWS.S3; 25 | 26 | constructor( 27 | @Inject(CONFIG_CONNECTION_OPTIONS) 28 | private _options: AWS.S3.Types.ClientConfiguration, 29 | ) { 30 | Logger.log('initialising Aws Module', 'AWS S3 SERVICE'); 31 | this._s3 = new AWS.S3(_options); 32 | } 33 | 34 | async upload(params: AWS.S3.Types.PutObjectRequest) { 35 | return this._s3 36 | .putObject(params) 37 | .promise() 38 | .then((info: AWS.S3.Types.PutObjectOutput) => { 39 | Logger.log(`success[S3]: ${JSON.stringify(info)}`); 40 | return [ 41 | { 42 | statusCode: HttpStatus.OK, 43 | message: 'success', 44 | data: { 45 | url: `https://${params.Bucket}.s3-${this._s3.config.region}.amazonaws.com/${params.Key}`, 46 | }, 47 | }, 48 | ]; 49 | }) 50 | .catch((err: AWS.AWSError) => { 51 | Logger.error( 52 | err.message, 53 | `success[S3]: ${JSON.stringify(err)}`, 54 | ); 55 | throw new HttpException( 56 | { 57 | statusCode: err.statusCode, 58 | message: 'error', 59 | data: err, 60 | }, 61 | HttpStatus.BAD_REQUEST, 62 | ); 63 | }); 64 | } 65 | 66 | async getObject(params: AWS.S3.Types.GetObjectAclRequest) { 67 | try { 68 | return this._s3 69 | .getObject(params) 70 | .promise() 71 | .then(fileData => { 72 | return fileData.Body.toString('utf-8'); 73 | }); 74 | } catch (error) { 75 | throw new HttpException( 76 | { 77 | statusCode: error.statusCode, 78 | message: 'error', 79 | data: error, 80 | }, 81 | HttpStatus.BAD_REQUEST, 82 | ); 83 | } 84 | } 85 | 86 | async getUploadSignedUrl(params: IGetSignedUrlRequest) { 87 | try { 88 | return this._s3 89 | .getSignedUrlPromise('putObject', { 90 | ...params, 91 | ACL: 'public-read', 92 | }) 93 | .then((signedUrl: string) => { 94 | Logger.log( 95 | `signed url generated successfully: ${signedUrl}`, 96 | ); 97 | return signedUrl; 98 | }); 99 | } catch (err) { 100 | Logger.error( 101 | err.message, 102 | `unable to generate the signed url: ${JSON.stringify(err)}`, 103 | ); 104 | throw new HttpException(err.message, HttpStatus.BAD_REQUEST); 105 | } 106 | } 107 | 108 | async copyObject(params: CopyObjectRequest) { 109 | try { 110 | return this._s3.copyObject(params, async function(err, data) { 111 | if (err) Logger.log(err, err.stack); 112 | // an error occurred 113 | else { 114 | Logger.log(data); 115 | return data; 116 | } // successful response 117 | }); 118 | } catch (err) { 119 | Logger.error( 120 | err.message, 121 | `unable to copy object: ${JSON.stringify(err)}`, 122 | ); 123 | throw new HttpException(err.message, HttpStatus.BAD_REQUEST); 124 | } 125 | } 126 | 127 | async deleteObject(params: DeleteObjectRequest) { 128 | try { 129 | return this._s3.deleteObject(params).promise(); 130 | } catch (err) { 131 | Logger.error( 132 | err.message, 133 | `unable to delete object: ${JSON.stringify(err)}`, 134 | ); 135 | throw new HttpException(err.message, HttpStatus.BAD_REQUEST); 136 | } 137 | } 138 | 139 | async listObjects(params: ListObjectsRequest) { 140 | try { 141 | return this._s3.listObjects(params).promise(); 142 | } catch (err) { 143 | Logger.error(err.message, `unable to ${JSON.stringify(err)}`); 144 | throw new HttpException(err.message, HttpStatus.BAD_REQUEST); 145 | } 146 | } 147 | 148 | async checkExistenceFileFromBucket(params: AWS.S3.Types.HeadObjectRequest) { 149 | try { 150 | // Check if the object exists 151 | const signedUrl = await this._s3.headObject(params).promise(); 152 | 153 | return signedUrl ? true: false 154 | } catch (err) { 155 | // Log the error and throw an exception 156 | console.error('Error checking object existence:', err.message); 157 | Logger.error(err.message, `Unable to ${JSON.stringify(err)}`); 158 | return false 159 | } 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /src/service/aws.ses.service.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | import { HttpStatus, HttpException, Inject, Injectable, Logger } from '@nestjs/common'; 3 | import { createTransport, SendMailOptions, SentMessageInfo, Transporter } from 'nodemailer'; 4 | import { Options } from 'nodemailer/lib/smtp-connection'; 5 | 6 | import { CONFIG_CONNECTION_OPTIONS } from '../constants'; 7 | 8 | @Injectable() 9 | export class AwsSesService { 10 | private readonly _transporter: Transporter; 11 | 12 | constructor(@Inject(CONFIG_CONNECTION_OPTIONS) private _options: Options) { 13 | Logger.log('initialising AWS Module', 'SES SERVICE'); 14 | // create reusable transporter object using the default SMTP transport 15 | this._transporter = createTransport(this._options); 16 | } 17 | 18 | /** 19 | * 20 | * @param {SendMailOptions} mailOptions 21 | */ 22 | async sendMail(mailOptions: SendMailOptions) { 23 | // promise send mail 24 | return this._transporter 25 | .sendMail(mailOptions) 26 | .then((info: SentMessageInfo) => { 27 | Logger.log('success[sendMail]:', info); 28 | return { 29 | statusCode: HttpStatus.OK, 30 | message: 'Mail Sent', 31 | data: info, 32 | }; 33 | }) 34 | .catch((err) => { 35 | Logger.log('error[sendMail]:', err); 36 | throw new HttpException({ 37 | statusCode: HttpStatus.BAD_REQUEST, 38 | message: 'Failed to send', 39 | data: err, 40 | }, HttpStatus.BAD_REQUEST); 41 | }); 42 | } 43 | } -------------------------------------------------------------------------------- /src/service/aws.sns.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, Inject, Logger, HttpStatus, HttpException } from '@nestjs/common'; 2 | import { SNS } from 'aws-sdk'; 3 | import { PublishResponse, PublishInput } from 'aws-sdk/clients/sns'; 4 | import { ConfigurationOptions } from 'aws-sdk'; 5 | 6 | import { CONFIG_CONNECTION_OPTIONS } from '../constants'; 7 | 8 | /** 9 | * @export 10 | * @class AwsSnsService 11 | */ 12 | @Injectable() 13 | export class AwsSnsService { 14 | private readonly _sns: SNS; 15 | constructor(@Inject(CONFIG_CONNECTION_OPTIONS) private _options: ConfigurationOptions) { 16 | Logger.log('initialising AWS Module', 'SNS SERVICE'); 17 | this._sns = new SNS(this._options); 18 | } 19 | 20 | async sendSMS(smsOptions: PublishInput) { 21 | 22 | return this._sns 23 | .publish(smsOptions) 24 | .promise() 25 | .then((info: PublishResponse) => { 26 | Logger.log(` success[sendSms]: ${JSON.stringify(info)}`); 27 | return [ 28 | { 29 | statusCode: HttpStatus.OK, 30 | message: 'Sms sent', 31 | data: info, 32 | }, 33 | ]; 34 | }) 35 | .catch((err) => { 36 | Logger.error('error[sendSms]:', err); 37 | throw new HttpException({ 38 | statusCode: HttpStatus.BAD_REQUEST, 39 | message: 'Failed to send', 40 | data: err, 41 | }, HttpStatus.BAD_REQUEST); 42 | }); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/service/generator.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | import * as uuid from 'uuid/v1'; 3 | 4 | /** 5 | * @export 6 | * @class GeneratorService 7 | */ 8 | @Injectable() 9 | export class GeneratorService { 10 | public uuid(): string { 11 | return uuid(); 12 | } 13 | 14 | public fileName(ext: string) { 15 | return this.uuid() + '.' + ext; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /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 | 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 | -------------------------------------------------------------------------------- /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 | "exclude": [ 4 | "node_modules", 5 | "dist", 6 | "test", 7 | "**/*spec.ts" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "declaration": true, 5 | "noImplicitAny": false, 6 | "importHelpers": true, 7 | "removeComments": true, 8 | "noLib": false, 9 | "allowSyntheticDefaultImports": true, 10 | "emitDecoratorMetadata": true, 11 | "experimentalDecorators": true, 12 | "target": "es2017", 13 | "sourceMap": true, 14 | "outDir": "./dist", 15 | "baseUrl": "./src", 16 | "incremental": true 17 | }, 18 | "include": [ 19 | "src/**/*", 20 | "index.ts" 21 | ], 22 | "exclude": [ 23 | "node_modules", 24 | "**/*.spec.ts" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "defaultSeverity": "error", 3 | "extends": [ 4 | "tslint:recommended" 5 | ], 6 | "rulesDirectory": [ 7 | "node_modules/tslint-eslint-rules/dist/rules", 8 | "tslint-config-prettier", 9 | "tslint-consistent-codestyle" 10 | ], 11 | "jsRules": { 12 | "no-unused-expression": true 13 | }, 14 | "rules": { 15 | "no-angle-bracket-type-assertion": false, 16 | "adjacent-overload-signatures": true, 17 | "array-type": [ 18 | true, 19 | "array-simple" 20 | ], 21 | "arrow-parens": true, 22 | "arrow-return-shorthand": true, 23 | "no-multi-spaces": true, 24 | "ban-comma-operator": true, 25 | "class-name": true, 26 | "comment-format": [ 27 | true, 28 | "check-space" 29 | ], 30 | "eofline": true, 31 | "forin": true, 32 | "indent": [ 33 | true, 34 | "spaces" 35 | ], 36 | "new-parens": true, 37 | "no-arg": true, 38 | "no-conditional-assignment": true, 39 | "no-consecutive-blank-lines": [ 40 | true, 41 | 1 42 | ], 43 | "no-console": [ 44 | true, 45 | "debug", 46 | "log", 47 | "time", 48 | "timeEnd", 49 | "trace" 50 | ], 51 | "no-construct": true, 52 | "no-debugger": true, 53 | "no-default-export": true, 54 | "no-duplicate-imports": true, 55 | "no-duplicate-switch-case": true, 56 | "no-empty-interface": true, 57 | "no-eval": true, 58 | "no-implicit-dependencies": true, 59 | "no-invalid-this": true, 60 | "no-inferrable-types": [ 61 | true, 62 | "ignore-params" 63 | ], 64 | "no-irregular-whitespace": true, 65 | "no-require-imports": true, 66 | "no-return-await": true, 67 | "no-shadowed-variable": true, 68 | "no-sparse-arrays": true, 69 | "no-string-literal": true, 70 | "no-submodule-imports": false, 71 | "no-switch-case-fall-through": true, 72 | "no-this-assignment": true, 73 | "no-trailing-whitespace": true, 74 | "no-unnecessary-callback-wrapper": true, 75 | "no-unnecessary-initializer": true, 76 | "no-unsafe-finally": true, 77 | "no-unused-expression": true, 78 | "no-var-keyword": true, 79 | "number-literal-format": true, 80 | "object-literal-shorthand": true, 81 | "one-line": [ 82 | true, 83 | "check-open-brace", 84 | "check-catch", 85 | "check-else", 86 | "check-finally", 87 | "check-whitespace" 88 | ], 89 | "one-variable-per-declaration": [ 90 | true, 91 | "ignore-for-loop" 92 | ], 93 | "only-arrow-functions": [ 94 | true, 95 | "allow-named-functions" 96 | ], 97 | "prefer-const": true, 98 | "prefer-for-of": true, 99 | "prefer-object-spread": true, 100 | "prefer-switch": [ 101 | true, 102 | { 103 | "min-cases": 3 104 | } 105 | ], 106 | "quotemark": [ 107 | true, 108 | "single", 109 | "avoid-escape" 110 | ], 111 | "radix": true, 112 | "semicolon": [ 113 | true, 114 | "always" 115 | ], 116 | "space-before-function-paren": [ 117 | true, 118 | { 119 | "anonymous": false, 120 | "named": false, 121 | "asyncArrow": true, 122 | "method": false, 123 | "constructor": false 124 | } 125 | ], 126 | "space-within-parens": [ 127 | true, 128 | 0 129 | ], 130 | "switch-final-break": true, 131 | "trailing-comma": [ 132 | true, 133 | { 134 | "singleline": "never", 135 | "multiline": "always" 136 | } 137 | ], 138 | "triple-equals": [ 139 | true, 140 | "allow-null-check" 141 | ], 142 | "typedef-whitespace": [ 143 | true, 144 | { 145 | "call-signature": "nospace", 146 | "index-signature": "nospace", 147 | "parameter": "nospace", 148 | "property-declaration": "nospace", 149 | "variable-declaration": "nospace" 150 | } 151 | ], 152 | "unified-signatures": true, 153 | "use-isnan": true, 154 | "variable-name": [ 155 | true, 156 | "ban-keywords" 157 | ], 158 | "whitespace": [ 159 | true, 160 | "check-branch", 161 | "check-decl", 162 | "check-operator", 163 | "check-separator", 164 | "check-type", 165 | "check-type-operator", 166 | "check-rest-spread" 167 | ], 168 | /* custom rules */ 169 | "no-unused": [ 170 | true, 171 | "unused-class-expression-name", 172 | "unused-function-expression-name", 173 | "unused-catch-binding" 174 | ], 175 | "ext-curly": false, 176 | "naming-convention": [ 177 | true, 178 | { 179 | "type": "default", 180 | "format": "camelCase", 181 | "leadingUnderscore": "forbid", 182 | "trailingUnderscore": "forbid" 183 | }, 184 | { 185 | "type": "variable", 186 | "modifiers": [ 187 | "global", 188 | "const" 189 | ], 190 | "format": [ 191 | "camelCase", 192 | "PascalCase", 193 | "UPPER_CASE" 194 | ] 195 | }, 196 | { 197 | "type": "parameter", 198 | "modifiers": "unused", 199 | "leadingUnderscore": "allow" 200 | }, 201 | { 202 | "type": "member", 203 | "modifiers": "private", 204 | "leadingUnderscore": "require" 205 | }, 206 | { 207 | "type": "member", 208 | "modifiers": "protected", 209 | "leadingUnderscore": "require" 210 | }, 211 | { 212 | "type": "property", 213 | "modifiers": [ 214 | "public", 215 | "static", 216 | "const" 217 | ], 218 | "format": "UPPER_CASE" 219 | }, 220 | { 221 | "type": "type", 222 | "format": "PascalCase" 223 | }, 224 | { 225 | "type": "interface", 226 | "prefix": "I" 227 | }, 228 | { 229 | "type": "genericTypeParameter", 230 | "regex": "^[A-Z]$" 231 | }, 232 | { 233 | "type": "enumMember", 234 | "format": "PascalCase" 235 | } 236 | ], 237 | "no-as-type-assertion": true, 238 | "no-accessor-recursion": true, 239 | "no-collapsible-if": true, 240 | "no-return-undefined": [ 241 | true, 242 | "allow-void-expression" 243 | ], 244 | // "no-unnecessary-else": true, 245 | "no-unnecessary-type-annotation": true, 246 | "no-var-before-return": true, 247 | "object-shorthand-properties-first": true, 248 | "parameter-properties": [ 249 | true, 250 | "leading", 251 | "member-access" 252 | ], 253 | "prefer-const-enum": true, 254 | "prefer-while": true, 255 | "member-access": [ 256 | false 257 | ], 258 | "ordered-imports": [ 259 | false 260 | ], 261 | "max-line-length": [ 262 | true, 263 | 150 264 | ], 265 | "member-ordering": [ 266 | false 267 | ], 268 | "interface-name": [ 269 | false 270 | ], 271 | "object-literal-sort-keys": false 272 | } 273 | } 274 | --------------------------------------------------------------------------------