5htp-core 0.1.2 → 0.2.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 (148) 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 -11
  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/components.less +52 -0
  9. package/src/client/assets/css/core.less +7 -28
  10. package/src/client/assets/css/theme.less +1 -1
  11. package/src/client/assets/css/{borders.less → utils/borders.less} +0 -0
  12. package/src/client/assets/css/{layouts.less → utils/layouts.less} +0 -0
  13. package/src/client/assets/css/{medias.less → utils/medias.less} +14 -1
  14. package/src/client/assets/css/{sizing.less → utils/sizing.less} +0 -0
  15. package/src/client/assets/css/{spacing.less → utils/spacing.less} +0 -0
  16. package/src/client/components/Card/index.tsx +13 -7
  17. package/src/client/components/Dialog/Manager.tsx +41 -14
  18. package/src/client/components/Dialog/index.less +2 -4
  19. package/src/client/components/Form/index.tsx +1 -1
  20. package/src/client/components/Row/index.less +0 -2
  21. package/src/client/components/Table/index.tsx +3 -2
  22. package/src/client/components/button.tsx +2 -2
  23. package/src/client/components/containers/Popover/index.tsx +1 -1
  24. package/src/client/components/containers/champs.less +0 -2
  25. package/src/client/components/data/spintext/index.tsx +1 -1
  26. package/src/client/components/dropdown/index.tsx +1 -1
  27. package/src/client/components/index.ts +23 -0
  28. package/src/client/components/input/BaseV2/index.less +0 -2
  29. package/src/client/components/input/BaseV2/index.tsx +1 -1
  30. package/src/client/components/input/Date/index.less +0 -2
  31. package/src/client/components/input/Periode/index.less +0 -2
  32. package/src/client/components/input/Radio/index.less +0 -2
  33. package/src/client/components/input/UploadImage/index.less +0 -2
  34. package/src/client/components/input/UploadImage/index.tsx +1 -1
  35. package/src/client/hooks/index.ts +5 -0
  36. package/src/client/hooks/useState/index.tsx +2 -2
  37. package/src/client/hooks.ts +22 -0
  38. package/src/client/index.ts +5 -0
  39. package/src/client/pages/_layout/landing/index.tsx +0 -2
  40. package/src/client/pages/_messages/400.tsx +2 -2
  41. package/src/client/pages/_messages/401.tsx +2 -2
  42. package/src/client/pages/_messages/403.tsx +2 -2
  43. package/src/client/pages/_messages/404.tsx +2 -2
  44. package/src/client/pages/_messages/500.tsx +2 -2
  45. package/src/client/pages/bug.tsx +1 -1
  46. package/src/client/pages/useHeader.tsx +1 -1
  47. package/src/client/{context/captcha.ts → services/captcha/index.ts} +0 -0
  48. package/src/client/services/metrics/index.ts +37 -0
  49. package/src/client/{router → services/router/components}/Link.tsx +1 -1
  50. package/src/client/services/router/components/Page.tsx +59 -0
  51. package/src/client/{router/component.tsx → services/router/components/router.tsx} +52 -74
  52. package/src/client/services/router/index.tsx +453 -0
  53. package/src/client/services/router/request/api.ts +227 -0
  54. package/src/client/{router → services/router}/request/history.ts +0 -0
  55. package/src/client/services/router/request/index.ts +52 -0
  56. package/src/client/services/router/response/index.tsx +107 -0
  57. package/src/client/services/router/response/page.ts +90 -0
  58. package/src/client/{context/socket.ts → services/socket/index.ts} +2 -2
  59. package/src/client/utils/dom.ts +1 -1
  60. package/src/common/app/index.ts +9 -0
  61. package/src/common/data/chaines/index.ts +9 -6
  62. package/src/common/data/input/validate.ts +3 -166
  63. package/src/common/data/objets.ts +25 -0
  64. package/src/common/data/tableaux.ts +8 -0
  65. package/src/common/errors/index.ts +3 -1
  66. package/src/common/router/index.ts +67 -88
  67. package/src/common/router/layouts.ts +50 -0
  68. package/src/common/router/register.ts +62 -0
  69. package/src/common/router/request/api.ts +72 -0
  70. package/src/common/router/request/index.ts +31 -0
  71. package/src/common/router/{response.ts → response/index.ts} +9 -13
  72. package/src/common/router/response/page.ts +46 -54
  73. package/src/common/validation/index.ts +3 -0
  74. package/src/common/validation/schema.ts +185 -0
  75. package/src/common/validation/validator.ts +95 -0
  76. package/src/common/validation/validators.ts +313 -0
  77. package/src/server/app/config.ts +9 -27
  78. package/src/server/app/index.ts +81 -124
  79. package/src/server/app/service.ts +98 -0
  80. package/src/server/app.tsconfig.json +0 -8
  81. package/src/server/index.ts +5 -0
  82. package/src/server/patch.ts +0 -6
  83. package/src/server/{data/Cache.ts → services/cache/index.ts} +79 -47
  84. package/src/server/services/console/bugReporter.ts +26 -16
  85. package/src/server/services/console/index.ts +59 -51
  86. package/src/server/services/cron/index.ts +12 -26
  87. package/src/server/services/database/bucket.ts +40 -0
  88. package/src/server/services/database/connection.ts +213 -80
  89. package/src/server/services/database/datatypes.ts +63 -40
  90. package/src/server/services/database/debug.ts +20 -0
  91. package/src/server/services/database/index.ts +295 -272
  92. package/src/server/services/database/metas.ts +246 -135
  93. package/src/server/services/database/stats.ts +151 -126
  94. package/src/server/services/email/index.ts +30 -62
  95. package/src/server/services/email/transporter.ts +38 -0
  96. package/src/server/services/{router/request/services → metrics}/detect.ts +8 -10
  97. package/src/server/services/{router/request/services/tracking.ts → metrics/index.ts} +68 -45
  98. package/src/server/services/{http → router/http}/index.ts +28 -70
  99. package/src/server/services/{http → router/http}/multipart.ts +0 -0
  100. package/src/server/services/{http → router/http}/session.ts.old +0 -0
  101. package/src/server/services/router/index.ts +273 -202
  102. package/src/server/services/router/request/api.ts +76 -0
  103. package/src/server/services/router/request/index.ts +16 -97
  104. package/src/server/services/router/request/service.ts +21 -0
  105. package/src/server/services/router/response/index.ts +131 -65
  106. package/src/server/services/router/response/{filter → mask}/Filter.ts +0 -0
  107. package/src/server/services/router/response/{filter → mask}/index.ts +0 -2
  108. package/src/server/services/router/response/{filter → mask}/selecteurs.ts +0 -0
  109. package/src/server/services/router/response/page/document.tsx +194 -0
  110. package/src/server/services/router/response/page/index.tsx +157 -0
  111. package/src/server/{libs/pages → services/router/response/page}/schemaGenerator.ts +0 -0
  112. package/src/server/services/router/service.ts +48 -0
  113. package/src/server/services/schema/index.ts +47 -0
  114. package/src/server/services/schema/request.ts +55 -0
  115. package/src/server/services/schema/router.ts +33 -0
  116. package/src/server/services/socket/index.ts +38 -43
  117. package/src/server/services/socket/scope.ts +6 -4
  118. package/src/server/services/users/index.ts +203 -0
  119. package/src/server/services/{auth/base.ts → users/old.ts} +28 -112
  120. package/src/server/services/users/router/index.ts +72 -0
  121. package/src/server/services/users/router/request.ts +49 -0
  122. package/src/server/{data → services_old}/SocketClient.ts +0 -0
  123. package/src/server/{data/Token.olg.ts → services_old/Token.old.ts} +0 -0
  124. package/src/server/{data → services_old}/aes.ts +0 -0
  125. package/src/types/aliases.d.ts +43 -2
  126. package/templates/composant.tsx +1 -1
  127. package/templates/modal.tsx +1 -1
  128. package/templates/page.tsx +1 -1
  129. package/tsconfig.common.json +0 -4
  130. package/src/client/assets/css/components/components.less +0 -31
  131. package/src/client/context/api.ts +0 -92
  132. package/src/client/context/index.ts +0 -246
  133. package/src/client/index.tsx +0 -129
  134. package/src/client/router/index.ts +0 -286
  135. package/src/client/router/request/index.ts +0 -106
  136. package/src/client/router/response/index.ts +0 -38
  137. package/src/client/router/route.ts +0 -75
  138. package/src/common/data/input/validators/basic.ts +0 -299
  139. package/src/common/data/input/validators/build.ts +0 -63
  140. package/src/common/router/request.ts +0 -83
  141. package/src/server/data/ApiClient.ts +0 -119
  142. package/src/server/data/input.ts +0 -41
  143. package/src/server/libs/pages/document.static.tsx +0 -41
  144. package/src/server/libs/pages/document.tsx +0 -203
  145. package/src/server/libs/pages/render.tsx +0 -90
  146. package/src/server/routes/auth.ts +0 -151
  147. package/src/server/services/redis/index.ts +0 -71
  148. package/src/server/services/router/request/services/auth.ts +0 -177
