proteum 1.0.0-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 (156) hide show
  1. package/.dockerignore +10 -0
  2. package/Rte.zip +0 -0
  3. package/cli/app/config.ts +54 -0
  4. package/cli/app/index.ts +195 -0
  5. package/cli/bin.js +11 -0
  6. package/cli/commands/build.ts +34 -0
  7. package/cli/commands/deploy/app.ts +29 -0
  8. package/cli/commands/deploy/web.ts +60 -0
  9. package/cli/commands/dev.ts +109 -0
  10. package/cli/commands/init.ts +85 -0
  11. package/cli/compiler/client/identite.ts +72 -0
  12. package/cli/compiler/client/index.ts +334 -0
  13. package/cli/compiler/common/babel/index.ts +170 -0
  14. package/cli/compiler/common/babel/plugins/index.ts +0 -0
  15. package/cli/compiler/common/babel/plugins/services.ts +579 -0
  16. package/cli/compiler/common/babel/routes/imports.ts +127 -0
  17. package/cli/compiler/common/babel/routes/routes.ts +1130 -0
  18. package/cli/compiler/common/files/autres.ts +39 -0
  19. package/cli/compiler/common/files/images.ts +35 -0
  20. package/cli/compiler/common/files/style.ts +78 -0
  21. package/cli/compiler/common/index.ts +154 -0
  22. package/cli/compiler/index.ts +532 -0
  23. package/cli/compiler/server/index.ts +211 -0
  24. package/cli/index.ts +189 -0
  25. package/cli/paths.ts +165 -0
  26. package/cli/print.ts +12 -0
  27. package/cli/tsconfig.json +38 -0
  28. package/cli/utils/index.ts +22 -0
  29. package/cli/utils/keyboard.ts +78 -0
  30. package/client/app/component.tsx +54 -0
  31. package/client/app/index.ts +142 -0
  32. package/client/app/service.ts +34 -0
  33. package/client/app.tsconfig.json +28 -0
  34. package/client/components/Button.tsx +298 -0
  35. package/client/components/Dialog/Manager.tsx +309 -0
  36. package/client/components/Dialog/card.tsx +208 -0
  37. package/client/components/Dialog/index.less +151 -0
  38. package/client/components/Dialog/status.less +176 -0
  39. package/client/components/Dialog/status.tsx +48 -0
  40. package/client/components/index.ts +2 -0
  41. package/client/components/types.d.ts +3 -0
  42. package/client/data/input.ts +32 -0
  43. package/client/global.d.ts +5 -0
  44. package/client/hooks.ts +22 -0
  45. package/client/index.ts +6 -0
  46. package/client/pages/_layout/index.less +6 -0
  47. package/client/pages/_layout/index.tsx +43 -0
  48. package/client/pages/bug.tsx.old +60 -0
  49. package/client/pages/useHeader.tsx +50 -0
  50. package/client/services/captcha/index.ts +67 -0
  51. package/client/services/router/components/Link.tsx +46 -0
  52. package/client/services/router/components/Page.tsx +55 -0
  53. package/client/services/router/components/router.tsx +218 -0
  54. package/client/services/router/index.tsx +521 -0
  55. package/client/services/router/request/api.ts +267 -0
  56. package/client/services/router/request/history.ts +5 -0
  57. package/client/services/router/request/index.ts +53 -0
  58. package/client/services/router/request/multipart.ts +147 -0
  59. package/client/services/router/response/index.tsx +128 -0
  60. package/client/services/router/response/page.ts +86 -0
  61. package/client/services/socket/index.ts +147 -0
  62. package/client/utils/dom.ts +77 -0
  63. package/common/app/index.ts +9 -0
  64. package/common/data/chaines/index.ts +54 -0
  65. package/common/data/dates.ts +179 -0
  66. package/common/data/markdown.ts +73 -0
  67. package/common/data/rte/nodes.ts +83 -0
  68. package/common/data/stats.ts +90 -0
  69. package/common/errors/index.tsx +326 -0
  70. package/common/router/index.ts +213 -0
  71. package/common/router/layouts.ts +93 -0
  72. package/common/router/register.ts +55 -0
  73. package/common/router/request/api.ts +77 -0
  74. package/common/router/request/index.ts +35 -0
  75. package/common/router/response/index.ts +45 -0
  76. package/common/router/response/page.ts +128 -0
  77. package/common/utils/rte.ts +183 -0
  78. package/common/utils.ts +7 -0
  79. package/doc/TODO.md +71 -0
  80. package/doc/front/router.md +27 -0
  81. package/doc/workspace/workspace.png +0 -0
  82. package/doc/workspace/workspace2.png +0 -0
  83. package/doc/workspace/workspace_26.01.22.png +0 -0
  84. package/package.json +171 -0
  85. package/server/app/commands.ts +141 -0
  86. package/server/app/container/config.ts +203 -0
  87. package/server/app/container/console/index.ts +550 -0
  88. package/server/app/container/index.ts +137 -0
  89. package/server/app/index.ts +273 -0
  90. package/server/app/service/container.ts +88 -0
  91. package/server/app/service/index.ts +235 -0
  92. package/server/app.tsconfig.json +28 -0
  93. package/server/context.ts +4 -0
  94. package/server/index.ts +4 -0
  95. package/server/services/auth/index.ts +250 -0
  96. package/server/services/auth/old.ts +277 -0
  97. package/server/services/auth/router/index.ts +95 -0
  98. package/server/services/auth/router/request.ts +54 -0
  99. package/server/services/auth/router/service.json +6 -0
  100. package/server/services/auth/service.json +6 -0
  101. package/server/services/cache/commands.ts +41 -0
  102. package/server/services/cache/index.ts +297 -0
  103. package/server/services/cache/service.json +6 -0
  104. package/server/services/cron/CronTask.ts +86 -0
  105. package/server/services/cron/index.ts +112 -0
  106. package/server/services/cron/service.json +6 -0
  107. package/server/services/disks/driver.ts +103 -0
  108. package/server/services/disks/drivers/local/index.ts +188 -0
  109. package/server/services/disks/drivers/local/service.json +6 -0
  110. package/server/services/disks/drivers/s3/index.ts +301 -0
  111. package/server/services/disks/drivers/s3/service.json +6 -0
  112. package/server/services/disks/index.ts +90 -0
  113. package/server/services/disks/service.json +6 -0
  114. package/server/services/email/index.ts +188 -0
  115. package/server/services/email/utils.ts +53 -0
  116. package/server/services/fetch/index.ts +201 -0
  117. package/server/services/fetch/service.json +7 -0
  118. package/server/services/models.7z +0 -0
  119. package/server/services/prisma/Facet.ts +142 -0
  120. package/server/services/prisma/index.ts +201 -0
  121. package/server/services/prisma/service.json +6 -0
  122. package/server/services/router/http/index.ts +217 -0
  123. package/server/services/router/http/multipart.ts +102 -0
  124. package/server/services/router/http/session.ts.old +40 -0
  125. package/server/services/router/index.ts +801 -0
  126. package/server/services/router/request/api.ts +87 -0
  127. package/server/services/router/request/index.ts +184 -0
  128. package/server/services/router/request/service.ts +21 -0
  129. package/server/services/router/request/validation/zod.ts +180 -0
  130. package/server/services/router/response/index.ts +338 -0
  131. package/server/services/router/response/mask/Filter.ts +323 -0
  132. package/server/services/router/response/mask/index.ts +60 -0
  133. package/server/services/router/response/mask/selecteurs.ts +92 -0
  134. package/server/services/router/response/page/document.tsx +160 -0
  135. package/server/services/router/response/page/index.tsx +196 -0
  136. package/server/services/router/service.json +6 -0
  137. package/server/services/router/service.ts +36 -0
  138. package/server/services/schema/index.ts +44 -0
  139. package/server/services/schema/request.ts +49 -0
  140. package/server/services/schema/router/index.ts +28 -0
  141. package/server/services/schema/router/service.json +6 -0
  142. package/server/services/schema/service.json +6 -0
  143. package/server/services/security/encrypt/aes/index.ts +85 -0
  144. package/server/services/security/encrypt/aes/service.json +6 -0
  145. package/server/services/socket/index.ts +162 -0
  146. package/server/services/socket/scope.ts +226 -0
  147. package/server/services/socket/service.json +6 -0
  148. package/server/services_old/SocketClient.ts +92 -0
  149. package/server/services_old/Token.old.ts +97 -0
  150. package/server/utils/slug.ts +79 -0
  151. package/tsconfig.common.json +45 -0
  152. package/tsconfig.json +3 -0
  153. package/types/aliases.d.ts +54 -0
  154. package/types/global/modules.d.ts +49 -0
  155. package/types/global/utils.d.ts +103 -0
  156. package/types/icons.d.ts +1 -0
