├── .env.example ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── docs ├── assets │ ├── css │ │ ├── main.css │ │ └── main.css.map │ ├── images │ │ ├── icons.png │ │ ├── icons@2x.png │ │ ├── widgets.png │ │ └── widgets@2x.png │ └── js │ │ ├── main.js │ │ └── search.js ├── classes │ ├── controller.html │ ├── example.html │ ├── examplecontroller.html │ └── firestorerepository.html ├── globals.html ├── index.html └── interfaces │ ├── icontroller.html │ ├── icustomerror.html │ ├── iexample.html │ └── ifirestorerepository.html ├── package.json ├── src ├── app.ts ├── controllers │ ├── controller.ts │ ├── example.controller.ts │ └── interfaces │ │ └── controller.interface.ts ├── db.ts ├── env.ts ├── index.ts ├── middleware │ └── error.middleware.ts ├── models │ ├── example.model.ts │ └── interfaces │ │ └── example.interface.ts ├── repositories │ ├── firestore.repository.ts │ └── interfaces │ │ └── firestore.interface.ts ├── routes │ ├── example.routes.ts │ └── index.ts └── utils │ └── error.interface.ts ├── tests └── repositories │ └── firestore.test.ts ├── tsconfig.json ├── tslint.json ├── views └── error.pug └── yarn.lock /.env.example: -------------------------------------------------------------------------------- 1 | SECRET_KEY=OneSecretKeyVeryHardToDiscover 2 | FIRESTORE_DB=https://example.firebaseio.com -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (https://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # TypeScript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # next.js build output 61 | .next 62 | 63 | # Output directory 64 | build/ 65 | 66 | # Keys directory 67 | keys/ 68 | 69 | # Doc directory 70 | doc/ 71 | 72 | # Generated tree file 73 | output.txt -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "node" 4 | 5 | before_script: 6 | - yarn install 7 | 8 | script: 9 | - npm run lint 10 | - npm run build -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Marcos Andrés Huck 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TypeScript + Express + Firestore 2 | An API REST created with Typescript and using Express and Firestore modules 3 | 4 | [![](https://travis-ci.org/marcoshuck/typescript-express-firestore.svg?branch=master)](https://travis-ci.org/marcoshuck/typescript-express-firestore) [![](https://david-dm.org/marcoshuck/typescript-express-firestore.svg)](https://david-dm.org/marcoshuck/typescript-express-firestore) ![](https://img.shields.io/github/forks/marcoshuck/typescript-express-firestore.svg) ![](https://img.shields.io/github/stars/marcoshuck/typescript-express-firestore.svg) ![](https://img.shields.io/github/license/marcoshuck/typescript-express-firestore.svg) ![](https://img.shields.io/github/issues/marcoshuck/typescript-express-firestore.svg) 5 | 6 | ## Features 7 | This project has or uses the following features: 8 | - Typescript. 9 | - Express. 10 | - Google Firestore. 11 | - Linting 12 | - Model - View - Controller pattern. 13 | - SOLID principles. 14 | - Class validation. 15 | - CI/CD with Travis. 16 | - Tests with mocha and chai. 17 | - Autogenerated documentation with typedoc. 18 | 19 | ## Getting started 20 | This application was created using NodeJS, you can look at the package.json file for more information about what packages have been used. 21 | 22 | You need to create a keys folder in the application root directory, and inside of it, you should move the .json file provided by Google Firestore. Read more information about this: [Google Firestore SDK documentation](https://firebase.google.com/docs/admin/setup?authuser=0). This file is required in [db.ts](https://github.com/marcoshuck/typescript-express-firestore/blob/master/src/db.ts#L3) 23 | 24 | 25 | ### Before start working on code 26 | `yarn install` or `npm install` 27 | 28 | ### Building 29 | `npm run build` 30 | Gets the ./build directory with js files. 31 | 32 | ### Source code analysis 33 | `npm run lint` 34 | Uses lint to analyze the source code. 35 | 36 | ### Starting the application 37 | `npm run start` 38 | Runs the application in a node instance. 39 | 40 | ### Watch mode (build) 41 | `npm run build-watch` 42 | Compiles the application every time some change has been made. 43 | 44 | ### Watch mode (start) 45 | `npm run start-watch` 46 | Runs the application every time some change has been made. Should be run in parallel with Build watch mode. 47 | 48 | ### Documentation 49 | `npm run doc` 50 | Generates the project's documentation using typedoc. 51 | 52 | ## API Endpoint 53 | In this application there is only one endpoint available, it's the [examples](https://github.com/marcoshuck/typescript-express-firestore/blob/master/src/routes/index.ts#L7) endpoint. 54 | You can check how any route works reading its specific controller class. For further information about the examples route, you can read the [ExampleController](https://github.com/marcoshuck/typescript-express-firestore/blob/master/src/controllers/example.controller.ts) class. 55 | 56 | ## Test 57 | The firestore test is related to my own firestore database. You can play around with the source file to understand mocha and chai modules. Be sure to check and change the id argument in both read and update methods. 58 | 59 | ## Project structure 60 | ``` 61 | | .env.example 62 | | .gitignore 63 | | .travis.yml 64 | | LICENSE 65 | | package.json 66 | | README.md 67 | | tsconfig.json 68 | | tslint.json 69 | | yarn.lock 70 | | 71 | +---src 72 | | | app.ts 73 | | | db.ts 74 | | | env.ts 75 | | | index.ts 76 | | | 77 | | +---controllers 78 | | | | controller.ts 79 | | | | example.controller.ts 80 | | | | 81 | | | \---interfaces 82 | | | controller.interface.ts 83 | | | 84 | | +---middleware 85 | | | error.middleware.ts 86 | | | 87 | | +---models 88 | | | | example.model.ts 89 | | | | 90 | | | \---interfaces 91 | | | example.interface.ts 92 | | | 93 | | +---repositories 94 | | | | firestore.repository.ts 95 | | | | 96 | | | \---interfaces 97 | | | firestore.interface.ts 98 | | | 99 | | +---routes 100 | | | example.routes.ts 101 | | | index.ts 102 | | | 103 | | \---utils 104 | | error.interface.ts 105 | | 106 | +---tests 107 | | \---repositories 108 | | firestore.test.ts 109 | | 110 | \---views 111 | error.pug 112 | ``` 113 | 114 | ## ToDo 115 | - JWT 116 | -------------------------------------------------------------------------------- /docs/assets/images/icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marcoshuck/typescript-express-firestore/63870a4c3e008ab83e7a38c4ab01166284775b4e/docs/assets/images/icons.png -------------------------------------------------------------------------------- /docs/assets/images/icons@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marcoshuck/typescript-express-firestore/63870a4c3e008ab83e7a38c4ab01166284775b4e/docs/assets/images/icons@2x.png -------------------------------------------------------------------------------- /docs/assets/images/widgets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marcoshuck/typescript-express-firestore/63870a4c3e008ab83e7a38c4ab01166284775b4e/docs/assets/images/widgets.png -------------------------------------------------------------------------------- /docs/assets/images/widgets@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marcoshuck/typescript-express-firestore/63870a4c3e008ab83e7a38c4ab01166284775b4e/docs/assets/images/widgets@2x.png -------------------------------------------------------------------------------- /docs/assets/js/search.js: -------------------------------------------------------------------------------- 1 | var typedoc = typedoc || {}; 2 | typedoc.search = typedoc.search || {}; 3 | typedoc.search.data = {"kinds":{"32":"Variable","64":"Function","128":"Class","256":"Interface","512":"Constructor","1024":"Property","2048":"Method"},"rows":[{"id":0,"kind":256,"name":"ICustomError","url":"interfaces/icustomerror.html","classes":"tsd-kind-interface"},{"id":1,"kind":1024,"name":"status","url":"interfaces/icustomerror.html#status","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"ICustomError"},{"id":2,"kind":1024,"name":"name","url":"interfaces/icustomerror.html#name","classes":"tsd-kind-property tsd-parent-kind-interface tsd-is-inherited","parent":"ICustomError"},{"id":3,"kind":1024,"name":"message","url":"interfaces/icustomerror.html#message","classes":"tsd-kind-property tsd-parent-kind-interface tsd-is-inherited","parent":"ICustomError"},{"id":4,"kind":1024,"name":"stack","url":"interfaces/icustomerror.html#stack","classes":"tsd-kind-property tsd-parent-kind-interface tsd-is-overwrite tsd-is-inherited","parent":"ICustomError"},{"id":5,"kind":1024,"name":"Error","url":"interfaces/icustomerror.html#error","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"ICustomError"},{"id":6,"kind":64,"name":"errorMiddleware","url":"globals.html#errormiddleware","classes":"tsd-kind-function"},{"id":7,"kind":256,"name":"IExample","url":"interfaces/iexample.html","classes":"tsd-kind-interface"},{"id":8,"kind":1024,"name":"firstName","url":"interfaces/iexample.html#firstname","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"IExample"},{"id":9,"kind":1024,"name":"middleName","url":"interfaces/iexample.html#middlename","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"IExample"},{"id":10,"kind":1024,"name":"lastName","url":"interfaces/iexample.html#lastname","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"IExample"},{"id":11,"kind":1024,"name":"birthday","url":"interfaces/iexample.html#birthday","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"IExample"},{"id":12,"kind":1024,"name":"country","url":"interfaces/iexample.html#country","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"IExample"},{"id":13,"kind":1024,"name":"province","url":"interfaces/iexample.html#province","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"IExample"},{"id":14,"kind":1024,"name":"city","url":"interfaces/iexample.html#city","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"IExample"},{"id":15,"kind":1024,"name":"genre","url":"interfaces/iexample.html#genre","classes":"tsd-kind-property tsd-parent-kind-interface","parent":"IExample"},{"id":16,"kind":128,"name":"Example","url":"classes/example.html","classes":"tsd-kind-class"},{"id":17,"kind":1024,"name":"firstName","url":"classes/example.html#firstname","classes":"tsd-kind-property tsd-parent-kind-class","parent":"Example"},{"id":18,"kind":1024,"name":"middleName","url":"classes/example.html#middlename","classes":"tsd-kind-property tsd-parent-kind-class","parent":"Example"},{"id":19,"kind":1024,"name":"lastName","url":"classes/example.html#lastname","classes":"tsd-kind-property tsd-parent-kind-class","parent":"Example"},{"id":20,"kind":1024,"name":"birthday","url":"classes/example.html#birthday","classes":"tsd-kind-property tsd-parent-kind-class","parent":"Example"},{"id":21,"kind":1024,"name":"country","url":"classes/example.html#country","classes":"tsd-kind-property tsd-parent-kind-class","parent":"Example"},{"id":22,"kind":1024,"name":"province","url":"classes/example.html#province","classes":"tsd-kind-property tsd-parent-kind-class","parent":"Example"},{"id":23,"kind":1024,"name":"city","url":"classes/example.html#city","classes":"tsd-kind-property tsd-parent-kind-class","parent":"Example"},{"id":24,"kind":1024,"name":"genre","url":"classes/example.html#genre","classes":"tsd-kind-property tsd-parent-kind-class","parent":"Example"},{"id":25,"kind":32,"name":"FIRESTORE_DB","url":"globals.html#firestore_db","classes":"tsd-kind-variable"},{"id":26,"kind":32,"name":"key","url":"globals.html#key","classes":"tsd-kind-variable tsd-is-not-exported"},{"id":27,"kind":32,"name":"db","url":"globals.html#db","classes":"tsd-kind-variable"},{"id":28,"kind":256,"name":"IFirestoreRepository","url":"interfaces/ifirestorerepository.html","classes":"tsd-kind-interface"},{"id":29,"kind":2048,"name":"create","url":"interfaces/ifirestorerepository.html#create","classes":"tsd-kind-method tsd-parent-kind-interface","parent":"IFirestoreRepository"},{"id":30,"kind":2048,"name":"readOne","url":"interfaces/ifirestorerepository.html#readone","classes":"tsd-kind-method tsd-parent-kind-interface","parent":"IFirestoreRepository"},{"id":31,"kind":2048,"name":"readAll","url":"interfaces/ifirestorerepository.html#readall","classes":"tsd-kind-method tsd-parent-kind-interface","parent":"IFirestoreRepository"},{"id":32,"kind":2048,"name":"update","url":"interfaces/ifirestorerepository.html#update","classes":"tsd-kind-method tsd-parent-kind-interface","parent":"IFirestoreRepository"},{"id":33,"kind":2048,"name":"delete","url":"interfaces/ifirestorerepository.html#delete","classes":"tsd-kind-method tsd-parent-kind-interface","parent":"IFirestoreRepository"},{"id":34,"kind":128,"name":"FirestoreRepository","url":"classes/firestorerepository.html","classes":"tsd-kind-class"},{"id":35,"kind":1024,"name":"collection","url":"classes/firestorerepository.html#collection","classes":"tsd-kind-property tsd-parent-kind-class","parent":"FirestoreRepository"},{"id":36,"kind":512,"name":"constructor","url":"classes/firestorerepository.html#constructor","classes":"tsd-kind-constructor tsd-parent-kind-class","parent":"FirestoreRepository"},{"id":37,"kind":2048,"name":"create","url":"classes/firestorerepository.html#create","classes":"tsd-kind-method tsd-parent-kind-class","parent":"FirestoreRepository"},{"id":38,"kind":2048,"name":"readOne","url":"classes/firestorerepository.html#readone","classes":"tsd-kind-method tsd-parent-kind-class","parent":"FirestoreRepository"},{"id":39,"kind":2048,"name":"readAll","url":"classes/firestorerepository.html#readall","classes":"tsd-kind-method tsd-parent-kind-class","parent":"FirestoreRepository"},{"id":40,"kind":2048,"name":"update","url":"classes/firestorerepository.html#update","classes":"tsd-kind-method tsd-parent-kind-class","parent":"FirestoreRepository"},{"id":41,"kind":2048,"name":"delete","url":"classes/firestorerepository.html#delete","classes":"tsd-kind-method tsd-parent-kind-class","parent":"FirestoreRepository"},{"id":42,"kind":256,"name":"IController","url":"interfaces/icontroller.html","classes":"tsd-kind-interface"},{"id":43,"kind":2048,"name":"create","url":"interfaces/icontroller.html#create","classes":"tsd-kind-method tsd-parent-kind-interface","parent":"IController"},{"id":44,"kind":2048,"name":"readOne","url":"interfaces/icontroller.html#readone","classes":"tsd-kind-method tsd-parent-kind-interface","parent":"IController"},{"id":45,"kind":2048,"name":"readAll","url":"interfaces/icontroller.html#readall","classes":"tsd-kind-method tsd-parent-kind-interface","parent":"IController"},{"id":46,"kind":2048,"name":"update","url":"interfaces/icontroller.html#update","classes":"tsd-kind-method tsd-parent-kind-interface","parent":"IController"},{"id":47,"kind":2048,"name":"delete","url":"interfaces/icontroller.html#delete","classes":"tsd-kind-method tsd-parent-kind-interface","parent":"IController"},{"id":48,"kind":128,"name":"Controller","url":"classes/controller.html","classes":"tsd-kind-class"},{"id":49,"kind":1024,"name":"repository","url":"classes/controller.html#repository","classes":"tsd-kind-property tsd-parent-kind-class tsd-is-private","parent":"Controller"},{"id":50,"kind":512,"name":"constructor","url":"classes/controller.html#constructor","classes":"tsd-kind-constructor tsd-parent-kind-class","parent":"Controller"},{"id":51,"kind":2048,"name":"create","url":"classes/controller.html#create","classes":"tsd-kind-method tsd-parent-kind-class","parent":"Controller"},{"id":52,"kind":2048,"name":"readOne","url":"classes/controller.html#readone","classes":"tsd-kind-method tsd-parent-kind-class","parent":"Controller"},{"id":53,"kind":2048,"name":"readAll","url":"classes/controller.html#readall","classes":"tsd-kind-method tsd-parent-kind-class","parent":"Controller"},{"id":54,"kind":2048,"name":"update","url":"classes/controller.html#update","classes":"tsd-kind-method tsd-parent-kind-class","parent":"Controller"},{"id":55,"kind":2048,"name":"delete","url":"classes/controller.html#delete","classes":"tsd-kind-method tsd-parent-kind-class","parent":"Controller"},{"id":56,"kind":128,"name":"ExampleController","url":"classes/examplecontroller.html","classes":"tsd-kind-class"},{"id":57,"kind":1024,"name":"collectionName","url":"classes/examplecontroller.html#collectionname","classes":"tsd-kind-property tsd-parent-kind-class tsd-is-static","parent":"ExampleController"},{"id":58,"kind":2048,"name":"create","url":"classes/examplecontroller.html#create","classes":"tsd-kind-method tsd-parent-kind-class tsd-is-static","parent":"ExampleController"},{"id":59,"kind":2048,"name":"readOne","url":"classes/examplecontroller.html#readone","classes":"tsd-kind-method tsd-parent-kind-class tsd-is-static","parent":"ExampleController"},{"id":60,"kind":2048,"name":"readAll","url":"classes/examplecontroller.html#readall","classes":"tsd-kind-method tsd-parent-kind-class tsd-is-static","parent":"ExampleController"},{"id":61,"kind":2048,"name":"update","url":"classes/examplecontroller.html#update","classes":"tsd-kind-method tsd-parent-kind-class tsd-is-static","parent":"ExampleController"},{"id":62,"kind":2048,"name":"delete","url":"classes/examplecontroller.html#delete","classes":"tsd-kind-method tsd-parent-kind-class tsd-is-static","parent":"ExampleController"},{"id":63,"kind":32,"name":"router","url":"globals.html#router","classes":"tsd-kind-variable"},{"id":64,"kind":32,"name":"app","url":"globals.html#app","classes":"tsd-kind-variable"}]}; -------------------------------------------------------------------------------- /docs/classes/example.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Example | Typescript + Express + Firestore - API Rest 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 |
47 | Menu 48 |
49 |
50 |
51 |
52 |
53 |
54 | 62 |

