5htp-core 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/changelog.md +5 -0
- package/doc/TODO.md +71 -0
- package/package.json +5 -4
- package/src/client/{App.tsx → app/component.tsx} +15 -8
- package/src/client/app/index.ts +128 -0
- package/src/client/app/service.ts +34 -0
- package/src/client/app.tsconfig.json +0 -4
- package/src/client/assets/css/medias.less +14 -0
- package/src/client/components/Card/index.tsx +2 -2
- package/src/client/components/Dialog/Manager.tsx +39 -12
- package/src/client/components/Form/index.tsx +1 -1
- package/src/client/components/button.tsx +2 -2
- package/src/client/components/containers/Popover/index.tsx +1 -1
- package/src/client/components/data/spintext/index.tsx +1 -1
- package/src/client/components/dropdown/index.tsx +1 -1
- package/src/client/components/index.ts +8 -0
- package/src/client/components/input/BaseV2/index.tsx +1 -1
- package/src/client/components/input/UploadImage/index.tsx +1 -1
- package/src/client/hooks/index.ts +5 -0
- package/src/client/hooks/useState/index.tsx +2 -2
- package/src/client/hooks.ts +22 -0
- package/src/client/index.ts +5 -0
- package/src/client/pages/_layout/landing/index.tsx +0 -2
- package/src/client/pages/_messages/400.tsx +2 -2
- package/src/client/pages/_messages/401.tsx +2 -2
- package/src/client/pages/_messages/403.tsx +2 -2
- package/src/client/pages/_messages/404.tsx +2 -2
- package/src/client/pages/_messages/500.tsx +2 -2
- package/src/client/pages/bug.tsx +1 -1
- package/src/client/pages/useHeader.tsx +1 -1
- package/src/client/{context/captcha.ts → services/captcha/index.ts} +0 -0
- package/src/client/services/metrics/index.ts +37 -0
- package/src/client/{router → services/router/components}/Link.tsx +1 -1
- package/src/client/services/router/components/Page.tsx +59 -0
- package/src/client/{router/component.tsx → services/router/components/router.tsx} +43 -74
- package/src/client/services/router/index.tsx +448 -0
- package/src/client/services/router/request/api.ts +229 -0
- package/src/client/{router → services/router}/request/history.ts +0 -0
- package/src/client/services/router/request/index.ts +52 -0
- package/src/client/services/router/response/index.tsx +107 -0
- package/src/client/services/router/response/page.ts +95 -0
- package/src/client/{context/socket.ts → services/socket/index.ts} +2 -2
- package/src/client/utils/dom.ts +1 -1
- package/src/common/app/index.ts +9 -0
- package/src/common/data/chaines/index.ts +9 -6
- package/src/common/data/input/validate.ts +3 -166
- package/src/common/data/objets.ts +25 -0
- package/src/common/data/tableaux.ts +8 -0
- package/src/common/errors/index.ts +3 -1
- package/src/common/router/index.ts +67 -88
- package/src/common/router/layouts.ts +50 -0
- package/src/common/router/register.ts +62 -0
- package/src/common/router/request/api.ts +72 -0
- package/src/common/router/request/index.ts +31 -0
- package/src/common/router/{response.ts → response/index.ts} +9 -13
- package/src/common/router/response/page.ts +40 -56
- package/src/common/validation/index.ts +3 -0
- package/src/common/validation/schema.ts +184 -0
- package/src/common/validation/validator.ts +88 -0
- package/src/common/validation/validators.ts +313 -0
- package/src/server/app/config.ts +9 -27
- package/src/server/app/index.ts +81 -124
- package/src/server/app/service.ts +98 -0
- package/src/server/app.tsconfig.json +0 -8
- package/src/server/error/index.ts +13 -0
- package/src/server/index.ts +5 -0
- package/src/server/patch.ts +0 -6
- package/src/server/{data/Cache.ts → services/cache/index.ts} +79 -47
- package/src/server/services/console/bugReporter.ts +26 -16
- package/src/server/services/console/index.ts +59 -51
- package/src/server/services/cron/index.ts +12 -26
- package/src/server/services/database/bucket.ts +40 -0
- package/src/server/services/database/connection.ts +206 -75
- package/src/server/services/database/datatypes.ts +63 -40
- package/src/server/services/database/index.ts +295 -272
- package/src/server/services/database/metas.ts +246 -135
- package/src/server/services/database/stats.ts +151 -126
- package/src/server/services/email/index.ts +28 -52
- package/src/server/services/{router/request/services → metrics}/detect.ts +8 -10
- package/src/server/services/{router/request/services/tracking.ts → metrics/index.ts} +68 -45
- package/src/server/services/{http → router/http}/index.ts +28 -70
- package/src/server/services/{http → router/http}/multipart.ts +0 -0
- package/src/server/services/{http → router/http}/session.ts.old +0 -0
- package/src/server/services/router/index.ts +273 -203
- package/src/server/services/router/request/api.ts +73 -0
- package/src/server/services/router/request/index.ts +16 -97
- package/src/server/services/router/request/service.ts +21 -0
- package/src/server/services/router/response/index.ts +125 -64
- package/src/server/services/router/response/{filter → mask}/Filter.ts +0 -0
- package/src/server/services/router/response/{filter → mask}/index.ts +0 -2
- package/src/server/services/router/response/{filter → mask}/selecteurs.ts +0 -0
- package/src/server/services/router/response/page/document.tsx +194 -0
- package/src/server/services/router/response/page/index.tsx +157 -0
- package/src/server/{libs/pages → services/router/response/page}/schemaGenerator.ts +0 -0
- package/src/server/services/router/service.ts +48 -0
- package/src/server/services/schema/index.ts +47 -0
- package/src/server/services/schema/request.ts +55 -0
- package/src/server/services/schema/router.ts +33 -0
- package/src/server/services/socket/index.ts +38 -43
- package/src/server/services/socket/scope.ts +6 -4
- package/src/server/services/users/index.ts +203 -0
- package/src/server/services/{auth/base.ts → users/old.ts} +28 -112
- package/src/server/services/users/router/index.ts +72 -0
- package/src/server/services/users/router/request.ts +49 -0
- package/src/types/aliases.d.ts +43 -2
- package/templates/composant.tsx +1 -1
- package/templates/modal.tsx +1 -1
- package/templates/page.tsx +1 -1
- package/tsconfig.common.json +0 -4
- package/src/client/context/api.ts +0 -92
- package/src/client/context/index.ts +0 -246
- package/src/client/index.tsx +0 -129
- package/src/client/router/index.ts +0 -286
- package/src/client/router/request/index.ts +0 -106
- package/src/client/router/response/index.ts +0 -38
- package/src/client/router/route.ts +0 -75
- package/src/common/data/input/validators/basic.ts +0 -299
- package/src/common/data/input/validators/build.ts +0 -63
- package/src/common/router/request.ts +0 -83
- package/src/server/data/ApiClient.ts +0 -119
- package/src/server/data/input.ts +0 -41
- package/src/server/libs/pages/document.static.tsx +0 -41
- package/src/server/libs/pages/document.tsx +0 -203
- package/src/server/libs/pages/render.tsx +0 -90
- package/src/server/routes/auth.ts +0 -151
- package/src/server/services/redis/index.ts +0 -71
- package/src/server/services/router/request/services/auth.ts +0 -177
|
@@ -1,299 +0,0 @@
|
|
|
1
|
-
/*----------------------------------
|
|
2
|
-
- DEPENDANCES
|
|
3
|
-
----------------------------------*/
|
|
4
|
-
|
|
5
|
-
// Npm
|
|
6
|
-
import {
|
|
7
|
-
trim,
|
|
8
|
-
isISO8601, toDate,
|
|
9
|
-
isEmail, normalizeEmail,
|
|
10
|
-
isURL
|
|
11
|
-
} from 'validator';
|
|
12
|
-
|
|
13
|
-
// Libs
|
|
14
|
-
import { InputError } from '@common/errors';
|
|
15
|
-
import File from '@common/data/file';
|
|
16
|
-
|
|
17
|
-
// Libs métier
|
|
18
|
-
import { champ } from './build';
|
|
19
|
-
import { TSchemaChamp } from '../validate';
|
|
20
|
-
import NormalizedFile from '@common/data/file';
|
|
21
|
-
|
|
22
|
-
// Components
|
|
23
|
-
import NumberInput from '@client/components/input/Number';
|
|
24
|
-
import Dropdown from '@client/components/dropdown.old';
|
|
25
|
-
|
|
26
|
-
/*----------------------------------
|
|
27
|
-
- CONTENEURS
|
|
28
|
-
----------------------------------*/
|
|
29
|
-
export const object = (opts: TSchemaChamp<object> & {} = {}) => champ<object>('object', {
|
|
30
|
-
...opts,
|
|
31
|
-
valider: async (val: any, donneesSaisie: TObjetDonnees, donneesRetour: TObjetDonnees) => {
|
|
32
|
-
|
|
33
|
-
// TODO: executer seulement coté serveur
|
|
34
|
-
/*if (typeof val === 'string' && val.startsWith('{'))
|
|
35
|
-
try {
|
|
36
|
-
val = JSON.parse(val);
|
|
37
|
-
} catch (error) {
|
|
38
|
-
console.error('Unable to convert the given string into an object.');
|
|
39
|
-
}*/
|
|
40
|
-
|
|
41
|
-
if (typeof val !== 'object' || val.constructor !== Object)
|
|
42
|
-
throw new InputError("This value must be an object.");
|
|
43
|
-
|
|
44
|
-
return opts.valider ? await opts.valider(val, donneesSaisie, donneesRetour) : val;
|
|
45
|
-
},
|
|
46
|
-
})
|
|
47
|
-
|
|
48
|
-
export const array = (subtype?: Schema<any> | TSchemaChamp<any[]>, { choix, ...opts }: TSchemaChamp<any[]> & {} = {}) => {
|
|
49
|
-
|
|
50
|
-
if (subtype !== undefined)
|
|
51
|
-
subtype.choix = choix;
|
|
52
|
-
|
|
53
|
-
return champ<any[]>('array', {
|
|
54
|
-
...opts,
|
|
55
|
-
choix,
|
|
56
|
-
multiple: true, // Sélection multiple
|
|
57
|
-
subtype,
|
|
58
|
-
valider: async (items: any, donneesSaisie: TObjetDonnees, donneesRetour: TObjetDonnees) => {
|
|
59
|
-
|
|
60
|
-
//console.log('VALIDER ARRAY', items, donneesSaisie);
|
|
61
|
-
|
|
62
|
-
if (!Array.isArray(items))
|
|
63
|
-
throw new InputError("This value must be an array.");
|
|
64
|
-
|
|
65
|
-
// Verif items
|
|
66
|
-
if (subtype !== undefined) {
|
|
67
|
-
if (subtype instanceof Schema) {
|
|
68
|
-
|
|
69
|
-
console.log('TODO: VALIDER VIA SOUS SCHEMA');
|
|
70
|
-
|
|
71
|
-
} else {
|
|
72
|
-
|
|
73
|
-
for (let i = 0; i < items.length; i++)
|
|
74
|
-
items[i] = await subtype.valider(items[i], items);
|
|
75
|
-
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
return opts.valider ? await opts.valider(items, donneesSaisie, donneesRetour) : items;
|
|
80
|
-
},
|
|
81
|
-
})
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export const choice = (values: any[], opts: TSchemaChamp<any> & {} = {}) => champ<any>('object', {
|
|
85
|
-
...opts,
|
|
86
|
-
valider: async (val: any, donneesSaisie: TObjetDonnees, donneesRetour: TObjetDonnees) => {
|
|
87
|
-
|
|
88
|
-
if (!values.includes(val))
|
|
89
|
-
throw new InputError("Invalid value. Must be: " + values.join(', '));
|
|
90
|
-
|
|
91
|
-
return opts.valider ? await opts.valider(val, donneesSaisie, donneesRetour) : val;
|
|
92
|
-
},
|
|
93
|
-
})
|
|
94
|
-
|
|
95
|
-
/*----------------------------------
|
|
96
|
-
- CHAINES
|
|
97
|
-
----------------------------------*/
|
|
98
|
-
export const string = ({ min, max, ...opts }: TSchemaChamp<string> = {}) => champ<string>('string', {
|
|
99
|
-
...opts,
|
|
100
|
-
valider: async (val: any, donneesSaisie: TObjetDonnees, donneesRetour: TObjetDonnees, corriger?: boolean) => {
|
|
101
|
-
|
|
102
|
-
if (val === '')
|
|
103
|
-
val = undefined;
|
|
104
|
-
else if (typeof val === 'number')
|
|
105
|
-
return val.toString();
|
|
106
|
-
else if (typeof val !== 'string')
|
|
107
|
-
throw new InputError("This value must be a string.");
|
|
108
|
-
|
|
109
|
-
// Espaces blancs
|
|
110
|
-
val = trim(val);
|
|
111
|
-
|
|
112
|
-
// Taille min
|
|
113
|
-
if (val.length < min)
|
|
114
|
-
throw new InputError(`Must be at least ` + min + ' characters');
|
|
115
|
-
|
|
116
|
-
// Taille max
|
|
117
|
-
if (val.length > max)
|
|
118
|
-
if (corriger)
|
|
119
|
-
val = val.substring(0, max);
|
|
120
|
-
else
|
|
121
|
-
throw new InputError(`Must be up to ` + max + ' characters');
|
|
122
|
-
|
|
123
|
-
return opts.valider ? await opts.valider(val, donneesSaisie, donneesRetour) : val;
|
|
124
|
-
},
|
|
125
|
-
})
|
|
126
|
-
|
|
127
|
-
export const url = (opts: TSchemaChamp<string> & {} = {}) => string({
|
|
128
|
-
...opts,
|
|
129
|
-
valider: async (val: string, donneesSaisie: TObjetDonnees, donneesRetour: TObjetDonnees, corriger?: boolean) => {
|
|
130
|
-
|
|
131
|
-
if (!isURL(val, {
|
|
132
|
-
// https://www.npmjs.com/package/validator
|
|
133
|
-
}))
|
|
134
|
-
throw new InputError(`Please provide a valid URL.`);
|
|
135
|
-
|
|
136
|
-
return opts.valider ? await opts.valider(val, donneesSaisie, donneesRetour, corriger) : val;
|
|
137
|
-
},
|
|
138
|
-
})
|
|
139
|
-
|
|
140
|
-
export const email = (opts: TSchemaChamp<string> & {} = {}) => string({
|
|
141
|
-
...opts,
|
|
142
|
-
valider: async (val: any, donneesSaisie: TObjetDonnees, donneesRetour: TObjetDonnees, corriger?: boolean) => {
|
|
143
|
-
|
|
144
|
-
if (!isEmail(val))
|
|
145
|
-
throw new InputError("Please enter a valid email address.");
|
|
146
|
-
|
|
147
|
-
const retour = normalizeEmail(val);
|
|
148
|
-
|
|
149
|
-
return opts.valider ? await opts.valider(retour, donneesSaisie, donneesRetour, corriger) : retour;
|
|
150
|
-
|
|
151
|
-
},
|
|
152
|
-
})
|
|
153
|
-
|
|
154
|
-
/*----------------------------------
|
|
155
|
-
- NOMBRES
|
|
156
|
-
----------------------------------*/
|
|
157
|
-
// On ne spread pas min et max afin quils soient passés dans les props du composant
|
|
158
|
-
const nombre = (float: boolean) => ({ ...opts }: TSchemaChamp<number> & {} = {}) => champ<number>('nombre', {
|
|
159
|
-
// Force une valeur par défaut si requis
|
|
160
|
-
defaut: opts.opt ? undefined : (opts.min || 0),
|
|
161
|
-
rendu: NumberInput,
|
|
162
|
-
...opts,
|
|
163
|
-
valider: async (val: any, donneesSaisie: TObjetDonnees, donneesRetour: TObjetDonnees, corriger?: boolean) => {
|
|
164
|
-
|
|
165
|
-
// Vérifications suivantes inutiles si des valeurs spécifiques ont été fournies
|
|
166
|
-
if (opts.in === undefined) {
|
|
167
|
-
|
|
168
|
-
// Tente conversion chaine en nombre
|
|
169
|
-
if (typeof val === 'string')
|
|
170
|
-
val = float ? parseFloat(val) : parseInt(val);
|
|
171
|
-
|
|
172
|
-
if (opts.min === undefined)
|
|
173
|
-
opts.min = 0;
|
|
174
|
-
|
|
175
|
-
// Type de donnée
|
|
176
|
-
if (Number.isNaN(val) || typeof val !== 'number') {
|
|
177
|
-
if (corriger)
|
|
178
|
-
val = opts.min;
|
|
179
|
-
else
|
|
180
|
-
throw new InputError("This value must be a number.");
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
// Minimum
|
|
184
|
-
if (val < opts.min)
|
|
185
|
-
if (corriger)
|
|
186
|
-
val = opts.min;
|
|
187
|
-
else
|
|
188
|
-
throw new InputError(`Must be at least ` + opts.min);
|
|
189
|
-
|
|
190
|
-
// Maximum
|
|
191
|
-
if (opts.max !== undefined && val > opts.max)
|
|
192
|
-
if (corriger)
|
|
193
|
-
val = opts.max;
|
|
194
|
-
else
|
|
195
|
-
throw new InputError(`Must be up to ` + opts.max);
|
|
196
|
-
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
return opts.valider ? await opts.valider(val, donneesSaisie, donneesRetour, corriger) : val;
|
|
200
|
-
},
|
|
201
|
-
})
|
|
202
|
-
|
|
203
|
-
export const int = nombre(false);
|
|
204
|
-
|
|
205
|
-
export const float = nombre(true);
|
|
206
|
-
|
|
207
|
-
export const bool = (opts: TSchemaChamp<boolean> & {} = {}) => champ<boolean>('bool', {
|
|
208
|
-
defaut: false,
|
|
209
|
-
...opts,
|
|
210
|
-
valider: async (val: any, donneesSaisie: TObjetDonnees, donneesRetour: TObjetDonnees) => {
|
|
211
|
-
|
|
212
|
-
if (typeof val !== 'boolean' && !['true', 'false'].includes(val))
|
|
213
|
-
throw new InputError("This value must be a boolean.");
|
|
214
|
-
|
|
215
|
-
val = !!val;
|
|
216
|
-
|
|
217
|
-
return opts.valider ? await opts.valider(val, donneesSaisie, donneesRetour) : val;
|
|
218
|
-
|
|
219
|
-
},
|
|
220
|
-
})
|
|
221
|
-
|
|
222
|
-
/*----------------------------------
|
|
223
|
-
- AUTRES
|
|
224
|
-
----------------------------------*/
|
|
225
|
-
export const date = (opts: TSchemaChamp<Date> & {} = {}) => champ<Date>('date', {
|
|
226
|
-
//defaut: new Date,
|
|
227
|
-
...opts,
|
|
228
|
-
valider: async (val: any, donneesSaisie: TObjetDonnees, donneesRetour: TObjetDonnees): Promise<Date> => {
|
|
229
|
-
|
|
230
|
-
const chaine = typeof val == 'string';
|
|
231
|
-
|
|
232
|
-
// Chaine = format iso
|
|
233
|
-
if (chaine) {
|
|
234
|
-
|
|
235
|
-
if (!isISO8601(val))
|
|
236
|
-
throw new InputError("This value must be a date.");
|
|
237
|
-
|
|
238
|
-
val = toDate(val);
|
|
239
|
-
|
|
240
|
-
} else if (!(val instanceof Date))
|
|
241
|
-
throw new InputError("This value must be a date.");
|
|
242
|
-
|
|
243
|
-
return opts.valider ? await opts.valider(val, donneesSaisie, donneesRetour) : val;
|
|
244
|
-
|
|
245
|
-
},
|
|
246
|
-
})
|
|
247
|
-
|
|
248
|
-
/*----------------------------------
|
|
249
|
-
- FICHIER
|
|
250
|
-
----------------------------------*/
|
|
251
|
-
export type TOptsValidateurFichier = TSchemaChamp<object> & {
|
|
252
|
-
type?: (keyof typeof raccourcisMime) | string[], // Raccourci, ou liste de mimetype
|
|
253
|
-
taille?: number
|
|
254
|
-
}
|
|
255
|
-
const raccourcisMime = {
|
|
256
|
-
image: ['image/jpeg', 'image/png']
|
|
257
|
-
}
|
|
258
|
-
export const validateurFichier = async (
|
|
259
|
-
{ type, taille, ...opts }: TOptsValidateurFichier = {},
|
|
260
|
-
val: any,
|
|
261
|
-
donneesSaisie: TObjetDonnees,
|
|
262
|
-
donneesRetour: TObjetDonnees
|
|
263
|
-
): Promise<File | undefined> => {
|
|
264
|
-
|
|
265
|
-
console.log('VALIDER FICHIER', type, val);
|
|
266
|
-
|
|
267
|
-
if (!(val instanceof NormalizedFile))
|
|
268
|
-
throw new InputError(`Must be a File (${typeof val} received)`);
|
|
269
|
-
|
|
270
|
-
// MIME
|
|
271
|
-
if (type !== undefined) {
|
|
272
|
-
|
|
273
|
-
let mimetypes: string[];
|
|
274
|
-
|
|
275
|
-
// Raccourcis
|
|
276
|
-
if (typeof type === 'string') {
|
|
277
|
-
if (type in raccourcisMime)
|
|
278
|
-
mimetypes = raccourcisMime[type as keyof typeof raccourcisMime]
|
|
279
|
-
else
|
|
280
|
-
throw new Error(`Aucune liste de mimetype référencée pour le type de fichier « ${type} »`);
|
|
281
|
-
} else
|
|
282
|
-
mimetypes = type;
|
|
283
|
-
|
|
284
|
-
// Vérification
|
|
285
|
-
const mimeFichier = val.type;
|
|
286
|
-
if (!mimetypes.includes(mimeFichier))
|
|
287
|
-
throw new InputError('Only the following formats are allowed: ' + mimetypes.join(', ') + '. The file you gave is ' + mimeFichier + '.');
|
|
288
|
-
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
// Taille
|
|
292
|
-
if (taille) {
|
|
293
|
-
const tailleFichier = val.size / 1024 / 1024; // Mo
|
|
294
|
-
if (tailleFichier > taille)
|
|
295
|
-
throw new InputError(`Le fichier ne doit pas faire plus de ${taille} Mo (taille reçue: ${tailleFichier} Mo)`);
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
return opts.valider ? await opts.valider(val, donneesSaisie, donneesRetour) : val;
|
|
299
|
-
}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
/*----------------------------------
|
|
2
|
-
- DEPENDANCES
|
|
3
|
-
----------------------------------*/
|
|
4
|
-
|
|
5
|
-
// Libs
|
|
6
|
-
import { InputError } from '@common/errors';
|
|
7
|
-
import * as basicValidators from './basic';
|
|
8
|
-
|
|
9
|
-
// Components
|
|
10
|
-
import Input from '@client/components/input';
|
|
11
|
-
|
|
12
|
-
/*----------------------------------
|
|
13
|
-
- TYPES
|
|
14
|
-
----------------------------------*/
|
|
15
|
-
|
|
16
|
-
import { TSchemaChampComplet, TSchema } from '../validate';
|
|
17
|
-
|
|
18
|
-
export const EXCLURE_VALEUR = "action:exclure";
|
|
19
|
-
|
|
20
|
-
/*----------------------------------
|
|
21
|
-
- VALIDATION DE BASE
|
|
22
|
-
----------------------------------*/
|
|
23
|
-
// Remplace un simple !val, qui compterait un zéro comme une valeur vide
|
|
24
|
-
export const valeurVide = (val: any) => val === undefined || val === '' || val === null;
|
|
25
|
-
|
|
26
|
-
export const champ = <TValeur>(
|
|
27
|
-
type: string,
|
|
28
|
-
opts: Omit<TSchemaChampComplet<TValeur>, 'type'>
|
|
29
|
-
): TSchemaChampComplet<TValeur> => {
|
|
30
|
-
return {
|
|
31
|
-
...opts,
|
|
32
|
-
type: type,
|
|
33
|
-
rendu: Input,
|
|
34
|
-
valider: async (val: any, donneesSaisie: TObjetDonnees, donneesRetour: TObjetDonnees, valider?: boolean) => {
|
|
35
|
-
|
|
36
|
-
if (valeurVide(val)) {
|
|
37
|
-
// Optionnel, on skip
|
|
38
|
-
if (opts.opt === true)
|
|
39
|
-
return undefined;
|
|
40
|
-
// Requis
|
|
41
|
-
else
|
|
42
|
-
throw new InputError("Please enter a value");
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
if (opts.valider !== undefined)
|
|
46
|
-
val = await opts.valider(val, donneesSaisie, donneesRetour, valider);
|
|
47
|
-
|
|
48
|
-
// La valeur ayant passé les étapes de validation
|
|
49
|
-
// On considère que son type correspond aintenant à celui attendu
|
|
50
|
-
return val as TValeur | undefined;
|
|
51
|
-
},
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export default (validators) => ({
|
|
56
|
-
|
|
57
|
-
...basicValidators,
|
|
58
|
-
|
|
59
|
-
...validators,
|
|
60
|
-
|
|
61
|
-
new: <TSchemaA extends TSchema>(schema: TSchemaA): TSchemaA => schema,
|
|
62
|
-
|
|
63
|
-
})
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
/*----------------------------------
|
|
2
|
-
- DEPENDANCES
|
|
3
|
-
----------------------------------*/
|
|
4
|
-
|
|
5
|
-
// Core
|
|
6
|
-
import Response, { TResponseData } from './response';
|
|
7
|
-
import PageResponse from './response/page';
|
|
8
|
-
import { TRoute } from '.';
|
|
9
|
-
import type { HttpMethod } from "@server/services/router";
|
|
10
|
-
|
|
11
|
-
/*----------------------------------
|
|
12
|
-
- TYPES
|
|
13
|
-
----------------------------------*/
|
|
14
|
-
|
|
15
|
-
// Modeles
|
|
16
|
-
import type { User } from '@models';
|
|
17
|
-
|
|
18
|
-
export type TFetcherList = { [id: string]: TFetcher }
|
|
19
|
-
|
|
20
|
-
export type TFetcher<TData extends unknown = unknown> = {
|
|
21
|
-
|
|
22
|
-
// For async calls: api.post(...).then((data) => ...)
|
|
23
|
-
then: (callback: (data: TData) => void) => Promise<TData>,
|
|
24
|
-
run: () => Promise<TData>,
|
|
25
|
-
|
|
26
|
-
method: HttpMethod,
|
|
27
|
-
path: string,
|
|
28
|
-
data?: object,
|
|
29
|
-
options?: TApiFetchOptions
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export type TFetcherArgs = [
|
|
33
|
-
method: HttpMethod,
|
|
34
|
-
path: string,
|
|
35
|
-
data?: object,
|
|
36
|
-
options?: TApiFetchOptions
|
|
37
|
-
]
|
|
38
|
-
|
|
39
|
-
export type TApiFetchOptions = {
|
|
40
|
-
captcha?: string, // Action id (required by recaptcha)
|
|
41
|
-
onProgress?: (percent: number) => void
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/*----------------------------------
|
|
45
|
-
- CONTEXT
|
|
46
|
-
----------------------------------*/
|
|
47
|
-
export default abstract class BaseRequest {
|
|
48
|
-
|
|
49
|
-
// Permet d'accèder à l'instance complète via spread
|
|
50
|
-
public request: this = this;
|
|
51
|
-
public host!: string;
|
|
52
|
-
|
|
53
|
-
public data: TObjetDonnees = {};
|
|
54
|
-
public abstract response?: Response;
|
|
55
|
-
public user: User | null = null;
|
|
56
|
-
|
|
57
|
-
public constructor(
|
|
58
|
-
public path: string,
|
|
59
|
-
) {
|
|
60
|
-
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
public api = {
|
|
64
|
-
get: <TData extends unknown = unknown>(path: string, data?: TObjetDonnees, opts?: TApiFetchOptions) =>
|
|
65
|
-
this.createFetcher<TData>('GET', path, data, opts),
|
|
66
|
-
|
|
67
|
-
post: <TData extends unknown = unknown>(path: string, data?: TObjetDonnees, opts?: TApiFetchOptions) =>
|
|
68
|
-
this.createFetcher<TData>('POST', path, data, opts),
|
|
69
|
-
|
|
70
|
-
put: <TData extends unknown = unknown>(path: string, data?: TObjetDonnees, opts?: TApiFetchOptions) =>
|
|
71
|
-
this.createFetcher<TData>('PUT', path, data, opts),
|
|
72
|
-
|
|
73
|
-
delete: <TData extends unknown = unknown>(path: string, data?: TObjetDonnees, opts?: TApiFetchOptions) =>
|
|
74
|
-
this.createFetcher<TData>('DELETE', path, data, opts),
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
public abstract createFetcher<TData extends unknown = unknown>(...args: TFetcherArgs): TFetcher<TData>;
|
|
78
|
-
|
|
79
|
-
public abstract fetchSync(fetchers: TFetcherList): Promise<TObjetDonnees>;
|
|
80
|
-
|
|
81
|
-
public abstract fetchAsync(...args: TFetcherArgs): Promise<any>;
|
|
82
|
-
|
|
83
|
-
}
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
/*----------------------------------
|
|
2
|
-
- DEPENDANCES
|
|
3
|
-
----------------------------------*/
|
|
4
|
-
|
|
5
|
-
// Npm
|
|
6
|
-
import { Logger } from "tslog";
|
|
7
|
-
import axios, { AxiosResponse, AxiosRequestConfig, AxiosError } from 'axios';
|
|
8
|
-
import httpAdapter from 'axios/lib/adapters/http';
|
|
9
|
-
|
|
10
|
-
// Libs
|
|
11
|
-
import Cache from '@server/data/Cache';
|
|
12
|
-
|
|
13
|
-
/*----------------------------------
|
|
14
|
-
- TYPES
|
|
15
|
-
----------------------------------*/
|
|
16
|
-
declare module 'axios' {
|
|
17
|
-
export interface AxiosRequestConfig {
|
|
18
|
-
fallback?: string; // ID donnée cache
|
|
19
|
-
cache?: string; // ID donnée cache
|
|
20
|
-
cacheExpiration?: number | Date | null,
|
|
21
|
-
retry?: number;
|
|
22
|
-
debug?: boolean
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const debug = false;
|
|
27
|
-
|
|
28
|
-
/*----------------------------------
|
|
29
|
-
- MODULE
|
|
30
|
-
----------------------------------*/
|
|
31
|
-
// FIX: On créé une nouvelle instance d'axios ici, car si on utilise l'instance globale,
|
|
32
|
-
// Les intercepteurs seront empilés à la suite à chaque reload HMR
|
|
33
|
-
export default axios.create({
|
|
34
|
-
timeout: process.env.environnement === 'local'
|
|
35
|
-
? 10000 // Connexion pourrie à la maison
|
|
36
|
-
: 5000,
|
|
37
|
-
validateStatus: function (status: number) {
|
|
38
|
-
return status >= 200 && status < 300;
|
|
39
|
-
},
|
|
40
|
-
adapter: async (config: AxiosRequestConfig) => {
|
|
41
|
-
|
|
42
|
-
//const logger = new Logger({ prefix: [config.url] });
|
|
43
|
-
|
|
44
|
-
console.log(`Création de la requête`, { params: config.params, data: config.data });
|
|
45
|
-
|
|
46
|
-
const envoyer = (tentative: number = 1) => httpAdapter(config).then(async (res: AxiosResponse) => {
|
|
47
|
-
|
|
48
|
-
console.log(`Status:`, res.status ,`Reponse:`, typeof res.data);
|
|
49
|
-
|
|
50
|
-
// Mise en cache
|
|
51
|
-
const cacheId: string | undefined = config.fallback || config.cache;
|
|
52
|
-
if (cacheId !== undefined) {
|
|
53
|
-
console.log(`Enregistrement de la réponse dans le cache (ID: ${cacheId})`);
|
|
54
|
-
await Cache.set(cacheId, res.data, config.cacheExpiration);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return res;
|
|
58
|
-
|
|
59
|
-
}).catch(async (err: AxiosError) => {
|
|
60
|
-
|
|
61
|
-
// err peut être une simple instance d'Error
|
|
62
|
-
|
|
63
|
-
console.error("Error during API request:", {
|
|
64
|
-
method: config.method,
|
|
65
|
-
url: config.url,
|
|
66
|
-
body: config.data,
|
|
67
|
-
headers: config.headers,
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
if (err.isAxiosError && err.response) {
|
|
71
|
-
console.error("Response:", {
|
|
72
|
-
status: err.response.status + ' ' + err.response.statusText,
|
|
73
|
-
headers: err.response.headers,
|
|
74
|
-
body: err.response.data
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
throw err;
|
|
79
|
-
|
|
80
|
-
// Nouvelle tentative
|
|
81
|
-
if (
|
|
82
|
-
config.retry !== undefined && tentative < config.retry
|
|
83
|
-
&&
|
|
84
|
-
err.response !== undefined && err.response.status >= 400
|
|
85
|
-
) {
|
|
86
|
-
console.log(`Tentative n°` + (tentative + 1));
|
|
87
|
-
return await envoyer(tentative + 1);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// Fallback via cache
|
|
91
|
-
const fallback = config.fallback === undefined
|
|
92
|
-
? undefined
|
|
93
|
-
: await Cache.get(config.fallback)
|
|
94
|
-
|
|
95
|
-
// Aucun fallback = impossible de continuer
|
|
96
|
-
if (!err) {
|
|
97
|
-
console.log(`Aucun fallback disponible, on fait remonter l'erreur.`);
|
|
98
|
-
throw err;
|
|
99
|
-
} else
|
|
100
|
-
console.log(`Utilisation des données en fallback via le cache (ID: ${config.fallback})`/*, fallback*/);
|
|
101
|
-
|
|
102
|
-
return {
|
|
103
|
-
data: fallback,
|
|
104
|
-
status: 200,
|
|
105
|
-
statusText: 'OK',
|
|
106
|
-
headers: {},
|
|
107
|
-
config: config,
|
|
108
|
-
request: err.request
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
})
|
|
113
|
-
|
|
114
|
-
return config.cache === undefined
|
|
115
|
-
? await envoyer()
|
|
116
|
-
: await Cache.get(config.cache, () => envoyer(), config.cacheExpiration);
|
|
117
|
-
|
|
118
|
-
}
|
|
119
|
-
})
|
package/src/server/data/input.ts
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
/*----------------------------------
|
|
2
|
-
- DEPENDANCES
|
|
3
|
-
----------------------------------*/
|
|
4
|
-
|
|
5
|
-
// Libs métier
|
|
6
|
-
import buildValidators, { EXCLURE_VALEUR, champ } from '@common/data/input/validators/build';
|
|
7
|
-
import { validateurFichier, TOptsValidateurFichier } from '@common/data/input/validators/basic';
|
|
8
|
-
|
|
9
|
-
/*----------------------------------
|
|
10
|
-
- VALIDATEURS
|
|
11
|
-
----------------------------------*/
|
|
12
|
-
export default buildValidators({
|
|
13
|
-
|
|
14
|
-
file: ({ ...opts }: TOptsValidateurFichier & {}) => champ<object>('fichier', {
|
|
15
|
-
...opts,
|
|
16
|
-
valider: async (val: any, donneesSaisie: TObjetDonnees, donneesRetour: TObjetDonnees) => {
|
|
17
|
-
|
|
18
|
-
// Chaine = url ancien fichier = exclusion de la valeur pour conserver l'ancien fichier
|
|
19
|
-
// NOTE: Si la valeur est présente mais undefined, alors on supprimera le fichier
|
|
20
|
-
if (typeof val === 'string')
|
|
21
|
-
return EXCLURE_VALEUR;
|
|
22
|
-
|
|
23
|
-
// Validation universelle
|
|
24
|
-
const fichier = await validateurFichier(opts, val, donneesSaisie, donneesRetour);
|
|
25
|
-
|
|
26
|
-
if (fichier === undefined)
|
|
27
|
-
return fichier;
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
// Résolution image
|
|
31
|
-
if (opts.sharp !== undefined) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return opts.valider ? await opts.valider(fichier, donneesSaisie, donneesRetour) : fichier;
|
|
38
|
-
}
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
});
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
/*----------------------------------
|
|
2
|
-
- DEPENDANCES
|
|
3
|
-
----------------------------------*/
|
|
4
|
-
|
|
5
|
-
// Npm
|
|
6
|
-
import React from 'react';
|
|
7
|
-
|
|
8
|
-
// Core
|
|
9
|
-
import app, { services } from '@server/app';
|
|
10
|
-
|
|
11
|
-
/*----------------------------------
|
|
12
|
-
- COMPOSANT
|
|
13
|
-
----------------------------------*/
|
|
14
|
-
export default () => {
|
|
15
|
-
|
|
16
|
-
const routesForClient = JSON.stringify(services.router.ssrRoutes);
|
|
17
|
-
return (
|
|
18
|
-
<html lang="en">
|
|
19
|
-
<head>
|
|
20
|
-
{/* Format */}
|
|
21
|
-
<meta charSet="utf-8" />
|
|
22
|
-
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1" />
|
|
23
|
-
|
|
24
|
-
{/* CSS */}
|
|
25
|
-
<link rel="stylesheet" type="text/css" href="/public/icons.css" />
|
|
26
|
-
<link rel="preload" href="/public/client.css" as="style" />
|
|
27
|
-
<link rel="stylesheet" type="text/css" href="/public/client.css" />
|
|
28
|
-
|
|
29
|
-
{/* JS */}
|
|
30
|
-
<script type="text/javascript" dangerouslySetInnerHTML={{
|
|
31
|
-
__html: `window.routes=${routesForClient};` + (app.env.profile === 'dev' ? 'window.dev = true;' : '')
|
|
32
|
-
}} />
|
|
33
|
-
<link rel="preload" href="/public/client.js" as="script" />
|
|
34
|
-
<script defer type="text/javascript" src="/public/client.js" />
|
|
35
|
-
|
|
36
|
-
</head>
|
|
37
|
-
<body></body>
|
|
38
|
-
</html>
|
|
39
|
-
);
|
|
40
|
-
|
|
41
|
-
}
|