@@ -0,0 +1,90 @@
1
+ import hInterval from 'human-interval';
2
+
3
+ type TObjDonneesStats = { [cheminStats: string]: number }
4
+ export type TStat<TDonnees extends TObjDonneesStats> = { date: string } & TDonnees
5
+ export type TTimeStat<TDonnees extends TObjDonneesStats> = { time: number } & TDonnees
6
+
7
+ /*----------------------------------
8
+ - OUTILS DE TRAITEMENT
9
+ ----------------------------------*/
10
+ type TRetourStats<TDonnees extends TObjDonneesStats> = {
11
+ graph: TTimeStat<TDonnees>[],
12
+ total: TDonnees,
13
+
14
+ start: Date,
15
+ end: Date,
16
+ interval: number,
17
+ }
18
+
19
+ export const buildStats = <TDonnees extends TObjDonneesStats>(
20
+ periodStr: string,
21
+ intervalStr: string,
22
+ data: TStat<TDonnees>[]
23
+ ): TRetourStats<TDonnees> => {
24
+
25
+ // NOTE: On ne génère pas le timestamp via la bdd pour éviter les incohérences de timezone
26
+
27
+ if (!Array.isArray(data)) {
28
+ console.log('data =', data);
29
+ throw new Error(`Stats data must be an array (received ${typeof data}). See console for full provided data.`);
30
+ }
31
+
32
+ const periodTime = hInterval(periodStr);
33
+ if (periodTime === undefined) throw new Error(`Invalid period string`);
34
+ const intervalTime = hInterval(intervalStr);
35
+ if (intervalTime === undefined) throw new Error(`Invalid interval string`);
36
+
37
+ let start = Date.now() - periodTime
38
+ start -= start % intervalTime; // Round start date to the specified interval
39
+ const end = Date.now()
40
+
41
+ const total: TDonnees = {} as TDonnees
42
+ let graph: TTimeStat<TDonnees>[] = []
43
+ if (data.length > 0) {
44
+
45
+ // Group data by time
46
+ const groups: { [timestamp: number]: TTimeStat<TDonnees> } = {};
47
+ for (const { date, ...stats } of data) {
48
+
49
+ if (date === undefined)
50
+ throw new Error(`La date est absente des données statistiques. Est-elle bien spécifiée dans le SELECT ?`);
51
+
52
+ const timeA = new Date(date).getTime();
53
+ groups[timeA] = { time: timeA, ...stats };
54
+ }
55
+
56
+ // Completion
57
+ for (let timeA = start; timeA <= end; timeA += intervalTime) {
58
+
59
+ const stats = { time: timeA, ...total }
60
+
61
+ if (groups[timeA] !== undefined)
62
+ for (const nom in groups[timeA]) {
63
+
64
+ // numeric value only
65
+ if (typeof groups[timeA][nom] !== 'number')
66
+ continue;
67
+
68
+ // Add cumulated value
69
+ stats[nom] = stats[nom] === undefined
70
+ ? groups[timeA][nom]
71
+ : stats[nom] + groups[timeA][nom];
72
+
73
+ total[nom] = stats[nom];
74
+
75
+ }
76
+
77
+ graph.push(stats);
78
+
79
+ }
80
+ }
81
+
82
+ return {
83
+ graph,
84
+ total,
85
+ start: new Date(start),
86
+ end: new Date(end),
87
+ interval: intervalTime
88
+ };
89
+
90
+ }
@@ -0,0 +1,326 @@
1
+ import React from 'react';
2
+ import type { ComponentChild } from 'preact';
3
+
4
+ import type { TJsonLog } from '@server/app/container/console';
5
+ import type ServerRequest from '@server/services/router/request';
6
+ import type { TBasicUser } from '@server/services/auth';
7
+
8
+ /*----------------------------------
9
+ - TYPES
10
+ ----------------------------------*/
11
+
12
+ export type TListeErreursSaisie<TClesDonnees extends string = string> = {[champ in TClesDonnees]: string[]}
13
+
14
+ export type TJsonError = {
15
+ code: number,
16
+ origin?: string,
17
+ message: string,
18
+ // Form fields
19
+ errors?: TListeErreursSaisie
20
+ } & TErrorDetails
21
+
22
+ type TErrorDetails = {
23
+
24
+ // Allow to identify the error catched (ex: displaying custop content, running custom actions, ...)
25
+ id?: string,
26
+ data?: {},
27
+
28
+ cta?: {
29
+ label: string,
30
+ link: string,
31
+ },
32
+
33
+ // For debugging
34
+ stack?: string,
35
+ origin?: string,
36
+ }
37
+
38
+ /*----------------------------------
39
+ - TYPES: AUTH REQUIRED FEATURE
40
+ ----------------------------------*/
41
+
42
+ /**
43
+ * Global, augmentable feature catalog used to constrain the `feature` argument
44
+ * of `AuthRequired`.
45
+ *
46
+ * Default behavior (no augmentation): `feature` stays a free-form string.
47
+ * App behavior (augmentation provided by the host app): `feature` becomes a
48
+ * curated union of feature keys.
49
+ */
50
+ declare global {
51
+ interface TAuthRequiredFeatureCatalog {}
52
+ }
53
+
54
+ type TAuthRequiredFeatureKey = Extract<keyof TAuthRequiredFeatureCatalog, string>;
55
+ type TAuthRequiredFeature = [TAuthRequiredFeatureKey] extends [never]
56
+ ? string
57
+ : TAuthRequiredFeatureKey;
58
+
59
+ /*----------------------------------
60
+ - TYPES: BUG REPORT
61
+ ----------------------------------*/
62
+
63
+ export type ServerBug = {
64
+
65
+ // Context
66
+ hash: string,
67
+ isDuplicate: boolean,
68
+ date: Date, // Timestamp
69
+ channelType?: string,
70
+ channelId?: string,
71
+
72
+ // User
73
+ user?: TBasicUser | null,
74
+ ip?: string | null,
75
+
76
+ // Request
77
+ request?: {
78
+ method: ServerRequest["method"],
79
+ url: ServerRequest["url"],
80
+ data: ServerRequest["data"],
81
+ validatedData: ServerRequest["validatedData"],
82
+ headers: ServerRequest["headers"],
83
+ cookies: ServerRequest["cookies"],
84
+ },
85
+
86
+ // Error
87
+ title?: string,
88
+ stacktraces: string[],
89
+ context: object[],
90
+ }
91
+
92
+ export type TCatchedError = Error | CoreError | Anomaly;
93
+
94
+ /*----------------------------------
95
+ - ERREURS
96
+ ----------------------------------*/
97
+ export abstract class CoreError extends Error {
98
+
99
+ public static msgDefaut: string;
100
+
101
+ public abstract http: number;
102
+ public title: string = "Uh Oh ...";
103
+ public message: string;
104
+ public details: TErrorDetails = {};
105
+
106
+ // Note: On ne le redéfini pas ici, car déjà présent dans Error
107
+ // La redéfinition reset la valeur du stacktrace
108
+ //public stack?: string;
109
+
110
+ public constructor(message?: string, details?: TErrorDetails) {
111
+
112
+ super(message);
113
+
114
+ this.message = message || (this.constructor as typeof CoreError).msgDefaut;
115
+ this.details = details || {};
116
+
117
+ // Inject stack
118
+ if (details !== undefined)
119
+ this.stack = details.stack;
120
+
121
+ }
122
+
123
+ public json(): TJsonError {
124
+
125
+ return {
126
+ code: this.http,
127
+ message: this.message,
128
+ ...this.details
129
+ }
130
+ }
131
+
132
+ public toString() {
133
+ return this.message;
134
+ }
135
+
136
+ public render?(): ComponentChild;
137
+ }
138
+
139
+ export class InputError extends CoreError {
140
+ public http = 400;
141
+ public title = "Bad Request";
142
+ public static msgDefaut = "Bad Request.";
143
+ }
144
+
145
+ export class InputErrorSchema extends CoreError {
146
+
147
+ public http = 400;
148
+ public title = "Bad Request";
149
+ public static msgDefaut = "Bad Request.";
150
+
151
+ private static listeToString(liste: TListeErreursSaisie) {
152
+ let chaines: string[] = []
153
+ for (const champ in liste)
154
+ chaines.push(champ + ': ' + liste[champ].join('. '));
155
+ return chaines.join('; ');
156
+ }
157
+
158
+ public constructor( public errors: TListeErreursSaisie, details?: TErrorDetails) {
159
+
160
+ super( InputErrorSchema.listeToString(errors), details );
161
+
162
+ }
163
+
164
+ public json(): TJsonError {
165
+ return {
166
+ ...super.json(),
167
+ errors: this.errors,
168
+ }
169
+ }
170
+
171
+ public render(): ComponentChild {
172
+ return (
173
+ <ul class="col al-left">
174
+ {Object.keys(this.errors).map( champ => (
175
+ <li>{champ}: {this.errors[champ].join('. ')}</li>
176
+ ))}
177
+ </ul>
178
+ )
179
+ }
180
+ }
181
+
182
+ export class AuthRequired extends CoreError {
183
+ public http = 401;
184
+ public title = "Authentication Required";
185
+ public static msgDefaut = "Please Login to Continue.";
186
+
187
+ public constructor(message: string, feature?: TAuthRequiredFeature);
188
+ public constructor(message: string, motivation: string | undefined, details: TErrorDetails | undefined);
189
+ public constructor(
190
+ message: string,
191
+ public feature?: string,
192
+ details?: TErrorDetails
193
+ ) {
194
+ super(message, details);
195
+ }
196
+
197
+ public json(): TJsonError & { feature?: string } {
198
+ return {
199
+ ...super.json(),
200
+ feature: this.feature,
201
+ }
202
+ }
203
+ }
204
+
205
+ export class UpgradeRequired extends CoreError {
206
+ public http = 402;
207
+ public title = "Upgrade Required";
208
+ public static msgDefaut = "Please Upgrade to Continue.";
209
+
210
+ public constructor(
211
+ message: string,
212
+ public feature: string,
213
+ details?: TErrorDetails
214
+ ) {
215
+ super(message, details);
216
+ }
217
+
218
+ public json(): TJsonError & { feature: string } {
219
+ return {
220
+ ...super.json(),
221
+ feature: this.feature,
222
+ }
223
+ }
224
+ }
225
+
226
+ export class Forbidden extends CoreError {
227
+ public http = 403;
228
+ public title = "Access Denied";
229
+ public static msgDefaut = "You do not have sufficient permissions to access this content.";
230
+ }
231
+
232
+ export class NotFound extends CoreError {
233
+ public http = 404;
234
+ public title = "Not Found";
235
+ public static msgDefaut = "The resource you asked for was not found.";
236
+ }
237
+
238
+ export class Gone extends CoreError {
239
+ public http = 410;
240
+ public title = "Gone";
241
+ public static msgDefaut = "The resource you asked for has been removed.";
242
+ }
243
+
244
+ export class RateLimit extends CoreError {
245
+ public http = 429;
246
+ public title = "You're going too fast";
247
+ public static msgDefaut = "Please slow down a bit and retry again later.";
248
+ }
249
+
250
+ export class Anomaly extends CoreError {
251
+
252
+ public http = 500;
253
+ public title = "Technical Error";
254
+ public static msgDefaut = "A technical error has occurred. A notification has just been sent to the admin.";
255
+
256
+ public constructor(
257
+ message: string,
258
+ public dataForDebugging?: object,
259
+ public originalError?: Error,
260
+ ) {
261
+ super(message);
262
+ }
263
+ }
264
+
265
+ export class NotAvailable extends CoreError {
266
+
267
+ // TODO: page erreur pour code 503
268
+ public http = 404;
269
+ public title = "Not Available";
270
+ public static msgDefaut = "Sorry, the service is currently not available.";
271
+ }
272
+
273
+ export class NetworkError extends Error {
274
+ public title = "Network Error";
275
+ }
276
+
277
+
278
+ export const viaHttpCode = (
279
+ code: number,
280
+ message: string,
281
+ details?: TErrorDetails
282
+ ): CoreError => {
283
+ return fromJson({
284
+ code,
285
+ message,
286
+ ...details
287
+ });
288
+ }
289
+
290
+ export const toJson = (e: Error | CoreError): TJsonError => {
291
+
292
+ if (('json' in e) && typeof e.json === 'function')
293
+ return e.json();
294
+
295
+ const details = ('details' in e)
296
+ ? e.details
297
+ : { stack: e.stack };
298
+
299
+ return { code: 500, message: e.message, ...details }
300
+ }
301
+
302
+ export const fromJson = ({ code, message, ...details }: TJsonError) => {
303
+
304
+ switch (code) {
305
+ case 400:
306
+ if (details.errors)
307
+ return new InputErrorSchema( details.errors, details );
308
+ else
309
+ return new InputError( message, details );
310
+
311
+ case 401: return new AuthRequired( message, (details as any).feature, details );
312
+
313
+ case 402: return new UpgradeRequired( message, details.feature, details );
314
+
315
+ case 403: return new Forbidden( message, details );
316
+
317
+ case 404: return new NotFound( message, details );
318
+
319
+ case 429: return new RateLimit( message, details );
320
+
321
+ default: return new Anomaly( message, details );
322
+ }
323
+
324
+ }
325
+
326
+ export default CoreError;
@@ -0,0 +1,213 @@
1
+ /*----------------------------------
2
+ - DEPENDANCES
3
+ ----------------------------------*/
4
+
5
+ // Npm
6
+ import type zod from 'zod';
7
+
8
+ // types
9
+ import type {
10
+ default as ClientRouter,
11
+ TRouterContext as ClientRouterContext,
12
+ TRegisterPageArgs
13
+ } from '@client/services/router';
14
+
15
+ import type {
16
+ TAnyRouter,
17
+ TRouterContext as ServerRouterContext,
18
+ TRouteHttpMethod
19
+ } from '@server/services/router';
20
+
21
+ import type RouterRequest from './request';
22
+
23
+ import type { TUserRole } from '@server/services/auth';
24
+
25
+ import type { TAppArrowFunction } from '@common/app';
26
+
27
+ // Specfic
28
+ import type { default as Page, TFrontRenderer, TDataProvider } from './response/page';
29
+
30
+ /*----------------------------------
31
+ - TYPES: ROUTES
32
+ ----------------------------------*/
33
+
34
+ export type { Layout } from './layouts';
35
+
36
+ export type { default as Request } from './request';
37
+ export type { default as Response } from './response';
38
+
39
+ export type ClientOrServerRouter = ClientRouter | TAnyRouter;
40
+
41
+ export type TRoute<RouterContext extends TClientOrServerContextForPage = TClientOrServerContextForPage> = {
42
+
43
+ // Match
44
+ method: TRouteHttpMethod,
45
+ path: string,
46
+
47
+ // Execute
48
+ schema?: zod.ZodSchema,
49
+ controller: TRouteController<RouterContext>,
50
+ options: TRouteOptions
51
+ } & (
52
+ // With regex
53
+ {
54
+ regex: RegExp,
55
+ keys: (number | string)[],
56
+ }
57
+ // Without regex (for ex: controllers)
58
+ |
59
+ {
60
+ regex?: undefined,
61
+ keys?: undefined,
62
+ }
63
+ )
64
+
65
+ export type TErrorRoute<RouterContext extends TClientOrServerContextForPage = TClientOrServerContextForPage> = {
66
+ code,
67
+ controller: TRouteController<RouterContext>,
68
+ options: TRouteOptions
69
+ }
70
+
71
+ export type TAnyRoute<RouterContext extends TClientOrServerContextForPage = TClientOrServerContextForPage> =
72
+ TRoute<RouterContext> | TErrorRoute<RouterContext>
73
+
74
+ // ClientRouterContext already includes server context
75
+ export type TClientOrServerContext = ClientRouterContext;// | ServerRouterContext;
76
+
77
+ export type TClientOrServerContextForPage = With<TClientOrServerContext, 'page'>
78
+
79
+ export type TRouteController<RouterContext extends TClientOrServerContextForPage = TClientOrServerContextForPage> =
80
+ (context: RouterContext) => /* Page to render */Page | /* Any data (html, json) */Promise<any>
81
+
82
+ export type TRouteOptions = {
83
+
84
+ // Injected by the page plugin
85
+ filepath?: string,
86
+ data?: TDataProvider
87
+
88
+ // Indexing
89
+ bodyId?: string,
90
+ priority: number,
91
+ preload?: boolean,
92
+
93
+ // Resolving
94
+ domain?: string,
95
+ accept?: string,
96
+ raw?: boolean, // true to return raw data
97
+ auth?: TUserRole | boolean,
98
+ redirectLogged?: string, // Redirect to this route if auth: false and user is logged
99
+
100
+ // Rendering
101
+ static?: {
102
+ refresh?: string,
103
+ urls: string[]
104
+ },
105
+ whenStatic?: boolean, // If true, the route is only executed even if the page is cached
106
+ canonicalParams?: string[], // For SEO + unique ID for static cache
107
+ layout?: false | string, // The nale of the layout
108
+
109
+ // To cleanup
110
+ TESTING?: boolean,
111
+ logging?: boolean,
112
+ }
113
+
114
+ export type TRouteModule<TRegisteredRoute = any> = {
115
+ // exporing __register is a way to know we axport a TAppArrowFunction
116
+ __register?: TAppArrowFunction<TRegisteredRoute>
117
+ }
118
+
119
+ export type TDomainsList = {
120
+ [endpointId: string]: string
121
+ } & {
122
+ current: string
123
+ }
124
+
125
+ export const defaultOptions = {
126
+ priority: 0,
127
+ }
128
+
129
+ /*----------------------------------
130
+ - FUNCTIONS
131
+ ----------------------------------*/
132
+ export const buildUrl = (
133
+ path: string,
134
+ params: {[key: string]: any},
135
+ domains: {[alias: string]: string},
136
+ absolute: boolean
137
+ ) => {
138
+
139
+ let prefix: string = '';
140
+
141
+ // Relative to domain
142
+ if (path[0] === '/' && absolute)
143
+ prefix = domains.current;
144
+ // Other domains of the project
145
+ else if (path[0] === '@') {
146
+
147
+ // Extract domain ID from path
148
+ let domainId: string;
149
+ let slackPos = path.indexOf('/');
150
+ if (slackPos === -1)
151
+ slackPos = path.length;
152
+ domainId = path.substring(1, slackPos);
153
+ path = path.substring(slackPos);
154
+
155
+ // Get domain
156
+ const domain = domains[ domainId ];
157
+ if (domain === undefined)
158
+ throw new Error("Unknown API endpoint ID: " + domainId);
159
+
160
+ // Return full url
161
+ prefix = domain;
162
+
163
+ // Absolute URL
164
+ }
165
+
166
+ // Path parapeters
167
+ const searchParams = new URLSearchParams();
168
+ for (const key in params) {
169
+
170
+ // Exclude undefined of empty
171
+ if (!params[key])
172
+ continue;
173
+ // Path placeholder
174
+ else if (path.includes(':' + key))
175
+ path = path.replace(':' + key, params[key]);
176
+ // Query string
177
+ else
178
+ searchParams.set(key, params[key]);
179
+ }
180
+
181
+ // Return final url
182
+ return prefix + path + (searchParams.toString() ? '?' + searchParams.toString() : '');
183
+ }
184
+
185
+ export const matchRoute = (route: TRoute, request: RouterRequest) => {
186
+
187
+ // Match Path
188
+ const match = route.regex.exec(request.path);
189
+ if (!match)
190
+ return false;
191
+
192
+ // Extract URL params
193
+ for (let iKey = 0; iKey < route.keys.length; iKey++) {
194
+ const key = route.keys[iKey];
195
+ const value = match[iKey + 1];
196
+ if (typeof key === 'string' && value) // number = sans nom
197
+ request.data[key] = decodeURIComponent( value.replaceAll('+', '%20') );
198
+ }
199
+
200
+ return true;
201
+ }
202
+
203
+ /*----------------------------------
204
+ - BASE ROUTER
205
+ ----------------------------------*/
206
+
207
+ export default abstract class RouterInterface {
208
+
209
+ public abstract page<TControllerData extends TObjetDonnees = {}>(...args: TRegisterPageArgs<TControllerData>);
210
+
211
+ public abstract error(code: number, options, renderer: TFrontRenderer<{}, { message: string }>);
212
+
213
+ }