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.
Files changed (127) 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 -8
  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/medias.less +14 -0
  9. package/src/client/components/Card/index.tsx +2 -2
  10. package/src/client/components/Dialog/Manager.tsx +39 -12
  11. package/src/client/components/Form/index.tsx +1 -1
  12. package/src/client/components/button.tsx +2 -2
  13. package/src/client/components/containers/Popover/index.tsx +1 -1
  14. package/src/client/components/data/spintext/index.tsx +1 -1
  15. package/src/client/components/dropdown/index.tsx +1 -1
  16. package/src/client/components/index.ts +8 -0
  17. package/src/client/components/input/BaseV2/index.tsx +1 -1
  18. package/src/client/components/input/UploadImage/index.tsx +1 -1
  19. package/src/client/hooks/index.ts +5 -0
  20. package/src/client/hooks/useState/index.tsx +2 -2
  21. package/src/client/hooks.ts +22 -0
  22. package/src/client/index.ts +5 -0
  23. package/src/client/pages/_layout/landing/index.tsx +0 -2
  24. package/src/client/pages/_messages/400.tsx +2 -2
  25. package/src/client/pages/_messages/401.tsx +2 -2
  26. package/src/client/pages/_messages/403.tsx +2 -2
  27. package/src/client/pages/_messages/404.tsx +2 -2
  28. package/src/client/pages/_messages/500.tsx +2 -2
  29. package/src/client/pages/bug.tsx +1 -1
  30. package/src/client/pages/useHeader.tsx +1 -1
  31. package/src/client/{context/captcha.ts → services/captcha/index.ts} +0 -0
  32. package/src/client/services/metrics/index.ts +37 -0
  33. package/src/client/{router → services/router/components}/Link.tsx +1 -1
  34. package/src/client/services/router/components/Page.tsx +59 -0
  35. package/src/client/{router/component.tsx → services/router/components/router.tsx} +43 -74
  36. package/src/client/services/router/index.tsx +448 -0
  37. package/src/client/services/router/request/api.ts +229 -0
  38. package/src/client/{router → services/router}/request/history.ts +0 -0
  39. package/src/client/services/router/request/index.ts +52 -0
  40. package/src/client/services/router/response/index.tsx +107 -0
  41. package/src/client/services/router/response/page.ts +95 -0
  42. package/src/client/{context/socket.ts → services/socket/index.ts} +2 -2
  43. package/src/client/utils/dom.ts +1 -1
  44. package/src/common/app/index.ts +9 -0
  45. package/src/common/data/chaines/index.ts +9 -6
  46. package/src/common/data/input/validate.ts +3 -166
  47. package/src/common/data/objets.ts +25 -0
  48. package/src/common/data/tableaux.ts +8 -0
  49. package/src/common/errors/index.ts +3 -1
  50. package/src/common/router/index.ts +67 -88
  51. package/src/common/router/layouts.ts +50 -0
  52. package/src/common/router/register.ts +62 -0
  53. package/src/common/router/request/api.ts +72 -0
  54. package/src/common/router/request/index.ts +31 -0
  55. package/src/common/router/{response.ts → response/index.ts} +9 -13
  56. package/src/common/router/response/page.ts +40 -56
  57. package/src/common/validation/index.ts +3 -0
  58. package/src/common/validation/schema.ts +184 -0
  59. package/src/common/validation/validator.ts +88 -0
  60. package/src/common/validation/validators.ts +313 -0
  61. package/src/server/app/config.ts +9 -27
  62. package/src/server/app/index.ts +81 -124
  63. package/src/server/app/service.ts +98 -0
  64. package/src/server/app.tsconfig.json +0 -8
  65. package/src/server/error/index.ts +13 -0
  66. package/src/server/index.ts +5 -0
  67. package/src/server/patch.ts +0 -6
  68. package/src/server/{data/Cache.ts → services/cache/index.ts} +79 -47
  69. package/src/server/services/console/bugReporter.ts +26 -16
  70. package/src/server/services/console/index.ts +59 -51
  71. package/src/server/services/cron/index.ts +12 -26
  72. package/src/server/services/database/bucket.ts +40 -0
  73. package/src/server/services/database/connection.ts +206 -75
  74. package/src/server/services/database/datatypes.ts +63 -40
  75. package/src/server/services/database/index.ts +295 -272
  76. package/src/server/services/database/metas.ts +246 -135
  77. package/src/server/services/database/stats.ts +151 -126
  78. package/src/server/services/email/index.ts +28 -52
  79. package/src/server/services/{router/request/services → metrics}/detect.ts +8 -10
  80. package/src/server/services/{router/request/services/tracking.ts → metrics/index.ts} +68 -45
  81. package/src/server/services/{http → router/http}/index.ts +28 -70
  82. package/src/server/services/{http → router/http}/multipart.ts +0 -0
  83. package/src/server/services/{http → router/http}/session.ts.old +0 -0
  84. package/src/server/services/router/index.ts +273 -203
  85. package/src/server/services/router/request/api.ts +73 -0
  86. package/src/server/services/router/request/index.ts +16 -97
  87. package/src/server/services/router/request/service.ts +21 -0
  88. package/src/server/services/router/response/index.ts +125 -64
  89. package/src/server/services/router/response/{filter → mask}/Filter.ts +0 -0
  90. package/src/server/services/router/response/{filter → mask}/index.ts +0 -2
  91. package/src/server/services/router/response/{filter → mask}/selecteurs.ts +0 -0
  92. package/src/server/services/router/response/page/document.tsx +194 -0
  93. package/src/server/services/router/response/page/index.tsx +157 -0
  94. package/src/server/{libs/pages → services/router/response/page}/schemaGenerator.ts +0 -0
  95. package/src/server/services/router/service.ts +48 -0
  96. package/src/server/services/schema/index.ts +47 -0
  97. package/src/server/services/schema/request.ts +55 -0
  98. package/src/server/services/schema/router.ts +33 -0
  99. package/src/server/services/socket/index.ts +38 -43
  100. package/src/server/services/socket/scope.ts +6 -4
  101. package/src/server/services/users/index.ts +203 -0
  102. package/src/server/services/{auth/base.ts → users/old.ts} +28 -112
  103. package/src/server/services/users/router/index.ts +72 -0
  104. package/src/server/services/users/router/request.ts +49 -0
  105. package/src/types/aliases.d.ts +43 -2
  106. package/templates/composant.tsx +1 -1
  107. package/templates/modal.tsx +1 -1
  108. package/templates/page.tsx +1 -1
  109. package/tsconfig.common.json +0 -4
  110. package/src/client/context/api.ts +0 -92
  111. package/src/client/context/index.ts +0 -246
  112. package/src/client/index.tsx +0 -129
  113. package/src/client/router/index.ts +0 -286
  114. package/src/client/router/request/index.ts +0 -106
  115. package/src/client/router/response/index.ts +0 -38
  116. package/src/client/router/route.ts +0 -75
  117. package/src/common/data/input/validators/basic.ts +0 -299
  118. package/src/common/data/input/validators/build.ts +0 -63
  119. package/src/common/router/request.ts +0 -83
  120. package/src/server/data/ApiClient.ts +0 -119
  121. package/src/server/data/input.ts +0 -41
  122. package/src/server/libs/pages/document.static.tsx +0 -41
  123. package/src/server/libs/pages/document.tsx +0 -203
  124. package/src/server/libs/pages/render.tsx +0 -90
  125. package/src/server/routes/auth.ts +0 -151
  126. package/src/server/services/redis/index.ts +0 -71
  127. package/src/server/services/router/request/services/auth.ts +0 -177
