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
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// INSPIRATION:
|
|
3
3
|
// https://adonisjs.com/docs/4.1/routing
|
|
4
4
|
// https://laravel.com/docs/8.x/routing
|
|
5
|
-
// https://github.com/adonisjs/http-server/blob/develop/src/
|
|
5
|
+
// https://github.com/adonisjs/http-server/blob/develop/src/ServerRouter/indexApi.ts
|
|
6
6
|
// https://github.com/expressjs/express/blob/06d11755c99fe4c1cddf8b889a687448b568472d/lib/response.js#L1016
|
|
7
7
|
|
|
8
8
|
/*----------------------------------
|
|
@@ -12,179 +12,258 @@
|
|
|
12
12
|
// Npm
|
|
13
13
|
import type express from 'express';
|
|
14
14
|
import { v4 as uuid } from 'uuid';
|
|
15
|
+
import type { GlobImportedWithMetas } from 'babel-plugin-glob-import';
|
|
15
16
|
|
|
16
|
-
// Core
|
|
17
|
+
// Core
|
|
18
|
+
import Application, { Service } from '@server/app';
|
|
17
19
|
import context from '@server/context';
|
|
18
|
-
import
|
|
19
|
-
import
|
|
20
|
-
|
|
21
|
-
import TrackingService from './request/services/tracking';
|
|
22
|
-
|
|
23
|
-
// Core: libs
|
|
24
|
-
import app, { $ } from '@server/app';
|
|
25
|
-
import { NotFound } from '@common/errors';
|
|
26
|
-
|
|
27
|
-
// Core: types
|
|
28
|
-
import type { TSsrUnresolvedRoute, TRegisterPageArgs } from '@client/router';
|
|
29
|
-
import BaseRouter, {
|
|
30
|
-
TBaseRoute, TRoute, TErrorRoute,
|
|
20
|
+
import { Erreur, NotFound } from '@common/errors';
|
|
21
|
+
import BaseRouter, {
|
|
22
|
+
TRoute, TErrorRoute, TRouteModule,
|
|
31
23
|
TRouteOptions, defaultOptions
|
|
32
24
|
} from '@common/router';
|
|
33
|
-
import {
|
|
25
|
+
import { buildRegex, getRegisterPageArgs } from '@common/router/register';
|
|
26
|
+
import { layoutsList } from '@common/router/layouts';
|
|
27
|
+
import { TFetcherArgs } from '@common/router/request/api';
|
|
28
|
+
import type { TFrontRenderer } from '@common/router/response/page';
|
|
29
|
+
import type { TSsrUnresolvedRoute, TRegisterPageArgs } from '@client/services/router';
|
|
30
|
+
|
|
31
|
+
// Specific
|
|
32
|
+
import RouterService from './service';
|
|
33
|
+
import ServerRequest from "./request";
|
|
34
|
+
import ServerResponse, { TRouterContext } from './response';
|
|
35
|
+
import Page from './response/page';
|
|
36
|
+
import HTTP, { Config as HttpServiceConfig } from './http';
|
|
37
|
+
import DocumentRenderer from './response/page/document';
|
|
34
38
|
|
|
35
39
|
/*----------------------------------
|
|
36
|
-
-
|
|
40
|
+
- TYPES
|
|
37
41
|
----------------------------------*/
|
|
38
42
|
|
|
39
|
-
export
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
+
export { default as RouterService } from './service';
|
|
44
|
+
export { default as RequestService } from './request/service';
|
|
45
|
+
export type { default as Request } from "./request";
|
|
46
|
+
export type { default as Response, TRouterContext } from "./response";
|
|
47
|
+
export type { TRoute } from '@common/router';
|
|
48
|
+
|
|
49
|
+
export type TApiRegisterArgs<TRouter extends ServerRouter> = ([
|
|
50
|
+
path: string,
|
|
51
|
+
controller: TServerController<TRouter>
|
|
52
|
+
] | [
|
|
53
|
+
path: string,
|
|
54
|
+
options: Partial<TRouteOptions>,
|
|
55
|
+
controller: TServerController<TRouter>
|
|
56
|
+
])
|
|
43
57
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
58
|
+
export type TServerController<TRouter extends ServerRouter> = (context: TRouterContext<TRouter>) => any;
|
|
59
|
+
|
|
60
|
+
export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'OPTIONS'
|
|
61
|
+
export type TRouteHttpMethod = HttpMethod | '*';
|
|
62
|
+
|
|
63
|
+
export type TApiResponseData = {
|
|
64
|
+
data: any,
|
|
65
|
+
triggers?: { [cle: string]: any }
|
|
52
66
|
}
|
|
53
67
|
|
|
68
|
+
export type HttpHeaders = { [cle: string]: string }
|
|
69
|
+
|
|
54
70
|
/*----------------------------------
|
|
55
|
-
-
|
|
71
|
+
- SERVICE CONFIG
|
|
56
72
|
----------------------------------*/
|
|
57
73
|
|
|
58
|
-
|
|
59
|
-
export type { default as Response } from "./response";
|
|
60
|
-
|
|
61
|
-
export type TApiRegisterArgs = ([
|
|
62
|
-
path: string,
|
|
63
|
-
controller: TServerController
|
|
64
|
-
] | [
|
|
65
|
-
path: string,
|
|
66
|
-
options: Partial<TRouteOptions>,
|
|
67
|
-
controller: TServerController
|
|
68
|
-
])
|
|
74
|
+
const LogPrefix = '[router]';
|
|
69
75
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
76
|
+
export type TRouterServicesList = {
|
|
77
|
+
[serviceName: string]: RouterService<ServerRouter>
|
|
78
|
+
}
|
|
73
79
|
|
|
74
|
-
export type
|
|
80
|
+
export type Config<
|
|
81
|
+
TServiceList extends TRouterServicesList = TRouterServicesList,
|
|
82
|
+
TAdditionnalSsrData extends {} = {}
|
|
83
|
+
> = {
|
|
75
84
|
|
|
76
|
-
|
|
85
|
+
debug: boolean,
|
|
77
86
|
|
|
78
|
-
|
|
79
|
-
export type TRouteHttpMethod = HttpMethod | '*';
|
|
87
|
+
http: HttpServiceConfig
|
|
80
88
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
89
|
+
// Set it as a function, so when we instanciate the services, we can callthis.router to pass the router instance in roiuter services
|
|
90
|
+
services: TServiceList,
|
|
91
|
+
|
|
92
|
+
ssrData: (request: ServerRequest<ServerRouter>) => Promise<TAdditionnalSsrData>,
|
|
93
|
+
|
|
94
|
+
// Protections against bots
|
|
95
|
+
// TODO: move to Protection service
|
|
96
|
+
/*security: {
|
|
97
|
+
recaptcha: {
|
|
98
|
+
prv: string,
|
|
99
|
+
pub: string
|
|
100
|
+
},
|
|
101
|
+
iphub: string
|
|
102
|
+
},*/
|
|
85
103
|
}
|
|
86
104
|
|
|
87
|
-
export type
|
|
88
|
-
|
|
89
|
-
triggers?: {[cle: string]: any}
|
|
105
|
+
export type Hooks = {
|
|
106
|
+
|
|
90
107
|
}
|
|
91
108
|
|
|
92
109
|
/*----------------------------------
|
|
93
110
|
- CLASSE
|
|
94
111
|
----------------------------------*/
|
|
95
|
-
export class
|
|
112
|
+
export default class ServerRouter<
|
|
113
|
+
TConfig extends Config = Config,
|
|
114
|
+
TApplication extends Application = Application
|
|
115
|
+
> extends Service<TConfig, Hooks, TApplication> implements BaseRouter {
|
|
96
116
|
|
|
97
|
-
|
|
117
|
+
// Services
|
|
118
|
+
public http: HTTP;
|
|
119
|
+
public services: TConfig["services"];
|
|
120
|
+
public render: DocumentRenderer;
|
|
98
121
|
|
|
122
|
+
// Indexed
|
|
99
123
|
public routes: TRoute[] = []; // API + pages front front
|
|
100
|
-
|
|
124
|
+
public errors: { [code: number]: TErrorRoute } = {};
|
|
101
125
|
public ssrRoutes: TSsrUnresolvedRoute[] = [];
|
|
102
126
|
|
|
103
127
|
/*----------------------------------
|
|
104
128
|
- SERVICE
|
|
105
129
|
----------------------------------*/
|
|
106
130
|
|
|
107
|
-
public constructor() {
|
|
108
|
-
|
|
109
|
-
app
|
|
131
|
+
public constructor(app: TApplication, config: TConfig) {
|
|
132
|
+
|
|
133
|
+
super(app, config);
|
|
134
|
+
|
|
135
|
+
this.http = new HTTP(config.http, this);
|
|
136
|
+
this.render = new DocumentRenderer(this);
|
|
137
|
+
this.services = config.services;
|
|
138
|
+
|
|
110
139
|
}
|
|
111
140
|
|
|
112
|
-
public async
|
|
141
|
+
public async register() {
|
|
142
|
+
|
|
143
|
+
// Since route registering requires all services to be ready,
|
|
144
|
+
// We load routes only when all services are ready
|
|
145
|
+
this.app.on('ready', async () => {
|
|
113
146
|
|
|
147
|
+
// Use require to avoid circular references
|
|
148
|
+
this.registerRoutes([
|
|
149
|
+
...require("metas:@/server/routes/**/*.ts"),
|
|
150
|
+
...require("metas:@/client/pages/**/*.tsx"),
|
|
151
|
+
...require("metas:@client/pages/**/*.tsx")
|
|
152
|
+
]);
|
|
153
|
+
})
|
|
114
154
|
}
|
|
115
155
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
156
|
+
public async start() {
|
|
157
|
+
this.startServices();
|
|
158
|
+
}
|
|
119
159
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
public get = (...args: TApiRegisterArgs) => this.registerApi('GET', ...args);
|
|
123
|
-
public post = (...args: TApiRegisterArgs) => this.registerApi('POST', ...args);
|
|
124
|
-
public put = (...args: TApiRegisterArgs) => this.registerApi('PUT', ...args);
|
|
125
|
-
public delete = (...args: TApiRegisterArgs) => this.registerApi('DELETE', ...args)
|
|
160
|
+
private async startServices() {
|
|
161
|
+
console.log(LogPrefix, `Starting router services`);
|
|
126
162
|
|
|
127
|
-
|
|
163
|
+
for (const serviceId in this.services) {
|
|
164
|
+
const service = this.services[serviceId];
|
|
165
|
+
service.attach(this);
|
|
166
|
+
await service.register();
|
|
167
|
+
}
|
|
168
|
+
}
|
|
128
169
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
let controller: TServerController;
|
|
170
|
+
private registerRoutes(defModules: GlobImportedWithMetas<TRouteModule>) {
|
|
171
|
+
for (const routeModule of defModules) {
|
|
132
172
|
|
|
133
|
-
|
|
134
|
-
(
|
|
135
|
-
|
|
136
|
-
([path, options, controller] = args)
|
|
173
|
+
const register = routeModule.exports.__register;
|
|
174
|
+
if (!register)
|
|
175
|
+
continue;
|
|
137
176
|
|
|
138
|
-
|
|
177
|
+
console.log(LogPrefix, `Register file:`, routeModule.matches.join('/'));
|
|
178
|
+
register(this.app);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
this.afterRegister();
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/*----------------------------------
|
|
185
|
+
- REGISTER
|
|
186
|
+
----------------------------------*/
|
|
187
|
+
|
|
188
|
+
public page(...args: TRegisterPageArgs) {
|
|
189
|
+
|
|
190
|
+
const { path, options, controller, renderer } = getRegisterPageArgs(...args);
|
|
191
|
+
|
|
192
|
+
const { regex, keys } = buildRegex(path);
|
|
139
193
|
|
|
140
194
|
const route: TRoute = {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
path: path,
|
|
195
|
+
method: 'GET',
|
|
196
|
+
path,
|
|
144
197
|
regex,
|
|
145
|
-
keys
|
|
198
|
+
keys,
|
|
199
|
+
controller: (context: TRouterContext<this>) => new Page(controller, renderer, context),
|
|
146
200
|
options: {
|
|
147
201
|
...defaultOptions,
|
|
202
|
+
accept: 'html', // Les pages retournent forcémment du html
|
|
148
203
|
...options
|
|
149
204
|
},
|
|
150
|
-
controller
|
|
151
205
|
}
|
|
152
206
|
|
|
153
207
|
this.routes.push(route);
|
|
154
208
|
|
|
155
|
-
return
|
|
209
|
+
return this;
|
|
210
|
+
|
|
156
211
|
}
|
|
157
212
|
|
|
158
|
-
|
|
213
|
+
public error(
|
|
214
|
+
code: number,
|
|
215
|
+
options: TRoute["options"],
|
|
216
|
+
renderer: TFrontRenderer<{}, { message: string }>
|
|
217
|
+
) {
|
|
218
|
+
this.errors[code] = {
|
|
219
|
+
code,
|
|
220
|
+
controller: (context: TRouterContext<this>) => new Page(null, renderer, context),
|
|
221
|
+
options
|
|
222
|
+
};
|
|
223
|
+
}
|
|
159
224
|
|
|
160
|
-
|
|
225
|
+
public all = (...args: TApiRegisterArgs<this>) => this.registerApi('*', ...args);
|
|
226
|
+
public options = (...args: TApiRegisterArgs<this>) => this.registerApi('OPTIONS', ...args);
|
|
227
|
+
public get = (...args: TApiRegisterArgs<this>) => this.registerApi('GET', ...args);
|
|
228
|
+
public post = (...args: TApiRegisterArgs<this>) => this.registerApi('POST', ...args);
|
|
229
|
+
public put = (...args: TApiRegisterArgs<this>) => this.registerApi('PUT', ...args);
|
|
230
|
+
public delete = (...args: TApiRegisterArgs<this>) => this.registerApi('DELETE', ...args)
|
|
161
231
|
|
|
162
|
-
|
|
232
|
+
protected registerApi(method: TRouteHttpMethod, ...args: TApiRegisterArgs<this>): this {
|
|
163
233
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
234
|
+
let path: string;
|
|
235
|
+
let options: Partial<TRouteOptions> = {};
|
|
236
|
+
let controller: TServerController<this>;
|
|
237
|
+
|
|
238
|
+
if (args.length === 2)
|
|
239
|
+
([path, controller] = args)
|
|
240
|
+
else
|
|
241
|
+
([path, options, controller] = args)
|
|
242
|
+
|
|
243
|
+
const { regex, keys } = buildRegex(path);
|
|
244
|
+
|
|
245
|
+
const route: TRoute = {
|
|
246
|
+
|
|
247
|
+
method: method,
|
|
248
|
+
path: path,
|
|
168
249
|
regex,
|
|
169
|
-
keys: keys
|
|
250
|
+
keys: keys,
|
|
170
251
|
options: {
|
|
171
252
|
...defaultOptions,
|
|
172
|
-
accept: 'html', // Les pages retournent forcémment du html
|
|
173
253
|
...options
|
|
174
254
|
},
|
|
175
|
-
controller
|
|
255
|
+
controller
|
|
256
|
+
}
|
|
176
257
|
|
|
177
|
-
|
|
178
|
-
});
|
|
258
|
+
this.routes.push(route);
|
|
179
259
|
|
|
180
260
|
return this;
|
|
181
|
-
|
|
182
261
|
}
|
|
183
262
|
|
|
184
263
|
private async afterRegister() {
|
|
185
264
|
|
|
186
265
|
console.info("Pre-Loading request services");
|
|
187
|
-
await TrackingService.LoadCache();
|
|
266
|
+
//await TrackingService.LoadCache();
|
|
188
267
|
|
|
189
268
|
console.info("Loading routes ...");
|
|
190
269
|
|
|
@@ -206,19 +285,19 @@ export class Router extends BaseRouter {
|
|
|
206
285
|
console.info(`Registered routes:`);
|
|
207
286
|
for (const route of this.routes) {
|
|
208
287
|
|
|
288
|
+
const chunkId = route.options["id"];
|
|
289
|
+
|
|
209
290
|
console.info('-',
|
|
210
|
-
route.type,
|
|
211
291
|
route.method,
|
|
212
292
|
route.path,
|
|
213
293
|
' :: ', JSON.stringify(route.options)
|
|
214
294
|
);
|
|
215
295
|
|
|
216
|
-
if (
|
|
296
|
+
if (route.options["id"])
|
|
217
297
|
this.ssrRoutes.push({
|
|
218
|
-
type: route.type,
|
|
219
298
|
regex: route.regex.source,
|
|
220
299
|
keys: route.keys,
|
|
221
|
-
chunk:
|
|
300
|
+
chunk: chunkId
|
|
222
301
|
});
|
|
223
302
|
|
|
224
303
|
}
|
|
@@ -227,15 +306,26 @@ export class Router extends BaseRouter {
|
|
|
227
306
|
for (const code in this.errors) {
|
|
228
307
|
|
|
229
308
|
const route = this.errors[code];
|
|
230
|
-
|
|
309
|
+
const chunkId = route.options["id"];
|
|
310
|
+
|
|
311
|
+
console.info('-', code,
|
|
312
|
+
' :: ', JSON.stringify(route.options)
|
|
313
|
+
);
|
|
231
314
|
|
|
232
315
|
this.ssrRoutes.push({
|
|
233
|
-
|
|
234
|
-
chunk:
|
|
235
|
-
code
|
|
316
|
+
code: parseInt(code),
|
|
317
|
+
chunk: chunkId,
|
|
236
318
|
});
|
|
237
319
|
}
|
|
238
320
|
|
|
321
|
+
console.info(`Registered layouts:`);
|
|
322
|
+
for (const layoutId in layoutsList) {
|
|
323
|
+
|
|
324
|
+
const layout = layoutsList[layoutId];
|
|
325
|
+
|
|
326
|
+
console.info('-', layoutId, layout);
|
|
327
|
+
}
|
|
328
|
+
|
|
239
329
|
console.info(this.routes.length + " routes where registered.");
|
|
240
330
|
}
|
|
241
331
|
|
|
@@ -257,6 +347,7 @@ export class Router extends BaseRouter {
|
|
|
257
347
|
let requestId = uuid();
|
|
258
348
|
const request = new ServerRequest(
|
|
259
349
|
requestId,
|
|
350
|
+
|
|
260
351
|
req.method as HttpMethod,
|
|
261
352
|
req.path, // url sans params
|
|
262
353
|
// Exclusion de req.files, car le middleware multipart les a normalisé dans req.body
|
|
@@ -267,7 +358,11 @@ export class Router extends BaseRouter {
|
|
|
267
358
|
this
|
|
268
359
|
);
|
|
269
360
|
|
|
270
|
-
|
|
361
|
+
// Hook
|
|
362
|
+
await this.runHook('request', request);
|
|
363
|
+
|
|
364
|
+
// TODO: move to tracking
|
|
365
|
+
/*const now = new Date;
|
|
271
366
|
|
|
272
367
|
// Identify Guest & create log entry
|
|
273
368
|
const username = request.user?.name;
|
|
@@ -280,41 +375,18 @@ export class Router extends BaseRouter {
|
|
|
280
375
|
|
|
281
376
|
const keepLogs = request.ip !== '86.76.176.80';
|
|
282
377
|
if (!keepLogs)
|
|
283
|
-
requestId = 'admin'
|
|
378
|
+
requestId = 'admin';*/
|
|
284
379
|
|
|
285
380
|
// Create request context so we can access request context across all the request-triggered libs
|
|
286
381
|
context.run({ channelType: 'request', channelId: requestId }, async () => {
|
|
287
382
|
|
|
288
|
-
let response: ServerResponse
|
|
383
|
+
let response: ServerResponse<this>;
|
|
289
384
|
try {
|
|
290
|
-
|
|
291
|
-
// Auth
|
|
292
|
-
request.user = await AuthService.decode(req, true);
|
|
293
385
|
|
|
294
386
|
// Bulk API Requests
|
|
295
387
|
if (request.path === '/api' && typeof request.data.fetchers === "object") {
|
|
296
388
|
|
|
297
|
-
|
|
298
|
-
for (const id in request.data.fetchers) {
|
|
299
|
-
|
|
300
|
-
const [method, path, data] = request.data.fetchers[id] as TFetcherArgs;
|
|
301
|
-
|
|
302
|
-
const response = await this.resolve(
|
|
303
|
-
request.children(method, path, data)
|
|
304
|
-
);
|
|
305
|
-
|
|
306
|
-
responseData[id] = response.data;
|
|
307
|
-
|
|
308
|
-
// TODO: merge response.headers ?
|
|
309
|
-
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
// Status
|
|
313
|
-
res.status(200);
|
|
314
|
-
// Data
|
|
315
|
-
res.json(responseData);
|
|
316
|
-
|
|
317
|
-
return;
|
|
389
|
+
return await this.resolveApiBatch(request);
|
|
318
390
|
|
|
319
391
|
} else {
|
|
320
392
|
response = await this.resolve(request);
|
|
@@ -330,8 +402,9 @@ export class Router extends BaseRouter {
|
|
|
330
402
|
// Data
|
|
331
403
|
res.send(response.data);
|
|
332
404
|
|
|
333
|
-
|
|
334
|
-
|
|
405
|
+
// TODO: move to tracking
|
|
406
|
+
/*if (newClient)
|
|
407
|
+
console.client({
|
|
335
408
|
id: clientId,
|
|
336
409
|
ip: request.ip,
|
|
337
410
|
user: username,
|
|
@@ -340,7 +413,7 @@ export class Router extends BaseRouter {
|
|
|
340
413
|
activity: now,
|
|
341
414
|
});
|
|
342
415
|
|
|
343
|
-
|
|
416
|
+
console.request({
|
|
344
417
|
|
|
345
418
|
id: requestId,
|
|
346
419
|
date: now,
|
|
@@ -355,85 +428,46 @@ export class Router extends BaseRouter {
|
|
|
355
428
|
|
|
356
429
|
statusCode: response.statusCode,
|
|
357
430
|
time: Date.now() - now.valueOf()
|
|
358
|
-
})
|
|
431
|
+
});*/
|
|
359
432
|
});
|
|
360
|
-
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
private async handleError(e: Error, request: ServerRequest) {
|
|
364
|
-
|
|
365
|
-
const code = 'http' in e ? e.http : 500;
|
|
366
|
-
const route = this.errors[code];
|
|
367
|
-
if (route === undefined)
|
|
368
|
-
throw new Error(`No route for error code ${code}`);
|
|
369
|
-
|
|
370
|
-
const response = new ServerResponse(request).status(code).setRoute(route);
|
|
371
|
-
|
|
372
|
-
// Rapport / debug
|
|
373
|
-
if (code === 500) {
|
|
374
|
-
|
|
375
|
-
for (const callback of app.hooks.error)
|
|
376
|
-
callback(e);
|
|
377
|
-
|
|
378
|
-
$.console.bugReport.server(e, request);
|
|
379
|
-
|
|
380
|
-
// Pour déboguer les erreurs HTTP
|
|
381
|
-
} else if (app.env.profile === "dev")
|
|
382
|
-
console.warn(e);
|
|
383
|
-
|
|
384
|
-
if (request.accepts("html"))
|
|
385
|
-
await response.runController( route, { message: e.message });
|
|
386
|
-
else if (request.accepts("json"))
|
|
387
|
-
await response.json(e.message);
|
|
388
|
-
else
|
|
389
|
-
await response.text(e.message);
|
|
390
|
-
|
|
391
|
-
return response;
|
|
392
|
-
|
|
393
433
|
}
|
|
394
434
|
|
|
395
|
-
public async resolve(
|
|
435
|
+
public async resolve(request: ServerRequest<this>): Promise<ServerResponse<this>> {
|
|
396
436
|
|
|
397
|
-
console.info(request.ip, request.method, request.domain, request.path);
|
|
437
|
+
console.info(request.ip, request.method, request.domain, request.path, 'user =', request.user);
|
|
398
438
|
|
|
399
|
-
const response = new ServerResponse(request);
|
|
439
|
+
const response = new ServerResponse<this>(request);
|
|
400
440
|
|
|
401
|
-
|
|
441
|
+
await this.runHook('resolve', request);
|
|
402
442
|
|
|
403
443
|
for (const route of this.routes) {
|
|
404
444
|
|
|
405
|
-
// Method
|
|
445
|
+
// Match Method
|
|
406
446
|
if (request.method !== route.method && route.method !== '*')
|
|
407
447
|
continue;
|
|
408
448
|
|
|
409
|
-
// Response format
|
|
449
|
+
// Match Response format
|
|
410
450
|
if (!request.accepts(route.options.accept))
|
|
411
451
|
continue;
|
|
412
452
|
|
|
413
|
-
//
|
|
453
|
+
// Match Path
|
|
414
454
|
const match = route.regex.exec(request.path);
|
|
415
455
|
if (!match)
|
|
416
456
|
continue;
|
|
417
457
|
|
|
418
|
-
//
|
|
419
|
-
if (route.options.TESTING === true && !(request.user && request.user.email === "Decentraliseur"))
|
|
420
|
-
break;
|
|
421
|
-
|
|
422
|
-
// Auth
|
|
423
|
-
if (route.options.auth !== undefined)
|
|
424
|
-
request.auth.check(route.options.auth);
|
|
425
|
-
|
|
426
|
-
//console.log('Resolved route:', route.regex.source);
|
|
427
|
-
|
|
458
|
+
// Extract URL params
|
|
428
459
|
for (let iKey = 0; iKey < route.keys.length; iKey++) {
|
|
429
460
|
const nomParam = route.keys[iKey];
|
|
430
461
|
if (typeof nomParam === 'string') // number = sans nom
|
|
431
462
|
request.data[nomParam] = match[iKey + 1]
|
|
432
463
|
}
|
|
433
464
|
|
|
465
|
+
// Run on resolution hooks. Ex: authentication check
|
|
466
|
+
await this.runHook('resolved', route);
|
|
467
|
+
|
|
434
468
|
// Create response
|
|
435
469
|
await response.runController(route);
|
|
436
|
-
if (response.wasProvided)
|
|
470
|
+
if (response.wasProvided)
|
|
437
471
|
// On continue l'itération des routes, sauf si des données ont été fournie dans la réponse (.json(), .html(), ...)
|
|
438
472
|
return response;
|
|
439
473
|
}
|
|
@@ -441,20 +475,56 @@ export class Router extends BaseRouter {
|
|
|
441
475
|
throw new NotFound(`The requested endpoint was not found.`);
|
|
442
476
|
}
|
|
443
477
|
|
|
444
|
-
|
|
478
|
+
private async resolveApiBatch( request: ServerRequest<this> ) {
|
|
479
|
+
|
|
480
|
+
const responseData: TObjetDonnees = {};
|
|
481
|
+
for (const id in request.data.fetchers) {
|
|
482
|
+
|
|
483
|
+
const [method, path, data] = request.data.fetchers[id] as TFetcherArgs;
|
|
484
|
+
|
|
485
|
+
const response = await this.resolve(
|
|
486
|
+
request.children(method, path, data)
|
|
487
|
+
);
|
|
488
|
+
|
|
489
|
+
responseData[id] = response.data;
|
|
490
|
+
|
|
491
|
+
// TODO: merge response.headers ?
|
|
445
492
|
|
|
446
|
-
/*----------------------------------
|
|
447
|
-
- REGISTER SERVICE
|
|
448
|
-
----------------------------------*/
|
|
449
|
-
app.register('router', Router);
|
|
450
|
-
declare global {
|
|
451
|
-
namespace Core {
|
|
452
|
-
interface Services {
|
|
453
|
-
router: Router;
|
|
454
493
|
}
|
|
494
|
+
|
|
495
|
+
// Status
|
|
496
|
+
request.res.status(200);
|
|
497
|
+
// Data
|
|
498
|
+
request.res.json(responseData);
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
private async handleError(e: Erreur, request: ServerRequest<ServerRouter>) {
|
|
502
|
+
|
|
503
|
+
const code = 'http' in e ? e.http : 500;
|
|
504
|
+
const route = this.errors[code];
|
|
505
|
+
if (route === undefined)
|
|
506
|
+
throw new Error(`No route for error code ${code}`);
|
|
507
|
+
|
|
508
|
+
const response = new ServerResponse(request).status(code).setRoute(route);
|
|
509
|
+
|
|
510
|
+
// Rapport / debug
|
|
511
|
+
if (code === 500) {
|
|
512
|
+
|
|
513
|
+
await this.app.runHook('error', e, request);
|
|
514
|
+
|
|
515
|
+
// Pour déboguer les erreurs HTTP
|
|
516
|
+
} else if (this.app.env.profile === "dev")
|
|
517
|
+
console.warn(e);
|
|
518
|
+
|
|
519
|
+
if (request.accepts("html"))
|
|
520
|
+
await response.runController(route, { message: e.message });
|
|
521
|
+
else if (request.accepts("json"))
|
|
522
|
+
await response.json(e.message);
|
|
523
|
+
else
|
|
524
|
+
await response.text(e.message);
|
|
525
|
+
|
|
526
|
+
return response;
|
|
527
|
+
|
|
455
528
|
}
|
|
456
|
-
}
|
|
457
529
|
|
|
458
|
-
|
|
459
|
-
// Bacause import router from '@router'; need to be available both on client and sevrer side.
|
|
460
|
-
export default app.services.router;
|
|
530
|
+
}
|