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
@@ -2,70 +2,89 @@
2
2
  - DEPENDANCES
3
3
  ----------------------------------*/
4
4
 
5
- // Npm
6
- import { pathToRegexp, Key } from 'path-to-regexp';
7
- import type { ComponentChild } from 'preact';
5
+ import { Layout } from './layouts';
8
6
 
9
7
  // types
10
8
  import type {
11
- TRegisterPageArgs,
12
- TClientRoute,
13
- TFrontRenderer
14
- } from '@client/router';
9
+ default as ClientRouter,
10
+ TRouterContext as ClientRouterContext,
11
+ TRegisterPageArgs
12
+ } from '@client/services/router';
15
13
 
16
- import type { ClientContext } from '@client/context';
14
+ import type {
15
+ default as ServerRouter,
16
+ TRouterContext as ServerRouterContext,
17
+ TRouteHttpMethod
18
+ } from '@server/services/router';
17
19
 
18
- import type { TSchema } from '@common/data/input/validate';
20
+ import type { TUserRole } from '@server/services/users';
19
21
 
20
- import type { TApiServerRoute } from '@server/services/router';
22
+ import type { TAppArrowFunction } from '@common/app';
21
23
 
22
- import type { TUserRole } from '@server/services/auth/base';
24
+ // Specfic
25
+ import type ApiClient from './request/api';
26
+ import type Request from './request';
27
+ import type Response from './response';
28
+ import type { default as Page, TFrontRenderer } from './response/page';
23
29
 
24
30
  /*----------------------------------
25
- - TYPES: layouts
31
+ - TYPES: ROUTES
26
32
  ----------------------------------*/
27
33
 
28
- import layouts from '@/client/pages/**/_layout/index.tsx';
29
-
30
- type LayoutComponent = (attributes: { context: ClientContext }) => ComponentChild;
31
- export type Layout = { path: string, Component: LayoutComponent }
32
- const getLayout = (routePath: string | undefined): Layout | undefined => {
33
-
34
- let layout: Layout | undefined = layouts[''];
35
- if (routePath) {
36
- for (const layoutPath in layouts)
37
- if (routePath === layoutPath || routePath.startsWith( layoutPath + '/' ))
38
- layout = { path: layoutPath, Component: layouts[layoutPath] };
39
- }
40
- //layout && console.log(`${routePath}: Using Layout: ${layout.path}`);
41
- return layout;
42
- }
34
+ export type { Layout } from './layouts';
43
35
 
44
- /*----------------------------------
45
- - TYPES: ROUTES
46
- ----------------------------------*/
36
+ export type { default as Request } from './request';
37
+ export type { default as Response } from './response';
47
38
 
