├── .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) [](https://david-dm.org/marcoshuck/typescript-express-firestore)    
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 |
52 |
53 |
54 |
62 |
Class Example
63 |
64 |
65 |
66 |
67 |
68 |
69 |
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 |
290 |
291 |
Legend
292 |
293 |
294 | Module
295 | Object literal
296 | Variable
297 | Function
298 | Function with type parameter
299 | Index signature
300 | Type alias
301 |
302 |
303 | Enumeration
304 | Enumeration member
305 | Property
306 | Method
307 |
308 |
309 | Interface
310 | Interface with type parameter
311 | Constructor
312 | Property
313 | Method
314 | Index signature
315 |
316 |
317 | Class
318 | Class with type parameter
319 | Constructor
320 | Property
321 | Method
322 | Accessor
323 | Index signature
324 |
325 |
326 | Inherited constructor
327 | Inherited property
328 | Inherited method
329 | Inherited accessor
330 |
331 |
332 | Protected property
333 | Protected method
334 | Protected accessor
335 |
336 |
337 | Private property
338 | Private method
339 | Private accessor
340 |
341 |
342 | Static property
343 | Static method
344 |
345 |
346 |
347 |
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 |
52 |
53 |
54 |
62 |
Class ExampleController
63 |
64 |
65 |
66 |
67 |
68 |
69 |
76 |
77 | Hierarchy
78 |
79 |
80 | ExampleController
81 |
82 |
83 |
84 |
85 | Index
86 |
87 |
88 |
89 | Properties
90 |
93 |
94 |
104 |
105 |
106 |
107 |
108 | Properties
109 |
110 |
111 | Static collectionName
112 | collectionName: string = "examples"
113 |
114 |
115 | Defined in controllers/example.controller.ts:16
116 |
117 |
118 |
123 |
124 |
125 |
126 | Methods
127 |
128 |
129 | Static create
130 |
131 | create( req: Request , res: Response , next: NextFunction ) : void
132 |
133 |
134 |
135 |
136 |
137 | Defined in controllers/example.controller.ts:24
138 |
139 |
140 |
145 | Parameters
146 |
147 |
148 | req: Request
149 |
152 |
153 |
154 | res: Response
155 |
158 |
159 |
160 | next: NextFunction
161 |
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 |
179 |
180 | Defined in controllers/example.controller.ts:81
181 |
182 |
183 |
188 | Parameters
189 |
190 |
191 | req: Request
192 |
195 |
196 |
197 | res: Response
198 |
201 |
202 |
203 | next: NextFunction
204 |
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 |
222 |
223 | Defined in controllers/example.controller.ts:57
224 |
225 |
226 |
231 | Parameters
232 |
233 |
234 | req: Request
235 |
238 |
239 |
240 | res: Response
241 |
244 |
245 |
246 | next: NextFunction
247 |
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 |
265 |
266 | Defined in controllers/example.controller.ts:45
267 |
268 |
269 |
274 | Parameters
275 |
276 |
277 | req: Request
278 |
281 |
282 |
283 | res: Response
284 |
287 |
288 |
289 | next: NextFunction
290 |
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 |
308 |
309 | Defined in controllers/example.controller.ts:69
310 |
311 |
312 |
317 | Parameters
318 |
319 |
320 | req: Request
321 |
324 |
325 |
326 | res: Response
327 |
330 |
331 |
332 | next: NextFunction
333 |
336 |
337 |
338 | Returns void
339 |
340 |
341 |
342 |
343 |
344 |
423 |
424 |
425 |
426 |
427 |
Legend
428 |
429 |
430 | Module
431 | Object literal
432 | Variable
433 | Function
434 | Function with type parameter
435 | Index signature
436 | Type alias
437 |
438 |
439 | Enumeration
440 | Enumeration member
441 | Property
442 | Method
443 |
444 |
445 | Interface
446 | Interface with type parameter
447 | Constructor
448 | Property
449 | Method
450 | Index signature
451 |
452 |
453 | Class
454 | Class with type parameter
455 | Constructor
456 | Property
457 | Method
458 | Accessor
459 | Index signature
460 |
461 |
462 | Inherited constructor
463 | Inherited property
464 | Inherited method
465 | Inherited accessor
466 |
467 |
468 | Protected property
469 | Protected method
470 | Protected accessor
471 |
472 |
473 | Private property
474 | Private method
475 | Private accessor
476 |
477 |
478 | Static property
479 | Static method
480 |
481 |
482 |
483 |
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 |
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 |
123 |
124 | Defined in repositories/firestore.repository.ts:5
125 |
126 |
127 | Parameters
128 |
129 |
130 | db: Firestore
131 |
132 |
133 | collectionName: string
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 | Properties
143 |
144 |
145 | collection
146 | collection: CollectionReference
147 |
148 |
149 | Defined in repositories/firestore.repository.ts:5
150 |
151 |
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 |
360 |
361 |
Legend
362 |
363 |
364 | Module
365 | Object literal
366 | Variable
367 | Function
368 | Function with type parameter
369 | Index signature
370 | Type alias
371 |
372 |
373 | Enumeration
374 | Enumeration member
375 | Property
376 | Method
377 |
378 |
379 | Interface
380 | Interface with type parameter
381 | Constructor
382 | Property
383 | Method
384 | Index signature
385 |
386 |
387 | Class
388 | Class with type parameter
389 | Constructor
390 | Property
391 | Method
392 | Accessor
393 | Index signature
394 |
395 |
396 | Inherited constructor
397 | Inherited property
398 | Inherited method
399 | Inherited accessor
400 |
401 |
402 | Protected property
403 | Protected method
404 | Protected accessor
405 |
406 |
407 | Private property
408 | Private method
409 | Private accessor
410 |
411 |
412 | Static property
413 | Static method
414 |
415 |
416 |
417 |
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 |
52 |
53 |
54 |
59 |
Typescript + Express + Firestore - API Rest
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 | Index
68 |
69 |
70 |
79 |
80 | Interfaces
81 |
87 |
88 |
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 |
114 |
115 | Defined in env.ts:7
116 |
117 |
118 |
119 |
120 |
121 | Const app
122 | app: Express = express.default()
123 |
124 |
125 | Defined in app.ts:7
126 |
127 |
128 |
129 |
130 |
131 | Const db
132 | db: Firestore = admin.firestore()
133 |
134 |
135 | Defined in db.ts:12
136 |
137 |
138 |
139 |
140 |
141 | Const key
142 | key: any = require("../keys/serviceAccountKey.json")
143 |
144 |
145 | Defined in db.ts:5
146 |
147 |
148 |
149 |
150 |
151 | Const router
152 | router: Router = Router()
153 |
154 |
155 | Defined in routes/example.routes.ts:4
156 | Defined in routes/index.ts:5
157 |
158 |
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 |
172 |
173 | Defined in middleware/error.middleware.ts:11
174 |
175 |
176 |
181 | Parameters
182 |
183 |
184 | err: Error
185 |
188 |
189 |
190 | req: Request
191 |
194 |
195 |
196 | res: Response
197 |
200 |
201 |
202 | next: NextFunction
203 |
206 |
207 |
208 | Returns void
209 |
210 |
211 |
212 |
213 |
214 |
269 |
270 |
271 |
272 |
273 |
Legend
274 |
275 |
276 | Module
277 | Object literal
278 | Variable
279 | Function
280 | Function with type parameter
281 | Index signature
282 | Type alias
283 |
284 |
285 | Enumeration
286 | Enumeration member
287 | Property
288 | Method
289 |
290 |
291 | Interface
292 | Interface with type parameter
293 | Constructor
294 | Property
295 | Method
296 | Index signature
297 |
298 |
299 | Class
300 | Class with type parameter
301 | Constructor
302 | Property
303 | Method
304 | Accessor
305 | Index signature
306 |
307 |
308 | Inherited constructor
309 | Inherited property
310 | Inherited method
311 | Inherited accessor
312 |
313 |
314 | Protected property
315 | Protected method
316 | Protected accessor
317 |
318 |
319 | Private property
320 | Private method
321 | Private accessor
322 |
323 |
324 | Static property
325 | Static method
326 |
327 |
328 |
329 |
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 |
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 |
166 |
167 |
168 |
223 |
224 |
225 |
226 |
227 |
Legend
228 |
229 |
230 | Module
231 | Object literal
232 | Variable
233 | Function
234 | Function with type parameter
235 | Index signature
236 | Type alias
237 |
238 |
239 | Enumeration
240 | Enumeration member
241 | Property
242 | Method
243 |
244 |
245 | Interface
246 | Interface with type parameter
247 | Constructor
248 | Property
249 | Method
250 | Index signature
251 |
252 |
253 | Class
254 | Class with type parameter
255 | Constructor
256 | Property
257 | Method
258 | Accessor
259 | Index signature
260 |
261 |
262 | Inherited constructor
263 | Inherited property
264 | Inherited method
265 | Inherited accessor
266 |
267 |
268 | Protected property
269 | Protected method
270 | Protected accessor
271 |
272 |
273 | Private property
274 | Private method
275 | Private accessor
276 |
277 |
278 | Static property
279 | Static method
280 |
281 |
282 |
283 |
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 |
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 |
100 |
101 | Methods
102 |
103 |
104 | create
105 |
106 | create( req: Request , res: Response , next: NextFunction ) : DocumentData | undefined
107 |
108 |
109 |
110 |
111 |
112 | Defined in controllers/interfaces/controller.interface.ts:5
113 |
114 |
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 |
143 |
144 | Defined in controllers/interfaces/controller.interface.ts:9
145 |
146 |
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 |
175 |
176 | Defined in controllers/interfaces/controller.interface.ts:7
177 |
178 |
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 |
207 |
208 | Defined in controllers/interfaces/controller.interface.ts:6
209 |
210 |
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 |
239 |
240 | Defined in controllers/interfaces/controller.interface.ts:8
241 |
242 |
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 |
343 |
344 |
Legend
345 |
346 |
347 | Module
348 | Object literal
349 | Variable
350 | Function
351 | Function with type parameter
352 | Index signature
353 | Type alias
354 |
355 |
356 | Enumeration
357 | Enumeration member
358 | Property
359 | Method
360 |
361 |
362 | Interface
363 | Interface with type parameter
364 | Constructor
365 | Property
366 | Method
367 | Index signature
368 |
369 |
370 | Class
371 | Class with type parameter
372 | Constructor
373 | Property
374 | Method
375 | Accessor
376 | Index signature
377 |
378 |
379 | Inherited constructor
380 | Inherited property
381 | Inherited method
382 | Inherited accessor
383 |
384 |
385 | Protected property
386 | Protected method
387 | Protected accessor
388 |
389 |
390 | Private property
391 | Private method
392 | Private accessor
393 |
394 |
395 | Static property
396 | Static method
397 |
398 |
399 |
400 |
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 |
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 |
106 |
107 | Defined in D:/Programacion/Repositorios/PersonalGit/typescript-express-firestore/node_modules/typescript/lib/lib.es5.d.ts:974
108 |
109 |
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 |
150 |
151 | Defined in utils/error.interface.ts:2
152 |
153 |
154 |
155 |
156 |
157 |
233 |
234 |
235 |
236 |
237 |
Legend
238 |
239 |
240 | Module
241 | Object literal
242 | Variable
243 | Function
244 | Function with type parameter
245 | Index signature
246 | Type alias
247 |
248 |
249 | Enumeration
250 | Enumeration member
251 | Property
252 | Method
253 |
254 |
255 | Interface
256 | Interface with type parameter
257 | Constructor
258 | Property
259 | Method
260 | Index signature
261 |
262 |
263 | Class
264 | Class with type parameter
265 | Constructor
266 | Property
267 | Method
268 | Accessor
269 | Index signature
270 |
271 |
272 | Inherited constructor
273 | Inherited property
274 | Inherited method
275 | Inherited accessor
276 |
277 |
278 | Protected property
279 | Protected method
280 | Protected accessor
281 |
282 |
283 | Private property
284 | Private method
285 | Private accessor
286 |
287 |
288 | Static property
289 | Static method
290 |
291 |
292 |
293 |
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 |
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 |
110 |
111 | Defined in models/interfaces/example.interface.ts:7
112 |
113 |
114 |
115 |
116 |
117 | Optional city
118 | city: undefined | string
119 |
120 |
121 | Defined in models/interfaces/example.interface.ts:10
122 |
123 |
124 |
125 |
126 |
127 | Optional country
128 | country: undefined | string
129 |
130 |
131 | Defined in models/interfaces/example.interface.ts:8
132 |
133 |
134 |
135 |
136 |
137 | Optional firstName
138 | firstName: undefined | string
139 |
140 |
141 | Defined in models/interfaces/example.interface.ts:4
142 |
143 |
144 |
145 |
146 |
147 | Optional genre
148 | genre: undefined | string
149 |
150 |
151 | Defined in models/interfaces/example.interface.ts:11
152 |
153 |
154 |
155 |
156 |
157 | Optional lastName
158 | lastName: undefined | string
159 |
160 |
161 | Defined in models/interfaces/example.interface.ts:6
162 |
163 |
164 |
165 |
166 |
167 | Optional middleName
168 | middleName: undefined | string
169 |
170 |
171 | Defined in models/interfaces/example.interface.ts:5
172 |
173 |
174 |
175 |
176 |
177 | Optional province
178 | province: undefined | string
179 |
180 |
181 | Defined in models/interfaces/example.interface.ts:9
182 |
183 |
184 |
185 |
186 |
187 |
272 |
273 |
274 |
275 |
276 |
Legend
277 |
278 |
279 | Module
280 | Object literal
281 | Variable
282 | Function
283 | Function with type parameter
284 | Index signature
285 | Type alias
286 |
287 |
288 | Enumeration
289 | Enumeration member
290 | Property
291 | Method
292 |
293 |
294 | Interface
295 | Interface with type parameter
296 | Constructor
297 | Property
298 | Method
299 | Index signature
300 |
301 |
302 | Class
303 | Class with type parameter
304 | Constructor
305 | Property
306 | Method
307 | Accessor
308 | Index signature
309 |
310 |
311 | Inherited constructor
312 | Inherited property
313 | Inherited method
314 | Inherited accessor
315 |
316 |
317 | Protected property
318 | Protected method
319 | Protected accessor
320 |
321 |
322 | Private property
323 | Private method
324 | Private accessor
325 |
326 |
327 | Static property
328 | Static method
329 |
330 |
331 |
332 |
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 |
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 |
100 |
101 | Methods
102 |
103 |
104 | create
105 |
106 | create( object: DocumentData ) : Promise < DocumentReference >
107 |
108 |
109 |
110 |
111 |
112 | Defined in repositories/interfaces/firestore.interface.ts:4
113 |
114 |
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 |
134 |
135 | Defined in repositories/interfaces/firestore.interface.ts:8
136 |
137 |
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 |
157 |
158 | Defined in repositories/interfaces/firestore.interface.ts:6
159 |
160 |
161 | Returns Promise < DocumentReference [] >
162 |
163 |
164 |
165 |
166 |
167 | readOne
168 |
169 | readOne( id: string ) : Promise < DocumentReference >
170 |
171 |
172 |
173 |
174 |
175 | Defined in repositories/interfaces/firestore.interface.ts:5
176 |
177 |
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 |
197 |
198 | Defined in repositories/interfaces/firestore.interface.ts:7
199 |
200 |
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 |
295 |
296 |
Legend
297 |
298 |
299 | Module
300 | Object literal
301 | Variable
302 | Function
303 | Function with type parameter
304 | Index signature
305 | Type alias
306 |
307 |
308 | Enumeration
309 | Enumeration member
310 | Property
311 | Method
312 |
313 |
314 | Interface
315 | Interface with type parameter
316 | Constructor
317 | Property
318 | Method
319 | Index signature
320 |
321 |
322 | Class
323 | Class with type parameter
324 | Constructor
325 | Property
326 | Method
327 | Accessor
328 | Index signature
329 |
330 |
331 | Inherited constructor
332 | Inherited property
333 | Inherited method
334 | Inherited accessor
335 |
336 |
337 | Protected property
338 | Protected method
339 | Protected accessor
340 |
341 |
342 | Private property
343 | Private method
344 | Private accessor
345 |
346 |
347 | Static property
348 | Static method
349 |
350 |
351 |
352 |
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
--------------------------------------------------------------------------------
An example schema
73 |