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
@@ -0,0 +1,76 @@
1
+ /*----------------------------------
2
+ - DEPENDANCES
3
+ ----------------------------------*/
4
+
5
+ // Core
6
+
7
+ import RequestService from './service';
8
+
9
+ import ApiClientService, {
10
+ TApiFetchOptions, TFetcherList, TFetcherArgs, TFetcher
11
+ } from '@common/router/request/api';
12
+
13
+ /*----------------------------------
14
+ - TYPES
15
+ ----------------------------------*/
16
+
17
+
18
+ /*----------------------------------
19
+ - SERVICE
20
+ ----------------------------------*/
21
+ export default class ApiClientRequest extends RequestService implements ApiClientService {
22
+
23
+ public async start() {
24
+
25
+ }
26
+
27
+ /*----------------------------------
28
+ - HIGH LEVEL
29
+ ----------------------------------*/
30
+
31
+ public get = <TData extends unknown = unknown>(path: string, data?: TObjetDonnees, opts?: TApiFetchOptions) =>
32
+ this.createFetcher<TData>('GET', path, data, opts);
33
+
34
+ public post = <TData extends unknown = unknown>(path: string, data?: TObjetDonnees, opts?: TApiFetchOptions) =>
35
+ this.createFetcher<TData>('POST', path, data, opts);
36
+
37
+ public put = <TData extends unknown = unknown>(path: string, data?: TObjetDonnees, opts?: TApiFetchOptions) =>
38
+ this.createFetcher<TData>('PUT', path, data, opts);
39
+
40
+ public delete = <TData extends unknown = unknown>(path: string, data?: TObjetDonnees, opts?: TApiFetchOptions) =>
41
+ this.createFetcher<TData>('DELETE', path, data, opts);
42
+
43
+ /*----------------------------------
44
+ - API CALLS FROM SERVER
45
+ ----------------------------------*/
46
+
47
+ public createFetcher<TData extends unknown = unknown>(...[method, path, data, options]: TFetcherArgs): TFetcher<TData> {
48
+ return {
49
+ method, path, data, options,
50
+ then: () => { throw new Error("Async resolvers should not be run from server side."); },
51
+ run: () => { throw new Error("Async resolvers should not be run from server side."); },
52
+ };
53
+ }
54
+
55
+ public async fetchSync(fetchers: TFetcherList, alreadyLoadedData: {}): Promise<TObjetDonnees> {
56
+
57
+ const fetchedData: TObjetDonnees = { ...alreadyLoadedData };
58
+
59
+ for (const id in fetchers) {
60
+
61
+ const { method, path, data, options } = fetchers[id];
62
+ //this.router.config.debug && console.log(`[api] Resolving from internal api`, method, path, data);
63
+
64
+ // We don't fetch the already given data
65
+ if (id in fetchedData)
66
+ continue;
67
+
68
+ // Create a children request to resolve the api data
69
+ const internalHeaders = { accept: 'application/json' }
70
+ const request = this.request.children(method, path, data, { ...internalHeaders/*, ...headers*/ });
71
+ fetchedData[id] = await request.router.resolve(request).then(res => res.data);
72
+ }
73
+
74
+ return fetchedData;
75
+ }
76
+ }
@@ -8,34 +8,30 @@ import ISO6391 from 'iso-639-1';
8
8
  import accepts from 'accepts';
9
9
  import Bowser from "bowser";
10
10
 
11
- // Core libs
12
- import validateurs from '@server/data/input';
13
- import { TSchema, validate as validerSchema, TDonneesValidees } from '@common/data/input/validate';
14
- import app from '@server/app';
11
+ // Core
12
+ import BaseRequest from '@common/router/request';
15
13
 
16
- // Core libs: router
14
+ // Specific
17
15
  import ServerResponse from '../response';
18
- import BaseRequest, { TFetcherArgs, TFetcher, TFetcherList } from '@common/router/request';
19
-
20
- // Extensions
21
- import AuthService from './services/auth';
22
- import SecurityService from './services/detect';
23
- import TrackingService from './services/tracking';
24
-
25
- const debug = true;
16
+ import ApiClient from './api';
26
17
 
27
18
  /*----------------------------------
28
19
  - TYPES
29
20
  ----------------------------------*/
30
21
 