@@ -0,0 +1,73 @@
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): Promise<TObjetDonnees> {
56
+
57
+ const resolved: TObjetDonnees = {};
58
+
59
+ for (const id in fetchers) {
60
+
61
+ const { method, path, data, options } = fetchers[id];
62
+
63
+ //this.router.config.debug && console.log(`[api] Resolving from internal api`, method, path, data);
64
+
65
+ const internalHeaders = { accept: 'application/json' }
66
+ const request = this.request.children(method, path, data, { ...internalHeaders/*, ...headers*/ });
67
+ resolved[id] = await request.router.resolve(request).then(res => res.data);
68
+
69
+ }
70
+
71
+ return resolved;
72
+ }
73
+ }
@@ -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,140 @@ 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);
62
102
 
63
- const context = new ClientContext(this.request);
103
+ // Run controller
104
+ const response = await this.route.controller( context );
64
105
 
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 }
106
+ // Handle response type
107
+ if (response === undefined)
108
+ return;
70
109
 
71
- // Render page
72
- const document = await render.page(page, this, context);
73
- this.html(document);
110
+ // Default data type for `return <raw data>`
111
+ if (response instanceof Page)
112
+ await this.render(response, context, additionnalData);
113
+ else if (typeof response === 'string' && this.route.options.accept === 'html')
114
+ await this.html(response);
115
+ else
116
+ await this.json(response);
117
+ }
118
+
119
+ /*----------------------------------
120
+ - INTERNAL
121
+ ----------------------------------*/
74
122
 
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");
123
+ // Start controller services
124
+ private createContext( route: TRoute ): TRequestContext {
78
125
 
79
- } else {
80
126
 
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
- }
127
+ const contextServices: Partial<TRouterContextServices<TRouter>> = {}
128
+ for (const serviceName in this.router.services) {
87
129
 
88
- const controllerData = additionnalData === undefined
89
- ? this.request.data
90
- // Example: error message for error pages
91
- : { ...this.request.data, ...additionnalData }
130
+ const routerService = this.router.services[serviceName];
131
+ contextServices[ serviceName ] = routerService.requestService( this.request );
92
132
 
93
- // Run controller
94
- const returnedData = await this.route.controller(this.request, controllerData);
133
+ }
95
134
 
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
- }
135
+ const context: TRequestContext = {
136
+ // Router context
137
+ app: this.app,
138
+ context: undefined as TRequestContext,
139
+ request: this.request,
140
+ response: this,
141
+ route: route,
142
+ api: this.request.api,
143
+ // Router services
144
+ ...(contextServices as TRouterContextServices<TRouter>),
103
145
  }