48
- export type TBaseRoute = {
49
- path: string,
39
+ export type ClientOrServerRouter = ClientRouter | ServerRouter;
40
+
41
+ export type TRoute<RouterContext extends TClientOrServerContext = TClientOrServerContext> = {
50
42
 
43
+ // Match
44
+ method: TRouteHttpMethod,
45
+ path: string,
51
46
  regex: RegExp,
52
47
  keys: (number | string)[],
53
48
 
49
+ // Execute
50
+ controller: TRouteController<RouterContext>,//TServerController<TRouter> | TFrontRenderer<TRouter>,
54
51
  options: TRouteOptions
55
52
  }
56
53
 
57
- export type TRoute = TApiServerRoute | TClientRoute;
58
-
59
- export type TErrorRoute = {
60
- type: 'PAGE',
61
- renderer: TFrontRenderer,
62
- options: {}
54
+ export type TErrorRoute<RouterContext extends TClientOrServerContext = TClientOrServerContext> = {
55
+ code,
56
+ controller: TRouteController<RouterContext>,
57
+ options: TRouteOptions
63
58
  }
64
59
 
60
+ export type TClientOrServerContext<
61
+ TClientOnlyContextKeys extends keyof ClientRouterContext = keyof (ClientRouterContext | ServerRouterContext)
62
+ > = (
63
+ (
64
+ {[serverContextKey in keyof ServerRouterContext/*Omit<ClientRouterContext, TClientOnlyContextKeys>*/]: undefined}
65
+ &
66
+ ClientRouterContext
67
+ )
68
+ |
69
+ (
70
+ // Tell that all the keys of client context are existing but undefined
71
+ // This avoids errors: "Property 'page' is optional in type '{ app: Application; ..."
72
+ // When we destructure the context from the page controller
73
+ // While making reference to a key only available in client context
74
+ // So here, we put the
75
+ {[clientContextKey in keyof ClientRouterContext/*Omit<ClientRouterContext, TClientOnlyContextKeys>*/]: undefined}
76
+ &
77
+ ServerRouterContext
78
+ )
79
+ )
80
+
81
+ export type TRouteController<RouterContext extends TClientOrServerContext = TClientOrServerContext> =
82
+ (context: RouterContext) => /* Page to render */Page | /* Any data (html, json) */Promise<any>
83
+
65
84
  export type TRouteOptions = {
66
85
 
67
86
  // Injected by the page plugin
68
- filepath: string,
87
+ filepath?: string,
69
88
 
70
89
  // Indexing
71
90
  bodyId?: string,
@@ -78,7 +97,7 @@ export type TRouteOptions = {
78
97
 
79
98
  // Access Restriction
80
99
  auth?: TUserRole | boolean,
81
- form?: TSchema,
100
+ //form?: TSchema,
82
101
  layout?: false | Layout,
83
102
 
84
103
  TESTING?: boolean,
@@ -86,6 +105,11 @@ export type TRouteOptions = {
86
105
 
87
106
  }
88
107
 
108
+ export type TRouteModule<TRegisteredRoute = any> = {
109
+ // exporing __register is a way to know we axport a TAppArrowFunction
110
+ __register?: TAppArrowFunction<TRegisteredRoute>
111
+ }
112
+
89
113
  export const defaultOptions = {
90
114
  priority: 0,
91
115
  }
@@ -94,55 +118,10 @@ export const defaultOptions = {
94
118
  - BASE ROUTER
95
119
  ----------------------------------*/
96
120
 
97
- export default abstract class BaseRouter {
98
-
99
- public page = <TControllerData extends TObjetDonnees = {}>(...args: TRegisterPageArgs<TControllerData>) =>
100
- this.registerPage(...args);
101
-
102
- public error = (code: number, options, renderer: TFrontRenderer<{ message: string }>) =>
103
- this.registerErrorPage(code, options, renderer);
104
-
105
- protected abstract registerPage(...page: TRegisterPageArgs ): any;
106
-
107
- public errors: { [code: number]: TErrorRoute } = {};
108
- protected registerErrorPage( code: number, options, renderer: TFrontRenderer ) {
109
- return this.errors[code] = {
110
- type: 'PAGE',
111
- renderer,
112
- options
113
- };
114
- }
115
-
116
- protected getRegisterPageArgs(...args: TRegisterPageArgs) {
117
-
118
- const [path, options, controller, renderer] = args;
119
-
120
- // S'il s'agit d'une page, son id doit avoir été injecté via le plugin babel
121
- if (options["id"] === undefined)
122
- throw new Error(`ID not found for the following page route: ${path}`);
123
-
124
- // Bind layout
125
- if (options.layout !== false)
126
- options.layout = getLayout(options.filepath);
127
-
128
- return { path, options, controller, renderer }
129
-
130
- }
131
-
132
- protected buildRegex( path: string ) {
133
-
134
- // pathToRegexp ne supporte plus les wildcards depuis 4.0
135
- if (path.endsWith('*'))
136
- path = path.substring(0, path.length - 1) + '(.*)';
137
-
138
- // path => regex
139
- const keys: Key[] = []
140
- const regex = pathToRegexp(path, keys, {
141
- sensitive: true
142
- });
121
+ export default abstract class RouterInterface {
143
122
 
144
- return { keys, regex }
123
+ public abstract page<TControllerData extends TObjetDonnees = {}>(...args: TRegisterPageArgs<TControllerData>);
145
124
 
146
- }
125
+ public abstract error(code: number, options, renderer: TFrontRenderer<{}, { message: string }>);
147
126
 
148
127
  }
@@ -0,0 +1,50 @@
1
+ /*----------------------------------
2
+ - DEPENDANCES
3
+ ----------------------------------*/
4
+
5
+ // Npm
6
+ import type { ComponentChild } from 'preact';
7
+ // Core
8
+ import type { ClientContext } from '@/client/context';
9
+ // App
10
+ import layouts from '@/client/pages/**/_layout/index.tsx';
11
+
12
+ /*----------------------------------
13
+ - CONST
14
+ ----------------------------------*/
15
+
16
+ export const layoutsList = layouts as ImportedLayouts;
17
+
18
+ /*----------------------------------
19
+ - TYPES
20
+ ----------------------------------*/
21
+ type LayoutComponent = (attributes: { context: ClientContext }) => ComponentChild;
22
+
23
+ export type Layout = { path: string, Component: LayoutComponent }
24
+
25
+ export type ImportedLayouts = {
26
+ [chunkId: string]: Layout["Component"]
27
+ }
28
+
29
+ /*----------------------------------
30
+ - UTILS
31
+ ----------------------------------*/
32
+ // TODO: getLayot only on server side, and pass the layout chunk id
33
+ export const getLayout = (routePath: string | undefined): Layout | undefined => {
34
+
35
+ //console.log(`[router][layouts] Get layout for "${routePath}".`);
36
+
37
+ let layout: Layout | undefined;
38
+ if (routePath) {
39
+ for (const layoutPath in layouts)
40
+ if (routePath === layoutPath || routePath.startsWith( layoutPath + '_' ))
41
+ layout = {
42
+ path: layoutPath,
43
+ Component: layouts[layoutPath]
44
+ };
45
+ }
46
+
47
+ //console.log(`[router][layouts] Get layout for "${routePath}". Found:`, layout);
48
+
49
+ return layout;
50
+ }
@@ -0,0 +1,62 @@
1
+ /*----------------------------------
2
+ - DEPENDANCES
3
+ ----------------------------------*/
4
+
5
+ // Npm
6
+ import { pathToRegexp, Key } from 'path-to-regexp';
7
+
8
+ // Core
9
+ import { getLayout } from './layouts';
10
+
11
+ // types
12
+ import type { TRouteOptions } from '.';
13
+ import type { TDataProvider, TFrontRenderer } from './response/page';
14
+ import type { TRegisterPageArgs } from '@client/services/router';
15
+
16
+ /*----------------------------------
17
+ - UTILS
18
+ ----------------------------------*/
19
+
20
+ export const getRegisterPageArgs = (...args: TRegisterPageArgs) => {
21
+
22
+ let path: string;
23
+ let options: Partial<TRouteOptions> = {};
24
+ let controller: TDataProvider|null;
25
+ let renderer: TFrontRenderer;
26
+
27
+ if (args.length === 3)
28
+ ([path, controller, renderer] = args)
29
+ else
30
+ ([path, options, controller, renderer] = args)
31
+
32
+ // S'il s'agit d'une page, son id doit avoir été injecté via le plugin babel
33
+ const chunkId = options["id"];
34
+ if (chunkId === undefined)
35
+ throw new Error(`ID has not injected for the following page route: ${path}`);
36
+
37
+ // Bind layout
38
+ if (options.layout !== false)
39
+ options.layout = getLayout(chunkId);
40
+
41
+ return { path, options, controller, renderer }
42
+
43
+ }
44
+
45
+ export const buildRegex = ( path: string ) => {
46
+
47
+ // pathToRegexp ne supporte plus les wildcards depuis 4.0
48
+ if (path.endsWith('*'))
49
+ path = path.substring(0, path.length - 1) + '(.*)';
50
+
51
+ // path => regex
52
+ const keys: Key[] = []
53
+ const regex = pathToRegexp(path, keys, {
54
+ sensitive: true
55
+ });
56
+
57
+ return {
58
+ keys: keys.map(k => k.name),
59
+ regex
60
+ }
61
+
62
+ }
@@ -0,0 +1,72 @@
1
+ /*----------------------------------
2
+ - DEPENDANCES
3
+ ----------------------------------*/
4
+
5
+ import type { HttpMethod } from '@server/services/router';
6
+
7
+ /*----------------------------------
8
+ - TYPES
9
+ ----------------------------------*/
10
+
11
+ export type TFetcherList = { [id: string]: TFetcher }
12
+
13
+ export type TFetcher<TData extends unknown = unknown> = {
14
+
15
+ // For async calls: api.post(...).then((data) => ...)
16
+ then: (callback: (data: TData) => void) => Promise<TData>,
17
+ run: () => Promise<TData>,
18
+
19
+ method: HttpMethod,
20
+ path: string,
21
+ data?: object,
22
+ options?: TApiFetchOptions
23
+ }
24
+
25
+ export type TFetcherArgs = [
26
+ method: HttpMethod,
27
+ path: string,
28
+ data?: object,
29
+ options?: TApiFetchOptions
30
+ ]
31
+
32
+ export type TApiFetchOptions = {
33
+ captcha?: string, // Action id (required by recaptcha)
34
+ onProgress?: (percent: number) => void
35
+ }
36
+
37
+ // https://stackoverflow.com/questions/44851268/typescript-how-to-extract-the-generic-parameter-from-a-type
38
+ type TypeWithGeneric<T> = TFetcher<T>
39
+ type extractGeneric<Type> = Type extends TypeWithGeneric<infer X> ? X : never
40
+
41
+ export type TDataReturnedByFetchers<TProvidedData extends TFetcherList = {}> = {
42
+ [Property in keyof TProvidedData]: undefined | (extractGeneric<TProvidedData[Property]> extends ((...args: any[]) => any)
43
+ ? ThenArg<ReturnType< extractGeneric<TProvidedData[Property]> >>
44
+ : extractGeneric<TProvidedData[Property]>
45
+ )
46
+ }
47
+
48
+ /*----------------------------------
49
+ - CLASS
50
+ ----------------------------------*/
51
+ export default abstract class ApiClient {
52
+
53
+ /*----------------------------------
54
+ - TOP LEVEL
55
+ ----------------------------------*/
56
+
57
+ public abstract get<TData extends unknown = unknown>(path: string, data?: TObjetDonnees, opts?: TApiFetchOptions): TFetcher<TData>;
58
+
59
+ public abstract post<TData extends unknown = unknown>(path: string, data?: TObjetDonnees, opts?: TApiFetchOptions): TFetcher<TData>;
60
+
61
+ public abstract put<TData extends unknown = unknown>(path: string, data?: TObjetDonnees, opts?: TApiFetchOptions): TFetcher<TData>;
62
+
63
+ public abstract delete<TData extends unknown = unknown>(path: string, data?: TObjetDonnees, opts?: TApiFetchOptions): TFetcher<TData>;
64
+
65
+ /*----------------------------------
66
+ - LOW LEVEL
67
+ ----------------------------------*/
68
+
69
+ public abstract createFetcher<TData extends unknown = unknown>(...args: TFetcherArgs): TFetcher<TData>;
70
+
71
+ public abstract fetchSync(fetchers: TFetcherList): Promise<TObjetDonnees>;
72
+ }
@@ -0,0 +1,31 @@
1
+ /*----------------------------------
2
+ - DEPENDANCES
3
+ ----------------------------------*/
4
+
5
+ // Core
6
+ import Response from '../response';
7
+
8
+ /*----------------------------------
9
+ - TYPES
10
+ ----------------------------------*/
11
+
12
+
13
+ /*----------------------------------
14
+ - CONTEXT
15
+ ----------------------------------*/
16
+ export default abstract class BaseRequest {
17
+
18
+ // Permet d'accèder à l'instance complète via spread
19
+ public request: this = this;
20
+ public host!: string;
21
+
22
+ public data: TObjetDonnees = {};
23
+ public abstract response?: Response;
24
+ public user: User | null = null;
25
+
26
+ public constructor(
27
+ public path: string,
28
+ ) {
29
+
30
+ }
31
+ }
@@ -6,30 +6,26 @@
6
6
  import { FunctionalComponent } from "preact";
7
7
 
8
8
  // Core
9
- import { TRoute } from ".";
10
- import BaseRequest from './request';
11
- import { TClientRoute, TFrontRenderer } from '@client/router';
12
- import PageResponse from './response/page';
13
- import { ClientContext } from '@client/context';
9
+ import { TRoute } from "..";
10
+ import type ClientRequest from '@client/services/router';
11
+ import Page from '@client/services/router/response/page'
14
12
 
15
13
  /*----------------------------------
16
14
  - TYPES
17
15
  ----------------------------------*/
18
16
 
19
- export { default as PageResponse } from './response/page';
20
-
21
- export type TResponseData = PageResponse | unknown
17
+ type TResponseData = Page
22
18
 
23
19
  /*----------------------------------
24
20
  - CONTEXT
25
21
  ----------------------------------*/
26
22
  export default abstract class BaseResponse<
27
- TData extends TResponseData = TResponseData,
28
- TRequest extends BaseRequest = BaseRequest
23
+ TData extends TResponseData = Page,
24
+ TRequest extends ClientRequest = ClientRequest
29
25
  > {
30
26
 
31
- public data?: any;
32
- public request: With<TRequest, 'response'>;
27
+ public data?: TData;
28
+ public request: TRequest;
33
29
  public route?: TRoute;
34
30
 
35
31
  public constructor(
@@ -37,7 +33,7 @@ export default abstract class BaseResponse<
37
33
  ) {
38
34
  // ServerResponse et ClientResponse assignent request.response
39
35
  request.response = this;
40
- this.request = request as With<TRequest, 'response'>;
36
+ this.request = request as TRequest;
41
37
  }
42
38
 
43
39
  public setRoute(route: TRoute) {
@@ -2,19 +2,38 @@
2
2
  - DEPENDANCES
3
3
  ----------------------------------*/
4
4
 
5
- import type { ComponentChild } from 'preact';
5
+ import type { ComponentChild, FunctionComponent } from 'preact';
6
6
 
7
7
  // Core libs
8
- import { TClientRoute, TFrontRenderer } from '@client/router';
9
- import { TFetcherList } from '@common/router/request';
10
- import { history } from '@client/router/request/history';
11
- import { ClientContext } from '@client/context';
8
+ import { ClientOrServerRouter, TClientOrServerContext } from '@common/router';
9
+ import { TFetcherList, TDataReturnedByFetchers } from '@common/router/request/api';
10
+ import { history } from '@client/services/router/request/history';
12
11
 
13
12
  /*----------------------------------
14
13
  - TYPES
15
14
  ----------------------------------*/
16
15
 
17
- type TResource = {
16
+ // The function that fetch data from the api before to pass them as context to the renderer
17
+ export type TDataProvider<TProvidedData extends TFetcherList = {}> =
18
+ (context: TClientOrServerContext/* & TUrlData */) => TProvidedData
19
+
20
+
21
+
22
+ // The function that renders routes
23
+ export type TFrontRenderer<
24
+ TProvidedData extends TFetcherList = {},
25
+ TAdditionnalData = {},
26
+ TRouter = ClientOrServerRouter,
27
+ > = FunctionComponent<(
28
+ TClientOrServerContext
29
+ &
30
+ TDataReturnedByFetchers<TProvidedData>
31
+ &
32
+ TAdditionnalData
33
+ )>;
34
+
35
+ // Script or CSS resource
36
+ export type TPageResource = {
18
37
  id: string,
19
38
  attrs?: TObjetDonnees
20
39
  } & ({
@@ -27,70 +46,35 @@ type TResource = {
27
46
  /*----------------------------------
28
47
  - CLASS
29
48
  ----------------------------------*/
30
- export default class PageResponse {
31
-
32
- // Render
33
- public id: string;
34
- public data: TObjetDonnees = {};
35
- public loading: ComponentChild = false;
36
- public component: TFrontRenderer;
49
+ export default class PageResponse<TRouter extends ClientOrServerRouter = ClientOrServerRouter> {
37
50
 
38
51
  // Metadata
52
+ public chunkId: string;
39
53
  public title?: string;
40
54
  public description?: string;
41
55
  public bodyClass: Set<string> = new Set<string>();
42
56
  public bodyId?: string;
43
57
 
44
- // resources
58
+ // Resources
45
59
  public amp?: boolean;
46
- public scripts: TResource[] = [];
47
- public style: TResource[] = [];
48
-
49
- // State
50
- public hash?: string; // Element id to scroll to
51
-
52
- public constructor(
53
- public context: ClientContext,
54
- public route: TClientRoute,
55
- data: TObjetDonnees = {},
56
- ) {
57
- this.id = route.options.id; // Binded by the pages babel plugin
58
- this.bodyId = route.options.bodyId;
59
- this.component = route.renderer;
60
- this.data = data;
61
- this.hash = context.request.hash;
62
- }
60
+ public scripts: TPageResource[] = [];
61
+ public style: TPageResource[] = [];
63
62
 
64
- // API data fetchers
63
+ // Data
65
64
  public fetchers: TFetcherList = {};
65
+ public data: TObjetDonnees = {};
66
66
 
67
- // Should be called AFTER rendering the page
68
- public updateClient() {
67
+ public constructor(
68
+ public dataProvider: TDataProvider | null,
69
+ public renderer: TFrontRenderer,
70
+ public context: TClientOrServerContext
71
+ ) {
69
72
 
70
- document.body.id = this.bodyId || this.id;
71
- document.title = this.title || APP_NAME;
72
- document.body.className = [...this.bodyClass].join(' ');
73
-
73
+ this.chunkId = context.route.options["id"];
74
+
74
75
  }
75
76
 
76
-
77
77
  public async fetchData() {
78
- this.isDataLoaded = true;
79
- this.data = await this.context.request.fetchSync(this.fetchers);
80
- return this.data;
81
- }
82
-
83
- public setAllData( callback: (data: {[k: string]: any}) => void) {
84
- console.warn(`page.setAllData not yet attached to the page Reatc component.`);
85
- }
86
- public setData( key: string, value: ((value: any) => void) | any ) {
87
- this.setAllData(old => ({
88
- ...old,
89
- [key]: typeof value === 'function' ? value(old[key]) : value
90
- }));
91
- }
92
-
93
- public go( url: string ) {
94
- history?.replace(url);
78
+ return await this.context.request.api.fetchSync( this.fetchers );
95
79
  }
96
80
  }
@@ -0,0 +1,3 @@
1
+ export { default as Schema } from './schema';
2
+ export { default as Validators } from './validators';
3
+ export { default as Validator } from './validator';