5htp-core 0.1.2 → 0.2.1

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.
Files changed (148) hide show
  1. package/changelog.md +5 -0
  2. package/doc/TODO.md +71 -0
  3. package/package.json +5 -4
  4. package/src/client/{App.tsx → app/component.tsx} +15 -11
  5. package/src/client/app/index.ts +128 -0
  6. package/src/client/app/service.ts +34 -0
  7. package/src/client/app.tsconfig.json +0 -4
  8. package/src/client/assets/css/components.less +52 -0
  9. package/src/client/assets/css/core.less +7 -28
  10. package/src/client/assets/css/theme.less +1 -1
  11. package/src/client/assets/css/{borders.less → utils/borders.less} +0 -0
  12. package/src/client/assets/css/{layouts.less → utils/layouts.less} +0 -0
  13. package/src/client/assets/css/{medias.less → utils/medias.less} +14 -1
  14. package/src/client/assets/css/{sizing.less → utils/sizing.less} +0 -0
  15. package/src/client/assets/css/{spacing.less → utils/spacing.less} +0 -0
  16. package/src/client/components/Card/index.tsx +13 -7
  17. package/src/client/components/Dialog/Manager.tsx +41 -14
  18. package/src/client/components/Dialog/index.less +2 -4
  19. package/src/client/components/Form/index.tsx +1 -1
  20. package/src/client/components/Row/index.less +0 -2
  21. package/src/client/components/Table/index.tsx +3 -2
  22. package/src/client/components/button.tsx +2 -2
  23. package/src/client/components/containers/Popover/index.tsx +1 -1
  24. package/src/client/components/containers/champs.less +0 -2
  25. package/src/client/components/data/spintext/index.tsx +1 -1
  26. package/src/client/components/dropdown/index.tsx +1 -1
  27. package/src/client/components/index.ts +23 -0
  28. package/src/client/components/input/BaseV2/index.less +0 -2
  29. package/src/client/components/input/BaseV2/index.tsx +1 -1
  30. package/src/client/components/input/Date/index.less +0 -2
  31. package/src/client/components/input/Periode/index.less +0 -2
  32. package/src/client/components/input/Radio/index.less +0 -2
  33. package/src/client/components/input/UploadImage/index.less +0 -2
  34. package/src/client/components/input/UploadImage/index.tsx +1 -1
  35. package/src/client/hooks/index.ts +5 -0
  36. package/src/client/hooks/useState/index.tsx +2 -2
  37. package/src/client/hooks.ts +22 -0
  38. package/src/client/index.ts +5 -0
  39. package/src/client/pages/_layout/landing/index.tsx +0 -2
  40. package/src/client/pages/_messages/400.tsx +2 -2
  41. package/src/client/pages/_messages/401.tsx +2 -2
  42. package/src/client/pages/_messages/403.tsx +2 -2
  43. package/src/client/pages/_messages/404.tsx +2 -2
  44. package/src/client/pages/_messages/500.tsx +2 -2
  45. package/src/client/pages/bug.tsx +1 -1
  46. package/src/client/pages/useHeader.tsx +1 -1
  47. package/src/client/{context/captcha.ts → services/captcha/index.ts} +0 -0
  48. package/src/client/services/metrics/index.ts +37 -0
  49. package/src/client/{router → services/router/components}/Link.tsx +1 -1
  50. package/src/client/services/router/components/Page.tsx +59 -0
  51. package/src/client/{router/component.tsx → services/router/components/router.tsx} +52 -74
  52. package/src/client/services/router/index.tsx +453 -0
  53. package/src/client/services/router/request/api.ts +227 -0
  54. package/src/client/{router → services/router}/request/history.ts +0 -0
  55. package/src/client/services/router/request/index.ts +52 -0
  56. package/src/client/services/router/response/index.tsx +107 -0
  57. package/src/client/services/router/response/page.ts +90 -0
  58. package/src/client/{context/socket.ts → services/socket/index.ts} +2 -2
  59. package/src/client/utils/dom.ts +1 -1
  60. package/src/common/app/index.ts +9 -0
  61. package/src/common/data/chaines/index.ts +9 -6
  62. package/src/common/data/input/validate.ts +3 -166
  63. package/src/common/data/objets.ts +25 -0
  64. package/src/common/data/tableaux.ts +8 -0
  65. package/src/common/errors/index.ts +3 -1
  66. package/src/common/router/index.ts +67 -88
  67. package/src/common/router/layouts.ts +50 -0
  68. package/src/common/router/register.ts +62 -0
  69. package/src/common/router/request/api.ts +72 -0
  70. package/src/common/router/request/index.ts +31 -0
  71. package/src/common/router/{response.ts → response/index.ts} +9 -13
  72. package/src/common/router/response/page.ts +46 -54
  73. package/src/common/validation/index.ts +3 -0
  74. package/src/common/validation/schema.ts +185 -0
  75. package/src/common/validation/validator.ts +95 -0
  76. package/src/common/validation/validators.ts +313 -0
  77. package/src/server/app/config.ts +9 -27
  78. package/src/server/app/index.ts +81 -124
  79. package/src/server/app/service.ts +98 -0
  80. package/src/server/app.tsconfig.json +0 -8
  81. package/src/server/index.ts +5 -0
  82. package/src/server/patch.ts +0 -6
  83. package/src/server/{data/Cache.ts → services/cache/index.ts} +79 -47
  84. package/src/server/services/console/bugReporter.ts +26 -16
  85. package/src/server/services/console/index.ts +59 -51
  86. package/src/server/services/cron/index.ts +12 -26
  87. package/src/server/services/database/bucket.ts +40 -0
  88. package/src/server/services/database/connection.ts +213 -80
  89. package/src/server/services/database/datatypes.ts +63 -40
  90. package/src/server/services/database/debug.ts +20 -0
  91. package/src/server/services/database/index.ts +295 -272
  92. package/src/server/services/database/metas.ts +246 -135
  93. package/src/server/services/database/stats.ts +151 -126
  94. package/src/server/services/email/index.ts +30 -62
  95. package/src/server/services/email/transporter.ts +38 -0
  96. package/src/server/services/{router/request/services → metrics}/detect.ts +8 -10
  97. package/src/server/services/{router/request/services/tracking.ts → metrics/index.ts} +68 -45
  98. package/src/server/services/{http → router/http}/index.ts +28 -70
  99. package/src/server/services/{http → router/http}/multipart.ts +0 -0
  100. package/src/server/services/{http → router/http}/session.ts.old +0 -0
  101. package/src/server/services/router/index.ts +273 -202
  102. package/src/server/services/router/request/api.ts +76 -0
  103. package/src/server/services/router/request/index.ts +16 -97
  104. package/src/server/services/router/request/service.ts +21 -0
  105. package/src/server/services/router/response/index.ts +131 -65
  106. package/src/server/services/router/response/{filter → mask}/Filter.ts +0 -0
  107. package/src/server/services/router/response/{filter → mask}/index.ts +0 -2
  108. package/src/server/services/router/response/{filter → mask}/selecteurs.ts +0 -0
  109. package/src/server/services/router/response/page/document.tsx +194 -0
  110. package/src/server/services/router/response/page/index.tsx +157 -0
  111. package/src/server/{libs/pages → services/router/response/page}/schemaGenerator.ts +0 -0
  112. package/src/server/services/router/service.ts +48 -0
  113. package/src/server/services/schema/index.ts +47 -0
  114. package/src/server/services/schema/request.ts +55 -0
  115. package/src/server/services/schema/router.ts +33 -0
  116. package/src/server/services/socket/index.ts +38 -43
  117. package/src/server/services/socket/scope.ts +6 -4
  118. package/src/server/services/users/index.ts +203 -0
  119. package/src/server/services/{auth/base.ts → users/old.ts} +28 -112
  120. package/src/server/services/users/router/index.ts +72 -0
  121. package/src/server/services/users/router/request.ts +49 -0
  122. package/src/server/{data → services_old}/SocketClient.ts +0 -0
  123. package/src/server/{data/Token.olg.ts → services_old/Token.old.ts} +0 -0
  124. package/src/server/{data → services_old}/aes.ts +0 -0
  125. package/src/types/aliases.d.ts +43 -2
  126. package/templates/composant.tsx +1 -1
  127. package/templates/modal.tsx +1 -1
  128. package/templates/page.tsx +1 -1
  129. package/tsconfig.common.json +0 -4
  130. package/src/client/assets/css/components/components.less +0 -31
  131. package/src/client/context/api.ts +0 -92
  132. package/src/client/context/index.ts +0 -246
  133. package/src/client/index.tsx +0 -129
  134. package/src/client/router/index.ts +0 -286
  135. package/src/client/router/request/index.ts +0 -106
  136. package/src/client/router/response/index.ts +0 -38
  137. package/src/client/router/route.ts +0 -75
  138. package/src/common/data/input/validators/basic.ts +0 -299
  139. package/src/common/data/input/validators/build.ts +0 -63
  140. package/src/common/router/request.ts +0 -83
  141. package/src/server/data/ApiClient.ts +0 -119
  142. package/src/server/data/input.ts +0 -41
  143. package/src/server/libs/pages/document.static.tsx +0 -41
  144. package/src/server/libs/pages/document.tsx +0 -203
  145. package/src/server/libs/pages/render.tsx +0 -90
  146. package/src/server/routes/auth.ts +0 -151
  147. package/src/server/services/redis/index.ts +0 -71
  148. package/src/server/services/router/request/services/auth.ts +0 -177
