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,98 @@
1
+ /*----------------------------------
2
+ - DEPENDANCES
3
+ ----------------------------------*/
4
+
5
+ import Application from ".";
6
+
7
+ /*----------------------------------
8
+ - TYPES: OPTIONS
9
+ ----------------------------------*/
10
+
11
+ export type AnyService = Service<{}, {}, Application>
12
+
13
+ type THookCallback<THookArgs extends THookOptions> = (...args: THookArgs["args"]) => Promise<void>;
14
+
15
+ type THooksList = {
16
+ [hookName: string]: THookOptions
17
+ }
18
+
19
+ type THookOptions = {
20
+ args: any[]
21
+ }
22
+
23
+ export type TPriority = -2 | -1 | 0 | 1 | 2
24
+
25
+ /*----------------------------------
26
+ - CONFIG
27
+ ----------------------------------*/
28
+
29
+ const LogPrefix = '[service]';
30
+
31
+ /*----------------------------------
32
+ - CLASS
33
+ ----------------------------------*/
34
+ export default abstract class Service<
35
+ TConfig extends {},
36
+ THooks extends THooksList,
37
+ TApplication extends Application
38
+ > {
39
+
40
+ public priority: TPriority = 0;
41
+ public started?: Promise<void>;
42
+
43
+ public constructor(
44
+ public app: TApplication,
45
+ public config: TConfig,
46
+ ) {
47
+
48
+ if (!( this instanceof Application ))
49
+ // Make the app aware of his services
50
+ app.registerService(this);
51
+
52
+ }
53
+
54
+ public abstract register?(): Promise<void>;
55
+
56
+ public abstract start?(): Promise<void>;
57
+
58
+ /*----------------------------------
59
+ - HOOKS
60
+ ----------------------------------*/
61
+ public hooks: {[name in keyof THooks]?: THookCallback< THooks[name] >[]} = {}
62
+
63
+ public on<THookName extends keyof THooksList>(
64
+ name: THookName,
65
+ callback: THookCallback<THooksList[THookName]>
66
+ ) {
67
+
68
+ const callbacks = this.hooks[ name ];
69
+ if (callbacks)
70
+ callbacks.push( callback );
71
+ else
72
+ this.hooks[ name ] = [callback]
73
+
74
+ return this;
75
+ }
76
+
77
+ public runHook<THookName extends keyof THooksList>(
78
+ name: THookName,
79
+ ...args: THooksList[THookName]["args"]
80
+ ) {
81
+
82
+ const callbacks = this.hooks[name];
83
+ if (!callbacks)
84
+ return console.info(LogPrefix, `No ${name} hook defined in the current service instance.`);
85
+
86
+ console.info(`[hook] Run all ${name} hook (${callbacks.length}).`);
87
+ return Promise.all(
88
+ callbacks.map(
89
+ cb => cb(...args).catch(e => {
90
+ console.error(`[hook] Error while executing hook ${name}:`, e);
91
+ })
92
+ )
93
+ ).then(() => {
94
+ console.info(`[hook] Hooks ${name} executed with success.`);
95
+ })
96
+ }
97
+
98
+ }
@@ -5,18 +5,10 @@
5
5
  "baseUrl": "..",
