Skip to content

Commit 7403d6f

Browse files
đŸ„fr translations for part4: intro and some of part4a
1 parent fdb3313 commit 7403d6f

File tree

2 files changed

+351
-0
lines changed

2 files changed

+351
-0
lines changed

‎src/content/4/fr/part4.md‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
mainImage: ../../../images/part-4.svg
3+
part: 4
4+
lang: fr
5+
---
6+
7+
<div class="intro">
8+
9+
Dans cette partie, nous allons continuer notre travail sur le backend. Notre premier grand thĂšme sera l'Ă©criture de tests unitaires et d'intĂ©gration pour le backend. AprĂšs avoir couvert les tests, nous examinerons la mise en Ɠuvre de l'authentification et de l'autorisation des utilisateurs.
10+
11+
<i>Partie mise à jour le 22 janvier 2023</i>
12+
- <i>Aucun changement majeur</i>
13+
14+
</div>

‎src/content/4/fr/part4a.md‎

Lines changed: 337 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,337 @@
1+
---
2+
mainImage: ../../../images/part-4.svg
3+
part: 4
4+
letter: a
5+
lang: fr
6+
---
7+
8+
<div class="content">
9+
10+
Poursuivons notre travail sur le backend de l'application de notes que nous avons commencé dans la [partie 3](/fr/part3).
11+
12+
### Structure du projet
13+
Avant de passer au sujet des tests, nous allons modifier la structure de notre projet pour respecter les meilleures pratiques de Node.js.
14+
15+
AprÚs avoir apporté les modifications à la structure de répertoire de notre projet, nous obtenons la structure suivante :
16+
17+
```bash
18+
├── index.js
19+
├── app.js
20+
├── build
21+
│ └── ...
22+
├── controllers
23+
│ └── notes.js
24+
├── models
25+
│ └── note.js
26+
├── package-lock.json
27+
├── package.json
28+
├── utils
29+
│ ├── config.js
30+
│ ├── logger.js
31+
│ └── middleware.js
32+
```
33+
34+
Jusqu'à présent, nous avons utilisé <i>console.log</i> et <i>console.error</i> pour afficher différentes informations du code.
35+
Cependant, ce n'est pas une trÚs bonne façon de faire les choses.
36+
Séparons toute l'impression dans la console de son propre module <i>utils/logger.js</i> :
37+
38+
```js
39+
const info = (...params) => {
40+
console.log(...params)
41+
}
42+
43+
const error = (...params) => {
44+
console.error(...params)
45+
}
46+
47+
module.exports = {
48+
info, error
49+
}
50+
```
51+
Le journalisateur dispose de deux fonctions, __info__ pour afficher les messages de journalisation normaux, et __error__ pour tous les messages d'erreur.
52+
53+
Extraire la journalisation dans son propre module est une bonne idée à plus d'un titre. Si nous voulions commencer à écrire des journaux dans un fichier ou les envoyer à un service de journalisation externe comme [graylog] (https://www.graylog.org/) ou [papertrail] (https://papertrailapp.com), nous n'aurions à effectuer des modifications qu'à un seul endroit.
54+
55+
Le contenu du fichier <i>index.js</i> utilisé pour démarrer l'application est simplifié comme suit :
56+
57+
```js
58+
const app = require('./app') // l'application Express
59+
const config = require('./utils/config')
60+
const logger = require('./utils/logger')
61+
62+
app.listen(config.PORT, () => {
63+
logger.info(`Server running on port ${config.PORT}`)
64+
})
65+
```
66+
67+
Le fichier <i>index.js</i> n'importe que l'application réelle depuis le fichier <i>app.js</i>, puis démarre l'application. La fonction info du module journalisateur est utilisée pour l'affichage console indiquant que l'application est en cours d'exécution.
68+
69+
Maintenant, l'application Express et le code qui s'occupe du serveur web sont sĂ©parĂ©s l'un de l'autre selon les [meilleures](https://dev.to/nermineslimane/always-separate-app-and-server-files--1nc7) [pratiques](https://nodejsbestpractices.com/sections/projectstructre/separateexpress). L'un des avantages de cette mĂ©thode est que l'application peut dĂ©sormais ĂȘtre testĂ©e au niveau des appels API HTTP sans effectuer rĂ©ellement des appels via HTTP sur le rĂ©seau, ce qui rend l'exĂ©cution des tests plus rapide.
70+
71+
La gestion des variables d'environnement est extraite dans un fichier séparé <i>utils/config.js</i> :
72+
73+
```js
74+
require('dotenv').config()
75+
76+
const PORT = process.env.PORT
77+
const MONGODB_URI = process.env.MONGODB_URI
78+
79+
module.exports = {
80+
MONGODB_URI,
81+
PORT
82+
}
83+
84+
```
85+
86+
Les autres parties de l'application peuvent accéder aux variables d'environnement en important le module de configuration :
87+
88+
```js
89+
const config = require('./utils/config')
90+
91+
logger.info(`Serveur en cours d'exécution sur le port ${config.PORT}`)
92+
93+
```
94+
95+
Les gestionnaires de routes ont également été déplacés dans un module dédié. Les gestionnaires d'événements des routes sont couramment appelés <i>contrÎleurs</i>, et c'est pourquoi nous avons créé un nouveau répertoire <i>controllers</i>. Toutes les routes liées aux notes sont désormais dans le module <i>notes.js</i> sous le répertoire <i>controllers</i>.
96+
97+
Le contenu du module <i>notes.js</i> est le suivant :
98+
99+
```js
100+
const notesRouter = require('express').Router()
101+
const Note = require('../models/note')
102+
103+
notesRouter.get('/', (request, response) => {
104+
Note.find({}).then(notes => {
105+
response.json(notes)
106+
})
107+
})
108+
109+
notesRouter.get('/:id', (request, response, next) => {
110+
Note.findById(request.params.id)
111+
.then(note => {
112+
if (note) {
113+
response.json(note)
114+
} else {
115+
response.status(404).end()
116+
}
117+
})
118+
.catch(error => next(error))
119+
})
120+
121+
notesRouter.post('/', (request, response, next) => {
122+
const body = request.body
123+
124+
const note = new Note({
125+
content: body.content,
126+
important: body.important || false,
127+
})
128+
129+
note.save()
130+
.then(savedNote => {
131+
response.json(savedNote)
132+
})
133+
.catch(error => next(error))
134+
})
135+
136+
notesRouter.delete('/:id', (request, response, next) => {
137+
Note.findByIdAndRemove(request.params.id)
138+
.then(() => {
139+
response.status(204).end()
140+
})
141+
.catch(error => next(error))
142+
})
143+
144+
notesRouter.put('/:id', (request, response, next) => {
145+
const body = request.body
146+
147+
const note = {
148+
content: body.content,
149+
important: body.important,
150+
}
151+
152+
Note.findByIdAndUpdate(request.params.id, note, { new: true })
153+
.then(updatedNote => {
154+
response.json(updatedNote)
155+
})
156+
.catch(error => next(error))
157+
})
158+
159+
module.exports = notesRouter
160+
```
161+
162+
Ceci est presque une copie conforme de notre précédent fichier <i>index.js</i>.
163+
164+
Cependant, il y a quelques changements importants. Au tout début du fichier, nous créons un nouvel objet [router](http://expressjs.com/en/api.html#router):
165+
166+
```js
167+
const notesRouter = require('express').Router()
168+
169+
//...
170+
171+
module.exports = notesRouter
172+
173+
```
174+
175+
Le module exporte le router pour qu'il soit disponible pour tous les consommateurs du module.
176+
177+
Toutes les routes sont maintenant dĂ©finies pour l'objet router, de la mĂȘme maniĂšre que ce que nous avons fait auparavant avec l'objet reprĂ©sentant l'ensemble de l'application.
178+
179+
Il convient de noter que les chemins dans les gestionnaires de routes ont été raccourcis. Dans la version précédente, nous avions :
180+
181+
```js
182+
app.delete('/api/notes/:id', (request, response) => {
183+
184+
```
185+
186+
Et dans la version actuelle, nous avons :
187+
188+
```js
189+
notesRouter.delete('/:id', (request, response) => {
190+
191+
```
192+
Alors qu'est-ce que ces objets router exactement ? Le manuel Express fournit l'explication suivante :
193+
194+
> <i>Un objet router est une instance isolée de middleware et de routes. Vous pouvez le considérer comme une "mini-application", capable uniquement de réaliser des fonctions de middleware et de routage. Chaque application Express a un router d'application intégré.</i>
195+
196+
Le router est en fait un <i>middleware</i>, qui peut ĂȘtre utilisĂ© pour dĂ©finir des "routes associĂ©es" en un seul endroit, qui est gĂ©nĂ©ralement placĂ© dans son propre module.
197+
198+
Le fichier <i>app.js</i> qui crée l'application réelle prend le router en compte comme indiqué ci-dessous:
199+
200+
```js
201+
const notesRouter = require('./controllers/notes')
202+
app.use('/api/notes', notesRouter)
203+
```
204+
205+
Le routeur que nous avons dĂ©fini prĂ©cĂ©demment est utilisĂ© si l'URL de la requĂȘte commence par <i>/api/notes</i>. Pour cette raison, l'objet notesRouter doit seulement dĂ©finir les parties relatives des routes, c'est-Ă -dire le chemin vide <i>/</i> ou simplement le paramĂštre <i>/:id</i>.
206+
207+
AprÚs avoir effectué ces modifications, notre fichier <i>app.js</i> ressemble à ceci:
208+
209+
```js
210+
const config = require('./utils/config')
211+
const express = require('express')
212+
const app = express()
213+
const cors = require('cors')
214+
const notesRouter = require('./controllers/notes')
215+
const middleware = require('./utils/middleware')
216+
const logger = require('./utils/logger')
217+
const mongoose = require('mongoose')
218+
219+
mongoose.set('strictQuery', false)
220+
221+
logger.info('connecting to', config.MONGODB_URI)
222+
223+
mongoose.connect(config.MONGODB_URI)
224+
.then(() => {
225+
logger.info('connected to MongoDB')
226+
})
227+
.catch((error) => {
228+
logger.error('error connecting to MongoDB:', error.message)
229+
})
230+
231+
app.use(cors())
232+
app.use(express.static('build'))
233+
app.use(express.json())
234+
app.use(middleware.requestLogger)
235+
236+
app.use('/api/notes', notesRouter)
237+
238+
app.use(middleware.unknownEndpoint)
239+
app.use(middleware.errorHandler)
240+
241+
module.exports = app
242+
```
243+
244+
Le fichier utilise différents middlewares, dont l'un est le <i>notesRouter</i> qui est attaché à la route <i>/api/notes</i>.
245+
246+
Notre middleware personnalisé a été déplacé vers un nouveau module <i>utils/middleware.js</i> :
247+
248+
```js
249+
const logger = require('./logger')
250+
251+
const requestLogger = (request, response, next) => {
252+
logger.info('Method:', request.method)
253+
logger.info('Path: ', request.path)
254+
logger.info('Body: ', request.body)
255+
logger.info('---')
256+
next()
257+
}
258+
259+
const unknownEndpoint = (request, response) => {
260+
response.status(404).send({ error: 'unknown endpoint' })
261+
}
262+
263+
const errorHandler = (error, request, response, next) => {
264+
logger.error(error.message)
265+
266+
if (error.name === 'CastError') {
267+
return response.status(400).send({ error: 'malformatted id' })
268+
} else if (error.name === 'ValidationError') {
269+
return response.status(400).json({ error: error.message })
270+
}
271+
272+
next(error)
273+
}
274+
275+
module.exports = {
276+
requestLogger,
277+
unknownEndpoint,
278+
errorHandler
279+
}
280+
```
281+
282+
La responsabilité d'établir la connexion à la base de données a été confiée au module <i>app.js</i>. Le fichier <i>note.js</i> dans le répertoire <i>models</i> ne définit que le schéma Mongoose pour les notes.
283+
284+
```js
285+
const mongoose = require('mongoose')
286+
287+
const noteSchema = new mongoose.Schema({
288+
content: {
289+
type: String,
290+
required: true,
291+
minlength: 5
292+
},
293+
important: Boolean,
294+
})
295+
296+
noteSchema.set('toJSON', {
297+
transform: (document, returnedObject) => {
298+
returnedObject.id = returnedObject._id.toString()
299+
delete returnedObject._id
300+
delete returnedObject.__v
301+
}
302+
})
303+
304+
module.exports = mongoose.model('Note', noteSchema)
305+
```
306+
307+
En résumé, la structure du répertoire ressemble à ceci aprÚs les modifications apportées :
308+
309+
```bash
310+
├── index.js
311+
├── app.js
312+
├── build
313+
│ └── ...
314+
├── controllers
315+
│ └── notes.js
316+
├── models
317+
│ └── note.js
318+
├── package-lock.json
319+
├── package.json
320+
├── utils
321+
│ ├── config.js
322+
│ ├── logger.js
323+
│ └── middleware.js
324+
```
325+
326+
Pour les applications plus petites, la structure n'a pas une grande importance. Une fois que l'application commence à devenir plus grande, il faut établir une certaine structure et séparer les différentes responsabilités de l'application en modules séparés. Cela facilitera grandement le développement de l'application.
327+
328+
Il n'y a pas de structure de répertoire stricte ou de convention de nommage de fichiers requise pour les applications Express. En revanche, Ruby on Rails nécessite une structure spécifique. Notre structure actuelle suit simplement certaines des meilleures pratiques que vous pouvez trouver sur Internet.
329+
330+
Vous pouvez trouver le code de notre application actuelle dans son intégralité dans la branche <i>part4-1</i> de ce [dépÎt GitHub](https://github.com/fullstack-hy2020/part3-notes-backend/tree/part4-1).
331+
332+
Si vous clonez le projet pour vous-mĂȘme, exĂ©cutez la commande npm install avant de lancer l'application avec npm start.
333+
334+
</div>
335+
336+
### Notes Ă  l'export
337+

0 commit comments

Comments
 (0)