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
|
@@ -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
|
|
12
|
-
import
|
|
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
|
-
//
|
|
14
|
+
// Specific
|
|
17
15
|
import ServerResponse from '../response';
|
|
18
|
-
import
|
|
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 {
|
|
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
|
|
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:
|
|
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
|
-
|
|
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:
|
|
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
|
|
16
|
-
import
|
|
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
|
|
24
|
-
import {
|
|
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
|
|
32
|
+
export type TBasicSSrData = {
|
|
33
33
|
request: { data: TObjetDonnees, id: string },
|
|
34
|
-
page: {
|
|
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<
|
|
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
|
|
96
|
+
public async runController( route: TRoute, additionnalData: {} = {} ) {
|
|
58
97
|
|
|
59
98
|
this.route = route;
|
|
60
99
|
|
|
61
|
-
|
|
100
|
+
// Create response context for controllers
|
|
101
|
+
const context = this.createContext(route);
|
|
62
102
|
|
|
63
|
-
|
|
103
|
+
// Run controller
|
|
104
|
+
const response = await this.route.controller( context );
|
|
64
105
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
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
|
-
|
|
72
|
-
|
|
73
|
-
this.
|
|
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
|
-
|
|
76
|
-
|
|
77
|
-
this.request.res.setHeader("Expires", "0");
|
|
123
|
+
// Start controller services
|
|
124
|
+
private createContext( route: TRoute ): TRequestContext {
|
|
78
125
|
|
|
79
|
-
} else {
|
|
80
126
|
|
|
81
|
-
|
|
82
|
-
|
|
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
|
|
89
|
-
|
|
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
|
-
|
|
94
|
-
const returnedData = await this.route.controller(this.request, controllerData);
|
|
133
|
+
}
|
|
95
134
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
|
File without changes
|
|
File without changes
|