Skip to content

Commit 4f86ea1

Browse files
committed
feat(api): add drag effect, refactor curriculum service, seeder, add pdp routes
1 parent 1e90ac5 commit 4f86ea1

20 files changed

Lines changed: 692 additions & 272 deletions

@apps/backend/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
*.sqlite
22
node_modules
33
dist
4+
uploads

@apps/backend/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
"dependencies": {
3434
"@fastify/cookie": "catalog:",
3535
"@fastify/cors": "catalog:",
36+
"@fastify/multipart": "^9.4.0",
3637
"@fastify/passport": "catalog:",
3738
"@fastify/session": "catalog:",
3839
"@fastify/swagger": "catalog:",

@apps/backend/src/app/app.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import {
2727
SectionsModule,
2828
SectionItemsModule,
2929
} from "@libs/users-backend";
30+
import multipart from "@fastify/multipart";
3031

3132
export type FastifyInstanceType = FastifyInstance<
3233
RawServerDefault,
@@ -48,6 +49,12 @@ export class App {
4849
loggerInstance,
4950
});
5051

52+
fastifyInstance.register(multipart, {
53+
limits: {
54+
fileSize: 10 * 1024 * 1024, // 10MB
55+
},
56+
});
57+
5158
fastifyInstance.addContentTypeParser(
5259
"application/vnd.api+json",
5360
// @ts-expect-error

@apps/backend/src/seeders/curriculumInjector.seeder.ts

Lines changed: 81 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -63,34 +63,41 @@ export default function curriculumInjectorSeeder(em: EntityManager) {
6363

6464
// ── CV 1 : CV complet (toutes sections) ──────────────
6565
const cv1 = em.create(CurriculumEntity, {
66-
id: "e2e-curriculum-1",
66+
id: "e2e-c1",
6767
userId: "e2e-login-user",
6868
title: "CV Complet - Amaury Deflorenne",
6969
createdAt: new Date("2025-06-01"),
7070
updatedAt: new Date("2025-06-01"),
7171
}) as CurriculumEntityType;
7272

73-
const s1Perso = createSection(em, "e2e-s1-perso", cv1, tPerso!, "Informations personnelles", 1);
74-
const s1Profil = createSection(em, "e2e-s1-profil", cv1, tProfil!, "Profil", 2);
75-
const s1Exp = createSection(em, "e2e-s1-exp", cv1, tExperiences!, "Expériences", 3);
76-
const s1Form = createSection(em, "e2e-s1-form", cv1, tFormation!, "Formations", 4);
77-
const s1Comp = createSection(em, "e2e-s1-comp", cv1, tCompetences!, "Compétences", 5);
78-
const s1Langue = createSection(em, "e2e-s1-langue", cv1, tLangue!, "Langues", 6);
79-
const s1Centres = createSection(em, "e2e-s1-centres", cv1, tCentres!, "Centres d'intérêt", 7);
80-
const s1Refs = createSection(em, "e2e-s1-refs", cv1, tReferences!, "Références", 8);
73+
const c1Perso = createSection(
74+
em,
75+
"e2e-c1-s1-perso",
76+
cv1,
77+
tPerso!,
78+
"Informations personnelles",
79+
0,
80+
);
81+
const c1Profil = createSection(em, "e2e-c1-s2-profil", cv1, tProfil!, "Profil", 1);
82+
const c1Exp = createSection(em, "e2e-c1-s3-exp", cv1, tExperiences!, "Expériences", 2);
83+
const c1Form = createSection(em, "e2e-c1-s4-form", cv1, tFormation!, "Formations", 3);
84+
const c1Comp = createSection(em, "e2e-c1-s5-comp", cv1, tCompetences!, "Compétences", 4);
85+
const c1Langue = createSection(em, "e2e-c1-s6-langue", cv1, tLangue!, "Langues", 5);
86+
const c1Centres = createSection(em, "e2e-c1-s7-centres", cv1, tCentres!, "Centres d'intérêt", 6);
87+
const c1Refs = createSection(em, "e2e-c1-s8-refs", cv1, tReferences!, "Références", 7);
8188

82-
createItem(em, "e2e-item-1-perso", s1Perso, 1, {
89+
createItem(em, "e2e-c1-s1-perso-i1", c1Perso, 0, {
8390
firstName: "Amaury",
8491
lastName: "Deflorenne",
8592
email: "amaury@gmail.com",
8693
phone: "0601020304",
8794
address: "123 rue de la paix, 75000 Paris",
8895
});
89-
createItem(em, "e2e-item-1-profil", s1Profil, 1, {
96+
createItem(em, "e2e-c1-s2-profil-i1", c1Profil, 0, {
9097
description:
9198
"Développeur fullstack passionné avec 5 ans d'expérience en JavaScript et TypeScript. Spécialisé dans les architectures modernes et les applications web performantes.",
9299
});
93-
createItem(em, "e2e-item-1-exp-1", s1Exp, 1, {
100+
createItem(em, "e2e-c1-s3-exp-i1", c1Exp, 0, {
94101
employer: "Triptyk",
95102
position: "Développeur Fullstack",
96103
city: "Lyon",
@@ -99,7 +106,7 @@ export default function curriculumInjectorSeeder(em: EntityManager) {
99106
description:
100107
"Développement d'applications web avec Ember.js et Node.js. Mise en place d'architectures microservices.",
101108
});
102-
createItem(em, "e2e-item-1-exp-2", s1Exp, 2, {
109+
createItem(em, "e2e-c1-s3-exp-i2", c1Exp, 1, {
103110
employer: "WebAgency",
104111
position: "Développeur Frontend",
105112
city: "Paris",
@@ -108,7 +115,7 @@ export default function curriculumInjectorSeeder(em: EntityManager) {
108115
description:
109116
"Intégration et développement d'interfaces React. Optimisation des performances frontend.",
110117
});
111-
createItem(em, "e2e-item-1-exp-3", s1Exp, 3, {
118+
createItem(em, "e2e-c1-s3-exp-i3", c1Exp, 2, {
112119
employer: "StartupX",
113120
position: "Stagiaire Développeur",
114121
city: "Lyon",
@@ -117,7 +124,7 @@ export default function curriculumInjectorSeeder(em: EntityManager) {
117124
description:
118125
"Stage de fin d'études axé sur le développement d'une application mobile en React Native.",
119126
});
120-
createItem(em, "e2e-item-1-exp-4", s1Exp, 4, {
127+
createItem(em, "e2e-c1-s3-exp-i4", c1Exp, 3, {
121128
employer: "Freelance",
122129
position: "Développeur Web",
123130
city: "Lyon",
@@ -126,7 +133,7 @@ export default function curriculumInjectorSeeder(em: EntityManager) {
126133
description:
127134
"Réalisation de plusieurs projets web pour des clients locaux, principalement en JavaScript.",
128135
});
129-
createItem(em, "e2e-item-1-exp-5", s1Exp, 5, {
136+
createItem(em, "e2e-c1-s3-exp-i5", c1Exp, 4, {
130137
employer: "Université de Lyon",
131138
position: "Assistant de Recherche",
132139
city: "Lyon",
@@ -135,39 +142,38 @@ export default function curriculumInjectorSeeder(em: EntityManager) {
135142
description:
136143
"Participation à un projet de recherche sur les systèmes distribués. Publication d'un article dans une conférence internationale.",
137144
});
138-
createItem(em, "e2e-item-1-form-1", s1Form, 1, {
145+
createItem(em, "e2e-c1-s4-form-i1", c1Form, 0, {
139146
school: "Université de Lyon",
140147
degree: "Master Informatique",
141148
field: "Génie Logiciel",
142149
startDate: "2018-09-01",
143150
endDate: "2020-06-30",
144151
description: "Spécialisation en architecture logicielle et développement web.",
145152
});
146-
createItem(em, "e2e-item-1-form-2", s1Form, 2, {
153+
createItem(em, "e2e-c1-s4-form-i2", c1Form, 1, {
147154
school: "Université de Paris",
148155
degree: "Licence Informatique",
149156
field: "Informatique",
150157
startDate: "2015-09-01",
151158
endDate: "2018-06-30",
152159
description: "Formation généraliste en informatique.",
153160
});
154-
createItem(em, "e2e-item-1-form-3", s1Form, 3, {
161+
createItem(em, "e2e-c1-s4-form-i3", c1Form, 2, {
155162
school: "Lycée Jean Moulin",
156163
degree: "Baccalauréat Scientifique",
157164
field: "Sciences de l'ingénieur",
158165
startDate: "2012-09-01",
159166
endDate: "2015-06-30",
160167
description: "Mention Bien.",
161168
});
162-
createItem(em, "e2e-item-1-comp-1", s1Comp, 1, { competence: "TypeScript", level: "Expert" });
163-
createItem(em, "e2e-item-1-comp-1", s1Comp, 1, { competence: "TypeScript", level: "Expert" });
164-
createItem(em, "e2e-item-1-comp-2", s1Comp, 2, { competence: "Ember.js", level: "Avancé" });
165-
createItem(em, "e2e-item-1-comp-3", s1Comp, 3, { competence: "Node.js", level: "Avancé" });
166-
createItem(em, "e2e-item-1-langue-1", s1Langue, 1, { language: "Français", level: "Natif" });
167-
createItem(em, "e2e-item-1-langue-2", s1Langue, 2, { language: "Anglais", level: "C1" });
168-
createItem(em, "e2e-item-1-centres-1", s1Centres, 1, { name: "Open source" });
169-
createItem(em, "e2e-item-1-centres-2", s1Centres, 2, { name: "Randonnée" });
170-
createItem(em, "e2e-item-1-ref-1", s1Refs, 1, {
169+
createItem(em, "e2e-c1-s5-comp-i1", c1Comp, 0, { competence: "TypeScript", level: "Expert" });
170+
createItem(em, "e2e-c1-s5-comp-i2", c1Comp, 1, { competence: "Ember.js", level: "Avancé" });
171+
createItem(em, "e2e-c1-s5-comp-i3", c1Comp, 2, { competence: "Node.js", level: "Avancé" });
172+
createItem(em, "e2e-c1-s6-langue-i1", c1Langue, 0, { language: "Français", level: "Natif" });
173+
createItem(em, "e2e-c1-s6-langue-i2", c1Langue, 1, { language: "Anglais", level: "C1" });
174+
createItem(em, "e2e-c1-s7-centres-i1", c1Centres, 0, { name: "Open source" });
175+
createItem(em, "e2e-c1-s7-centres-i2", c1Centres, 1, { name: "Randonnée" });
176+
createItem(em, "e2e-c1-s8-ref-i1", c1Refs, 0, {
171177
name: "Jean Dupont",
172178
entreprise: "Triptyk",
173179
email: "jean.dupont@triptyk.eu",
@@ -177,79 +183,93 @@ export default function curriculumInjectorSeeder(em: EntityManager) {
177183

178184
// ── CV 2 : CV junior (moins de sections) ─────────────
179185
const cv2 = em.create(CurriculumEntity, {
180-
id: "e2e-curriculum-2",
186+
id: "e2e-c2",
181187
userId: "e2e-login-user",
182188
title: "CV Junior - Sophie Martin",
183189
createdAt: new Date("2025-09-15"),
184190
updatedAt: new Date("2025-09-15"),
185191
}) as CurriculumEntityType;
186192

187-
const s2Perso = createSection(em, "e2e-s2-perso", cv2, tPerso!, "Informations personnelles", 1);
188-
const s2Profil = createSection(em, "e2e-s2-profil", cv2, tProfil!, "Profil", 2);
189-
const s2Form = createSection(em, "e2e-s2-form", cv2, tFormation!, "Formations", 3);
190-
const s2Comp = createSection(em, "e2e-s2-comp", cv2, tCompetences!, "Compétences", 4);
191-
const s2Langue = createSection(em, "e2e-s2-langue", cv2, tLangue!, "Langues", 5);
193+
const s2Perso = createSection(
194+
em,
195+
"e2e-c2-s1-perso",
196+
cv2,
197+
tPerso!,
198+
"Informations personnelles",
199+
0,
200+
);
201+
const s2Profil = createSection(em, "e2e-c2-s2-profil", cv2, tProfil!, "Profil", 1);
202+
const s2Form = createSection(em, "e2e-c2-s3-form", cv2, tFormation!, "Formations", 2);
203+
const s2Comp = createSection(em, "e2e-c2-s4-comp", cv2, tCompetences!, "Compétences", 3);
204+
const s2Langue = createSection(em, "e2e-c2-s5-langue", cv2, tLangue!, "Langues", 4);
192205

193-
createItem(em, "e2e-item-2-perso", s2Perso, 1, {
206+
createItem(em, "e2e-c2-s1-perso-i1", s2Perso, 0, {
194207
firstName: "Sophie",
195208
lastName: "Martin",
196209
email: "sophie.martin@outlook.com",
197210
phone: "0698765432",
198211
address: "45 avenue Foch, 69000 Lyon",
199212
});
200-
createItem(em, "e2e-item-2-profil", s2Profil, 1, {
213+
createItem(em, "e2e-c2-s2-profil-i1", s2Profil, 0, {
201214
description:
202215
"Étudiante en master informatique à la recherche d'une alternance. Motivée, rigoureuse et passionnée par le développement web.",
203216
});
204-
createItem(em, "e2e-item-2-form-1", s2Form, 1, {
217+
createItem(em, "e2e-c2-s3-form-i1", s2Form, 0, {
205218
school: "INSA Lyon",
206219
degree: "Master Ingénierie Logicielle",
207220
field: "Informatique",
208221
startDate: "2023-09-01",
209222
endDate: "2025-06-30",
210223
description: "Formation en alternance, spécialisation web et cloud.",
211224
});
212-
createItem(em, "e2e-item-2-form-2", s2Form, 2, {
225+
createItem(em, "e2e-c2-s3-form-i2", s2Form, 1, {
213226
school: "IUT de Lyon",
214227
degree: "BUT Informatique",
215228
field: "Informatique",
216229
startDate: "2020-09-01",
217230
endDate: "2023-06-30",
218231
description: "Formation pratique en développement logiciel.",
219232
});
220-
createItem(em, "e2e-item-2-comp-1", s2Comp, 1, { competence: "React", level: "Intermédiaire" });
221-
createItem(em, "e2e-item-2-comp-2", s2Comp, 2, { competence: "Python", level: "Intermédiaire" });
222-
createItem(em, "e2e-item-2-langue-1", s2Langue, 1, { language: "Français", level: "Natif" });
223-
createItem(em, "e2e-item-2-langue-2", s2Langue, 2, { language: "Anglais", level: "B2" });
224-
createItem(em, "e2e-item-2-langue-3", s2Langue, 3, { language: "Espagnol", level: "B1" });
233+
createItem(em, "e2e-c2-s4-comp-i1", s2Comp, 0, { competence: "React", level: "Intermédiaire" });
234+
createItem(em, "e2e-c2-s4-comp-i2", s2Comp, 1, { competence: "Python", level: "Intermédiaire" });
235+
createItem(em, "e2e-c2-s5-langue-i1", s2Langue, 0, { language: "Français", level: "Natif" });
236+
createItem(em, "e2e-c2-s5-langue-i2", s2Langue, 1, { language: "Anglais", level: "B2" });
237+
createItem(em, "e2e-c2-s5-langue-i3", s2Langue, 2, { language: "Espagnol", level: "B1" });
225238

226239
// ── CV 3 : CV senior (expériences longues) ────────────
227240
const cv3 = em.create(CurriculumEntity, {
228-
id: "e2e-curriculum-3",
241+
id: "e2e-c3",
229242
userId: "e2e-login-user",
230243
title: "CV Senior - Marc Leblanc",
231244
createdAt: new Date("2025-11-01"),
232245
updatedAt: new Date("2025-11-01"),
233246
}) as CurriculumEntityType;
234-
const s3Perso = createSection(em, "e2e-s3-perso", cv3, tPerso!, "Informations personnelles", 1);
235-
const s3Profil = createSection(em, "e2e-s3-profil", cv3, tProfil!, "Profil", 2);
236-
const s3Exp = createSection(em, "e2e-s3-exp", cv3, tExperiences!, "Expériences", 3);
237-
const s3Form = createSection(em, "e2e-s3-form", cv3, tFormation!, "Formations", 4);
238-
const s3Comp = createSection(em, "e2e-s3-comp", cv3, tCompetences!, "Compétences", 5);
239-
const s3Refs = createSection(em, "e2e-s3-refs", cv3, tReferences!, "Références", 6);
247+
const s3Perso = createSection(
248+
em,
249+
"e2e-c3-s1-perso",
250+
cv3,
251+
tPerso!,
252+
"Informations personnelles",
253+
1,
254+
);
255+
const s3Profil = createSection(em, "e2e-c3-s2-profil", cv3, tProfil!, "Profil", 2);
256+
const s3Exp = createSection(em, "e2e-c3-s3-exp", cv3, tExperiences!, "Expériences", 3);
257+
const s3Form = createSection(em, "e2e-c3-s4-form", cv3, tFormation!, "Formations", 4);
258+
const s3Comp = createSection(em, "e2e-c3-s5-comp", cv3, tCompetences!, "Compétences", 5);
259+
const s3Refs = createSection(em, "e2e-c3-s6-refs", cv3, tReferences!, "Références", 6);
240260

241-
createItem(em, "e2e-item-3-perso", s3Perso, 1, {
261+
createItem(em, "e2e-c3-s1-perso-i1", s3Perso, 0, {
242262
firstName: "Marc",
243263
lastName: "Leblanc",
244264
email: "marc.leblanc@gmail.com",
245265
phone: "0677889900",
246266
address: "8 place Bellecour, 69002 Lyon",
247267
});
248-
createItem(em, "e2e-item-3-profil", s3Profil, 1, {
268+
createItem(em, "e2e-c3-s2-profil-i1", s3Profil, 0, {
249269
description:
250270
"Architecte logiciel avec 15 ans d'expérience. Expert en conception de systèmes distribués, microservices et cloud AWS. Passionné par les bonnes pratiques et le mentoring.",
251271
});
252-
createItem(em, "e2e-item-3-exp-1", s3Exp, 1, {
272+
createItem(em, "e2e-c3-s3-exp-i1", s3Exp, 0, {
253273
employer: "BNP Paribas",
254274
position: "Architecte Solutions",
255275
city: "Paris",
@@ -258,7 +278,7 @@ export default function curriculumInjectorSeeder(em: EntityManager) {
258278
description:
259279
"Conception et supervision de l'architecture SI pour les services de paiement en ligne. Équipe de 12 développeurs.",
260280
});
261-
createItem(em, "e2e-item-3-exp-2", s3Exp, 2, {
281+
createItem(em, "e2e-c3-s3-exp-i2", s3Exp, 1, {
262282
employer: "Capgemini",
263283
position: "Tech Lead Java",
264284
city: "Lyon",
@@ -267,33 +287,33 @@ export default function curriculumInjectorSeeder(em: EntityManager) {
267287
description:
268288
"Lead technique sur des projets grands comptes. Mise en place CI/CD et pratiques DevOps.",
269289
});
270-
createItem(em, "e2e-item-3-exp-3", s3Exp, 3, {
290+
createItem(em, "e2e-c3-s3-exp-i3", s3Exp, 2, {
271291
employer: "Sopra Steria",
272292
position: "Développeur Backend",
273293
city: "Lyon",
274294
startDate: "2010-09-01",
275295
endDate: "2014-03-31",
276296
description: "Développement d'applications Java EE pour le secteur bancaire.",
277297
});
278-
createItem(em, "e2e-item-3-form-1", s3Form, 1, {
298+
createItem(em, "e2e-c3-s4-form-i1", s3Form, 0, {
279299
school: "École Centrale Paris",
280300
degree: "Diplôme d'ingénieur",
281301
field: "Informatique & Systèmes",
282302
startDate: "2007-09-01",
283303
endDate: "2010-06-30",
284304
description: "Grande école d'ingénieurs, majeure systèmes d'information.",
285305
});
286-
createItem(em, "e2e-item-3-comp-1", s3Comp, 1, { competence: "Java / Spring", level: "Expert" });
287-
createItem(em, "e2e-item-3-comp-2", s3Comp, 2, { competence: "AWS", level: "Expert" });
288-
createItem(em, "e2e-item-3-comp-3", s3Comp, 3, { competence: "Kubernetes", level: "Avancé" });
289-
createItem(em, "e2e-item-3-ref-1", s3Refs, 1, {
306+
createItem(em, "e2e-c3-s5-comp-i1", s3Comp, 0, { competence: "Java / Spring", level: "Expert" });
307+
createItem(em, "e2e-c3-s5-comp-i2", s3Comp, 1, { competence: "AWS", level: "Expert" });
308+
createItem(em, "e2e-c3-s5-comp-i3", s3Comp, 2, { competence: "Kubernetes", level: "Avancé" });
309+
createItem(em, "e2e-c3-s6-refs-i1", s3Refs, 0, {
290310
name: "Claire Morin",
291311
entreprise: "BNP Paribas",
292312
email: "c.morin@bnp.fr",
293313
phone: "0145678901",
294314
city: "Paris",
295315
});
296-
createItem(em, "e2e-item-3-ref-2", s3Refs, 2, {
316+
createItem(em, "e2e-c3-s6-refs-i2", s3Refs, 1, {
297317
name: "Thomas Renard",
298318
entreprise: "Capgemini",
299319
email: "t.renard@capgemini.com",

@apps/backend/src/seeders/models/personal-informations.schema.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"title": "Informations personnelles",
33
"properties": [
4+
{ "key": "profilePicture", "label": "Photo de profil", "type": "file" },
45
{ "key": "firstName", "label": "Prénom", "type": "text" },
56
{ "key": "lastName", "label": "Nom", "type": "text" },
67
{ "key": "email", "label": "Email", "type": "email" },

@libs/users-backend/.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
*.sqlite
22
node_modules
3-
dist
3+
dist
4+
uploads

@libs/users-backend/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
"dependencies": {
3232
"@fastify/cookie": "catalog:",
3333
"@fastify/cors": "catalog:",
34+
"@fastify/multipart": "^9.4.0",
3435
"@fastify/passport": "catalog:",
3536
"@fastify/session": "catalog:",
3637
"@fastify/swagger": "catalog:",

@libs/users-backend/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ export * from "#src/routes/section-items/create.route.js";
5454
export * from "#src/routes/section-items/update.route.js";
5555
export * from "#src/routes/section-items/delete.route.js";
5656
export * from "#src/routes/section-items/update.reorder.route.js";
57+
export * from "#src/routes/section-items/upload.pdp.route.js";
58+
export * from "#src/routes/section-items/get.pdp.route.js";
5759

5860
export const entities = [
5961
UserEntity,

@libs/users-backend/src/init.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ import { CreateSectionItemRoute } from "./routes/section-items/create.route.ts";
4949
import { UpdateSectionItemRoute } from "./routes/section-items/update.route.ts";
5050
import { DeleteSectionItemRoute } from "./routes/section-items/delete.route.ts";
5151
import { ReorderSectionItemsRoute } from "./routes/section-items/update.reorder.route.ts";
52+
import { UploadPdpRoute } from "./routes/section-items/upload.pdp.route.ts";
53+
import { GetPdpRoute } from "./routes/section-items/get.pdp.route.ts";
5254

5355
import { ListSectionTemplatesRoute } from "./routes/section-templates/list.route.ts";
5456

@@ -280,6 +282,8 @@ export class SectionItemsModule implements ModuleInterface<FastifyInstanceTypeFo
280282
new UpdateSectionItemRoute(repository),
281283
new DeleteSectionItemRoute(repository),
282284
new ReorderSectionItemsRoute(repository, this.context.em.getRepository(SectionsEntity)),
285+
new UploadPdpRoute(repository),
286+
new GetPdpRoute(repository),
283287
];
284288

285289
f.setErrorHandler((error, request, reply) => {

0 commit comments

Comments
 (0)