6
6
  "paths": {
7
7
 
8
- // RAPPEL: Mettre à jour webpack externals
9
-
10
8
  "@client/*": ["../node_modules/5htp-core/src/client/*"],
11
9
  "@common/*": ["../node_modules/5htp-core/src/common/*"],
12
10
  "@server/*": ["../node_modules/5htp-core/src/server/*"],
13
11
 
14
- "@validator": ["../node_modules/5htp-core/src/server/data/input"],
15
- "@router": ["../node_modules/5htp-core/src/server/services/router"],
16
- "@errors": ["../node_modules/5htp-core/src/common/errors"],
17
-
18
- "@models": ["../server/models"],
19
-
20
12
  "@/*": ["./*"],
21
13
 
22
14
  // ATTENTION: Les références à preact doivent toujours pointer vers la même instance
@@ -0,0 +1,5 @@
1
+ import Application from '@/server';
2
+
3
+ const app = new Application();
4
+
5
+ app.start();
@@ -1,9 +1,3 @@
1
- const moduleAlias = require('module-alias')
2
- moduleAlias.addAliases({
3
- 'react': "preact/compat",
4
- 'react-dom': "preact/compat",
5
- })
6
-
7
1
  /*----------------------------------
8
2
  - DATES & TIMZEONE
9
3
  ----------------------------------*/
@@ -10,7 +10,7 @@ import hInterval from 'human-interval';
10
10
  import fs from 'fs-extra';
11
11
 
12
12
  // Core
13
- import app from '@server/app';
13
+ import Application, { Service } from '@server/app';
14
14
 
15
15
  // Libs
16
16
 
@@ -18,15 +18,17 @@ import app from '@server/app';
18
18
  - CONFIG
19
19
  ----------------------------------*/
20
20
 
21
- const debug = false;
21
+ const LogPrefix = '[cache]';
22
22
 
23
23
  /*----------------------------------
24
24
  - TYPES
25
25
  ----------------------------------*/
26
26
 
27
- type TPrimitiveValue = string | boolean | number | undefined | {[key: string]: TPrimitiveValue} | TPrimitiveValue[];
27
+ type TPrimitiveValue = string | boolean | number | undefined | TPrimitiveValue[] | {
28
+ [key: string]: TPrimitiveValue
29
+ }
28
30
 
29
- type TExpirationDelay = string | number | Date | null;
31
+ type TExpirationDelay = 'never' | string | number | Date;
30
32
 
31
33
  type CacheEntry = {
32
34
  // Value
@@ -35,47 +37,70 @@ type CacheEntry = {
35
37
  expiration?: number
36
38
  };
37
39
 
40
+ /*----------------------------------
41
+ - TYPES
42
+ ----------------------------------*/
43
+
44
+ export type Config = {
45
+ debug: boolean
46
+ }
47
+
48
+ export type Hooks = {
49
+
50
+ }
51
+
38
52
  /*----------------------------------
39
53
  - SERVICE
40
54
  ----------------------------------*/
41
- class Cache {
55
+ export default class Cache extends Service<Config, Hooks, Application> {
42
56
 
43
- private cacheFile = path.join(app.path.data, 'cache/mem.json');
57
+ private cacheFile = path.join(this.app.path.data, 'cache/mem.json');
44
58
 
45
59
  private data: {[key: string]: CacheEntry | undefined} = {};
46
60
 
47
61
  private changes: number = 0;
48
62
 
49
- public constructor() {
63
+ public async register() {
64
+
65
+
66
+ }
67
+
68
+ public async start() {
50
69
 
51
70
  setInterval(() => this.cleanMem(), 10000);
52
71
 
72
+ // Restore persisted data
53
73
  if (fs.existsSync(this.cacheFile))
54
74
  this.data = fs.readJSONSync(this.cacheFile)
55
75
  }
56
76
 
57
77
  private cleanMem() {
58
78
 
59
- debug && console.log("[cache] Clean memory");
60
-
79
+ // Remove expired data
61
80
  const now = Date.now();
62
81
  for (const key in this.data) {
63
82
  const entry = this.data[ key ];
64
- if (entry?.expiration && entry.expiration < now)
83
+ if (entry?.expiration && entry.expiration < now) {
84
+ this.config.debug && console.log(LogPrefix, `Delete expired data: ${key}`);
65
85
  this.del(key);
86
+ }
66
87
  }
67
88
 
68
- if (this.changes > 0)
89
+ // Write changes
90
+ if (this.changes > 0) {
69
91
  fs.outputJSONSync(this.cacheFile, this.data);
92
+ this.config.debug && console.log(LogPrefix, `Flush ${this.changes} changes`);
93
+ this.changes = 0;
94
+ }
70
95
  }
71
96
 
72
97
  // Expiration = Durée de vie en secondes ou date max
73
98
  // Retourne null quand pas de valeur
74
99
  public get<TValeur extends TPrimitiveValue>(
75
100
  cle: string,
76
- func?: (() => Promise<TValeur>),
77
- expiration?: TExpirationDelay,
78
- avecDetails?: true
101
+ func: (() => Promise<TValeur>),
102
+ expiration: TExpirationDelay,
103
+ avecDetails: true
79
104
  ): Promise<CacheEntry>;
80
105
 
81
106
  public get<TValeur extends TPrimitiveValue>(
@@ -83,47 +108,44 @@ class Cache {
83
108
  func: (() => Promise<TValeur>),
84
109
  expiration?: TExpirationDelay,
85
110
  avecDetails?: false
86
- ): Promise<null | TValeur>;
111
+ ): Promise<TValeur>;
87
112
 
88
113
  public async get<TValeur extends TPrimitiveValue>(
89
114
  cle: string,
90
- func?: (() => Promise<TValeur>),
91
- expiration?: TExpirationDelay,
115
+ func: (() => Promise<TValeur>),
116
+ expiration: TExpirationDelay = 'never',
92
117
  avecDetails?: boolean
93
- ): Promise<null | TValeur | CacheEntry> {
118
+ ): Promise<TValeur | CacheEntry> {
94
119
 
95
- let retour: CacheEntry | undefined = this.data[cle];
96
-
97
- debug && console.log(`[cache] Get "${cle}".`);
120
+ let entry: CacheEntry | undefined = this.data[cle];
98
121
 
99
122
  // Expired
100
- if (retour?.expiration && retour.expiration < Date.now()){
101
- debug && console.log(`[cache] Key ${cle} expired.`);
102
- retour = undefined;
123
+ if (entry?.expiration && entry.expiration < Date.now()){
124
+ this.config.debug && console.log(LogPrefix, `Key ${cle} expired.`);
125
+ entry = undefined;
103
126
  }
104
127
 
105
128
  // Donnée inexistante
106
- if (retour === undefined && func !== undefined) {
129
+ if (entry === undefined) {
130
+
131
+ this.config.debug && console.log(LogPrefix, `Get "${cle}": refresh value`);
107
132
 
108
133
  // Rechargement
109
- retour = {
134
+ entry = {
110
135
  value: await func(),
111
- expiration: expiration
112
- ? this.delayToTimestamp(expiration)
113
- : undefined
136
+ expiration: this.delayToTimestamp(expiration)
114
137
  }
115
138
 
116
139
  // undefined retourné = pas d'enregistrement
117
- if (retour.value !== undefined)
118
- await this.set(cle, retour, expiration);
119
- }
140
+ //if (entry.value !== undefined)
141
+ await this.set(cle, entry.value, expiration);
120
142
 
121
- if (retour === undefined)
122
- return null;
143
+ } else
144
+ this.config.debug && console.log(LogPrefix, `Get "${cle}": restored via cache`);
123
145
 
124
146
  return avecDetails
125
- ? retour
126
- : retour.value as TValeur;
147
+ ? entry
148
+ : entry.value as TValeur;
127
149
  };
128
150
 
129
151
  /**
@@ -137,9 +159,9 @@ class Cache {
137
159
  * - null: no expiration (default)
138
160
  * @returns A void promise
139
161
  */
140
- public set( cle: string, val: TPrimitiveValue, expiration: TExpirationDelay = null ): void {
162
+ public set( cle: string, val: TPrimitiveValue, expiration: TExpirationDelay = 'never' ): void {
141
163
 
142
- debug && console.log("[cache] Updating cache " + cle);
164
+ this.config.debug && console.log(LogPrefix, "Updating cache " + cle);
143
165
  this.data[ cle ] = {
144
166
  value: val,
145
167
  expiration: this.delayToTimestamp(expiration)
@@ -157,24 +179,34 @@ class Cache {
157
179
  /*----------------------------------
158
180
  - UTILS
159
181
  ----------------------------------*/
160
- private delayToTimestamp( delay: TExpirationDelay ): number {
182
+ /**
183
+ *
184
+ * @param delay
185
+ * @returns number (timestamp when the data expired) or undefined (never expires)
186
+ */
187
+ private delayToTimestamp( delay: TExpirationDelay ): number | undefined {
188
+
189
+ if (delay === 'now') {
190
+
191
+ return Date.now();
192
+
193
+ } else if (delay === 'never') {
194
+
195
+ return undefined;
161
196
 
162
197
  // H expression
163
- if (typeof delay === 'string') {
198
+ } else if (typeof delay === 'string') {
164
199
 
165
200
  const ms = hInterval(delay);
166
201
  if (ms === undefined) throw new Error(`Invalid period string: ` + delay);
167
202
  return Date.now() + ms;
168
203
 
169
- // Via durée de vie en secondes
204
+ // Lifetime in seconds
170
205
  } else if (typeof delay === 'number')
171
206
  return Date.now() + delay;
172
- // Date limite
173
- else if (delay !== null)
174
- return delay.getTime();
207
+
208
+ // Date limit
175
209
  else
176
- return Date.now();
210
+ return delay.getTime();
177
211
  }
178
212
  }
179
-
180
- export default new Cache;
@@ -6,8 +6,8 @@
6
6
  import { v4 as uuid } from 'uuid';
7
7
 
8
8
  // Core
9
- import app, { $ } from '@server/app';
10
- import type { Console } from '.';
9
+ import { SqlError } from '@server/services/database/debug';
10
+ import type Console from '.';
11
11
 
12
12
  // Types
13
13
  import type ServerRequest from '@server/services/router/request';
@@ -72,8 +72,6 @@ export type ApplicationBug = {
72
72
  stacktrace: string
73
73
  }
74
74
 
75
- const config = app.config.console;
76
-
77
75
  /*----------------------------------
78
76
  - CONFIG
79
77
  ----------------------------------*/
@@ -110,7 +108,8 @@ export default class BugReporter {
110
108
  private sentBugs: {[bugId: string]: number} = {};
111
109
 
112
110
  public constructor(
113
- private console: Console
111
+ private console: Console,
112
+ public app = console.app,
114
113
  ) {
115
114
 
116
115
  }
@@ -133,7 +132,16 @@ export default class BugReporter {
133
132
 
134
133
  public async server( error: Error, request?: ServerRequest ) {
135
134
 
136
- // error should be printed in the console, so they're acccessible from logs
135
+ // Print the error so it's accessible via logs
136
+ if (error instanceof SqlError) {
137
+ let printedQuery: string;
138
+ try {
139
+ printedQuery = this.console.printSql( error.query );
140
+ } catch (error) {
141
+ printedQuery = 'Failed to print query:' + (error || 'unknown error');
142
+ }
143
+ console.error(`Error caused by this query:`, printedQuery);
144
+ }
137
145
  console.error(LogPrefix, `Sending bug report for the following error:`, error);
138
146
 
139
147
  // Prevent duplicates
@@ -172,6 +180,7 @@ export default class BugReporter {
172
180
 
173
181
  await this.sendToTransporters(bugReport);
174
182
 
183
+ // TODO: Move on App side
175
184
  /*if (app.isLoaded('sql'))
176
185
  // Memorize
177
186
  $.sql.insert('BugServer', {
@@ -192,7 +201,7 @@ export default class BugReporter {
192
201
  error.message = "A bug report has been sent to my personal mailbox. Sorry for the inconvenience.";
193
202
  }
194
203
 
195
- public async app( report: AppBugInfos ) {
204
+ public async application( report: AppBugInfos ) {
196
205
 
197
206
  // Prevent duplicates
198
207
  if (!this.shouldSendReport(report.side, report.user, report.action, report.message))
@@ -224,17 +233,12 @@ export default class BugReporter {
224
233
  stacktrace: report.stacktrace,
225
234
  }
226
235
 
227
- await this.sendToTransporters(bugReport);
228
-
229
- /* // Send notification
230
- $.email.send({
231
- to: app.identity.author.email,
232
- subject: "Bug app: " + report.message,
233
- html: report
234
- });
235
236
 
237
+ // TODO:
236
238
  // Memorize
237
- $.sql.insert('BugApp', );*/
239
+ //$.sql.insert('BugApp', );
240
+
241
+ await this.sendToTransporters(bugReport);
238
242
  }
239
243
 
240
244
  private async sendToTransporters( bugReport: Bug, error?: Error ) {
@@ -245,6 +249,12 @@ export default class BugReporter {
245
249
  return false;
246
250
  }
247
251
 
252
+ // Don't send if we're in local (avoid to use credits: ex: email, sms)
253
+ if (this.app.env.name === 'local'){
254
+ console.warn(LogPrefix, `Error report sending aborted since we're local.`);
255
+ return false;
256
+ }
257
+
248
258
  // Send report to trabporters
249
259
  await Promise.all(
250
260
  this.transporters.map( transport => {
@@ -8,30 +8,31 @@ import { format as formatSql } from 'sql-formatter';
8
8
  import highlight from 'cli-highlight';
9
9
 
10
10
  // Core libs
11
- import app, { $ } from '@server/app';
12
- import logToHTML from './html';
11
+ import Application, { Service, TPriority } from '@server/app';
13
12
  import context from '@server/context';
13
+ import type ServerRequest from '@server/services/router/request';
14
+
15
+ // Specific
16
+ import logToHTML from './html';
14
17
  import BugReporter from "./bugReporter";
15
18
 
16
19
  /*----------------------------------
17
20
  - SERVICE CONFIG
18
21
  ----------------------------------*/
19
22
 
20
- export type TReportTransport = keyof typeof $
23
+ type TLogProfile = 'silly' | 'info' | 'warn' | 'error'
21
24
 
22
- export type ConsoleConfig = {
23
- bugReport: TReportTransport[]
25
+ export type Config = {
26
+ dev: {
27
+ level: TLogProfile,
28
+ },
29
+ prod: {
30
+ level: TLogProfile
31
+ }
24
32
  }
25
33
 
26
- declare global {
27
- namespace Core {
28
- interface EmailTransporters { }
29
- namespace Config {
30
- interface Services {
31
- console: ConsoleConfig
32
- }
33
- }
34
- }
34
+ export type Hooks = {
35
+
35
36
  }
36
37
 
37
38
  /*----------------------------------
@@ -103,7 +104,10 @@ const logFields = [
103
104
  /*----------------------------------
104
105
  - LOGGER
105
106
  ----------------------------------*/
106
- export class Console {
107
+ export default class Console extends Service<Config, Hooks, Application> {
108
+
109
+ // Load before all
110
+ public priority: TPriority = 2;
107
111
 
108
112
  // Services
109
113
  public logger!: Logger;
@@ -115,34 +119,50 @@ export class Console {
115
119
  public requests: TRequestLogs[] = [];
116
120
  public sqlQueries: TQueryLogs[] = [];
117
121
 
122
+ // Adapters
123
+ public log = console.log;
124
+ public warn = console.warn;
125
+ public info = console.info;
126
+ public error = console.error;
127
+
118
128
  /*----------------------------------
119
- - INSTANCE
120
- ----------------------------------*/
121
- public load() {
129
+ - INSTANCE
130
+ ----------------------------------*/
131
+ public async register() {
132
+
133
+ }
134
+
135
+ public async start() {
136
+
137
+ const envConfig = this.config[ this.app.env.profile ];
122
138
 
123
139
  this.logger = new Logger({
124
140
  overwriteConsole: true,
125
- //type: app.env.profile === 'dev' ? 'pretty' : 'hidden',
141
+ //type: this.app.env.profile === 'dev' ? 'pretty' : 'hidden',
126
142
  requestId: (): string => {
127
143
  const { channelType, channelId } = this.getChannel();
128
144
  return channelId === undefined ? channelType : channelType + ':' + channelId;
129
145
  },
130
146
  displayRequestId: false,
147
+ prettyInspectOptions: {
148
+ depth: 2
149
+ }
131
150
  });
132
151
 
133
152
  this.logger.attachTransport({
134
- silly: this.log.bind(this),
135
- debug: this.log.bind(this),
136
- trace: this.log.bind(this),
137
- info: this.log.bind(this),
138
- warn: this.log.bind(this),
139
- error: this.log.bind(this),
140
- fatal: this.log.bind(this),
141
- }, app.env.level);
153
+ silly: this.logEntry.bind(this),
154
+ debug: this.logEntry.bind(this),
155
+ trace: this.logEntry.bind(this),
156
+ info: this.logEntry.bind(this),
157
+ warn: this.logEntry.bind(this),
158
+ error: this.logEntry.bind(this),
159
+ fatal: this.logEntry.bind(this),
160
+ }, envConfig.level);
142
161
 
143
162
  setInterval(() => this.clean(), 60000);
144
163
 
145
- return this.logger;
164
+ // Send email report
165
+ this.app.on('error', (error: Error, request?: ServerRequest) => this.bugReport.server(error, request));
146
166
  }
147
167
 
148
168
  private clean() {
@@ -160,7 +180,7 @@ export class Console {
160
180
  }
161
181
  }
162
182
 
163
- private log(entry: ILogObject) {
183
+ private logEntry(entry: ILogObject) {
164
184
 
165
185
  const [channelType, channelId] = entry.requestId?.split(':') || ['master'];
166
186
  if (entry.requestId === 'admin')
@@ -175,10 +195,10 @@ export class Console {
175
195
  // remove webpack path
176
196
  if (miniLog.filePath !== undefined) {
177
197
 
178
- const appPrefix = '/webpack:/' + app.pkg.name + '/src/';
198
+ const appPrefix = '/webpack:/' + this.app.pkg.name + '/src/';
179
199
  const appPrefixIndex = miniLog.filePath.indexOf(appPrefix);
180
200
 
181
- const corePrefix = '/webpack:/' + app.pkg.name + '/node_modules/5htp-core/src/';
201
+ const corePrefix = '/webpack:/' + this.app.pkg.name + '/node_modules/5htp-core/src/';
182
202
  const corePrefixIndex = miniLog.filePath.indexOf(corePrefix);
183
203
 
184
204
  if (appPrefixIndex !== -1)
@@ -207,8 +227,8 @@ export class Console {
207
227
  - READ
208
228
  ----------------------------------*/
209
229
 
210
- public getClients() {
211
- return $.sql`
230
+ /*public getClients() {
231
+ return sql`
212
232
  SELECT * FROM logs.Clients
213
233
  ORDER BY activity DESC
214
234
  LIMIT 100
@@ -219,7 +239,7 @@ export class Console {
219
239
  return (
220
240
  this.clients.find(c => c.id === clientId)
221
241
  ||
222
- await $.sql`
242
+ await sql`
223
243
  SELECT * FROM logs.Clients
224
244
  WHERE id = ${clientId}
225
245
  `.first()
@@ -227,7 +247,7 @@ export class Console {
227
247
  }
228
248
 
229
249
  public getRequests(clientId?: string) {
230
- return $.sql`
250
+ return sql`
231
251
  SELECT * FROM logs.Requests
232
252
  ORDER BY date DESC
233
253
  LIMIT 100
@@ -238,7 +258,7 @@ export class Console {
238
258
  return (
239
259
  this.requests.find(r => r.id === requestId)
240
260
  ||
241
- await $.sql`
261
+ await sql`
242
262
  SELECT * FROM logs.Requests
243
263
  WHERE id = ${requestId}
244
264
  `.first()
@@ -251,13 +271,13 @@ export class Console {
251
271
  if (channelId !== undefined)
252
272
  filters.channelId = channelId;
253
273
 
254
- return $.sql`
274
+ return sql`
255
275
  SELECT * FROM logs.Queries
256
276
  WHERE :${filters}
257
277
  ORDER BY date DESC
258
278
  LIMIT 100
259
279
  `.all();
260
- }
280
+ }*/
261
281
 
262
282
  public async getLogs( channelType: ChannelInfos["channelType"], channelId?: string ) {
263
283
 
@@ -274,7 +294,7 @@ export class Console {
274
294
 
275
295
  public printHtml(logs: TLog[], full: boolean = false): string {
276
296
 
277
- let html = logs.map( log => logToHTML( log, this )).join('\n');
297
+ let html = logs.map( logEntry => logToHTML( logEntry, this )).join('\n');
278
298
 
279
299
  if (full) {
280
300
  const consoleCss = `background: #000; padding: 20px; font-family: 'Fira Mono', 'monospace', 'Monaco'; font-size: 12px; line-height: 20px;`
@@ -289,16 +309,4 @@ export class Console {
289
309
  { language: 'sql', ignoreIllegals: true }
290
310
  )
291
311
 
292
- }
293
-
294
- /*----------------------------------
295
- - REGISTER SERVICE
296
- ----------------------------------*/
297
- app.register('console', Console);
298
- declare global {
299
- namespace Core {
300
- interface Services {
301
- console: Console;
302
- }
303
- }
304
312
  }