5htp-core 0.3.7-3 → 0.3.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "5htp-core",
3
3
  "description": "Convenient TypeScript framework designed for Performance and Productivity.",
4
- "version": "0.3.7-3",
4
+ "version": "0.3.8",
5
5
  "author": "Gaetan Le Gac (https://github.com/gaetanlegac)",
6
6
  "repository": "git://github.com/gaetanlegac/5htp-core.git",
7
7
  "license": "MIT",
@@ -80,7 +80,9 @@
80
80
  "validator": "^13.7.0",
81
81
  "ws": "^8.2.2",
82
82
  "yaml": "^1.10.2",
83
- "yargs-parser": "^21.1.1"
83
+ "yargs-parser": "^21.1.1",
84
+ "youch": "^3.3.3",
85
+ "youch-terminal": "^2.2.3"
84
86
  },
85
87
  "devDependencies": {
86
88
  "@types/cookie": "^0.4.1",
@@ -15,7 +15,7 @@ import type {
15
15
  TRouteHttpMethod
16
16
  } from '@server/services/router';
17
17
 
18
- import type { TUserRole } from '@server/services/users';
18
+ import type { TUserRole } from '@server/services/auth';
19
19
 
20
20
  import type { TAppArrowFunction } from '@common/app';
21
21
 
@@ -145,10 +145,9 @@ export default class SchemaValidators {
145
145
  /*----------------------------------
146
146
  - CHAINES
147
147
  ----------------------------------*/
148
- public string = ({ min, max, include, ...opts }: TValidator<string> & {
148
+ public string = ({ min, max, ...opts }: TValidator<string> & {
149
149
  min?: number,
150
- max?: number,
151
- include?: string
150
+ max?: number
152
151
  } = {}) => new Validator<string>('string', (val, input, output, corriger?: boolean) => {
153
152
 
154
153
  // Check type
@@ -5,6 +5,8 @@
5
5
  // Node
6
6
  import { serialize } from 'v8';
7
7
  import { formatWithOptions } from 'util';
8
+ import Youch from 'youch';
9
+ import forTerminal from 'youch-terminal';
8
10
 
9
11
  // Npm
10
12
  import { v4 as uuid } from 'uuid';
@@ -13,8 +15,7 @@ import { format as formatSql } from 'sql-formatter';
13
15
  import highlight from 'cli-highlight';
14
16
 
15
17
  // Core libs
16
- import type { Application } from '@server/app';
17
- import Service from '@server/app/service';
18
+ import type ApplicationContainer from '..';
18
19
  import context from '@server/context';
19
20
  import type { ServerBug } from '@common/errors';
20
21
  import type ServerRequest from '@server/services/router/request';
@@ -117,7 +118,7 @@ const logLevels = {
117
118
  /*----------------------------------
118
119
  - LOGGER
119
120
  ----------------------------------*/
120
- export default class Console extends Service<Config, Hooks, Application, Services> {
121
+ export default class Console {
121
122
 
122
123
  // Services
123
124
  public logger!: Logger<ILogObj>;
@@ -138,18 +139,23 @@ export default class Console extends Service<Config, Hooks, Application, Service
138
139
  WARN: This service should depend on the less services as possible, and be usable ASAP.
139
140
  So bug reports can be sent at any state of the app, includoing thre most early
140
141
  */
141
- public constructor( parent: Application, config: Config, subservices: {}, app: Application ) {
142
+ public constructor(
143
+ private container: typeof ApplicationContainer,
144
+ private config: Config,
145
+ ) {
142
146
 
143
- super(parent, config, subservices, app);
147
+ console.log("Setting up Console shell module.");
144
148
 
145
149
  const origLog = console.log
146
150
 
147
- const envConfig = this.config[ this.app.env.profile === 'prod' ? 'prod' : 'dev' ];
151
+ const Env = container.Environment;
152
+
153
+ const envConfig = this.config[ Env.profile === 'prod' ? 'prod' : 'dev' ];
148
154
  const minLogLevel = logLevels[ envConfig.level ];
149
155
 
150
156
  this.logger = new Logger({
151
157
  // Use to improve performance in production
152
- hideLogPositionForProduction: this.app.env.profile === 'prod',
158
+ hideLogPositionForProduction: Env.profile === 'prod',
153
159
  type: 'pretty',
154
160
  prettyInspectOptions: {
155
161
  depth: 2
@@ -220,7 +226,7 @@ export default class Console extends Service<Config, Hooks, Application, Service
220
226
  if (filepath === undefined)
221
227
  return undefined;
222
228
 
223
- const projectRoot = this.app.container.path.root;
229
+ const projectRoot = this.container.path.root;
224
230
  if (filepath.startsWith( projectRoot ))
225
231
  filepath = filepath.substring( projectRoot.length )
226
232
 
@@ -259,6 +265,34 @@ export default class Console extends Service<Config, Hooks, Application, Service
259
265
 
260
266
  public async createBugReport( error: Error, request?: ServerRequest ) {
261
267
 
268
+ // Print error
269
+ this.logger.error(LogPrefix, `Sending bug report for the following error:`, error);
270
+ /*const youchRes = new Youch(error, {});
271
+ const jsonResponse = await youchRes.toJSON()
272
+ console.log( forTerminal(jsonResponse, {
273
+ // Defaults to false
274
+ displayShortPath: false,
275
+
276
+ // Defaults to single whitspace
277
+ prefix: ' ',
278
+
279
+ // Defaults to false
280
+ hideErrorTitle: false,
281
+
282
+ // Defaults to false
283
+ hideMessage: false,
284
+
285
+ // Defaults to false
286
+ displayMainFrameOnly: false,
287
+
288
+ // Defaults to 3
289
+ framesMaxLimit: 3,
290
+ }) );*/
291
+
292
+ const application = this.container.application;
293
+ if (application === undefined)
294
+ return console.error(LogPrefix, "Can't send bug report because the application is not instanciated");
295
+
262
296
  // Print the error so it's accessible via logs
263
297
  if (error instanceof SqlError) {
264
298
  let printedQuery: string;
@@ -269,7 +303,7 @@ export default class Console extends Service<Config, Hooks, Application, Service
269
303
  }
270
304
  console.error(`Error caused by this query:`, printedQuery);
271
305
  }
272
- console.error(LogPrefix, `Sending bug report for the following error:`, error);
306
+
273
307
  if (error.dataForDebugging !== undefined)
274
308
  console.error(LogPrefix, `More data about the error:`, error.dataForDebugging);
275
309
 
@@ -308,7 +342,7 @@ export default class Console extends Service<Config, Hooks, Application, Service
308
342
  logs: logsHtml
309
343
  }
310
344
 
311
- await this.app.reportBug( bugReport );
345
+ await application.reportBug( bugReport );
312
346
  }
313
347
 
314
348
  public getChannel() {
@@ -8,9 +8,11 @@ import './patch';
8
8
  import path from 'path';
9
9
 
10
10
  // Core
11
+ import type Application from '..';
11
12
  import type { StartedServicesIndex } from '../service';
12
13
  import Services, { ServicesContainer } from '../service/container';
13
14
  import ConfigParser, { TEnvConfig } from './config';
15
+ import Console from './console';
14
16
 
15
17
  /*----------------------------------
16
18
  - CLASS
@@ -26,6 +28,9 @@ export class ApplicationContainer<
26
28
  public Services = Services as ServicesContainer<TServicesIndex>;
27
29
  public Environment: TEnvConfig;
28
30
  public Identity: Config.Identity;
31
+ public Console: Console;
32
+
33
+ public application?: Application;
29
34
 
30
35
  public constructor() {
31
36
 
@@ -33,6 +38,16 @@ export class ApplicationContainer<
33
38
  const configParser = new ConfigParser( this.path.root );
34
39
  this.Environment = configParser.env();
35
40
  this.Identity = configParser.identity();
41
+ this.Console = new Console(this, {
42
+ debug: false,
43
+ bufferLimit: 10000,
44
+ dev: {
45
+ level: 'log'
46
+ },
47
+ prod: {
48
+ level: 'log'
49
+ }
50
+ });
36
51
  }
37
52
 
38
53
  // Context
@@ -51,6 +66,45 @@ export class ApplicationContainer<
51
66
  },
52
67
  }
53
68
 
69
+ public start( ApplicationClass: typeof Application ) {
70
+
71
+ // Instanciate Application
72
+ try {
73
+ this.application = new ApplicationClass;
74
+ } catch (error) {
75
+ this.handleBug(error, "Failed to instanciate the Application Class");
76
+ process.exit(1);
77
+ }
78
+
79
+ // Start application
80
+ try {
81
+ this.application.start();
82
+ } catch (error) {
83
+ this.handleBug(error, "Failed to start the Application");
84
+ process.exit(1);
85
+ }
86
+ }
87
+
88
+ public async handleBug( rejection: Error, message: string ) {
89
+ if (this.Console) {
90
+ try {
91
+
92
+ this.Console.createBugReport(rejection);
93
+
94
+ } catch (consoleError) {
95
+ console.error(
96
+ message, rejection,
97
+ "Failed to transmiss the previous error to console:", consoleError
98
+ );
99
+ process.exit(1);
100
+ }
101
+ } else {
102
+ console.error(message, rejection);
103
+ process.exit(1);
104
+ }
105
+ }
106
+
107
+
54
108
  /*----------------------------------
55
109
  - HMR
56
110
  - TODO: move in dev server
@@ -11,7 +11,7 @@ import ServicesContainer, {
11
11
  TRegisteredService,
12
12
  TServiceMetas
13
13
  } from './service/container';
14
- import type { ServerBug } from '../services/console';
14
+ import type { ServerBug } from './container/console';
15
15
 
16
16
  // Built-in
17
17
  import type { default as Router, Request as ServerRequest } from '@server/services/router';
@@ -82,9 +82,6 @@ export class Application<
82
82
  public debug: boolean = false;
83
83
  public launched: boolean = false;
84
84
 
85
- // Mandatory services
86
- public Console = this.use('Core/Console');
87
-
88
85
  /*----------------------------------
89
86
  - INIT
90
87
  ----------------------------------*/
@@ -98,7 +95,7 @@ export class Application<
98
95
  super(self, {}, {}, self);
99
96
 
100
97
  // Handle unhandled crash
101
- this.on('error', e => this.unhandledRejection(e));
98
+ this.on('error', e => this.container.handleBug(e, "An error occured in the application"));
102
99
 
103
100
  process.on('unhandledRejection', (error: any, promise: any) => {
104
101
  console.log("unhandledRejection");
@@ -126,7 +123,7 @@ export class Application<
126
123
  - LAUNCH
127
124
  ----------------------------------*/
128
125
 
129
- protected async start() {
126
+ public async start() {
130
127
 
131
128
  console.log("Build date", BUILD_DATE);
132
129
  console.log("Core version", CORE_VERSION);
@@ -204,25 +201,6 @@ export class Application<
204
201
  /*----------------------------------
205
202
  - ERROR HANDLING
206
203
  ----------------------------------*/
207
- private async unhandledRejection(rejection: Error) {
208
- if (this.Console) {
209
- try {
210
-
211
- this.Console.createBugReport(rejection);
212
-
213
- } catch (consoleError) {
214
- console.error(
215
- "Unhandled rejection", rejection,
216
- "Failed to transmiss the previous error to console:", consoleError
217
- );
218
- process.exit(1);
219
- }
220
- } else {
221
- console.error("Unhandled rejection", rejection);
222
- process.exit(1);
223
- }
224
- }
225
-
226
204
  // Default error handler
227
205
  public async reportBug( bug: ServerBug ) {
228
206
 
@@ -174,8 +174,7 @@ export default abstract class Service<
174
174
  if (serviceUseOptions.optional)
175
175
  return undefined;
176
176
  else {
177
- console.error(`Unable to use service "${serviceId}": This one hasn't been setup.`);
178
- process.exit(1);
177
+ throw new Error(`Unable to use service "${serviceId}": This one hasn't been setup.`);
179
178
  }
180
179
  }
181
180
 
@@ -200,8 +199,8 @@ export default abstract class Service<
200
199
  try {
201
200
  ServiceClass = registered.metas.class().default;
202
201
  } catch (error) {
203
- console.error("Failed to get the class of the", registered.metas.id, "service:", error);
204
- process.exit(1);
202
+ console.error("Failed to load the class of the", registered.metas.id, "service:", error);
203
+ throw error;
205
204
  }
206
205
 
207
206
  // Create class instance
@@ -215,8 +214,8 @@ export default abstract class Service<
215
214
  this.app || this
216
215
  )
217
216
  } catch (error) {
218
- console.error("Failed to instanciate class of the", registered.metas.id, "service:", error);
219
- process.exit(1);
217
+ console.error("Failed to instanciate class of the", registered.metas.id, "service");
218
+ throw error;
220
219
  }
221
220
 
222
221
  // Hande custom instance getter (ex: SQL callable class)
@@ -225,8 +224,8 @@ export default abstract class Service<
225
224
  try {
226
225
  serviceInstance = service.getServiceInstance();
227
226
  } catch (error) {
228
- console.error("Failed to get service instance for the ", registered.metas.id, "service:", error);
229
- process.exit(1);
227
+ console.error("Failed to get service instance for the ", registered.metas.id, "service");
228
+ throw error;
230
229
  }
231
230
 
232
231
  // Bind his own metas
@@ -1,4 +1,4 @@
1
1
  import { AsyncLocalStorage } from 'async_hooks';
2
- import type { ChannelInfos } from '@server/services/console';
2
+ import type { ChannelInfos } from '@server/app/container/console';
3
3
 
4
4
  export default new AsyncLocalStorage<ChannelInfos>();
@@ -1,12 +1,4 @@
1
- // Load Application container
2
- import './app/container';
3
-
4
- // Load services setup
1
+ import AppContainer from './app/container';
5
2
  import '@/server/config/*.ts';
6
-
7
- // Load Application
8
3
  import Application from '@/server';
9
- const application = new Application;
10
-
11
- // Start application
12
- application.start();
4
+ AppContainer.start( Application );
@@ -65,7 +65,7 @@ export type TServices = {
65
65
  /*----------------------------------
66
66
  - SERVICE
67
67
  ----------------------------------*/
68
- export default abstract class UsersManagementService<
68
+ export default abstract class AuthService<
69
69
  TUser extends {},
70
70
  TApplication extends Application,
71
71
  TJwtSession extends {} = {},
@@ -233,9 +233,19 @@ export default class SQL extends Service<Config, Hooks, Application, Services> {
233
233
  // SQL query
234
234
  } else if (typeof value === 'function' && value.string !== undefined)
235
235
  value = ' ' + value.string;
236
- else
237
- value = ' ' + mysql.escape(value);
236
+ // Escape value
237
+ else {
238
238
 
239
+ const lastKeyword = stringBefore.trim().split(' ').pop();
240
+
241
+ // Escape table name
242
+ if (lastKeyword === 'FROM')
243
+ value = '`' + value + '`';
244
+ else
245
+ value = mysql.escape(value);
246
+
247
+ value = ' ' + value;
248
+ }
239
249
  stringBefore += value;
240
250
 
241
251
  }
@@ -83,7 +83,6 @@ export default class FetchService extends Service<Config, Hooks, Application, Se
83
83
  if (this.services.disks)
84
84
  this.disk = this.services.disks.get( this.config.disk );
85
85
 
86
-
87
86
  }
88
87
 
89
88
  public async ready() {
@@ -116,8 +115,10 @@ export default class FetchService extends Service<Config, Hooks, Application, Se
116
115
  ) {
117
116
 
118
117
  // Parse url if router service is provided
119
- if (this.services.router !== undefined)
120
- url = this.services.router.url(url);
118
+ if (this.services.router === undefined)
119
+ throw new Error(`Please bind the Router service to the Fetch service in order to contact APIs.`);
120
+
121
+ url = this.services.router.url(url);
121
122
 
122
123
  // Send request
123
124
  const res = await got(url, {
@@ -14,7 +14,7 @@ import Service, { AnyService, TRegisteredService } from '@server/app/service';
14
14
  import SocketScope, { WebSocket } from './scope';
15
15
  import type Router from '@server/services/router';
16
16
  export type { WebSocket, default as SocketScope } from './scope';
17
- import type UsersManagementService from '../users';
17
+ import type UsersManagementService from '../auth';
18
18
 
19
19
  /*----------------------------------
20
20
  - TYPES
@@ -1,6 +0,0 @@
1
- {
2
- "id": "Core/Console",
3
- "name": "Console",
4
- "parent": "app",
5
- "dependences": []
6
- }
File without changes