31
- import type { default as Router, HttpMethod, HttpHeaders } from '@server/services/router';
22
+ import type {
23
+ default as Router, Config as RouterConfig,
24
+ HttpMethod, HttpHeaders
25
+ } from '@server/services/router';
32
26
 
33
27
  const localeFilter = (input: any) => typeof input === 'string' && ISO6391.validate(input) ? input : undefined;
34
28
 
35
29
  /*----------------------------------
36
30
  - CONTEXTE
37
31
  ----------------------------------*/
38
- export default class ServerRequest extends BaseRequest {
32
+ export default class ServerRequest<
33
+ TRouter extends Router = Router
34
+ > extends BaseRequest {
39
35
 
40
36
  /*----------------------------------
41
37
  - PROPRIÉTÉS
@@ -53,15 +49,15 @@ export default class ServerRequest extends BaseRequest {
53
49
  public cookies: TObjetDonnees = {};
54
50
 
55
51
  // reponse
56
- public response?: ServerResponse;
57
- public router: Router;
52
+ public response?: ServerResponse<TRouter>;
53
+ public router: TRouter;
58
54
 
59
55
  // Origin
60
56
  public req: express.Request;
61
57
  public res: express.Response;
62
58
 
63
59
  // Services
64
- //public analytics?: ua.Visitor;
60
+ public api: ApiClient;
65
61
 
66
62
  /*----------------------------------
67
63
  - INITIALISATION
@@ -75,7 +71,7 @@ export default class ServerRequest extends BaseRequest {
75
71
  headers: HttpHeaders | undefined,
76
72
 
77
73
  res: express.Response,
78
- router: Router ,
74
+ router: TRouter,
79
75
  isVirtual: boolean = false
80
76
  ) {
81
77
 
@@ -87,6 +83,7 @@ export default class ServerRequest extends BaseRequest {
87
83
  this.req = res.req;
88
84
  this.res = res
89
85
  this.router = router;
86
+ this.api = new ApiClient(this);
90
87
 
91
88
  this.host = this.req.get('host') as string;
92
89
  this.method = method;
@@ -96,16 +93,8 @@ export default class ServerRequest extends BaseRequest {
96
93
  this.cookies = res.req.cookies;
97
94
 
98
95
  this.ip = res.req.ip;
99
- if (this.ip === '::1' && app.env.localIP)
100
- this.ip = app.env.localIP;
101
96
 
102
97
  this.data = data || {};
103
-
104
- // FIX: L'utilisation du sprad sur la classe Servercontext fait perdre le contexte this à ses méthodes
105
- this.schema.validate = this.schema.validate.bind(this);
106
-
107
- //this.url = this.url.bind(this);
108
-
109
98
  }
110
99
 
111
100
  public children(method: HttpMethod, path: string, data: TObjetDonnees | undefined, headers?: HttpHeaders) {
@@ -163,74 +152,4 @@ export default class ServerRequest extends BaseRequest {
163
152
  const { os, browser } = info;
164
153
  return (os.name || 'Unknown OS') + ' ' + (os.versionName || os.version || '') + ' / ' + (browser.name || 'Unknown browser') + ' ' + (browser.version || '');
165
154
  }
166
-
167
- /*----------------------------------
168
- - SERVICES
169
- ----------------------------------*/
170
- public schema = {
171
- ...validateurs,
172
- // shortcut pour validation données requete
173
- validate: async <TSchemaA extends TSchema>(schema: TSchemaA): Promise<TDonneesValidees<TSchemaA>> => {
174
-
175
- console.log("Validate request data:", this.data);
176
-
177
- // Les InputError seront propagées vers le middleware dédié à la gestion des erreurs
178
- const { valeurs } = await validerSchema(
179
- schema,
180
- this.data,
181
- this.data,
182
- {},
183
- {
184
- critique: true,
185
- validationComplete: true,
186
- avecDependances: false
187
- },
188
- []
189
- );
190
-
191
- return valeurs;
192
- }
193
- };
194
-
195
- /*public url = (route: string, params: any = {}, absolu: boolean = true) =>
196
- url(route, params, absolu);*/
197
-
198
- public auth = new AuthService(this);
199
-
200
- public tracking = new TrackingService(this);
201
-
202
- public detect = new SecurityService(this);
203
-
204
- public createFetcher(...[method, path, data, options]: TFetcherArgs) {
205
- return {
206
- method, path, data, options,
207
- then: () => { throw new Error("Async resolvers should not be run from server side."); },
208
- run: () => { throw new Error("Async resolvers should not be run from server side."); },
209
- } as TFetcher;
210
- }
211
-
212
- public async fetchSync(fetchers: TFetcherList): Promise<TObjetDonnees> {
213
-
214
- const resolved: TObjetDonnees = {};
215
-
216
- for (const id in fetchers) {
217
-
218
- const { method, path, data, options } = fetchers[id];
219
-
220
- debug && console.log(`[api] Resolving from internal api`, method, path, data);
221
-
222
- const internalHeaders = { accept: 'application/json' }
223
- const request = this.request.children(method, path, data, { ...internalHeaders/*, ...headers*/ });
224
- resolved[id] = await request.router.resolve(request).then(res => res.data);
225
-
226
- }
227
-
228
- return resolved;
229
-
230
- }
231
-
232
- public fetchAsync(...args: TFetcherArgs): Promise<any> {
233
- throw new Error("Async resolvers should not be run from server side.");
234
- }
235
-
236
155
  }
@@ -0,0 +1,21 @@
1
+ /*----------------------------------
2
+ - DEPENDANCES
3
+ ----------------------------------*/
4
+
5
+ import type Router from '..';
6
+ import type ServerRequest from '.';
7
+
8
+ /*----------------------------------
9
+ - SERVICE
10
+ ----------------------------------*/
11
+ export default abstract class RequestService {
12
+
13
+ public constructor(
14
+ public request: ServerRequest<Router>,
15
+ public router = request.router,
16
+ public app = router.app
17
+ ) {
18
+
19
+ }
20
+
21
+ }
@@ -12,16 +12,16 @@ import fs from 'fs-extra';
12
12
  import express from 'express';
13
13
 
14
14
  // Core
15
- import { $ } from '@server/app';
16
- import { NotFound, Forbidden } from '@common/errors';
17
-
18
- // Libs métier
19
- import * as render from '../../../libs/pages/render';
20
- import filter from './filter';
15
+ import Application from '@server/app';
16
+ import type ServerRouter from '@server/services/router';
21
17
  import ServerRequest from '@server/services/router/request';
22
18
  import { TRoute } from '@common/router';
23
- import BaseResponse, { TResponseData, PageResponse } from '@common/router/response';
24
- import { ClientContext } from '@client/context';
19
+ import { NotFound, Forbidden } from '@common/errors';
20
+ import BaseResponse, { TResponseData } from '@common/router/response';
21
+ import Page from './page';
22
+
23
+ // To move into a new npm module: json-mask
24
+ import jsonMask from './mask';
25
25
 
26
26
  /*----------------------------------
27
27
  - TYPES
@@ -29,98 +29,145 @@ import { ClientContext } from '@client/context';
29
29
 
30
30
  const debug = true;
31
31
 
32
- export type TSsrData = {
32
+ export type TBasicSSrData = {
33
33
  request: { data: TObjetDonnees, id: string },
34
- page: { id: string, data?: TObjetDonnees },
35
- user: User | null
34
+ page: { chunkId: string, data?: TObjetDonnees },
35
+ //user: User | null
36
36
  }
37
37
 
38
+ export type TRouterContext<TRouter extends ServerRouter = ServerRouter> = (
39
+ // Request context
40
+ {
41
+ app: Application,
42
+ context: TRouterContext<TRouter>, // = this
43
+ request: ServerRequest<TRouter>,
44
+ api: ServerRequest<TRouter>["api"],
45
+ response: ServerResponse<TRouter>,
46
+ route: TRoute,
47
+ page?: Page,
48
+ user: User
49
+ }
50
+ &
51
+ TRouterContextServices<TRouter>
52
+ )
53
+
54
+ type TRouterContextWithPage = With<TRouterContext, 'page'>
55
+
56
+ export type TRouterContextServices<TRouter extends ServerRouter> = (
57
+ // Custom context via servuces
58
+ // For each roiuter service, return the request service (returned by roiuterService.requestService() )
59
+ {
60
+ [serviceName in keyof TRouter["services"]]: ReturnType< TRouter["services"][serviceName]["requestService"] >
61
+ }
62
+ )
63
+
64
+
38
65
  /*----------------------------------
39
66
  - CLASSE
40
67
  ----------------------------------*/
41
- export default class ServerResponse<TData extends TResponseData = TResponseData> extends BaseResponse<TData, ServerRequest> {
68
+ export default class ServerResponse<
69
+ TRouter extends ServerRouter,
70
+ TRequestContext = TRouterContext<ServerRouter>,
71
+ TData extends TResponseData = TResponseData
72
+ > extends BaseResponse<TData, ServerRequest<TRouter>> {
42
73
 
74
+ // Services
75
+ public app: Application;
76
+ public router: ServerRouter;
77
+
78
+ // Response metadata
43
79
  public statusCode: number = 200;
44
80
  public headers: {[cle: string]: string} = {}
45
- private triggers: {[cle: string]: any[]} = {}
46
81
  public cookie: express.Response["cookie"];
47
82
 
83
+ // If data was provided by at lead one controller
48
84
  public wasProvided = false;
49
85
 
50
- public constructor( request: ServerRequest ) {
86
+ public constructor( request: ServerRequest<TRouter> ) {
51
87
 
52
88
  super(request);
53
89
 
54
90
  this.cookie = this.request.res.cookie.bind(this.request.res);
91
+
92
+ this.router = request.router;
93
+ this.app = this.router.app;
55
94
  }
56
95
 
57
- public async runController( route: TRoute, additionnalData?: TObjetDonnees ) {
96
+ public async runController( route: TRoute, additionnalData: {} = {} ) {
58
97
 
59
98
  this.route = route;
60
99
 
61
- if (this.route.type === 'PAGE') {
100
+ // Create response context for controllers
101
+ const context = this.createContext(route);
102
+
103
+ // Run controller
104
+ const response = await this.route.controller( context );
105
+
106
+ // Handle response type
107
+ if (response === undefined)
108
+ return;
109
+
110
+ // No need to process the response
111
+ if (response instanceof ServerResponse)
112
+ return;
113
+ // Render react page to html
114
+ else if (response instanceof Page)
115
+ await this.render(response, context, additionnalData);
116
+ // Return HTML
117
+ else if (typeof response === 'string' && this.route.options.accept === 'html')
118
+ await this.html(response);
119
+ // Return JSON
120
+ else
121
+ await this.json(response);
122
+ }
62
123
 
63
- const context = new ClientContext(this.request);
124
+ /*----------------------------------
125
+ - INTERNAL
126
+ ----------------------------------*/
64
127
 
65
- // Prepare page & fetch data
66
- const page = await context.createPage(this.route);
67
- await page.fetchData();
68
- if (additionnalData !== undefined) // Example: error message for error pages
69
- page.data = { ...page.data, ...additionnalData }
128
+ // Start controller services
129
+ private createContext( route: TRoute ): TRequestContext {
70
130
 
71
- // Render page
72
- const document = await render.page(page, this, context);
73
- this.html(document);
74
131
 
75
- // Never put html in the cache
76
- // Because assets urls need to be updated when their hash has been changed by a release
77
- this.request.res.setHeader("Expires", "0");
132
+ const contextServices: Partial<TRouterContextServices<TRouter>> = {}
133
+ for (const serviceName in this.router.services) {
78
134
 
79
- } else {
135
+ const routerService = this.router.services[serviceName];
136
+ contextServices[ serviceName ] = routerService.requestService( this.request );
80
137
 
81
- // Validate form data
82
- if (this.route.options.form !== undefined) {
83
- const formData = await this.request.schema.validate( this.route.options.form );
84
- console.log("FORM DATA VIA RESPONSE", formData);
85
- this.request.data = { ...this.request.data, ...formData }
86
- }
138
+ }
87
139
 
88
- const controllerData = additionnalData === undefined
89
- ? this.request.data
90
- // Example: error message for error pages
91
- : { ...this.request.data, ...additionnalData }
140
+ const context: TRequestContext = {
141
+ // Router context
142
+ app: this.app,
143
+ context: undefined as TRequestContext,
144
+ request: this.request,
145
+ response: this,
146
+ route: route,
147
+ api: this.request.api,
148
+ // Router services
149
+ ...(contextServices as TRouterContextServices<TRouter>),
150
+ }
92
151
 
93
- // Run controller
94
- const returnedData = await this.route.controller(this.request, controllerData);
152
+ context.context = context;
95
153
 
96
- // Default data type for `return <raw data>`
97
- if (returnedData !== undefined && !(returnedData instanceof ServerResponse)) {
98
- if (typeof returnedData === 'string' && this.route.options.accept === 'html')
99
- await this.html(returnedData);
100
- else
101
- await this.json(returnedData);
102
- }
103
- }
154
+ return context;
104
155
  }
105
156
 
106
- /*----------------------------------
107
- - INTERNAL
108
- ----------------------------------*/
157
+ public async forSsr( page: Page<TRouter> ): Promise<TBasicSSrData> {
158
+
159
+ const customSsrData = await this.router.config.ssrData(this.request);
109
160
 
110
- public async forSsr(page: PageResponse): Promise<TSsrData> {
111
161
  return {
112
162
  request: {
113
163
  id: this.request.id,
114
164
  data: this.request.data,
115
165
  },
116
166
  page: {
117
- id: page.id,
167
+ chunkId: page.chunkId,
118
168
  data: page.data
119
169
  },
120
-
121
- user: this.request.user
122
- ? await filter(this.request.user, $.auth.SsrMask, this.request.user)
123
- : null
170
+ ...customSsrData
124
171
  }
125
172
  }
126
173
 
@@ -138,13 +185,34 @@ export default class ServerResponse<TData extends TResponseData = TResponseData>
138
185
  - DATA RESPONSE
139
186
  ----------------------------------*/
140
187
 
188
+ public async render( page: Page, context: TRouterContext, additionnalData: {} ) {
189
+
190
+ // Set page in context for the client side
191
+ context.page = page;
192
+
193
+ // Prepare page & fetch data
194
+ page.data = await page.fetchData();
195
+ if (additionnalData !== undefined) // Example: error message for error pages
196
+ page.data = { ...page.data, ...additionnalData }
197
+
198
+ // Render page
199
+ await this.router.runHook('render', page);
200
+ const document = await page.render();
201
+ this.html(document);
202
+
203
+ // Never put html in the cache
204
+ // Because assets urls need to be updated when their hash has been changed by a release
205
+ this.request.res.setHeader("Expires", "0");
206
+
207
+ }
208
+
141
209
  public async json(data?: any, mask?: string) {
142
210
 
143
- // RAPPEL: On filter aussi les requetes internes, car leurs données seront imprimées au SSR pour le contexte client
211
+ // RAPPEL: On jsonMask aussi les requetes internes, car leurs données seront imprimées au SSR pour le contexte client
144
212
  // filtreApi vérifie systèmatiquement si la donnée a été filtrée
145
213
  // NOTE: On évite le filtrage sans masque spécifié (performances + risques erreurs)
146
214
  if (mask !== undefined)
147
- data = await filter(data, mask, this.request.user);
215
+ data = await jsonMask(data, mask, this.request.user);
148
216
 
149
217
  this.headers['Content-Type'] = 'application/json';
150
218
  this.data = this.request.isVirtual ? data : JSON.stringify(data);
@@ -170,17 +238,15 @@ export default class ServerResponse<TData extends TResponseData = TResponseData>
170
238
  // TODO: https://github.com/adonisjs/http-server/blob/develop/src/Response/index.ts#L430
171
239
  public file( fichier: string ) {
172
240
 
173
- const app = this.request.router.app;
174
-
175
241
  // Securité
176
242
  if (fichier.includes('..'))
177
243
  throw new Forbidden("Disallowed");
178
244
 
179
245
  // Force absolute path
180
- if (!fichier.startsWith( app.path.root ))
246
+ if (!fichier.startsWith( this.app.path.root ))
181
247
  fichier = fichier[0] === '/'
182
- ? app.path.root + '/bin' + fichier
183
- : app.path.data + '/' + fichier;
248
+ ? this.app.path.root + '/bin' + fichier
249
+ : this.app.path.data + '/' + fichier;
184
250
 
185
251
  console.log(`[response] Serving file "${fichier}"`);
186
252
 
@@ -13,8 +13,6 @@ import Filter from './Filter';
13
13
  - TYPES
14
14
  ----------------------------------*/
15
15
 
16
- import type { User } from '@models';
17
-
18
16
  /*----------------------------------
19
17
  - CONFIG
20
18
  ----------------------------------*/