@@ -0,0 +1,227 @@
1
+ /*----------------------------------
2
+ - DEPENDANCES
3
+ ----------------------------------*/
4
+
5
+ // Npm
6
+ import axios, { AxiosResponse, AxiosError, AxiosRequestConfig } from 'axios';
7
+
8
+ // Core
9
+ import type { TApiResponseData } from '@server/services/router';
10
+ import ApiClientService, {
11
+ TApiFetchOptions, TFetcherList, TFetcherArgs, TFetcher
12
+ } from '@common/router/request/api';
13
+ import { instancierViaCode, NetworkError } from '@common/errors';
14
+ import type ClientApplication from '@client/app';
15
+
16
+ // Specific
17
+ import type { default as Router, Request } from '..';
18
+
19
+ /*----------------------------------
20
+ - TYPES
21
+ ----------------------------------*/
22
+
23
+ const debug = true;
24
+
25
+ export type Config = {
26
+
27
+ }
28
+
29
+ /*----------------------------------
30
+ - FUNCTION
31
+ ----------------------------------*/
32
+ export default class ApiClient implements ApiClientService {
33
+
34
+ // APO Client needs to know the current request so we can monitor which api request is made from which page
35
+ public constructor(
36
+ public app: ClientApplication,
37
+ public request: Request<Router>
38
+ ) {
39
+
40
+ }
41
+
42
+ /*----------------------------------
43
+ - HIGH LEVEL
44
+ ----------------------------------*/
45
+ public get = <TData extends unknown = unknown>(path: string, data?: TObjetDonnees, opts?: TApiFetchOptions) =>
46
+ this.createFetcher<TData>('GET', path, data, opts);
47
+
48
+ public post = <TData extends unknown = unknown>(path: string, data?: TObjetDonnees, opts?: TApiFetchOptions) =>
49
+ this.createFetcher<TData>('POST', path, data, opts);
50
+
51
+ public put = <TData extends unknown = unknown>(path: string, data?: TObjetDonnees, opts?: TApiFetchOptions) =>
52
+ this.createFetcher<TData>('PUT', path, data, opts);
53
+
54
+ public delete = <TData extends unknown = unknown>(path: string, data?: TObjetDonnees, opts?: TApiFetchOptions) =>
55
+ this.createFetcher<TData>('DELETE', path, data, opts);
56
+
57
+
58
+ public set( newData: TObjetDonnees ) {
59
+
60
+ console.log("[api] Update page data", newData);
61
+ if (this.app.page)
62
+ this.app.page.setAllData(curData => ({ ...curData, ...newData }));
63
+
64
+ }
65
+
66
+ public reload( ids?: string | string[], params?: TObjetDonnees ) {
67
+
68
+ if (this.app.page === undefined)
69
+ throw new Error("context.page is missing");
70
+
71
+ if (ids === undefined)
72
+ ids = Object.keys(this.app.page.fetchers);
73
+ else if (typeof ids === 'string')
74
+ ids = [ids];
75
+
76
+ console.log("[api] Reload data", ids, params, this.app.page.fetchers);
77
+
78
+ for (const id of ids) {
79
+
80
+ const fetcher = this.app.page.fetchers[id];
81
+ if (fetcher === undefined)
82
+ return console.error(`Unable to reload ${id}: Request not found in fetchers list.`);
83
+
84
+ if (params !== undefined)
85
+ fetcher.data = { ...(fetcher.data || {}), ...params };
86
+
87
+ console.log("[api][reload]", id, fetcher.method, fetcher.path, fetcher.data);
88
+ const indicator = this.toast.loading("Loading ...");
89
+
90
+ this.fetchAsync(fetcher.method, fetcher.path, fetcher.data).then((data) => {
91
+
92
+ this.set({ [id]: data });
93
+
94
+ }).finally(() => {
95
+
96
+ indicator.close(true);
97
+
98
+ })
99
+ }
100
+ }
101
+
102
+ /*----------------------------------
103
+ - LOW LEVEL
104
+ ----------------------------------*/
105
+ public createFetcher<TData extends unknown = unknown>(...args: TFetcherArgs): TFetcher<TData> {
106
+ const [method, path, data, options] = args;
107
+ return {
108
+ method, path, data, options,
109
+ // For async calls: api.post(...).then((data) => ...)
110
+ then: (callback: (data: any) => void) => this.fetchAsync<TData>(...args).then(callback),
111
+ catch: (callback: (data: any) => void) => this.fetchAsync(...args).catch(callback),
112
+ finally: (callback: () => void) => this.fetchAsync(...args).finally(callback),
113
+ run: () => this.fetchAsync(...args)
114
+ };
115
+ }
116
+
117
+ public async fetchAsync<TData extends unknown = unknown>(...[
118
+ method, path, data, options
119
+ ]: TFetcherArgs): Promise<TData> {
120
+
121
+ /*if (options?.captcha !== undefined)
122
+ await this.gui.captcha.check(options?.captcha);*/
123
+
124
+ return await this.fetch<TData>(method, path, data, options).catch((e) => {
125
+ this.app.handleError(e);
126
+ throw e;
127
+ })
128
+ }
129
+
130
+ public async fetchSync(fetchers: TFetcherList, alreadyLoadedData: {}): Promise<TObjetDonnees> {
131
+
132
+ // Pick the fetchers where the data is needed
133
+ const fetchersToRun: TFetcherList = {};
134
+ let fetchersCount: number = 0;
135
+ for (const fetcherId in fetchers)
136
+ if (!( fetcherId in alreadyLoadedData )) {
137
+ fetchersToRun[ fetcherId ] = fetchers[ fetcherId ]
138
+ fetchersCount++;
139
+ }
140
+
141
+ // Fetch all the api data thanks to one http request
142
+ const fetchedData = fetchersCount === 0
143
+ ? 0
144
+ : await this.fetch("POST", "/api", {
145
+ fetchers: fetchersToRun
146
+ }).then((res) => {
147
+
148
+ const data: TObjetDonnees = {};
149
+ for (const id in res)
150
+ data[id] = res[id];
151
+
152
+ return data;
153
+
154
+ });
155
+
156
+ return { ...alreadyLoadedData, ...fetchedData }
157
+ }
158
+
159
+ public configure = (...[method, path, data, options]: TFetcherArgs): AxiosRequestConfig => {
160
+
161
+ const { onProgress, captcha } = options || {};
162
+
163
+ debug && console.log(`[api] Sending request`, method, path, data);
164
+
165
+ const config: AxiosRequestConfig = {
166
+
167
+ url: path,
168
+ method: method,
169
+ headers: {
170
+ 'Content-Type': "application/json",
171
+ 'Accept': "application/json",
172
+ },
173
+
174
+ validateStatus: function (status: number) {
175
+ return status === 200;
176
+ },
177
+
178
+ onUploadProgress: onProgress === undefined ? undefined : (e) => {
179
+ const percentCompleted = Math.round((e.loaded * 100) / e.total);
180
+ onProgress(percentCompleted);
181
+ }
182
+
183
+ };
184
+
185
+ if (data) {
186
+ if (method === "GET")
187
+ config.params = data;
188
+ else {
189
+ config.data = data;
190
+ if (data instanceof FormData)
191
+ config.headers["Content-Type"] = 'multipart/form-data';
192
+ }
193
+ }
194
+
195
+ return config;
196
+ }
197
+
198
+ public fetch<TData = unknown>(...args: TFetcherArgs): Promise<TData> {
199
+
200
+ const config = this.configure(...args);
201
+
202
+ return axios.request(config)
203
+ .then((res: AxiosResponse<TApiResponseData>) => {
204
+
205
+ debug && console.log(`[api] Success:`, res);
206
+ return res.data as TData;
207
+
208
+ })
209
+ .catch((e: AxiosError) => {
210
+
211
+ if (e.response !== undefined) {
212
+
213
+ console.warn(`[api] Failure:`, e);
214
+ throw instancierViaCode(
215
+ e.response.status || 500,
216
+ e.response.data
217
+ );
218
+
219
+ // Erreur réseau: l'utilisateur n'ets probablement plus connecté à internet
220
+ } else {
221
+ const error = new NetworkError(e.message);
222
+ this.app.handleError(error);
223
+ throw error;
224
+ }
225
+ });
226
+ }
227
+ }
@@ -0,0 +1,52 @@
1
+ /*----------------------------------
2
+ - DEPENDANCES
3
+ ----------------------------------*/
4
+
5
+ // Npm
6
+ import { Location } from 'history';
7
+ import type Bowser from 'bowser';
8
+
9
+ // Core
10
+ import BaseRequest from '@common/router/request';
11
+
12
+ // Specific
13
+ import type ClientRouter from '..';
14
+ import ApiClient from './api';
15
+ import type ClientResponse from '../response';
16
+
17
+ /*----------------------------------
18
+ - TYPES
19
+ ----------------------------------*/
20
+
21
+
22
+ /*----------------------------------
23
+ - ROUTER
24
+ ----------------------------------*/
25
+ // Since we do SSR, the server router can also be passed here
26
+ export default class ClientRequest<TRouter extends ClientRouter = ClientRouter> extends BaseRequest {
27
+
28
+ public api: ApiClient;
29
+ public response?: ClientResponse<TRouter>;
30
+ public hash?: string;
31
+
32
+ public constructor(
33
+ location: Location,
34
+ public router: TRouter,
35
+ public app = router.app
36
+ ) {
37
+
38
+ super(location.pathname);
39
+
40
+ this.host = window.location.host;
41
+ this.hash = location.hash;
42
+
43
+ this.api = new ApiClient(this.app, this);
44
+ }
45
+
46
+ // To move to a service
47
+ public device(): Bowser.Parser.ParsedResult | undefined {
48
+ // We load bowser only when required
49
+ const Bowser = require("bowser");
50
+ return Bowser.parse(window.navigator.userAgent);
51
+ }
52
+ }
@@ -0,0 +1,107 @@
1
+ /*----------------------------------
2
+ - DEPENDANCES
3
+ ----------------------------------*/
4
+
5
+ // Libs
6
+ import type ServerRouter from '@server/services/router';
7
+ import type ServerResponse from '@server/services/router/response';
8
+
9
+ import type { TRoute, TErrorRoute } from '@common/router';
10
+ import BaseResponse from '@common/router/response';
11
+
12
+ import type ClientApplication from '@client/app';
13
+ import type { default as ClientRouter } from '@client/services/router'
14
+ import type ClientResponse from '@client/services/router/response'
15
+ import ClientRequest from '@client/services/router/request'
16
+ import ClientPage from '@client/services/router/response/page'
17
+ import { history } from '@client/services/router/request/history';
18
+ import CommonPage from '@common/router/response/page';
19
+
20
+ /*----------------------------------
21
+ - TYPES
22
+ ----------------------------------*/
23
+
24
+ export type TPageResponse<TRouter extends ClientRouter> = (
25
+ ClientResponse<TRouter, ClientPage>
26
+ |
27
+ ServerResponse<ServerRouter, ClientPage>
28
+ );
29
+
30
+ export type TRouterContext<TRouter extends ClientRouter = ClientRouter, TApplication extends ClientApplication = ClientApplication> = (
31
+ // ClientPage context
32
+ {
33
+ app: TApplication,
34
+ context: TRouterContext<TRouter, TApplication>,
35
+ request: ClientRequest<TRouter>,
36
+ route: TRoute<TRouter>,
37
+ api: ClientRequest<TRouter>["api"],
38
+ page: ClientPage<TRouter>,
39
+ user: User
40
+ }
41
+ &
42
+ // Expose client application services (api, socket, ...)
43
+ //TRouter["app"]
44
+ TApplication
45
+ )
46
+
47
+ /*----------------------------------
48
+ - ROUTER
49
+ ----------------------------------*/
50
+ export default class ClientPageResponse<
51
+ TRouter extends ClientRouter,
52
+ TData extends TResponseData = TResponseData
53
+ > extends BaseResponse<TData> {
54
+
55
+ public context: TRouterContext<TRouter, TRouter["app"]>;
56
+
57
+ public constructor(
58
+ public request: ClientRequest<TRouter>,
59
+ public route: TRoute | TErrorRoute,
60
+
61
+ public app = request.app,
62
+ ) {
63
+
64
+ super(request);
65
+
66
+ request.response = this;
67
+
68
+ // Create response context for controllers
69
+ this.context = this.createContext();
70
+ }
71
+
72
+ private createContext(): TRouterContext<TRouter, TRouter["app"]> {
73
+
74
+ const context: TRouterContext<TRouter, TRouter["app"]> = {
75
+ // App services (TODO: expose only services)
76
+ ...this.request.app,
77
+ // Router context
78
+ app: this.app,
79
+ context: undefined as unknown as TRouterContext<TRouter, TRouter["app"]>,
80
+ request: this.request,
81
+ route: this.route,
82
+ api: this.request.api,
83
+ }
84
+
85
+ context.context = context;
86
+
87
+ return context;
88
+ }
89
+
90
+ public async runController( additionnalData: {} = {} ): Promise<ClientPage> {
91
+
92
+ // Run contoller
93
+ const result = this.route.controller(this.context);
94
+
95
+ // Default data type for `return <raw data>`
96
+ if (result instanceof ClientPage)
97
+ await result.preRender(additionnalData);
98
+ else
99
+ throw new Error(`Unsupported response format: ${result.constructor?.name}`);
100
+
101
+ return result;
102
+ }
103
+
104
+ public redirect(url: string) {
105
+ history?.replace(url);
106
+ }
107
+ }
@@ -0,0 +1,90 @@
1
+ /*----------------------------------
2
+ - DEPENDANCES
3
+ ----------------------------------*/
4
+
5
+ // Npm
6
+ import type { ComponentChild } from 'preact';
7
+
8
+ // Core
9
+ import type { TClientOrServerContext } from '@common/router';
10
+ import PageResponse, { TDataProvider, TFrontRenderer } from "@common/router/response/page";
11
+
12
+ // Specific
13
+ import type ClientRouter from '..';
14
+
15
+ /*----------------------------------
16
+ - TYPES
17
+ ----------------------------------*/
18
+
19
+
20
+
21
+ /*----------------------------------
22
+ - CLASS
23
+ ----------------------------------*/
24
+
25
+ export default class ClientPage<TRouter = ClientRouter> extends PageResponse<TRouter> {
26
+
27
+ public isLoading: boolean = false;
28
+ public loading: false | ComponentChild;
29
+ public scrollToId: string;
30
+
31
+ public constructor(
32
+ public dataProvider: TDataProvider | null,
33
+ public component: TFrontRenderer,
34
+ public context: TClientOrServerContext,
35
+
36
+ public route = context.route
37
+ ) {
38
+
39
+ super(dataProvider, component, context);
40
+
41
+ this.bodyId = context.route.options.bodyId;
42
+ this.scrollToId = context.request.hash;
43
+ }
44
+
45
+ public async preRender( data?: TObjetDonnees ) {
46
+
47
+ // Add the page to the context
48
+ this.context.page = this;
49
+ this.isLoading = true;
50
+
51
+ // Data succesfully loaded
52
+ this.data = data || await this.fetchData();
53
+ this.isLoading = false;
54
+
55
+ return this;
56
+ }
57
+
58
+ /*----------------------------------
59
+ - ACTIONS
60
+ ----------------------------------*/
61
+ // Should be called AFTER rendering the page
62
+ public updateClient() {
63
+
64
+ document.body.id = this.bodyId || this.id;
65
+ document.title = this.title || APP_NAME;
66
+ document.body.className = [...this.bodyClass].join(' ');
67
+
68
+ }
69
+
70
+ public setAllData( callback: (data: {[k: string]: any}) => void) {
71
+ console.warn(`page.setAllData not yet attached to the page Reatc component.`);
72
+ }
73
+ public setData( key: string, value: ((value: any) => void) | any ) {
74
+ this.setAllData(old => ({
75
+ ...old,
76
+ [key]: typeof value === 'function' ? value(old[key]) : value
77
+ }));
78
+ }
79
+
80
+ public setLoading(state: boolean) {
81
+
82
+ if (state === true) {
83
+ if (!document.body.classList.contains("loading"))
84
+ document.body.classList.add("loading");
85
+ } else {
86
+ document.body.classList.remove("loading");
87
+ }
88
+
89
+ }
90
+ }
@@ -2,7 +2,7 @@
2
2
  - DEPENDANCES