Class Example

63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |

An example schema

73 |
74 |
75 |
76 |
77 |

Hierarchy

78 |
    79 |
  • 80 | Example 81 |
  • 82 |
83 |
84 |
85 |

Implements

86 | 89 |
90 |
91 |

Index

92 |
93 |
94 |
95 |

Properties

96 | 106 |
107 |
108 |
109 |
110 |
111 |

Properties

112 |
113 | 114 |

Optional birthday

115 |
birthday: Timestamp
116 | 122 |
123 |
124 | 125 |

Optional city

126 |
city: undefined | string
127 | 133 |
134 |
135 | 136 |

Optional country

137 |
country: undefined | string
138 | 144 |
145 |
146 | 147 |

Optional firstName

148 |
firstName: undefined | string
149 | 155 |
156 |
157 | 158 |

Optional genre

159 |
genre: undefined | string
160 | 166 |
167 |
168 | 169 |

Optional lastName

170 |
lastName: undefined | string
171 | 177 |
178 |
179 | 180 |

Optional middleName

181 |
middleName: undefined | string
182 | 188 |
189 |
190 | 191 |

Optional province

192 |
province: undefined | string
193 | 199 |
200 |
201 |
202 | 287 |
288 |
289 | 348 |
349 |

Generated using TypeDoc