146
+
147
+ context.context = context;
148
+
149
+ return context;
104
150
  }
105
151
 
106
- /*----------------------------------
107
- - INTERNAL
108
- ----------------------------------*/
152
+ public async forSsr( page: Page<TRouter> ): Promise<TBasicSSrData> {
153
+
154
+ const customSsrData = await this.router.config.ssrData(this.request);
109
155
 
110
- public async forSsr(page: PageResponse): Promise<TSsrData> {
111
156
  return {
112
157
  request: {
113
158
  id: this.request.id,
114
159
  data: this.request.data,
115
160
  },
116
161
  page: {
117
- id: page.id,
162
+ chunkId: page.chunkId,
118
163
  data: page.data
119
164
  },
120
-
121
- user: this.request.user
122
- ? await filter(this.request.user, $.auth.SsrMask, this.request.user)
123
- : null
165
+ ...customSsrData
124
166
  }
125
167
  }
126
168
 
@@ -138,13 +180,34 @@ export default class ServerResponse<TData extends TResponseData = TResponseData>
138
180
  - DATA RESPONSE
139
181
  ----------------------------------*/
140
182
 
183
+ public async render( page: Page, context: TRouterContext, additionnalData: {} ) {
184
+
185
+ // Set page in context for the client side
186
+ context.page = page;
187
+
188
+ // Prepare page & fetch data
189
+ await page.fetchData();
190
+ if (additionnalData !== undefined) // Example: error message for error pages
191
+ page.data = { ...page.data, ...additionnalData }
192
+
193
+ // Render page
194
+ await this.router.runHook('render', page);
195
+ const document = await page.render();
196
+ this.html(document);
197
+
198
+ // Never put html in the cache
199
+ // Because assets urls need to be updated when their hash has been changed by a release
200
+ this.request.res.setHeader("Expires", "0");
201
+
202
+ }
203
+
141
204
  public async json(data?: any, mask?: string) {
142
205
 
143
- // RAPPEL: On filter aussi les requetes internes, car leurs données seront imprimées au SSR pour le contexte client
206
+ // RAPPEL: On jsonMask aussi les requetes internes, car leurs données seront imprimées au SSR pour le contexte client
144
207
  // filtreApi vérifie systèmatiquement si la donnée a été filtrée
145
208
  // NOTE: On évite le filtrage sans masque spécifié (performances + risques erreurs)
146
209
  if (mask !== undefined)
147
- data = await filter(data, mask, this.request.user);
210
+ data = await jsonMask(data, mask, this.request.user);
148
211
 
149
212
  this.headers['Content-Type'] = 'application/json';
150
213
  this.data = this.request.isVirtual ? data : JSON.stringify(data);
@@ -170,17 +233,15 @@ export default class ServerResponse<TData extends TResponseData = TResponseData>
170
233
  // TODO: https://github.com/adonisjs/http-server/blob/develop/src/Response/index.ts#L430
171
234
  public file( fichier: string ) {
172
235
 
173
- const app = this.request.router.app;
174
-
175
236
  // Securité
176
237
  if (fichier.includes('..'))
177
238
  throw new Forbidden("Disallowed");
178
239
 
179
240
  // Force absolute path
180
- if (!fichier.startsWith( app.path.root ))
241
+ if (!fichier.startsWith( this.app.path.root ))
181
242
  fichier = fichier[0] === '/'
182
- ? app.path.root + '/bin' + fichier
183
- : app.path.data + '/' + fichier;
243
+ ? this.app.path.root + '/bin' + fichier
244
+ : this.app.path.data + '/' + fichier;
184
245
 
185
246
  console.log(`[response] Serving file "${fichier}"`);
186
247
 
@@ -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
  ----------------------------------*/