@@ -6,30 +6,26 @@
6
6
  import { FunctionalComponent } from "preact";
7
7
 
8
8
  // Core
9
- import { TRoute } from ".";
10
- import BaseRequest from './request';
11
- import { TClientRoute, TFrontRenderer } from '@client/router';
12
- import PageResponse from './response/page';
13
- import { ClientContext } from '@client/context';
9
+ import { TRoute } from "..";
10
+ import type ClientRequest from '@client/services/router';
11
+ import Page from '@client/services/router/response/page'
14
12
 
15
13
  /*----------------------------------
16
14
  - TYPES
17
15
  ----------------------------------*/
18
16
 
19
- export { default as PageResponse } from './response/page';
20
-
21
- export type TResponseData = PageResponse | unknown
17
+ type TResponseData = Page
22
18
 
23
19
  /*----------------------------------
24
20
  - CONTEXT
25
21
  ----------------------------------*/
26
22
  export default abstract class BaseResponse<
27
- TData extends TResponseData = TResponseData,
28
- TRequest extends BaseRequest = BaseRequest
23
+ TData extends TResponseData = Page,
24
+ TRequest extends ClientRequest = ClientRequest
29
25
  > {
30
26
 
31
- public data?: any;
32
- public request: With<TRequest, 'response'>;
27
+ public data?: TData;
28
+ public request: TRequest;
33
29
  public route?: TRoute;
34
30
 
35
31
  public constructor(
@@ -37,7 +33,7 @@ export default abstract class BaseResponse<
37
33
  ) {
38
34
  // ServerResponse et ClientResponse assignent request.response
39
35
  request.response = this;
40
- this.request = request as With<TRequest, 'response'>;
36
+ this.request = request as TRequest;
41
37
  }
42
38
 
43
39
  public setRoute(route: TRoute) {
@@ -2,19 +2,38 @@
2
2
  - DEPENDANCES
3
3
  ----------------------------------*/
4
4
 
5
- import type { ComponentChild } from 'preact';
5
+ import type { ComponentChild, FunctionComponent } from 'preact';
6
6
 
7
7
  // Core libs
8
- import { TClientRoute, TFrontRenderer } from '@client/router';
9
- import { TFetcherList } from '@common/router/request';
10
- import { history } from '@client/router/request/history';
11
- import { ClientContext } from '@client/context';
8
+ import { ClientOrServerRouter, TClientOrServerContext } from '@common/router';
9
+ import { TFetcherList, TDataReturnedByFetchers } from '@common/router/request/api';
10
+ import { history } from '@client/services/router/request/history';
12
11
 
13
12
  /*----------------------------------
14
13
  - TYPES
15
14
  ----------------------------------*/
16
15
 
17
- type TResource = {
16
+ // The function that fetch data from the api before to pass them as context to the renderer
17
+ export type TDataProvider<TProvidedData extends TFetcherList = {}> =
18
+ (context: TClientOrServerContext/* & TUrlData */) => TProvidedData
19
+
20
+
21
+
22
+ // The function that renders routes
23
+ export type TFrontRenderer<
24
+ TProvidedData extends TFetcherList = {},
25
+ TAdditionnalData = {},
26
+ TRouter = ClientOrServerRouter,
27
+ > = FunctionComponent<(
28
+ TClientOrServerContext
29
+ &
30
+ TDataReturnedByFetchers<TProvidedData>
31
+ &
32
+ TAdditionnalData
33
+ )>;
34
+
35
+ // Script or CSS resource
36
+ export type TPageResource = {
18
37
  id: string,
19
38
  attrs?: TObjetDonnees
20
39
  } & ({
@@ -27,70 +46,43 @@ type TResource = {
27
46
  /*----------------------------------
28
47
  - CLASS
29
48
  ----------------------------------*/
30
- export default class PageResponse {
31
-
32
- // Render
33
- public id: string;
34
- public data: TObjetDonnees = {};
35
- public loading: ComponentChild = false;
36
- public component: TFrontRenderer;
49
+ export default class PageResponse<TRouter extends ClientOrServerRouter = ClientOrServerRouter> {
37
50
 
38
51
  // Metadata
52
+ public chunkId: string;
39
53
  public title?: string;
40
54
  public description?: string;
41
55
  public bodyClass: Set<string> = new Set<string>();
42
56
  public bodyId?: string;
43
57
 
44
- // resources
58
+ // Resources
45
59
  public amp?: boolean;
46
- public scripts: TResource[] = [];
47
- public style: TResource[] = [];
48
-
49
- // State
50
- public hash?: string; // Element id to scroll to
51
-
52
- public constructor(
53
- public context: ClientContext,
54
- public route: TClientRoute,
55
- data: TObjetDonnees = {},
56
- ) {
57
- this.id = route.options.id; // Binded by the pages babel plugin
58
- this.bodyId = route.options.bodyId;
59
- this.component = route.renderer;
60
- this.data = data;
61
- this.hash = context.request.hash;
62
- }
60
+ public scripts: TPageResource[] = [];
61
+ public style: TPageResource[] = [];
63
62
 
64
- // API data fetchers
63
+ // Data
65
64
  public fetchers: TFetcherList = {};
65
+ public data: TObjetDonnees = {};
66
66
 
67
- // Should be called AFTER rendering the page
68
- public updateClient() {
67
+ public constructor(
68
+ public dataProvider: TDataProvider | null,
69
+ public renderer: TFrontRenderer,
70
+ public context: TClientOrServerContext
71
+ ) {
69
72
 
70
- document.body.id = this.bodyId || this.id;
71
- document.title = this.title || APP_NAME;
72
- document.body.className = [...this.bodyClass].join(' ');
73
-
73
+ this.chunkId = context.route.options["id"];
74
+
74
75
  }
75
76
 
76
-
77
77
  public async fetchData() {
78
- this.isDataLoaded = true;
79
- this.data = await this.context.request.fetchSync(this.fetchers);
80
- return this.data;
81
- }
82
78
 
83
- public setAllData( callback: (data: {[k: string]: any}) => void) {
84
- console.warn(`page.setAllData not yet attached to the page Reatc component.`);
85
- }
86
- public setData( key: string, value: ((value: any) => void) | any ) {
87
- this.setAllData(old => ({
88
- ...old,
89
- [key]: typeof value === 'function' ? value(old[key]) : value
90
- }));
91
- }
79
+ // Load the fetchers list to load data if needed
80
+ if (this.dataProvider)
81
+ this.fetchers = this.dataProvider({ ...this.context, ...this.context.request.data });
92
82
 
93
- public go( url: string ) {
94
- history?.replace(url);
83
+ // Execute the fetchers for missing data
84
+ console.log(`[router][page] Fetching api data:` + Object.keys(this.fetchers));
85
+ this.data = await this.context.request.api.fetchSync( this.fetchers, this.data );
86
+ return this.data;
95
87
  }
96
88
  }
@@ -0,0 +1,3 @@
1
+ export { default as Schema } from './schema';
2
+ export { default as Validators } from './validators';
3
+ export { default as Validator } from './validator';
@@ -0,0 +1,185 @@
1
+ /*----------------------------------
2
+ - DEPENDANCES
3
+ ----------------------------------*/
4
+
5
+ // Core
6
+ import { Erreur, TListeErreursSaisie, InputErrorSchema } from '@common/errors';
7
+
8
+ // Specific
9
+ import { default as Validator, EXCLUDE_VALUE } from './validator';
10
+
11
+ /*----------------------------------
12
+ - TYPES
13
+ ----------------------------------*/
14
+
15
+ export type TSchemaFields = { [fieldName: string]: Schema<{}> | Validator<any> }
16
+
17
+ type TOptsValider = {
18
+ critique?: boolean,
19
+ validationComplete?: boolean,
20
+ avecDependances?: boolean,
21
+ corriger?: boolean,
22
+ }
23
+
24
+ export type TValidationResult<TFields extends TSchemaFields> = {
25
+ values: TValidatedData<TFields>,
26
+ nbErreurs: number,
27
+ erreurs: TListeErreursSaisie
28
+ }
29
+
30
+ export type TValidatedData<TFields extends TSchemaFields> = {
31
+ // For each field, the values returned by validator.validate()
32
+ [name in keyof TFields]: ReturnType<TFields[name]["validate"]>
33
+ }
34
+
35
+ /*----------------------------------
36
+ - CONST
37
+ ----------------------------------*/
38
+
39
+ const debug = true;
40
+
41
+ const LogPrefix = '[schema][validator]';
42
+
43
+ /*----------------------------------
44
+ - CLASS
45
+ ----------------------------------*/
46
+ export default class Schema<TFields extends TSchemaFields> {
47
+
48
+ public constructor(
49
+ public fields: TFields
50
+ ) {
51
+
52
+ }
53
+
54
+ public validate<TDonnees extends TObjetDonnees>(
55
+
56
+ dataToValidate: Partial<TDonnees>,
57
+ allData: TDonnees,
58
+ output: TObjetDonnees = {},
59
+
60
+ opts: TOptsValider = {},
61
+ chemin: string[] = []
62
+
63
+ ): TValidationResult<TFields> {
64
+
65
+ opts = {
66
+ critique: false,
67
+ validationComplete: false,
68
+ avecDependances: true,
69
+ corriger: false,
70
+ ...opts,
71
+ }
72
+
73
+ const clesAvalider = Object.keys(opts.validationComplete === true ? this.fields : dataToValidate);
74
+
75
+ let outputSchema = output;
76
+ for (const branche of chemin)
77
+ outputSchema = outputSchema[branche];
78
+
79
+ // Validation de chacune d'entre elles
80
+ let erreurs: TListeErreursSaisie = {};
81
+ let nbErreurs = 0;
82
+ for (const champ of clesAvalider) {
83
+
84
+ // La donnée est répertoriée dans le schema
85
+ const field = this.fields[champ];
86
+ if (field === undefined) {
87
+ debug && console.warn(LogPrefix, '[' + champ + ']', 'Exclusion (pas présent dans le schéma)');
88
+ continue;
89
+ }
90
+
91
+ const cheminA = [...chemin, champ]
92
+ const cheminAstr = cheminA.join('.')
93
+
94
+ // Sous-schema
95
+ if (field instanceof Schema) {
96
+
97
+ // Initialise la structure pour permettre l'assignement d'outputSchema
98
+ if (outputSchema[champ] === undefined)
99
+ outputSchema[champ] = {}
100
+
101
+ // The corresponding data should be an object
102
+ const schemadata = dataToValidate[champ];
103
+ if (typeof schemadata !== 'object') {
104
+ erreurs[ cheminAstr ] = [`Should be an object`];
105
+ nbErreurs++;
106
+ continue;
107
+ }
108
+
109
+ // Validate the data
110
+ const validationSchema = field.validate(
111
+
112
+ schemadata,
113
+ allData,
114
+ output,
115
+
116
+ opts,
117
+ cheminA
118
+ );
119
+ erreurs = { ...erreurs, ...validationSchema.erreurs };
120
+ nbErreurs += validationSchema.nbErreurs;
121
+
122
+ // Pas besoin d'assigner, car output est passé en référence
123
+ //output[champ] = validationSchema.values;
124
+
125
+
126
+ // I don't remind what is options.activer about
127
+ /*} else if (field.activer !== undefined && field.activer(allData) === false) {
128
+
129
+ delete outputSchema[champ];*/
130
+
131
+ // Validator
132
+ } else {
133
+
134
+ // Champ composé de plusieurs values
135
+ const valOrigine = field.options.as === undefined
136
+ ? dataToValidate[champ]
137
+ // Le champ regroupe plusieurs values (ex: Periode)
138
+ : field.options.as.map((nomVal: string) => dataToValidate[nomVal])
139
+
140
+ // Validation
141
+ try {
142
+
143
+ const val = field.validate(valOrigine, allData, output, opts.corriger);
144
+
145
+ // Exclusion seulement si explicitement demandé
146
+ // IMPORTANT: Conserver les values undefined
147
+ // La présence d'un valeur undefined peut être utile, par exemple, pour indiquer qu'on souhaite supprimer une donnée
148
+ // Exemple: undefinec = suppression fichier | Absende donnée = conservation fihcier actuel
149
+ if (val === EXCLUDE_VALUE)
150
+ debug && console.log(LogPrefix, '[' + cheminA + '] Exclusion demandée');
151
+ else
152
+ outputSchema[champ] = val;
153
+
154
+ debug && console.log(LogPrefix, '[' + cheminA + ']', valOrigine, '=>', val);
155
+
156
+ } catch (error) {
157
+
158
+ debug && console.warn(LogPrefix, '[' + cheminA + ']', valOrigine, '|| Erreur:', error);
159
+
160
+ if (error instanceof Erreur) {
161
+
162
+ // Référencement erreur
163
+ erreurs[cheminAstr] = [error.message]
164
+ nbErreurs++;
165
+
166
+ } else
167
+ throw error;
168
+ }
169
+ }
170
+ }
171
+
172
+ if (nbErreurs !== 0 && opts.critique === true) {
173
+ throw new InputErrorSchema(erreurs);
174
+ }
175
+
176
+ debug && console.log(LogPrefix, '', dataToValidate, '=>', output);
177
+
178
+ return {
179
+ values: output as TValidatedData<TFields>,
180
+ erreurs,
181
+ nbErreurs,
182
+ };
183
+
184
+ }
185
+ }
@@ -0,0 +1,95 @@
1
+ /*----------------------------------
2
+ - DEPENDANCES
3
+ ----------------------------------*/
4
+
5
+ // Npm
6
+ import type { ComponentChild } from 'preact'
7
+
8
+ // Core
9
+ import { InputError } from '@common/errors';
10
+
11
+ /*----------------------------------
12
+ - TYPES
13
+ ----------------------------------*/
14
+
15
+ export type TValidator<TValue> = {
16
+
17
+ rendu?: TFieldRenderer,
18
+
19
+ // I don't remind what is options.activer about
20
+ activer?: (donnees: TObjetDonnees) => boolean,
21
+ onglet?: string, // Sert juste d'identifiant secondaire. Ex: nom onglet correspondant
22
+
23
+ // Restrict to a specific set of values
24
+ in?: TValue[],
25
+
26
+ // Executé après le validateur propre au type
27
+ dependances?: string[],
28
+ opt?: true,
29
+ defaut?: TValue,
30
+ as?: string[], // Mapping personnalisé
31
+
32
+ }
33
+
34
+ export type TFieldRenderer = (props: any) => ComponentChild;
35
+
36
+ type TNonEmptyValue = Exclude<any, undefined | '' | null>
37
+
38
+ type TValidationArgs<TValue, TAllValues extends {}> = [
39
+ // For the value given as input in the validation function,
40
+ // Only the empty values were escluded
41
+ val: TNonEmptyValue,
42
+ input: TAllValues,
43
+ output: Partial<TAllValues>,
44
+ corriger?: boolean
45
+ ]
46
+
47
+ type TValidationFunction<TValue, TAllValues extends {} = {}> = (
48
+ ...args: TValidationArgs<TValue, TAllValues>
49
+ ) => TValue | typeof EXCLUDE_VALUE;
50
+
51
+ type TValidateReturnType<
52
+ TOptions extends TValidator<TValue>,
53
+ TValue extends any
54
+ > = TOptions extends { opt: true }
55
+ ? (undefined | TValue)
56
+ : TValue
57
+
58
+ /*----------------------------------
59
+ - CONST
60
+ ----------------------------------*/
61
+
62
+ export const EXCLUDE_VALUE = "action:exclure" as const;
63
+
64
+ /*----------------------------------
65
+ - CLASS
66
+ ----------------------------------*/
67
+ export default class Validator<TValue, TOptions extends TValidator<TValue> = TValidator<TValue>> {
68
+
69
+ public constructor(
70
+ public type: string,
71
+ public validateType: TValidationFunction<TValue>,
72
+ public options: TOptions
73
+ ) {
74
+
75
+ }
76
+
77
+ public isEmpty = (val: any) => val === undefined || val === '' || val === null
78
+
79
+ public validate(...[ val, input, output, correct ]: TValidationArgs<TValue, {}>): TValidateReturnType<TOptions, TValue> {
80
+
81
+ // Required value
82
+ if (this.isEmpty(val)) {
83
+ // Optionnel, on skip
84
+ if (this.options.opt === true)
85
+ return undefined as TValidateReturnType<TOptions, TValue>;
86
+ // Requis
87
+ else
88
+ throw new InputError("Please enter a value");
89
+ }
90
+
91
+ // Validate type
92
+ return this.validateType(val, input, output, correct) as TValidateReturnType<TOptions, TValue>;
93
+ }
94
+
95
+ }