350 |
351 |
352 | 353 | 354 | 355 | -------------------------------------------------------------------------------- /docs/classes/examplecontroller.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ExampleController | Typescript + Express + Firestore - API Rest 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 |
47 | Menu 48 |
49 |
50 |
51 |
52 |
53 |
54 | 62 |

Class ExampleController

63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |

The specific ExampleController used by the examples route handler.

73 |
74 |
75 |
76 |
77 |

Hierarchy

78 |
    79 |
  • 80 | ExampleController 81 |
  • 82 |
83 |
84 |
85 |

Index

86 |
87 |
88 |
89 |

Properties

90 | 93 |
94 |
95 |

Methods

96 | 103 |
104 |
105 |
106 |
107 |
108 |

Properties

109 |
110 | 111 |

Static collectionName

112 |
collectionName: string = "examples"
113 | 118 |
119 |
120 |

The collection's name used by this controller.

121 |
122 |
123 |
124 |
125 |
126 |

Methods

127 |
128 | 129 |

Static create

130 |
    131 |
  • create(req: Request, res: Response, next: NextFunction): void
  • 132 |
133 |
    134 |
  • 135 | 140 |
    141 |
    142 |

    A static method used to parse, validate and create a new Example document.

    143 |
    144 |
    145 |

    Parameters

    146 |
      147 |
    • 148 |
      req: Request
      149 |
      150 |

      The request received by the API Rest

      151 |
      152 |
    • 153 |
    • 154 |
      res: Response
      155 |
      156 |

      The response sent by the API Rest

      157 |
      158 |
    • 159 |
    • 160 |
      next: NextFunction
      161 |
      162 |

      The next function executed in the app's middleware

      163 |
      164 |
    • 165 |
    166 |

    Returns void

    167 |
  • 168 |
169 |
170 |
171 | 172 |

Static delete

173 |
    174 |
  • delete(req: Request, res: Response, next: NextFunction): void
  • 175 |
176 |
    177 |
  • 178 | 183 |
    184 |
    185 |

    A static method used to delete an Example document by the given id.

    186 |
    187 |
    188 |

    Parameters

    189 |
      190 |
    • 191 |
      req: Request
      192 |
      193 |

      The request received by the API Rest

      194 |
      195 |
    • 196 |
    • 197 |
      res: Response
      198 |
      199 |

      The response sent by the API Rest

      200 |
      201 |
    • 202 |
    • 203 |
      next: NextFunction
      204 |
      205 |

      The next function executed in the app's middleware

      206 |
      207 |
    • 208 |
    209 |

    Returns void

    210 |
  • 211 |
212 |
213 |
214 | 215 |

Static readAll

216 |
    217 |
  • readAll(req: Request, res: Response, next: NextFunction): void
  • 218 |
219 |
    220 |
  • 221 | 226 |
    227 |
    228 |

    A static method used to read all Example documents.

    229 |
    230 |
    231 |

    Parameters

    232 |
      233 |
    • 234 |
      req: Request
      235 |
      236 |

      The request received by the API Rest

      237 |
      238 |
    • 239 |
    • 240 |
      res: Response
      241 |
      242 |

      The response sent by the API Rest

      243 |
      244 |
    • 245 |
    • 246 |
      next: NextFunction
      247 |
      248 |

      The next function executed in the app's middleware

      249 |
      250 |
    • 251 |
    252 |

    Returns void

    253 |
  • 254 |
255 |
256 |
257 | 258 |

Static readOne

259 |
    260 |
  • readOne(req: Request, res: Response, next: NextFunction): void
  • 261 |
262 |
    263 |
  • 264 | 269 |
    270 |
    271 |

    A static method used to read one Example document by the given id.

    272 |
    273 |
    274 |

    Parameters

    275 |
      276 |
    • 277 |
      req: Request
      278 |
      279 |

      The request received by the API Rest

      280 |
      281 |
    • 282 |
    • 283 |
      res: Response
      284 |
      285 |

      The response sent by the API Rest

      286 |
      287 |
    • 288 |
    • 289 |
      next: NextFunction
      290 |
      291 |

      The next function executed in the app's middleware

      292 |
      293 |
    • 294 |
    295 |

    Returns void

    296 |
  • 297 |
298 |
299 |
300 | 301 |

Static update

302 |
    303 |
  • update(req: Request, res: Response, next: NextFunction): void
  • 304 |
305 |
    306 |
  • 307 | 312 |
    313 |
    314 |

    A static method used to update certain fields of an Example document by the given id.

    315 |
    316 |
    317 |

    Parameters

    318 |
      319 |
    • 320 |
      req: Request
      321 |
      322 |

      The request received by the API Rest

      323 |
      324 |
    • 325 |
    • 326 |
      res: Response
      327 |
      328 |

      The response sent by the API Rest

      329 |
      330 |
    • 331 |
    • 332 |
      next: NextFunction
      333 |
      334 |

      The next function executed in the app's middleware

      335 |
      336 |
    • 337 |
    338 |

    Returns void

    339 |
  • 340 |
341 |
342 |
343 |
344 | 423 |
424 |
425 | 484 |
485 |

Generated using TypeDoc

486 |
487 |
488 | 489 | 490 | 491 | -------------------------------------------------------------------------------- /docs/classes/firestorerepository.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | FirestoreRepository | Typescript + Express + Firestore - API Rest 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 |
47 | Menu 48 |
49 |
50 |
51 |
52 |
53 |
54 | 62 |

Class FirestoreRepository

63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |

Hierarchy

71 |
    72 |
  • 73 | FirestoreRepository 74 |
  • 75 |
76 |
77 |
78 |

Implements

79 | 82 |
83 |
84 |

Index

85 |
86 |
87 |
88 |

Constructors

89 | 92 |
93 |
94 |

Properties

95 | 98 |
99 |
100 |

Methods

101 | 108 |
109 |
110 |
111 |
112 |
113 |

Constructors

114 |
115 | 116 |

constructor

117 |
    118 |
  • new FirestoreRepository(db: Firestore, collectionName: string): FirestoreRepository
  • 119 |