3
3
  ----------------------------------*/
4
4
 
5
- import type { ClientContext } from '.';
5
+ import type { ClientContext } from '../../context';
6
6
 
7
7
  import type { TDialogControls } from '@client/components/Dialog/Manager';
8
8
 
@@ -131,7 +131,7 @@ export default class SocketClient {
131
131
 
132
132
  public scopes: { [name: string]: SocketScope } = {}
133
133
 
134
- public constructor(public context: ClientContext ) {
134
+ public constructor( public context: ClientContext ) {
135
135
 
136
136
 
137
137
  }
@@ -1,5 +1,5 @@
1
1
  import type { RefObject } from 'preact';
2
- import { history } from '@client/router/request/history';
2
+ import { history } from '@client/services/router/request/history';
3
3
 
4
4
  type ElementOrSelector = HTMLElement | string;
5
5
  export const deepContains = (
@@ -0,0 +1,9 @@
1
+ import type ClientApplication from '@client/app';
2
+ import type ServerApplication from '@server/app';
3
+
4
+ export type ClientOrServerApplication = ClientApplication | ServerApplication;
5
+
6
+ export type TAppArrowFunction<
7
+ TRegisteredData = void,
8
+ TApplication extends ClientOrServerApplication = ClientOrServerApplication
9
+ > = (app: TApplication) => TRegisteredData
@@ -11,6 +11,11 @@ export const nameToID = (name: string) => name.toLowerCase().replace(/[^a-z1-9]/
11
11
 
12
12
  export const ucfirst = (chaine: string): string => {
13
13
  return chaine.charAt(0).toUpperCase() + chaine.slice(1);
14
+ }
15
+
16
+ export const linkify = (texte: string): string => {
17
+ const regex = /((http|https)\:\/\/([a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(\/\S*)?))/gi;
18
+ return texte.replace(regex, '<a href="$1" target="_blank">$3</a>');
14
19
  }
15
20
 
16
21
  export const trim = (s: string, c: string) => {
@@ -19,12 +24,7 @@ export const trim = (s: string, c: string) => {
19
24
  return s.replace(new RegExp(
20
25
  "^[" + c + "]+|[" + c + "]+$", "g"
21
26
  ), "");
22
- }
23
-
24
- export const linkify = (texte: string): string => {
25
- const regex = /((http|https)\:\/\/([a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(\/\S*)?))/gi;
26
- return texte.replace(regex, '<a href="$1" target="_blank">$3</a>');
27
- }
27
+ }
28
28
 
29
29
  export const trimLeft = (chaine: string, toTrim: string) => chaine.startsWith(toTrim)
30
30
  ? chaine.substring(toTrim.length) : chaine;
@@ -32,6 +32,9 @@ export const trimLeft = (chaine: string, toTrim: string) => chaine.startsWith(to
32
32
  export const trimRight = (chaine: string, toTrim: string) => chaine.endsWith(toTrim)
33
33
  ? chaine.substring(0, -toTrim.length) : chaine;
34
34
 
35
+ export const escapeRegExp = (string: string) =>
36
+ string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
37
+
35
38
  /*----------------------------------
36
39
  - EXTRACT
37
40
  ----------------------------------*/