120 |
    121 |
  • 122 | 127 |

    Parameters

    128 |
      129 |
    • 130 |
      db: Firestore
      131 |
    • 132 |
    • 133 |
      collectionName: string
      134 |
    • 135 |
    136 |

    Returns FirestoreRepository

    137 |
  • 138 |
139 |
140 |
141 |
142 |

Properties

143 |
144 | 145 |

collection

146 |
collection: CollectionReference
147 | 152 |
153 |
154 |
155 |

Methods

156 |
157 | 158 |

create

159 |
    160 |
  • create(object: DocumentData): Promise<DocumentReference>
  • 161 |
162 |
    163 |
  • 164 | 170 |

    Parameters

    171 |
      172 |
    • 173 |
      object: DocumentData
      174 |
    • 175 |
    176 |

    Returns Promise<DocumentReference>

    177 |
  • 178 |
179 |
180 |
181 | 182 |

delete

183 |
    184 |
  • delete(id: string): Promise<DocumentReference>
  • 185 |
186 |
    187 |
  • 188 | 194 |

    Parameters

    195 |
      196 |
    • 197 |
      id: string
      198 |
    • 199 |
    200 |

    Returns Promise<DocumentReference>

    201 |
  • 202 |
203 |
204 |
205 | 206 |

readAll

207 |
    208 |
  • readAll(): Promise<DocumentReference[]>
  • 209 |
210 |
    211 |
  • 212 | 218 |

    Returns Promise<DocumentReference[]>

    219 |
  • 220 |
221 |
222 |
223 | 224 |

readOne

225 |
    226 |
  • readOne(id: string): Promise<DocumentReference>
  • 227 |
228 |
    229 |
  • 230 | 236 |

    Parameters

    237 |
      238 |
    • 239 |
      id: string
      240 |
    • 241 |
    242 |

    Returns Promise<DocumentReference>

    243 |
  • 244 |
245 |
246 |
247 | 248 |

update

249 |
    250 |
  • update(id: string, object: DocumentData): Promise<DocumentReference>
  • 251 |
252 |
    253 |
  • 254 | 260 |

    Parameters

    261 |
      262 |
    • 263 |
      id: string
      264 |
    • 265 |
    • 266 |
      object: DocumentData
      267 |
    • 268 |
    269 |

    Returns Promise<DocumentReference>

    270 |
  • 271 |
272 |
273 |
274 |
275 | 357 |
358 |
359 | 418 |
419 |

Generated using TypeDoc

420 |
421 |
422 | 423 | 424 | 425 | -------------------------------------------------------------------------------- /docs/globals.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Typescript + Express + Firestore - API Rest 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 |
47 | Menu 48 |
49 |
50 |
51 |
52 |
53 |
54 | 59 |

Typescript + Express + Firestore - API Rest

60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |

Index

68 |
69 |
70 |
71 |

Classes

72 | 78 |
79 |
80 |

Interfaces

81 | 87 |
88 |
89 |

Variables

90 | 97 |
98 |
99 |

Functions

100 | 103 |
104 |
105 |
106 |
107 |
108 |

Variables

109 |
110 | 111 |

Const FIRESTORE_DB

112 |
FIRESTORE_DB: undefined | string = process.env.FIRESTORE_DB
113 | 118 |
119 |
120 | 121 |

Const app

122 |
app: Express = express.default()
123 | 128 |
129 |
130 | 131 |

Const db

132 |
db: Firestore = admin.firestore()
133 | 138 |
139 |
140 | 141 |

Const key

142 |
key: any = require("../keys/serviceAccountKey.json")
143 | 148 |
149 |
150 | 151 |

Const router

152 |
router: Router = Router()
153 | 159 |
160 |
161 |
162 |

Functions

163 |
164 | 165 |

errorMiddleware

166 |
    167 |
  • errorMiddleware(err: Error, req: Request, res: Response, next: NextFunction): void
  • 168 |
169 |
    170 |
  • 171 | 176 |
    177 |
    178 |

    Middleware function used on the request's pipeline to deliver error messages.

    179 |
    180 |
    181 |

    Parameters

    182 |
      183 |
    • 184 |
      err: Error
      185 |
      186 |

      Custom error object

      187 |
      188 |
    • 189 |
    • 190 |
      req: Request
      191 |
      192 |

      The request that originated the error

      193 |
      194 |
    • 195 |
    • 196 |
      res: Response
      197 |
      198 |

      The response that's sent to the client

      199 |
      200 |
    • 201 |
    • 202 |
      next: NextFunction
      203 |
      204 |

      The next function executed in the app's middleware

      205 |
      206 |
    • 207 |
    208 |

    Returns void

    209 |
  • 210 |
211 |
212 |
213 |
214 | 269 |
270 |
271 | 330 |
331 |

Generated using TypeDoc

332 |
333 |
334 | 335 | 336 | 337 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Typescript + Express + Firestore - API Rest 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 |
47 | Menu 48 |
49 |
50 |
51 |
52 |
53 |
54 | 59 |

Typescript + Express + Firestore - API Rest

60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |

TypeScript + Express + Firestore

68 |

An API REST created with Typescript and using Express and Firestore modules

69 |

70 |

Features

71 |

This project has or uses the following features:

72 |
    73 |
  • Typescript.
  • 74 |
  • Express.
  • 75 |
  • Google Firestore.
  • 76 |
  • Model - View - Controller pattern.
  • 77 |
  • SOLID principles.
  • 78 |
  • Class validation.
  • 79 |
  • CI/CD with Travis.
  • 80 |
  • Tests with mocha and chai.
  • 81 |
  • Autogenerated documentation with typedoc.
  • 82 |
83 |

Getting started

84 |

This application was created using NodeJS, you can look at the package.json file for more information about what packages have been used.

85 |

You need to create a keys folder in the application root directory, and inside of it, you should move the .json file provided by Google Firestore. Read more information about this: Google Firestore SDK documentation. This file is required in db.ts

86 |

Before start working on code

87 |

yarn install or npm install

88 |

Building

89 |

npm run build 90 | Gets the ./build directory with js files.

91 |

Source code analysis

92 |

npm run lint 93 | Uses lint to analyze the source code.

94 |

Starting the application

95 |

npm run start 96 | Runs the application in a node instance.

97 |

Watch mode (build)

98 |

npm run build-watch 99 | Compiles the application every time some change has been made.

100 |

Watch mode (start)

101 |

npm run start-watch 102 | Runs the application every time some change has been made. Should be run in parallel with Build watch mode.

103 |

Documentation

104 |

npm run doc 105 | Generates the project's documentation using typedoc.

106 |

API Endpoint

107 |

In this application there is only one endpoint available, it's the examples endpoint. 108 | You can check how any route works reading its specific controller class. For further information about the examples route, you can read the ExampleController class.

109 |

Test

110 |

The firestore test is related to my own firestore database. You can play around with the source file to understand mocha and chai modules. Be sure to check and change the id argument in both read and update methods.

111 |

Project structure

112 |
|   .env.example
113 | |   .gitignore
114 | |   .travis.yml
115 | |   LICENSE
116 | |   package.json
117 | |   README.md
118 | |   tsconfig.json
119 | |   tslint.json
120 | |   yarn.lock
121 | |            
122 | +---src
123 | |   |   app.ts
124 | |   |   db.ts
125 | |   |   env.ts
126 | |   |   index.ts
127 | |   |   
128 | |   +---controllers
129 | |   |   |   controller.ts
130 | |   |   |   example.controller.ts
131 | |   |   |   
132 | |   |   \---interfaces
133 | |   |           controller.interface.ts
134 | |   |           
135 | |   +---middleware
136 | |   |       error.middleware.ts
137 | |   |       
138 | |   +---models
139 | |   |   |   example.model.ts
140 | |   |   |   
141 | |   |   \---interfaces
142 | |   |           example.interface.ts
143 | |   |           
144 | |   +---repositories
145 | |   |   |   firestore.repository.ts
146 | |   |   |   
147 | |   |   \---interfaces
148 | |   |           firestore.interface.ts
149 | |   |           
150 | |   +---routes
151 | |   |       example.routes.ts
152 | |   |       index.ts
153 | |   |       
154 | |   \---utils
155 | |           error.interface.ts
156 | |           
157 | +---tests
158 | |   \---repositories
159 | |           firestore.test.ts
160 | |           
161 | \---views
162 |         error.pug

ToDo

163 |
    164 |
  • JWT
  • 165 |
166 |
167 |
168 | 223 |
224 |
225 | 284 |
285 |

Generated using TypeDoc

286 |
287 |
288 | 289 | 290 | 291 | -------------------------------------------------------------------------------- /docs/interfaces/icontroller.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | IController | Typescript + Express + Firestore - API Rest 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 |
47 | Menu 48 |
49 |
50 |
51 |
52 |
53 |
54 | 62 |

Interface IController

63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |

Hierarchy

71 |
    72 |
  • 73 | IController 74 |
  • 75 |
76 |
77 |
78 |

Implemented by

79 | 82 |
83 |
84 |

Index

85 |
86 |
87 |
88 |

Methods

89 | 96 |
97 |
98 |
99 |
100 |
101 |

Methods

102 |
103 | 104 |

create

105 |
    106 |
  • create(req: Request, res: Response, next: NextFunction): DocumentData | undefined
  • 107 |
108 |
    109 |
  • 110 | 115 |

    Parameters

    116 |
      117 |
    • 118 |
      req: Request
      119 |
    • 120 |
    • 121 |
      res: Response
      122 |
    • 123 |
    • 124 |
      next: NextFunction
      125 |
    • 126 |
    127 |

    Returns DocumentData 128 | | 129 | undefined 130 |

    131 |
  • 132 |
133 |
134 |
135 | 136 |

delete

137 |
    138 |
  • delete(req: Request, res: Response, next: NextFunction): DocumentData | undefined
  • 139 |
140 |
    141 |
  • 142 | 147 |

    Parameters

    148 |
      149 |
    • 150 |
      req: Request
      151 |
    • 152 |
    • 153 |
      res: Response
      154 |
    • 155 |
    • 156 |
      next: NextFunction
      157 |
    • 158 |
    159 |

    Returns DocumentData 160 | | 161 | undefined 162 |

    163 |
  • 164 |
165 |
166 |
167 | 168 |

readAll

169 |
    170 |
  • readAll(req: Request, res: Response, next: NextFunction): DocumentData[] | undefined
  • 171 |
172 |
    173 |
  • 174 | 179 |

    Parameters

    180 |
      181 |
    • 182 |
      req: Request
      183 |
    • 184 |
    • 185 |
      res: Response
      186 |
    • 187 |
    • 188 |
      next: NextFunction
      189 |
    • 190 |
    191 |

    Returns DocumentData[] 192 | | 193 | undefined 194 |

    195 |
  • 196 |
197 |
198 |
199 | 200 |

readOne

201 |
    202 |
  • readOne(req: Request, res: Response, next: NextFunction): DocumentData | undefined
  • 203 |
204 |
    205 |
  • 206 | 211 |

    Parameters

    212 |
      213 |
    • 214 |
      req: Request
      215 |
    • 216 |
    • 217 |
      res: Response
      218 |
    • 219 |
    • 220 |
      next: NextFunction
      221 |
    • 222 |
    223 |

    Returns DocumentData 224 | | 225 | undefined 226 |

    227 |
  • 228 |
229 |
230 |
231 | 232 |

update

233 |
    234 |
  • update(req: Request, res: Response, next: NextFunction): DocumentData | undefined
  • 235 |
236 |
    237 |
  • 238 | 243 |

    Parameters

    244 |
      245 |
    • 246 |
      req: Request
      247 |
    • 248 |
    • 249 |
      res: Response
      250 |
    • 251 |
    • 252 |
      next: NextFunction
      253 |
    • 254 |
    255 |

    Returns DocumentData 256 | | 257 | undefined 258 |

    259 |
  • 260 |
261 |
262 |
263 |
264 | 340 |
341 |
342 | 401 |
402 |

Generated using TypeDoc

403 |
404 |
405 | 406 | 407 | 408 | -------------------------------------------------------------------------------- /docs/interfaces/icustomerror.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ICustomError | Typescript + Express + Firestore - API Rest 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 |
47 | Menu 48 |
49 |
50 |
51 |
52 |
53 |
54 | 62 |

Interface ICustomError

63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |

Hierarchy

71 |
    72 |
  • 73 | Error 74 |
      75 |
    • 76 | ICustomError 77 |
    • 78 |
    79 |
  • 80 |
81 |
82 |
83 |

Index

84 |
85 |
86 |
87 |

Properties

88 | 95 |
96 |
97 |
98 |
99 |
100 |

Properties

101 |
102 | 103 |

Error

104 |
Error: ErrorConstructor
105 | 110 |
111 |
112 | 113 |

message

114 |
message: string
115 | 121 |
122 |
123 | 124 |

name

125 |
name: string
126 | 132 |
133 |
134 | 135 |

Optional stack

136 |
stack: undefined | string
137 | 144 |
145 |
146 | 147 |

status

148 |
status: number
149 | 154 |
155 |
156 |
157 | 233 |
234 |
235 | 294 |
295 |

Generated using TypeDoc

296 |
297 |
298 | 299 | 300 | 301 | -------------------------------------------------------------------------------- /docs/interfaces/iexample.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | IExample | Typescript + Express + Firestore - API Rest 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 |
47 | Menu 48 |
49 |
50 |
51 |
52 |
53 |
54 | 62 |

Interface IExample

63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |

Hierarchy

71 |
    72 |
  • 73 | IExample 74 |
  • 75 |
76 |
77 |
78 |

Implemented by

79 | 82 |
83 |
84 |

Index

85 |
86 |
87 |
88 |

Properties

89 | 99 |
100 |
101 |
102 |
103 |
104 |

Properties

105 |
106 | 107 |

Optional birthday

108 |
birthday: Timestamp
109 | 114 |
115 |
116 | 117 |

Optional city

118 |
city: undefined | string
119 | 124 |
125 |
126 | 127 |

Optional country

128 |
country: undefined | string
129 | 134 |
135 |
136 | 137 |

Optional firstName

138 |
firstName: undefined | string
139 | 144 |
145 |
146 | 147 |

Optional genre

148 |
genre: undefined | string
149 | 154 |
155 |
156 | 157 |

Optional lastName

158 |
lastName: undefined | string
159 | 164 |
165 |
166 | 167 |

Optional middleName

168 |
middleName: undefined | string
169 | 174 |
175 |
176 | 177 |

Optional province

178 |
province: undefined | string
179 | 184 |
185 |
186 |
187 | 272 |
273 |
274 | 333 |
334 |

Generated using TypeDoc

335 |
336 |
337 | 338 | 339 | 340 | -------------------------------------------------------------------------------- /docs/interfaces/ifirestorerepository.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | IFirestoreRepository | Typescript + Express + Firestore - API Rest 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 |
47 | Menu 48 |
49 |
50 |
51 |
52 |
53 |
54 | 62 |

Interface IFirestoreRepository

63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |

Hierarchy

71 |
    72 |
  • 73 | IFirestoreRepository 74 |
  • 75 |
76 |
77 |
78 |

Implemented by

79 | 82 |
83 |
84 |

Index

85 |
86 |
87 |
88 |

Methods

89 | 96 |
97 |
98 |
99 |
100 |
101 |

Methods

102 |
103 | 104 |

create

105 |
    106 |
  • create(object: DocumentData): Promise<DocumentReference>
  • 107 |
108 |
    109 |
  • 110 | 115 |

    Parameters

    116 |
      117 |
    • 118 |
      object: DocumentData
      119 |
    • 120 |
    121 |

    Returns Promise<DocumentReference>

    122 |
  • 123 |
124 |
125 |
126 | 127 |

delete

128 |
    129 |
  • delete(id: string): Promise<DocumentReference>
  • 130 |
131 |
    132 |
  • 133 | 138 |

    Parameters

    139 |
      140 |
    • 141 |
      id: string
      142 |
    • 143 |
    144 |

    Returns Promise<DocumentReference>

    145 |
  • 146 |
147 |
148 |
149 | 150 |

readAll

151 |
    152 |
  • readAll(): Promise<DocumentReference[]>
  • 153 |
154 |
    155 |
  • 156 | 161 |

    Returns Promise<DocumentReference[]>

    162 |
  • 163 |
164 |
165 |
166 | 167 |

readOne

168 |
    169 |
  • readOne(id: string): Promise<DocumentReference>
  • 170 |
171 |
    172 |
  • 173 | 178 |

    Parameters

    179 |
      180 |
    • 181 |
      id: string
      182 |
    • 183 |
    184 |

    Returns Promise<DocumentReference>

    185 |
  • 186 |
187 |
188 |
189 | 190 |

update

191 |
    192 |
  • update(id: string, object: DocumentData): Promise<DocumentReference>
  • 193 |
194 |
    195 |
  • 196 | 201 |

    Parameters

    202 |
      203 |
    • 204 |
      id: string
      205 |
    • 206 |
    • 207 |
      object: DocumentData
      208 |
    • 209 |
    210 |

    Returns Promise<DocumentReference>

    211 |
  • 212 |
213 |
214 |
215 |
216 | 292 |
293 |
294 | 353 |
354 |

Generated using TypeDoc

355 |
356 |
357 | 358 | 359 | 360 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "typescript-express-firestore", 3 | "version": "1.0.0", 4 | "description": "An API REST created with Typescript and using Express and Firestore modules", 5 | "main": "./build/index.js", 6 | "scripts": { 7 | "build": "tsc", 8 | "start": "node", 9 | "lint": "tslint --project tslint.json", 10 | "build-watch": "tsc --watch", 11 | "start-watch": "nodemon", 12 | "test": "mocha --require ts-node/register tests/**/*.ts --timeout 20000", 13 | "doc": "typedoc --out docs --mode file --name \"Typescript + Express + Firestore - API Rest\" --exclude tests/**/*.ts" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/marcoshuck/typescript-express-firestore.git" 18 | }, 19 | "keywords": [ 20 | "Typescript", 21 | "Express", 22 | "Firestore" 23 | ], 24 | "author": "Marcos A. Huck ", 25 | "license": "MIT", 26 | "bugs": { 27 | "url": "https://github.com/marcoshuck/typescript-express-firestore/issues" 28 | }, 29 | "homepage": "https://github.com/marcoshuck/typescript-express-firestore#readme", 30 | "devDependencies": { 31 | "@firebase/app-types": "^0.3.2", 32 | "@types/chai": "^4.1.7", 33 | "@types/cors": "^2.8.4", 34 | "@types/dotenv": "^6.1.0", 35 | "@types/express": "^4.16.0", 36 | "@types/mocha": "^5.2.5", 37 | "chai": "^4.2.0", 38 | "mocha": "^5.2.0", 39 | "nodemon": "^1.18.9", 40 | "ts-node": "^7.0.1", 41 | "tslint": "^5.12.0", 42 | "typedoc": "^0.14.0", 43 | "typescript": "^3.2.2" 44 | }, 45 | "dependencies": { 46 | "class-validator": "^0.9.1", 47 | "cors": "^2.8.5", 48 | "dotenv": "^6.2.0", 49 | "express": "^4.16.4", 50 | "firebase-admin": "^6.4.0", 51 | "firebase-functions": "^2.1.0", 52 | "pug": "^2.0.3" 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/app.ts: -------------------------------------------------------------------------------- 1 | import cors from "cors"; 2 | import * as express from "express"; 3 | import path from "path"; 4 | import errorMiddleware from "./middleware/error.middleware"; 5 | import routes from "./routes"; 6 | 7 | const app = express.default(); 8 | 9 | app.set("views", path.join(__dirname, "../views")); 10 | app.set("view engine", "pug"); 11 | app.use(express.urlencoded({ extended: true })); 12 | app.use(express.json()); 13 | app.use(cors({ origin: true })); 14 | app.use("/", routes); 15 | 16 | app.use("/", errorMiddleware); 17 | 18 | export default app; 19 | -------------------------------------------------------------------------------- /src/controllers/controller.ts: -------------------------------------------------------------------------------- 1 | import { DocumentData, DocumentSnapshot } from "@google-cloud/firestore"; 2 | import {NextFunction, Request, Response} from "express"; 3 | import db from "../db"; 4 | import FirestoreRepository from "../repositories/firestore.repository"; 5 | import CustomError from "../utils/error.interface"; 6 | import IController from "./interfaces/controller.interface"; 7 | 8 | /** 9 | * Modular Controller with CRUD methods using Firestore repository and DocumentData type. 10 | */ 11 | export default class Controller implements IController { 12 | 13 | /** 14 | * Firebase repository used by CRUD methods. 15 | */ 16 | private repository: FirestoreRepository; 17 | 18 | constructor(collectionName: string) { 19 | this.repository = new FirestoreRepository(db, collectionName); 20 | } 21 | /** 22 | * Create a document in Firestore collection using the DocumentData received in the request body. 23 | * @param req The request received by the API Rest 24 | * @param res The response sent by the API Rest 25 | * @param next The next function executed in the app's middleware 26 | */ 27 | public create(req: Request, res: Response, next: NextFunction): DocumentData | undefined { 28 | let data: DocumentData | undefined; 29 | if (req.body == null) { 30 | const err: CustomError = new Error("The body was empty or undefined") as CustomError; 31 | err.status = 400; 32 | next(err); 33 | return; 34 | } 35 | this.repository.create(req.body).then((value) => { 36 | res.status(200).send(value.get().then((document) => { 37 | if (document.data()) { 38 | data = document.data(); 39 | } 40 | return data; 41 | })); 42 | }).catch((reason) => { 43 | next(reason); 44 | }); 45 | return data; 46 | } 47 | /** 48 | * Read one document by the given id. 49 | * @param req The request received by the API Rest 50 | * @param res The response sent by the API Rest 51 | * @param next The next function executed in the app's middleware 52 | */ 53 | public readOne(req: Request, res: Response, next: NextFunction): DocumentData | undefined { 54 | if (req.params.id == null) { 55 | const err: CustomError = new Error("The id was undefined") as CustomError; 56 | err.status = 400; 57 | next(err); 58 | return; 59 | } 60 | this.repository.readOne(req.params.id).then(async (value) => { 61 | res.status(200).send((await value.get()).data()); 62 | }).catch((reason) => { 63 | next(reason); 64 | }); 65 | return; 66 | } 67 | /** 68 | * Read all documents available in the Firestore collection. 69 | * @param req The request received by the API Rest 70 | * @param res The response sent by the API Rest 71 | * @param next The next function executed in the app's middleware 72 | */ 73 | public readAll(req: Request, res: Response, next: NextFunction): DocumentData[] | undefined { 74 | let dataArray: DocumentData[]; 75 | let allPromises: Array>; 76 | this.repository.readAll().then(async (list) => { 77 | if (list.length === 0) { 78 | const err: CustomError = new Error("The list of entities was empty") as CustomError; 79 | err.status = 204; 80 | next(err); 81 | return; 82 | } 83 | allPromises = new Array>(); 84 | list.forEach(async (item) => { 85 | allPromises.push(item.get()); 86 | }); 87 | Promise.all(allPromises).then(async (promises) => { 88 | dataArray = new Array(); 89 | promises.forEach(async (promise) => { 90 | dataArray.push(promise.data() as DocumentData); 91 | }); 92 | res.status(200).send(dataArray); 93 | return dataArray; 94 | }); 95 | }) 96 | .catch((reason) => { 97 | next(reason); 98 | }); 99 | return; 100 | } 101 | /** 102 | * Update document fields by the given id. 103 | * @param req The request received by the API Rest 104 | * @param res The response sent by the API Rest 105 | * @param next The next function executed in the app's middleware 106 | */ 107 | public update(req: Request, res: Response, next: NextFunction): DocumentData | undefined { 108 | if (req.body == null) { 109 | const err: CustomError = new Error("The body was empty or undefined") as CustomError; 110 | err.status = 400; 111 | next(err); 112 | return; 113 | } 114 | 115 | if (req.params.id == null) { 116 | const err: CustomError = new Error("The id was undefined") as CustomError; 117 | err.status = 400; 118 | next(err); 119 | return; 120 | } 121 | 122 | this.repository.update(req.params.id, req.body) 123 | .then(async (value) => { 124 | res.status(200).send((await value.get()).data()); 125 | }) 126 | .catch((reason) => { 127 | next(reason); 128 | }); 129 | return; 130 | } 131 | /** 132 | * Delete document by the given id 133 | * @param req The request received by the API Rest 134 | * @param res The response sent by the API Rest 135 | * @param next The next function executed in the app's middleware 136 | */ 137 | public delete(req: Request, res: Response, next: NextFunction): DocumentData | undefined { 138 | if (req.params.id == null) { 139 | const err: CustomError = new Error("The id was undefined") as CustomError; 140 | err.status = 400; 141 | next(err); 142 | return; 143 | } 144 | 145 | this.repository.delete(req.params.id).then(() => { 146 | res.status(200).send("The object was deleted."); 147 | }).catch((reason) => { 148 | next(reason); 149 | }); 150 | return; 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /src/controllers/example.controller.ts: -------------------------------------------------------------------------------- 1 | import {validate} from "class-validator"; 2 | import { NextFunction } from "connect"; 3 | import {Request, Response} from "express"; 4 | import Example from "../models/example.model"; 5 | import CustomError from "../utils/error.interface"; 6 | import Controller from "./controller"; 7 | 8 | /** 9 | * The specific ExampleController used by the examples route handler. 10 | */ 11 | export default class ExampleController { 12 | 13 | /** 14 | * The collection's name used by this controller. 15 | */ 16 | public static readonly collectionName: string = "examples"; 17 | 18 | /** 19 | * A static method used to parse, validate and create a new Example document. 20 | * @param req The request received by the API Rest 21 | * @param res The response sent by the API Rest 22 | * @param next The next function executed in the app's middleware 23 | */ 24 | public static create(req: Request, res: Response, next: NextFunction): void { 25 | const controller: Controller = new Controller(ExampleController.collectionName); 26 | let example: Example = new Example(); 27 | example = req.body; 28 | validate(example, { forbidUnknownValues: true }).then((errors) => { 29 | if (errors.length > 0) { 30 | const err: CustomError = new Error("The body was not validated") as CustomError; 31 | err.status = 400; 32 | next(err); 33 | return; 34 | } 35 | controller.create(req, res, next); 36 | return; 37 | }); 38 | } 39 | /** 40 | * A static method used to read one Example document by the given id. 41 | * @param req The request received by the API Rest 42 | * @param res The response sent by the API Rest 43 | * @param next The next function executed in the app's middleware 44 | */ 45 | public static readOne(req: Request, res: Response, next: NextFunction): void { 46 | const controller: Controller = new Controller(ExampleController.collectionName); 47 | controller.readOne(req, res, next); 48 | return; 49 | } 50 | 51 | /** 52 | * A static method used to read all Example documents. 53 | * @param req The request received by the API Rest 54 | * @param res The response sent by the API Rest 55 | * @param next The next function executed in the app's middleware 56 | */ 57 | public static readAll(req: Request, res: Response, next: NextFunction): void { 58 | const controller: Controller = new Controller(ExampleController.collectionName); 59 | controller.readAll(req, res, next); 60 | return; 61 | } 62 | 63 | /** 64 | * A static method used to update certain fields of an Example document by the given id. 65 | * @param req The request received by the API Rest 66 | * @param res The response sent by the API Rest 67 | * @param next The next function executed in the app's middleware 68 | */ 69 | public static update(req: Request, res: Response, next: NextFunction): void { 70 | const controller: Controller = new Controller(ExampleController.collectionName); 71 | controller.update(req, res, next); 72 | return; 73 | } 74 | 75 | /** 76 | * A static method used to delete an Example document by the given id. 77 | * @param req The request received by the API Rest 78 | * @param res The response sent by the API Rest 79 | * @param next The next function executed in the app's middleware 80 | */ 81 | public static delete(req: Request, res: Response, next: NextFunction): void { 82 | const controller: Controller = new Controller(ExampleController.collectionName); 83 | controller.delete(req, res, next); 84 | return; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/controllers/interfaces/controller.interface.ts: -------------------------------------------------------------------------------- 1 | import { DocumentData } from "@google-cloud/firestore"; 2 | import {NextFunction, Request, Response} from "express"; 3 | 4 | export default interface IController { 5 | create(req: Request, res: Response, next: NextFunction): DocumentData | undefined; 6 | readOne(req: Request, res: Response, next: NextFunction): DocumentData | undefined; 7 | readAll(req: Request, res: Response, next: NextFunction): DocumentData[] | undefined; 8 | update(req: Request, res: Response, next: NextFunction): DocumentData | undefined; 9 | delete(req: Request, res: Response, next: NextFunction): DocumentData | undefined; 10 | } 11 | -------------------------------------------------------------------------------- /src/db.ts: -------------------------------------------------------------------------------- 1 | import * as admin from "firebase-admin"; 2 | import FIRESTORE_DB from "./env"; 3 | 4 | // tslint:disable-next-line:no-var-requires 5 | const key = require("../keys/serviceAccountKey.json"); 6 | 7 | admin.initializeApp({ 8 | credential: admin.credential.cert(key), 9 | databaseURL: FIRESTORE_DB, 10 | }); 11 | 12 | const db: FirebaseFirestore.Firestore = admin.firestore(); 13 | db.settings({timestampsInSnapshots: true}); 14 | 15 | export default db; 16 | -------------------------------------------------------------------------------- /src/env.ts: -------------------------------------------------------------------------------- 1 | import * as dotenv from "dotenv"; 2 | 3 | dotenv.config({ 4 | path: "../", 5 | }); 6 | 7 | const FIRESTORE_DB = process.env.FIRESTORE_DB; 8 | 9 | export default FIRESTORE_DB; 10 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import app from "./app"; 2 | 3 | export default app.listen(8080, () => { 4 | // tslint:disable-next-line:no-console 5 | console.log("Initializing API: TypeScript + Express + Firestore"); 6 | }); 7 | -------------------------------------------------------------------------------- /src/middleware/error.middleware.ts: -------------------------------------------------------------------------------- 1 | import {NextFunction, Request, Response} from "express"; 2 | import CustomError from "../utils/error.interface"; 3 | 4 | /** 5 | * Middleware function used on the request's pipeline to deliver error messages. 6 | * @param err Custom error object 7 | * @param req The request that originated the error 8 | * @param res The response that's sent to the client 9 | * @param next The next function executed in the app's middleware 10 | */ 11 | export default function errorMiddleware(err: Error, req: Request, res: Response, next: NextFunction) { 12 | const error: CustomError = err as CustomError; 13 | res.status(error.status || 500).render("error", { 14 | error: err, 15 | message: error.message, 16 | status: error.status || 500, 17 | }); 18 | } 19 | -------------------------------------------------------------------------------- /src/models/example.model.ts: -------------------------------------------------------------------------------- 1 | import { Timestamp } from "@google-cloud/firestore"; 2 | import {IsAlpha, IsNotEmpty, IsString} from "class-validator"; 3 | import IExample from "./interfaces/example.interface"; 4 | 5 | /** 6 | * An example schema 7 | */ 8 | export default class Example implements IExample { 9 | @IsString() 10 | @IsAlpha() 11 | @IsNotEmpty() 12 | public firstName?: string; 13 | 14 | @IsString() 15 | @IsAlpha() 16 | @IsNotEmpty() 17 | public middleName?: string; 18 | 19 | @IsString() 20 | @IsAlpha() 21 | @IsNotEmpty() 22 | public lastName?: string; 23 | 24 | @IsNotEmpty() 25 | public birthday?: Timestamp; 26 | 27 | @IsString() 28 | @IsAlpha() 29 | @IsNotEmpty() 30 | public country?: string; 31 | 32 | @IsString() 33 | @IsAlpha() 34 | @IsNotEmpty() 35 | public province?: string; 36 | 37 | @IsString() 38 | @IsAlpha() 39 | @IsNotEmpty() 40 | public city?: string; 41 | 42 | @IsString() 43 | @IsAlpha() 44 | @IsNotEmpty() 45 | public genre?: string; 46 | } 47 | -------------------------------------------------------------------------------- /src/models/interfaces/example.interface.ts: -------------------------------------------------------------------------------- 1 | import { Timestamp } from "@google-cloud/firestore"; 2 | 3 | export default interface IExample { 4 | firstName?: string; 5 | middleName?: string; 6 | lastName?: string; 7 | birthday?: Timestamp; 8 | country?: string; 9 | province?: string; 10 | city?: string; 11 | genre?: string; 12 | } 13 | -------------------------------------------------------------------------------- /src/repositories/firestore.repository.ts: -------------------------------------------------------------------------------- 1 | import { CollectionReference, DocumentData, DocumentReference, 2 | DocumentSnapshot, Firestore } from "@google-cloud/firestore"; 3 | import IFirestoreRepository from "./interfaces/firestore.interface"; 4 | 5 | export default class FirestoreRepository implements IFirestoreRepository { 6 | public readonly collection: CollectionReference; 7 | 8 | constructor(db: Firestore, collectionName: string) { 9 | this.collection = db.collection(collectionName); 10 | } 11 | 12 | public async create(object: DocumentData): Promise { 13 | try { 14 | return await this.collection.add(object); 15 | } catch { 16 | throw new Error("Could not create object"); 17 | } 18 | } 19 | 20 | public async readOne(id: string): Promise { 21 | try { 22 | return await this.collection.doc(id); 23 | } catch { 24 | throw new Error("Could not read object"); 25 | } 26 | } 27 | 28 | public async readAll(): Promise { 29 | try { 30 | return await this.collection.listDocuments(); 31 | } catch { 32 | throw new Error("Could not read all objects"); 33 | } 34 | } 35 | 36 | public async update(id: string, object: DocumentData): Promise { 37 | try { 38 | const ref: DocumentReference = this.collection.doc(id); 39 | const snap: DocumentSnapshot = await ref.get(); 40 | if (!snap.exists) { 41 | return ref; 42 | } 43 | await ref.update(object); 44 | return ref; 45 | } catch { 46 | throw new Error("Could not update object"); 47 | } 48 | } 49 | 50 | public async delete(id: string): Promise { 51 | try { 52 | const ref: DocumentReference = this.collection.doc(id); 53 | await ref.delete(); 54 | return ref; 55 | } catch { 56 | throw new Error("Could not remove object"); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/repositories/interfaces/firestore.interface.ts: -------------------------------------------------------------------------------- 1 | import { DocumentData, DocumentReference } from "@google-cloud/firestore"; 2 | 3 | export default interface IFirestoreRepository { 4 | create(object: DocumentData): Promise; 5 | readOne(id: string): Promise; 6 | readAll(): Promise; 7 | update(id: string, object: DocumentData): Promise; 8 | delete(id: string): Promise; 9 | } 10 | -------------------------------------------------------------------------------- /src/routes/example.routes.ts: -------------------------------------------------------------------------------- 1 | import {Router} from "express"; 2 | import ExampleController from "../controllers/example.controller"; 3 | 4 | const router: Router = Router(); 5 | 6 | router.post("/", ExampleController.create); 7 | router.get("/:id", ExampleController.readOne); 8 | router.get("/", ExampleController.readAll); 9 | router.put("/:id", ExampleController.update); 10 | router.delete("/:id", ExampleController.delete); 11 | 12 | export default router; 13 | -------------------------------------------------------------------------------- /src/routes/index.ts: -------------------------------------------------------------------------------- 1 | import {Router} from "express"; 2 | 3 | import example from "./example.routes"; 4 | 5 | const router: Router = Router(); 6 | 7 | router.use("/examples", example); 8 | 9 | export default router; 10 | -------------------------------------------------------------------------------- /src/utils/error.interface.ts: -------------------------------------------------------------------------------- 1 | export default interface ICustomError extends Error { 2 | status: number; 3 | } 4 | -------------------------------------------------------------------------------- /tests/repositories/firestore.test.ts: -------------------------------------------------------------------------------- 1 | import { DocumentData } from "@google-cloud/firestore"; 2 | import {expect} from "chai"; 3 | import db from "../../src/db"; 4 | import FirestoreRepository from "../../src/repositories/firestore.repository"; 5 | 6 | describe("FirestoreRepository", () => { 7 | const repository: FirestoreRepository = new FirestoreRepository(db, "test"); 8 | 9 | describe("#create()", () => { 10 | it("can create a document without errors", (done) => { 11 | const newDocument: DocumentData = {name: "test", test: true}; 12 | repository.create(newDocument).then((ref) => { 13 | expect(ref).to.be.an("Object"); 14 | done(); 15 | }).catch((err) => { 16 | done(err); 17 | }); 18 | }); 19 | }); 20 | 21 | describe("#readOne()", () => { 22 | it("can read a document without errors", (done) => { 23 | repository.readOne("i5RE5BaDcHBGmOqUz5Oq").then((ref) => { 24 | expect(ref).to.be.an("Object"); 25 | done(); 26 | }).catch((err) => { 27 | done(err); 28 | }); 29 | }); 30 | 31 | it("cannot read data from an undefined document", (done) => { 32 | repository.readOne("1234").then((ref) => { 33 | ref.get().then((snap) => { 34 | // tslint:disable-next-line:no-unused-expression 35 | expect(snap.exists).to.be.false; 36 | done(); 37 | }).catch((err) => { 38 | done(err); 39 | }); 40 | }); 41 | }); 42 | }); 43 | 44 | describe("#readAll()", () => { 45 | it("can read all documents without errors", (done) => { 46 | repository.readAll().then((refs) => { 47 | if (refs.length < 3) { 48 | done(false); 49 | } 50 | done(); 51 | }).catch((err) => { 52 | done(err); 53 | }); 54 | }); 55 | }); 56 | 57 | describe("#update()", () => { 58 | it("can update a document without errors", (done) => { 59 | const updatedDocument: DocumentData = {name: "Test" + Date.now().toString()}; 60 | repository.update("oX8e2nueoihKvg1X6a98", updatedDocument).then((ref) => { 61 | ref.get().then((snap) => { 62 | expect(snap.data()).to.include({name: updatedDocument.name}); 63 | done(); 64 | }).catch((err) => { 65 | done(err); 66 | }); 67 | }); 68 | }); 69 | }); 70 | 71 | describe("#delete()", () => { 72 | it("can create and delete a document without errors", (done) => { 73 | const newDocument: DocumentData = {name: "A document to be deleted"}; 74 | repository.create(newDocument).then((newRef) => { 75 | repository.delete(newRef.id).then((deletedRef) => { 76 | deletedRef.get().then((snap) => { 77 | // tslint:disable-next-line:no-unused-expression 78 | expect(snap.exists).to.be.false; 79 | done(); 80 | }).catch((err) => { 81 | done(err); 82 | }); 83 | }); 84 | }); 85 | }); 86 | 87 | it("cannot delete an wrong or undefined id", (done) => { 88 | const newDocument: DocumentData = {name: "A document to be deleted"}; 89 | repository.create(newDocument).then((newRef) => { 90 | repository.delete(newRef.id + "error").then((deletedRef) => { 91 | deletedRef.get().then((snap) => { 92 | // tslint:disable-next-line:no-unused-expression 93 | expect(snap.exists).to.be.false; 94 | }).catch((err) => { 95 | done(err); 96 | }); 97 | newRef.get().then((snap) => { 98 | // tslint:disable-next-line:no-unused-expression 99 | expect(snap.exists).to.be.true; 100 | }).catch((err) => { 101 | done(err); 102 | }); 103 | done(); 104 | }); 105 | }); 106 | }); 107 | }); 108 | }); 109 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Basic Options */ 4 | "target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ 5 | "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ 6 | "lib": ["es2015"], /* Specify library files to be included in the compilation. */ 7 | // "allowJs": true, /* Allow javascript files to be compiled. */ 8 | // "checkJs": true, /* Report errors in .js files. */ 9 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 10 | // "declaration": true, /* Generates corresponding '.d.ts' file. */ 11 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 12 | "sourceMap": true, /* Generates corresponding '.map' file. */ 13 | // "outFile": "./", /* Concatenate and emit output to single file. */ 14 | "outDir": "./build", /* Redirect output structure to the directory. */ 15 | "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 16 | // "composite": true, /* Enable project compilation */ 17 | // "removeComments": true, /* Do not emit comments to output. */ 18 | // "noEmit": true, /* Do not emit outputs. */ 19 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 20 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 21 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 22 | 23 | /* Strict Type-Checking Options */ 24 | "strict": true, /* Enable all strict type-checking options. */ 25 | "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 26 | // "strictNullChecks": true, /* Enable strict null checks. */ 27 | "strictFunctionTypes": true, /* Enable strict checking of function types. */ 28 | "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ 29 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 30 | "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 31 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 32 | 33 | /* Additional Checks */ 34 | "noUnusedLocals": true, /* Report errors on unused locals. */ 35 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 36 | "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 37 | "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 38 | 39 | /* Module Resolution Options */ 40 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 41 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 42 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 43 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 44 | // "typeRoots": [], /* List of folders to include type definitions from. */ 45 | // "types": [], /* Type declaration files to be included in compilation. */ 46 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 47 | "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 48 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 49 | 50 | /* Source Map Options */ 51 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 52 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 53 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 54 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 55 | 56 | /* Experimental Options */ 57 | "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 58 | "emitDecoratorMetadata": true /* Enables experimental support for emitting type metadata for decorators. */ 59 | }, 60 | "exclude": [ 61 | "node_modules", 62 | "views", 63 | "tests" 64 | ] 65 | } -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "defaultSeverity": "error", 3 | "extends": "tslint:recommended", 4 | "jsRules": {}, 5 | "rules": {}, 6 | "rulesDirectory": [] 7 | } -------------------------------------------------------------------------------- /views/error.pug: -------------------------------------------------------------------------------- 1 | html 2 | head 3 | title= "API Rest - Error" 4 | body 5 | h1= status + " " + message 6 | p= err --------------------------------------------------------------------------------